Project import generated by Copybara.

GitOrigin-RevId: 54532fda9ad03e43c12b59fe162f44849d7db2ff
diff --git a/wlan_sd8987/Makefile b/wlan_sd8987/Makefile
new file mode 100755
index 0000000..c92175c
--- /dev/null
+++ b/wlan_sd8987/Makefile
@@ -0,0 +1,641 @@
+#  File: Makefile
+#
+#  Copyright 2008-2021 NXP
+#
+#  This software file (the File) is distributed by NXP
+#  under the terms of the GNU General Public License Version 2, June 1991
+#  (the License).  You may use, redistribute and/or modify the File in
+#  accordance with the terms and conditions of the License, a copy of which
+#  is available by writing to the Free Software Foundation, Inc.,
+#  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+#  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+#  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+#  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+#  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+#  this warranty disclaimer.
+#
+
+CONFIG_COMPATDIR=n
+ifeq ($(CONFIG_COMPATDIR), y)
+COMPATDIR=/lib/modules/$(KERNELVERSION_X86)/build/compat-wireless-3.2-rc1-1/include
+CC ?=		$(CROSS_COMPILE)gcc -I$(COMPATDIR)
+else
+CC ?=		$(CROSS_COMPILE)gcc
+endif
+
+LD ?=		$(CROSS_COMPILE)ld
+STRIP ?= 	$(CROSS_COMPILE)strip
+BACKUP=		/root/backup
+YMD=		`date +%Y%m%d%H%M`
+
+#############################################################################
+# Configuration Options
+#############################################################################
+# Multi-chipsets
+CONFIG_SD8887=n
+CONFIG_SD8897=n
+CONFIG_USB8897=n
+CONFIG_PCIE8897=n
+CONFIG_SD8977=n
+CONFIG_SD8978=n
+CONFIG_USB8978=n
+CONFIG_SD8997=n
+CONFIG_USB8997=n
+CONFIG_PCIE8997=n
+CONFIG_SD8987=y
+CONFIG_SD9097=n
+CONFIG_USB9097=n
+CONFIG_PCIE9097=n
+CONFIG_SD9098=n
+CONFIG_USB9098=n
+CONFIG_PCIE9098=n
+
+
+# Debug Option
+# DEBUG LEVEL n/1/2:
+# n: NO DEBUG
+# 1: Only PRINTM(MMSG,...), PRINTM(MFATAL,...), ...
+# 2: All PRINTM()
+CONFIG_DEBUG=1
+
+# Enable STA mode support
+CONFIG_STA_SUPPORT=y
+
+# Enable uAP mode support
+CONFIG_UAP_SUPPORT=y
+
+# Enable WIFIDIRECT support
+CONFIG_WIFI_DIRECT_SUPPORT=y
+
+# Enable Wi-Fi Latency mode setting support
+CONFIG_WIFI_SET_LATENCY_MODE=y
+
+# Re-association in driver
+CONFIG_REASSOCIATION=y
+
+
+# Manufacturing firmware support
+CONFIG_MFG_CMD_SUPPORT=y
+
+# OpenWrt support
+CONFIG_OPENWRT_SUPPORT=n
+
+# Big-endian platform
+CONFIG_BIG_ENDIAN=n
+
+
+
+ifeq ($(CONFIG_DRV_EMBEDDED_SUPPLICANT), y)
+CONFIG_EMBEDDED_SUPP_AUTH=y
+else
+ifeq ($(CONFIG_DRV_EMBEDDED_AUTHENTICATOR), y)
+CONFIG_EMBEDDED_SUPP_AUTH=y
+endif
+endif
+
+#ifdef SDIO_MMC
+# SDIO suspend/resume
+CONFIG_SDIO_SUSPEND_RESUME=y
+#endif
+
+# DFS testing support
+CONFIG_DFS_TESTING_SUPPORT=y
+
+
+
+
+# Use static link for app build
+export CONFIG_STATIC_LINK=y
+CONFIG_ANDROID_KERNEL=y
+
+#32bit app over 64bit kernel support
+CONFIG_USERSPACE_32BIT_OVER_KERNEL_64BIT=y
+
+
+#############################################################################
+# Select Platform Tools
+#############################################################################
+
+MODEXT = ko
+ccflags-y += -Wno-unknown-warning-option -Wno-typedef-redefinition -Wno-pointer-bool-conversion -Wno-self-assign -Wno-parentheses-equality
+ccflags-y += -I$(PWD)/mlan
+ccflags-y += -DLINUX
+
+
+
+
+
+ARCH ?= arm64
+CONFIG_IMX_SUPPORT=n
+ifeq ($(CONFIG_IMX_SUPPORT),y)
+ccflags-y += -DIMX_SUPPORT
+endif
+KERNELDIR ?= $(KERNEL_SRC)
+CROSS_COMPILE ?= /usr/local/arm/androidQ_toolchain/aarch64-linux-android-4.9/bin/aarch64-linux-android-
+
+LD += -S
+
+BINDIR = ../bin_wlan
+APPDIR= $(shell if test -d "mapp"; then echo mapp; fi)
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+
+	ccflags-y += -I$(KERNELDIR)/include
+
+	ccflags-y += -DFPNUM='"92"'
+
+ifeq ($(CONFIG_DEBUG),1)
+	ccflags-y += -DDEBUG_LEVEL1
+endif
+
+ifeq ($(CONFIG_DEBUG),2)
+	ccflags-y += -DDEBUG_LEVEL1
+	ccflags-y += -DDEBUG_LEVEL2
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_64BIT), y)
+	ccflags-y += -DMLAN_64BIT
+endif
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+	ccflags-y += -DSTA_SUPPORT
+ifeq ($(CONFIG_REASSOCIATION),y)
+	ccflags-y += -DREASSOCIATION
+endif
+else
+CONFIG_WIFI_DIRECT_SUPPORT=n
+CONFIG_STA_WEXT=n
+CONFIG_STA_CFG80211=n
+endif
+
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+	ccflags-y += -DUAP_SUPPORT
+else
+CONFIG_WIFI_DIRECT_SUPPORT=n
+CONFIG_UAP_WEXT=n
+CONFIG_UAP_CFG80211=n
+endif
+
+ifeq ($(CONFIG_WIFI_DIRECT_SUPPORT),y)
+	ccflags-y += -DWIFI_DIRECT_SUPPORT
+endif
+
+# Enables setting WiFi low-latency mode feature.
+ifeq ($(CONFIG_WIFI_SET_LATENCY_MODE), y)
+  ccflags-y += -DWIFI_LATENCY_MODE_SUPPORT
+endif
+
+ifeq ($(CONFIG_MFG_CMD_SUPPORT),y)
+	ccflags-y += -DMFG_CMD_SUPPORT
+endif
+
+ifeq ($(CONFIG_BIG_ENDIAN),y)
+	ccflags-y += -DBIG_ENDIAN_SUPPORT
+endif
+
+ifeq ($(CONFIG_USERSPACE_32BIT_OVER_KERNEL_64BIT),y)
+	ccflags-y += -DUSERSPACE_32BIT_OVER_KERNEL_64BIT
+endif
+
+#ifdef SDIO_MMC
+ifeq ($(CONFIG_SDIO_SUSPEND_RESUME),y)
+	ccflags-y += -DSDIO_SUSPEND_RESUME
+endif
+#endif
+
+
+ifeq ($(CONFIG_DFS_TESTING_SUPPORT),y)
+	ccflags-y += -DDFS_TESTING_SUPPORT
+endif
+
+
+ifeq ($(CONFIG_ANDROID_KERNEL), y)
+	ccflags-y += -DANDROID_KERNEL
+endif
+
+ifeq ($(CONFIG_OPENWRT_SUPPORT), y)
+	ccflags-y += -DOPENWRT
+endif
+
+ifeq ($(CONFIG_T50), y)
+	ccflags-y += -DT50
+	ccflags-y += -DT40
+	ccflags-y += -DT3T
+endif
+
+ifeq ($(CONFIG_SD8887),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD8887
+endif
+ifeq ($(CONFIG_SD8897),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD8897
+endif
+ifeq ($(CONFIG_SD8977),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD8977
+endif
+ifeq ($(CONFIG_SD8978),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD8978
+endif
+ifeq ($(CONFIG_SD8997),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD8997
+endif
+ifeq ($(CONFIG_SD8987),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD8987
+endif
+ifeq ($(CONFIG_SD9097),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD9097
+endif
+ifeq ($(CONFIG_SD9098),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSD9098
+endif
+ifeq ($(CONFIG_USB8897),y)
+	CONFIG_MUSB=y
+	ccflags-y += -DUSB8897
+endif
+ifeq ($(CONFIG_USB8997),y)
+	CONFIG_MUSB=y
+	ccflags-y += -DUSB8997
+endif
+ifeq ($(CONFIG_USB8978),y)
+	CONFIG_MUSB=y
+	ccflags-y += -DUSB8978
+endif
+ifeq ($(CONFIG_USB9097),y)
+	CONFIG_MUSB=y
+	ccflags-y += -DUSB9097
+endif
+ifeq ($(CONFIG_USB9098),y)
+	CONFIG_MUSB=y
+	ccflags-y += -DUSB9098
+endif
+ifeq ($(CONFIG_PCIE8897),y)
+	CONFIG_PCIE=y
+	ccflags-y += -DPCIE8897
+endif
+ifeq ($(CONFIG_PCIE8997),y)
+	CONFIG_PCIE=y
+	ccflags-y += -DPCIE8997
+endif
+ifeq ($(CONFIG_PCIE9097),y)
+	CONFIG_PCIE=y
+	ccflags-y += -DPCIE9097
+endif
+ifeq ($(CONFIG_PCIE9098),y)
+	CONFIG_PCIE=y
+	ccflags-y += -DPCIE9098
+endif
+ifeq ($(CONFIG_SDIO),y)
+	ccflags-y += -DSDIO
+	ccflags-y += -DSDIO_MMC
+endif
+ifeq ($(CONFIG_MUSB),y)
+	ccflags-y += -DUSB
+endif
+ifeq ($(CONFIG_PCIE),y)
+	ccflags-y += -DPCIE
+endif
+
+ifeq ($(CONFIG_MAC80211_SUPPORT),y)
+	ccflags-y += -DMAC80211_SUPPORT
+endif
+ifeq ($(CONFIG_MAC80211_SUPPORT_UAP),y)
+	ccflags-y += -DMAC80211_SUPPORT_UAP
+endif
+ifeq ($(CONFIG_MAC80211_SUPPORT_MESH),y)
+	ccflags-y += -DMAC80211_SUPPORT_MESH
+endif
+
+# add -Wno-packed-bitfield-compat when GCC version greater than 4.4
+GCC_VERSION := $(shell echo `gcc -dumpversion | cut -f1-2 -d.` \>= 4.4 | sed -e 's/\./*100+/g' | bc )
+ifeq ($(GCC_VERSION),1)
+	ccflags-y += -Wno-packed-bitfield-compat
+endif
+WimpGCC_VERSION := $(shell echo `gcc -dumpversion | cut -f1 -d.`| bc )
+ifeq ($(shell test $(WimpGCC_VERSION) -ge 7; echo $$?),0)
+ccflags-y += -Wimplicit-fallthrough=3
+endif
+#ccflags-y += -Wunused-but-set-variable
+#ccflags-y += -Wmissing-prototypes
+#ccflags-y += -Wold-style-definition
+#ccflags-y += -Wtype-limits
+#ccflags-y += -Wsuggest-attribute=format
+#ccflags-y += -Wmissing-include-dirs
+#############################################################################
+# Make Targets
+#############################################################################
+
+ifneq ($(KERNELRELEASE),)
+
+ifeq ($(CONFIG_WIRELESS_EXT),y)
+ifeq ($(CONFIG_WEXT_PRIV),y)
+	# Enable WEXT for STA
+	CONFIG_STA_WEXT=y
+	# Enable WEXT for uAP
+	CONFIG_UAP_WEXT=y
+else
+# Disable WEXT for STA
+	CONFIG_STA_WEXT=n
+# Disable WEXT for uAP
+	CONFIG_UAP_WEXT=n
+endif
+endif
+
+# Enable CFG80211 for STA
+ifeq ($(CONFIG_CFG80211),y)
+	CONFIG_STA_CFG80211=y
+else
+ifeq ($(CONFIG_CFG80211),m)
+	CONFIG_STA_CFG80211=y
+else
+	CONFIG_STA_CFG80211=n
+endif
+endif
+
+# OpenWrt
+ifeq ($(CONFIG_OPENWRT_SUPPORT), y)
+ifeq ($(CPTCFG_CFG80211),y)
+	CONFIG_STA_CFG80211=y
+else
+ifeq ($(CPTCFG_CFG80211),m)
+	CONFIG_STA_CFG80211=y
+else
+	CONFIG_STA_CFG80211=n
+endif
+endif
+endif
+
+# Enable CFG80211 for uAP
+ifeq ($(CONFIG_CFG80211),y)
+	CONFIG_UAP_CFG80211=y
+else
+ifeq ($(CONFIG_CFG80211),m)
+	CONFIG_UAP_CFG80211=y
+else
+	CONFIG_UAP_CFG80211=n
+endif
+endif
+
+# OpenWrt
+ifeq ($(CONFIG_OPENWRT_SUPPORT), y)
+ifeq ($(CPTCFG_CFG80211),y)
+	CONFIG_STA_CFG80211=y
+else
+ifeq ($(CPTCFG_CFG80211),m)
+	CONFIG_STA_CFG80211=y
+else
+	CONFIG_STA_CFG80211=n
+endif
+endif
+endif
+
+ifneq ($(CONFIG_STA_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_STA_WEXT=n
+	CONFIG_STA_CFG80211=n
+endif
+
+ifneq ($(CONFIG_UAP_SUPPORT),y)
+	CONFIG_WIFI_DIRECT_SUPPORT=n
+	CONFIG_UAP_WEXT=n
+	CONFIG_UAP_CFG80211=n
+endif
+
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ifeq ($(CONFIG_STA_WEXT),y)
+	ccflags-y += -DSTA_WEXT
+endif
+ifeq ($(CONFIG_STA_CFG80211),y)
+	ccflags-y += -DSTA_CFG80211
+endif
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+ifeq ($(CONFIG_UAP_WEXT),y)
+	ccflags-y += -DUAP_WEXT
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+	ccflags-y += -DUAP_CFG80211
+endif
+endif
+
+print:
+ifeq ($(CONFIG_STA_SUPPORT),y)
+ifeq ($(CONFIG_STA_WEXT),n)
+ifeq ($(CONFIG_STA_CFG80211),n)
+	@echo "Can not build STA without WEXT or CFG80211"
+	exit 2
+endif
+endif
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+ifeq ($(CONFIG_UAP_WEXT),n)
+ifeq ($(CONFIG_UAP_CFG80211),n)
+	@echo "Can not build UAP without WEXT or CFG80211"
+	exit 2
+endif
+endif
+endif
+
+
+
+
+
+MOALOBJS =	mlinux/moal_main.o \
+		mlinux/moal_ioctl.o \
+		mlinux/moal_shim.o \
+		mlinux/moal_eth_ioctl.o \
+		mlinux/moal_init.o
+
+MLANOBJS =	mlan/mlan_shim.o mlan/mlan_init.o \
+		mlan/mlan_txrx.o \
+		mlan/mlan_cmdevt.o mlan/mlan_misc.o \
+		mlan/mlan_cfp.o \
+		mlan/mlan_module.o
+
+MLANOBJS += mlan/mlan_wmm.o
+ifeq ($(CONFIG_MUSB),y)
+MLANOBJS += mlan/mlan_usb.o
+endif
+ifeq ($(CONFIG_SDIO),y)
+MLANOBJS += mlan/mlan_sdio.o
+endif
+ifeq ($(CONFIG_PCIE),y)
+MLANOBJS += mlan/mlan_pcie.o
+endif
+MLANOBJS += mlan/mlan_11n_aggr.o
+MLANOBJS += mlan/mlan_11n_rxreorder.o
+MLANOBJS += mlan/mlan_11n.o
+MLANOBJS += mlan/mlan_11ac.o
+MLANOBJS += mlan/mlan_11ax.o
+MLANOBJS += mlan/mlan_11d.o
+MLANOBJS += mlan/mlan_11h.o
+ifeq ($(CONFIG_STA_SUPPORT),y)
+MLANOBJS += mlan/mlan_meas.o
+MLANOBJS += mlan/mlan_scan.o \
+			mlan/mlan_sta_ioctl.o \
+			mlan/mlan_sta_rx.o \
+			mlan/mlan_sta_tx.o \
+			mlan/mlan_sta_event.o \
+			mlan/mlan_sta_cmd.o \
+			mlan/mlan_sta_cmdresp.o \
+			mlan/mlan_join.o
+ifeq ($(CONFIG_STA_WEXT),y)
+MOALOBJS += mlinux/moal_priv.o \
+            mlinux/moal_wext.o
+endif
+endif
+ifeq ($(CONFIG_UAP_SUPPORT),y)
+MLANOBJS += mlan/mlan_uap_ioctl.o
+MLANOBJS += mlan/mlan_uap_cmdevent.o
+MLANOBJS += mlan/mlan_uap_txrx.o
+MOALOBJS += mlinux/moal_uap.o
+ifeq ($(CONFIG_UAP_WEXT),y)
+MOALOBJS += mlinux/moal_uap_priv.o
+MOALOBJS += mlinux/moal_uap_wext.o
+endif
+endif
+ifeq ($(CONFIG_STA_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.o
+MOALOBJS += mlinux/moal_cfg80211_util.o
+MOALOBJS += mlinux/moal_sta_cfg80211.o
+endif
+ifeq ($(CONFIG_UAP_CFG80211),y)
+MOALOBJS += mlinux/moal_cfg80211.o
+MOALOBJS += mlinux/moal_cfg80211_util.o
+MOALOBJS += mlinux/moal_uap_cfg80211.o
+endif
+
+ifdef CONFIG_PROC_FS
+MOALOBJS += mlinux/moal_proc.o
+MOALOBJS += mlinux/moal_debug.o
+endif
+
+ifeq ($(CONFIG_MAC80211_SUPPORT),y)
+MOALOBJS += mlinux/moal_mac80211.o
+MLANOBJS += mlan/mlan_mac80211.o
+endif
+
+
+
+
+
+
+
+obj-m := mlan.o
+mlan-objs := $(MLANOBJS)
+
+ifeq ($(CONFIG_MUSB),y)
+MOALOBJS += mlinux/moal_usb.o
+endif
+ifeq ($(CONFIG_SDIO),y)
+MOALOBJS += mlinux/moal_sdio_mmc.o
+endif
+ifeq ($(CONFIG_PCIE),y)
+MOALOBJS += mlinux/moal_pcie.o
+endif
+obj-m += moal.o
+moal-objs := $(MOALOBJS)
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(M) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
+
+modules_install:
+	$(MAKE) INSTALL_MOD_STRIP=1 M=$(M) -C $(KERNELDIR) modules_install
+	mkdir -p ${OUT_DIR}/../vendor_lib/modules
+	cd ${OUT_DIR}/$(M)/; find -name mlan.ko -exec cp {} ${OUT_DIR}/../vendor_lib/modules/mlan.ko \;
+	cd ${OUT_DIR}/$(M)/; find -name moal.ko -exec cp {} ${OUT_DIR}/../vendor_lib/modules/moal.ko \;
+
+endif
+
+###############################################################
+
+export		CC LD ccflags-y KERNELDIR
+
+.PHONY: mapp/mlanconfig mapp/mlanutl clean distclean
+	@echo "Finished Making NXP Wlan Linux Driver"
+
+mapp/mlanconfig:
+	$(MAKE) -C $@
+mapp/mlanutl:
+	$(MAKE) -C $@
+
+echo:
+
+build:		echo default
+
+	@if [ ! -d $(BINDIR) ]; then \
+		mkdir $(BINDIR); \
+	fi
+
+	cp -f mlan.$(MODEXT) $(BINDIR)/mlan$(DBG).$(MODEXT)
+
+	cp -f moal.$(MODEXT) $(BINDIR)/moal$(DBG).$(MODEXT)
+	cp -rpf script/load $(BINDIR)/
+	cp -rpf script/unload $(BINDIR)/
+
+	cp -f README_MLAN $(BINDIR)
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanconfig $@ INSTALLDIR=$(BINDIR)
+	$(MAKE) -C mapp/mlanutl $@ INSTALLDIR=$(BINDIR)
+endif
+
+clean:
+	-find . -name "*.o" -exec rm {} \;
+	-find . -name "*.ko" -exec rm {} \;
+	-find . -name ".*.cmd" -exec rm {} \;
+	-find . -name "*.mod.c" -exec rm {} \;
+	-find . -name "Module.symvers" -exec rm {} \;
+	-find . -name "Module.markers" -exec rm {} \;
+	-find . -name "modules.order" -exec rm {} \;
+	-find . -name ".*.dwo" -exec rm {} \;
+	-find . -name "*dwo" -exec rm {} \;
+	-rm -rf .tmp_versions
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+endif
+#ifdef SDIO
+#endif // SDIO
+
+install: default
+
+	cp -f mlan.$(MODEXT) $(INSTALLDIR)/mlan$(DBG).$(MODEXT)
+	cp -f moal.$(MODEXT) $(INSTALLDIR)/moal$(DBG).$(MODEXT)
+	echo $(INSTALLDIR)
+	echo "MX Driver Installed"
+
+distclean:
+	-find . -name "*.o" -exec rm {} \;
+	-find . -name "*.orig" -exec rm {} \;
+	-find . -name "*.swp" -exec rm {} \;
+	-find . -name "*.*~" -exec rm {} \;
+	-find . -name "*~" -exec rm {} \;
+	-find . -name "*.d" -exec rm {} \;
+	-find . -name "*.a" -exec rm {} \;
+	-find . -name "tags" -exec rm {} \;
+	-find . -name ".*" -exec rm -rf 2> /dev/null \;
+	-find . -name "*.ko" -exec rm {} \;
+	-find . -name ".*.cmd" -exec rm {} \;
+	-find . -name "*.mod.c" -exec rm {} \;
+	-find . -name ".*.dwo" -exec rm {} \;
+	-find . -name "*dwo" -exec rm {} \;
+	-rm -rf .tmp_versions
+ifneq ($(APPDIR),)
+	$(MAKE) -C mapp/mlanconfig $@
+	$(MAKE) -C mapp/mlanutl $@
+endif
+
+# End of file
diff --git a/wlan_sd8987/README_MLAN b/wlan_sd8987/README_MLAN
new file mode 100755
index 0000000..d629987
--- /dev/null
+++ b/wlan_sd8987/README_MLAN
@@ -0,0 +1,1283 @@
+===============================================================================
+			U S E R  M A N U A L
+
+ Copyright 2008-2021 NXP
+
+
+1) FOR DRIVER BUILD
+
+	Goto source code directory wlan_src/.
+	make [clean] build
+	The driver and utility binaries can be found in ../bin_xxxx directory.
+	The driver code supports Linux kernel from 2.6.32 to 5.8.0.
+
+2) FOR DRIVER INSTALL
+
+	a) Copy firmware image to /lib/firmware/nxp/, copy wifi_mod_para.conf to /lib/firmware/nxp/.
+	b) Install WLAN driver
+	   There are drv_mode, max_sta_bss, max_uap_bss etc. module parameters.
+		The bit settings of drv_mode are,
+			Bit 0 :  STA
+			Bit 1 :  uAP
+			Bit 2 :  WIFIDIRECT
+
+		max_sta_bss: Maximum number of STA BSS (default 1, max 1)
+		sta_name: Name of the STA interface (default: "mlan")
+		max_uap_bss: Maximum number of uAP BSS (default 1, max 1)
+		uap_name: Name of the uAP interface (default: "uap")
+		max_wfd_bss: Maximum number of WIFIDIRECT BSS (default 1, max 1)
+		wfd_name: Name of the WIFIDIRECT interface (default: "wfd")
+		max_vir_bss: Number of Virtual interfaces (default 0)
+		uap_oper_ctrl: uAP operation control when in-STA disconnect with ext-AP
+                               0: default do nothing, 2: uAP stops and restarts automatically
+	   For example, to install multi-chip driver,
+		insmod mlan.ko
+		insmod moal.ko mod_para=nxp/wifi_mod_para.conf [drvdbg=0x7]
+	   wifi_mod_para.conf is used to support multi-chips which has different load module parameters. It contains
+           the module parameters for different chips.
+	c) Uninstall WLAN driver,
+		ifconfig mlanX down
+		ifconfig uapX down
+		rmmod moal
+		rmmod mlan
+
+	To load driver with MFG firmware file, use mfg_mode=1 when insmod WLAN driver and
+	specify MFG firmware name if needed.
+
+	There are some other parameters for debugging purpose etc. Use modinfo to check details.
+	  drvdbg=<bit mask of driver debug message control>
+	  dev_cap_mask=<Bit mask of the device capability>
+	  mac_addr=xx:xx:xx:xx:xx:xx <override the MAC address (in hex)>
+	  auto_ds=0|1|2 <use MLAN default | enable auto deepsleep | disable auto deepsleep>
+	  ps_mode=0|1|2 <use MLAN default | enable IEEE PS mode | disable IEEE PS mode>
+	  max_tx_buf=2048|4096|8192 <maximum AMSDU Tx buffer size>
+	  pm_keep_power=1|0 <PM keep power in suspend (default) | PM no power in suspend>
+	  shutdown_hs=1|0 <Enable HS when shutdown | No HS when shutdown (default)>
+	  cfg_11d=0|1|2 <use MLAN default | enable 11d | disable 11d>
+	  dts_enable=0|1 <Disable DTS | Enable DTS (default)>
+	  fw_name = <FW file name>
+		e.g. copy pcieuart9098_combo_v1.bin to firmware directory, fw_name=nxp/pcieuart9098_combo_v1.bin
+	  hw_test=0|1 <Disable hardware test (default) | Enable hardware test>
+	  fw_serial=0|1 <support parallel download FW | support serial download FW (default)>
+	  req_fw_nowait=0|1 <use request_firmware API (default) | use request_firmware_nowait API>
+      dfs53cfg=0|1|2 <use Fw Default | New W53 | Old W53>
+	  SD8887: antcfg=0|1|2|0xffff <default | Tx/Rx antenna 1 | Tx/Rx antenna 2 | enable antenna diversity>
+	  SD8897/SD8997: antcfg=0x11|0x13|0x33 <Bit0:Rx Path A, Bit1:Rx Path B, Bit 4:Tx Path A, Bit 5:Tx Path B>
+	  slew_rate: Slew Rate Control value = 0|1|2|3 (0 is the slowest slew rate and 03 has the highest slew rate (default))
+	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+		e.g. copy init_cfg.conf to firmware directory, init_cfg=nxp/init_cfg.conf
+	  cal_data_cfg=<CAL data config file name>
+		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=nxp/cal_data.conf
+          Note: Loading driver with 8887 must include correct cal_data_cfg parameter.
+	 dpd_data_cfg=<DPD data config file name>
+	   e.g. copy dpd_data.conf to firmware directory, dpd_data_cfg=nxp/dpd_data.conf
+	  txpwrlimit_cfg=<Tx power limit config file name>
+		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=nxp/txpwrlimit_cfg_set.conf
+      cntry_txpwr=0|1|2
+                  0: Disable setting tx power table of country (default)
+                  1: Enable setting tx power table of country
+                  2: Enable setting rgpower table of country
+	  init_hostcmd_cfg=<init hostcmd config file name>
+		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=nxp/init_hostcmd_cfg.conf
+	  band_steer_cfg=<band steer config file name>
+		e.g. generate bscfg.conf by band_steer_cfg.conf, then copy bscfg.conf to firmware directory, band_steer_cfg=nxp/bscfg.conf
+	  sdio_rx_aggr=1|0 <Enable SDIO rx aggr (default) | Disable SDIO rx aggr>
+	  cfg80211_wext=<bit mask of CFG80211 and WEXT control>
+		Bit 0: STA WEXT
+		Bit 1: uAP WEXT
+		Bit 2: STA CFG80211
+		Bit 3: uAP CFG80211
+	  reg_alpha2=<Regulatory alpha2 (default NULL)>
+	  skip_fwdnld=0|1 <enable FW download support (default) | disable FW download support>
+	  wq_sched_prio: Priority for work queue
+	  wq_sched_policy: Scheduling policy for work queue
+		(0: SCHED_NORMAL, 1: SCHED_FIFO, 2: SCHED_RR, 3: SCHED_BATCH, 5: SCHED_IDLE)
+		Please note that, both wq_sched_prio and wq_sched_policy should be provided
+		as module parameters. If wq_sched_policy is (0, 3 or 5), then wq_sched_prio
+		must be 0. wq_sched_prio should be 1 to 99 otherwise.
+	  rx_work=0|1|2 <default | Enable rx_work_queue | Disable rx_work_queue>
+	  pcie_int_mode=0|1|2 <Legacy mode, MSI mode (default), MSI-X mode>
+	  pcie_int_mode=0|1 <Legacy mode, MSI mode (default)>
+	  aggrctrl=1|0 <enable Tx aggr | disable Tx aggr>
+	  usb_aggr=0|1|2 <use MLAN default (disabled) | enable USB aggr | disable USB aggr>
+	  low_power_mode_enable=0|1 <disable low power mode (default)| enable low power mode>
+	  When low power mode is enabled, the output power will be clipped at ~+10dBm and the
+	  expected PA current is expected to be in the 80-90 mA range for b/g/n modes
+	wakelock_timeout=<set wakelock_timeout value (ms)>
+	pmic=0|1 <No pmic configure cmd sent to firmware | Send pmic configure cmd to firmware>
+	indication_gpio=0xXY <GPIO to indicate wakeup source and its level; high four bits X:
+                  level(0/1) for normal wakeup; low four bits Y: GPIO pin number. This parameter
+                  only works with specific board and firmware.>
+	hs_wake_interval=<Host sleep wakeup interval,it will round to nearest multiple dtim*beacon_period in fw>
+	disconnect_on_suspend=0|1 <Disable disconnect wifi on suspend (default) | Enable disconnect wifi on suspend>
+	hs_mimo_switch=0|1 <Disable dynamic MIMO-SISO switch during host sleep (default) | Enable dynamic MIMO-SISO switch during host sleep>
+	gtk_rekey_offload=0|1|2 <disable gtk_rekey_offload|enable gtk_rekey_offload (default) | enable gtk_rekey_offload in suspend mode only>
+	napi=0|1 <disable napi | enable napi>
+	fixed_beacon_buffer=0|1 <allocate default buffer size (default) | allocate max buffer size>
+	GoAgeoutTime=0|x <use default ageout time (default) | set Go age out time xTU(TU 100ms)>
+	multi_dtim=0|x <use default DTIM interval(default) | set x*beacon_period as DTIM interval>
+	inact_tmo=0|x <use default IEEE ps inactivity timout value (default) | use IEEE ps inactivity timeout value x ms>
+	uap_max_sta: Maximum number of STA for UAP/GO (default 0, max 64)
+	host_mlme=0|1 <Disable Host MLME support (default)| Enable Host MLME support>
+	country_ie_ignore=0|1 <Follow countryIE from AP and beacon hint enable (default) | Ignore countryIE from AP and beacon hint disable>
+	beacon_hints=0|1 <enable beacon hints(default) | disable beacon hints>
+
+	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
+	for module parameters.
+		insmod sdxxx.ko "<para1> <para2> ..."
+
+3) FOR DRIVER PROC & DEBUG
+
+	The following info are provided in /proc/net/mwlan/adapterX/mlanY|uapY|wfdY/info,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/adapterX/mlanY|uapY|wfdY/info.
+
+	driver_name = "wlan" or "uap"
+	driver_version = <chip id, firmware version and driver version>
+	interface_name = "mlanX", "uapX" or "wfdX"
+	bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown"
+	media_state = "Disconnected" | "Connected"
+	mac_address = <6-byte adapter MAC address>
+	multicase_count = <multicast address count>     // Only for STA
+	essid = <current SSID>                          // Only for STA
+	bssid = <current BSSID>                         // Only for STA
+	channel = <current channel>                     // Only for STA
+	region_code = <current region code>             // Only for STA
+	multicast_address[n] = <multicast address>      // Only for STA
+	num_tx_bytes = <number of bytes sent to device>
+	num_rx_bytes = <number of bytes received from device and sent to kernel>
+	num_tx_pkts = <number of packets sent to device>
+	num_rx_pkts = <number of packets received from device and sent to kernel>
+	num_tx_pkts_dropped = <number of Tx packets dropped by driver>
+	num_rx_pkts_dropped = <number of Rx packets dropped by driver>
+	num_tx_pkts_err = <number of Tx packets failed to send to device>
+	num_rx_pkts_err = <number of Rx packets failed to receive from device>
+	carrier "on" | "off"
+	tx queue "stopped" | "started"
+	tkip_mic_failures = 0                           // Only for uAP
+	ccmp_decrypt_errors = 0                         // Only for uAP
+	wep_undecryptable_count = 0                     // Only for uAP
+	wep_icv_error_count = 0                         // Only for uAP
+	decrypt_failure_count = 0                       // Only for uAP
+	mcast_tx_count = 0                              // Only for uAP
+	failed_count = 0                                // Only for uAP
+	retry_count = 0                                 // Only for uAP
+	multiple_retry_count = 0                        // Only for uAP
+	frame_duplicate_count = 0                       // Only for uAP
+	rts_success_count = 0                           // Only for uAP
+	rts_failure_count = 0                           // Only for uAP
+	ack_failure_count = 0                           // Only for uAP
+	rx_fragment_count = 0                           // Only for uAP
+	mcast_rx_frame_count = 0                        // Only for uAP
+	fcs_error_count = 0                             // Only for uAP
+	tx_frame_count = 0                              // Only for uAP
+	rsna_tkip_cm_invoked = 0                        // Only for uAP
+	rsna_4way_hshk_failures = 0                     // Only for uAP
+
+	The following debug info are provided in /proc/net/mwlan/adapterX/mlanY|uapY|wfdY/debug,
+	on kernel 2.6.24 or later, the entry is /proc/mwlan/adapterX/mlanY|uapY|wfdY/debug.
+
+	drvdbg = <bit mask of driver debug message control>
+	wmm_ac_vo = <number of packets sent to device from WMM AcVo queue>
+	wmm_ac_vi = <number of packets sent to device from WMM AcVi queue>
+	wmm_ac_be = <number of packets sent to device from WMM AcBE queue>
+	wmm_ac_bk = <number of packets sent to device from WMM AcBK queue>
+	max_tx_buf_size = <maximum Tx buffer size>
+	tx_buf_size = <current Tx buffer size>
+	curr_tx_buf_size = <current Tx buffer size in FW>
+	ps_mode = <0/1, CAM mode/PS mode>
+	ps_state = <0/1/2/3, awake state/pre-sleep state/sleep-confirm state/sleep state>
+	is_deep_sleep = <0/1, not deep sleep state/deep sleep state>    // Only for STA
+	wakeup_dev_req = <0/1, wakeup device not required/required>
+	wakeup_tries = <wakeup device count, cleared when device awake>
+	hs_configured = <0/1, host sleep not configured/configured>
+	hs_activated = <0/1, extended host sleep not activated/activated>
+	tx_pkts_queued = <number of Tx packets queued>
+	pps_uapsd_mode = <0/1, PPS/UAPSD mode disabled/enabled>     // Only for STA
+	sleep_pd = <sleep period in milliseconds>                   // Only for STA
+	qos_cfg = <WMM QoS info>                                    // Only for STA
+	tx_lock_flag = <0/1, Tx lock flag>                          // Only for STA
+	port_open = <0/1, port open flag>                           // Only for STA
+	scan_processing = <0/1, scan processing flag>               // Only for STA
+	num_bridge_pkts = <number of bridged packets>               // Only for uAP
+	num_drop_pkts = <number of dropped packets>                 // Only for uAP
+	num_tx_timeout = <number of Tx timeout>
+	num_cmd_timeout = <number of timeout commands>
+	timeout_cmd_id = <command id of the last timeout command>
+	timeout_cmd_act = <command action of the last timeout command>
+	last_cmd_id = <command id of the last several commands sent to device>
+	last_cmd_act = <command action of the last several commands sent to device>
+	last_cmd_index = <0 based last command index>
+	last_cmd_resp_id = <command id of the last several command responses received from device>
+	last_cmd_resp_index = <0 based last command response index>
+	last_event = <event id of the last several events received from device>
+	last_event_index = <0 based last event index>
+	num_cmd_h2c_fail = <number of commands failed to send to device>
+	num_cmd_sleep_cfm_fail = <number of sleep confirm failed to send to device>
+	num_tx_h2c_fail = <number of data packets failed to send to device>
+	num_cmdevt_c2h_fail = <number of commands/events failed to receive from device>
+	num_rx_c2h_fail = <number of data packets failed to receive from device>
+	num_int_read_fail = <number of interrupt read failures>
+	last_int_status = <last interrupt status>
+	num_evt_deauth = <number of deauthenticated events received from device>        // Only for STA
+	num_evt_disassoc = <number of disassociated events received from device>        // Only for STA
+	num_evt_link_lost = <number of link lost events received from device>           // Only for STA
+	num_cmd_deauth = <number of deauthenticate commands sent to device>             // Only for STA
+	num_cmd_assoc_ok = <number of associate commands with success return>           // Only for STA
+	num_cmd_assoc_fail = <number of associate commands with failure return>         // Only for STA
+	cmd_sent = <0/1, send command resources available/sending command to device>
+	data_sent = <0/1, send data resources available/sending data to device>
+	mp_rd_bitmap = <SDIO multi-port read bitmap>
+	curr_rd_port = <SDIO multi-port current read port>
+	mp_wr_bitmap = <SDIO multi-port write bitmap>
+	curr_wr_port = <SDIO multi-port current write port>
+	txbd_rdptr = <PCIE transmit read pointer>
+	txbd_wrptr = <PCIE transmit write pointer>
+	rxbd_rdptr = <PCIE recieve read pointer>
+	rxbd_wrptr = <PCIE recieve write pointer>
+	eventbd_rdptr = <PCIE event read pointer>
+	eventbd_wrptr = <PCIE event write pointer>
+	cmd_resp_received = <0/1, no cmd response to process/response received and yet to process>
+	event_received = <0/1, no event to process/event received and yet to process>
+	tx_cmd_urb_pending = <number of URB pending for cmd transmit>
+	tx_data_urb_pending = <number of URB pending for data transmit>
+	rx_cmd_urb_pending = <number of URB pending for cmd receive>
+	rx_data_urb_pending = <number of URB pending for data receive>
+	ioctl_pending = <number of ioctl pending>
+	tx_pending = <number of Tx packet pending>
+	rx_pending = <number of Rx packet pending>
+	lock_count = <number of lock used>
+	malloc_count = <number of malloc done>
+	mbufalloc_count = <number of mlan_buffer allocated>
+	malloc_cons_count = <number of consistent malloc done>
+	main_state = <current state of the main process>
+	sdiocmd53w = <SDIO Cmd53 write status>
+	sdiocmd53r = <SDIO Cmd52 read status>
+	hs_skip_count = <number of skipped suspends>
+	hs_force_count = <number of forced suspends>
+
+	Issue SDIO cmd52 read/write through proc.
+	Usage:
+		echo "sdcmd52rw=<func> <reg> [data]" > /proc/mwlan/adapterX/config
+	where the parameters:
+		func: The function number to use (0-7)
+		reg:  The address of the register
+		data: The value to write, read if the value is absent
+		For SDIO MMC driver, only function 0 and WLAN function access is allowed.
+		And there is a limitation for function 0 write, only vendor specific CCCR
+		registers (0xf0 -0xff) are permiited.
+	Examples:
+		echo "sdcmd52rw= 0 4" > /proc/mwlan/adapterX/config      # read func 0 address 4
+		cat /proc/mwlan/adapterX/config                          # display the register value
+		echo "sdcmd52rw= 1 3 0xf" > /proc/mwlan/adapterX/config  # write 0xf to func 1 address 3
+
+	Issue debug_dump command through proc.
+	Usage:
+		echo "debug_dump" > /proc/mwlan/adapterX/config
+
+	Examples:
+		echo "debug_dump" > /proc/mwlan/adapterX/config      # dump driver internal debug status.
+
+	Use dmesg or cat /var/log/debug to check driver debug messages.
+
+	Update /proc/sys/kernel/printk to change message log levels.
+	For example,
+	echo 6 > /proc/sys/kernel/printk    (messages with a higher priority than 6
+	                                     will be printed to the console)
+	echo 15 > /proc/sys/kernel/printk   (all messages will be printed to console)
+
+4) FOR FW RELOAD
+    a) Enable parallel firmware download in driver parameter
+       insmod sdxxx.ko fw_serial=0
+
+    b) default fw name for parallel firmware download
+       sd8887_wlan_a2.bin
+
+    c) Trigger FW reload
+       echo "fw_reload=1" > /proc/mwlan/adapterX/config   trigger inband firmware reset and reload firmware
+       echo "fw_reload=2" > /proc/mwlan/adapterX/config   trigger firmware reload
+       echo "fw_reload=3" > /proc/mwlan/adapterX/config   set firmware reload flag in driver.
+       echo "fw_reload=4" > /proc/mwlan/config   trigger pcie FLR and reload firmware.
+
+    (Note: This feature will be supported on Robin3 and KF2.
+           For CAC-A2, it only work with the board which supports parallel fw download)
+
+5) FOR RF test mode commands:
+
+    Following commands are used to perform RF testing of the wifi chipset.
+    Please not that these test mode commands can only be issued while the
+    device is in disconnected state and the uAP BSS is inactive.
+    Normal wifi operations cannot be used on entering RF Test Mode.
+
+    Enter RF Test Mode:
+	echo "rf_test_mode=1" > /proc/mwlan/adapterX/config
+
+    Exit RF Test Mode:
+	echo "rf_test_mode=0" > /proc/mwlan/adapterX/config
+    Please note that after exiting the RF Test Mode, the FW needs to be
+    reset in order to use normal wifi connectivity.
+
+    To get the set of available RF Test Mode commands, currently set
+    parameters values for each command and the output,
+	cat /proc/mwlan/adapterX/config
+
+    Set Tx Antenna
+	For 1x1 chipsets, 1:Main, 2:Aux when antenna diversity is supported
+	For 2x2 chipsets, 1:Path A, 2: Path B, 3: Path A+B
+			  Both Tx and Rx must be set to same antenna path
+	echo "tx_antenna=1" > /proc/mwlan/adapterX/config
+
+    Set Rx Antenna
+	For 1x1 chipsets, 1:Main, 2:Aux when antenna diversity is supported
+	For 2x2 chipsets, 1:Path A, 2:Path B, 3:Path A+B
+			  Both Tx and Rx must be set to same antenna path
+	echo "rx_antenna=1" > /proc/mwlan/adapterX/config
+
+    Set RF band  (0:2G, 1:5G)
+	For 2G, channel will be reset to 6, while for 5G, to channel 36
+	echo "band=0" > /proc/mwlan/adapterX/config
+
+    Set RF bandwidth  (0:20MHz, 1:40MHz, 4:80MHz)
+	echo "bw=0" > /proc/mwlan/adapterX/config
+
+    Set RF channel
+	echo "channel=6" > /proc/mwlan/adapterX/config
+
+    Set Radio Mode
+        echo "radio_mode=14 4" > /proc/mwlan/adapterX/config
+
+    Get and reset packet error rate
+	echo "get_and_reset_per" > /proc/mwlan/adapterX/config
+
+    Set Tx Power
+	This command will set power only if caldata is already loaded in the FW.
+	Power       (0 to 24 dBm)
+	Modulation  (0: CCK, 1:OFDM, 2:MCS)
+	Path ID     (0: PathA, 1:PathB, 2:PathA+B)
+	echo "tx_power=16 2 0" > /proc/mwlan/adapterX/config
+
+    Set Tx Continuous Mode
+	Start                 (0:disable, 1:enable)
+	Continuous Wave Mode  (0:disable, 1:enable)
+	Payload Pattern       (0 to 0xFFFFFFFF)
+	CS Mode               (Applicable only when continuous wave is disabled)
+	                      (0:disable, 1:enable)
+	Active SubChannel     (0:low, 1:upper, 3:both)
+	Tx Data Rate          (Rate Index corresponding to legacy/HT/VHT rates)
+
+	Example: To start continuous wave (tone) mode, first stop any ongoing
+	Tx and then start wave mode:
+	step1: echo "tx_continuous=0" > /proc/mwlan/adapterX/config
+	step2: echo "tx_continuous=1 1 0xAAA 0 3 7" > /proc/mwlan/adapterX/config
+
+	Example: To start continuous packet mode, first stop any ongoing Tx and
+	then start pkt mode:
+	step1: echo "tx_continuous=0" > /proc/mwlan/adapterX/config
+	step2: echo "tx_continuous=1 0 0xAAA 0 3 7" > /proc/mwlan/adapterX/config
+
+	stop:
+	echo "tx_continuous=0" > /proc/mwlan/adapterX/config
+
+    Set Tx Frame
+	Start                 (0:disable, 1:enable)
+	Tx Data Rate          (Rate Index corresponding to legacy/HT/VHT rates)
+	Payload Pattern       (0 to 0xFFFFFFFF)
+	Payload Length        (1 to 0x400)
+	Adjust Burst SIFS Gap (0:disable, 1:enable)
+	Burst SIFS in us      (0 to 255us)
+	Short Preamble        (0:disable, 1:enable)
+	Active SubChannel     (0:low, 1:upper, 3:both)
+	Short GI              (0:disable, 1:enable)
+	Adv Coding            (0:disable, 1:enable)
+	Beamforming           (0:disable, 1:enable)
+	GreenField Mode       (0:disable, 1:enable)
+	STBC                  (0:disable, 1:enable)
+	BSSID                 (xx:xx:xx:xx:xx:xx)
+
+	Example: To start Tx frame with duty cycle, first stop any ongoing Tx
+        and then start Tx frame:
+	echo "tx_frame=0" > /proc/mwlan/adapterX/config
+	echo "tx_frame=1 7 0xAAA 0x100 1 20 0 0 0 0 0 0 0 05:43:3f:c4:51" > /proc/mwlan/adapterX/config
+
+
+===============================================================================
+        U S E R  M A N U A L  F O R  MLANUTL
+
+NAME
+	mlanutl - configure the additional parameters available for NXP mdriver.
+
+SYNOPSIS
+	mlanutl -v
+	mlanutl <mlanX|uapX|wfdx> <command> [parameters] ...
+
+	mlanutl mlanX verext
+	mlanutl mlanX version
+	mlanutl mlanX hostcmd <conf> generate_raw <raw_data_file>
+	mlanutl mlanX getdatarate
+	mlanutl uapX getdatarate
+	mlanutl mlanX drvdbg [n]
+	mlanutl mlanX getlog
+	mlanutl mlanX getsignal [m] [n]
+	mlanutl mlanX signalextcfg [m]
+	mlanutl mlanX getsignalextv2 [m]
+	mlanutl mlanX getsignalext [m]
+	mlanutl mlanX get_txpwrlimit <n> [raw_data_file]
+	mlanutl mlanX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl uapX aggrpriotbl [<m0> <n0> <m1> <n1> ... <m7> <n7>]
+	mlanutl mlanX addbapara [<m> <n> <o> <p> <q>]
+	mlanutl uapX addbapara [<m> <n> <o> <p> <q>]
+	mlanutl mlanX addbareject [<m0> <m1> ... <m7>]
+	mlanutl uapX addbareject [<m0> <m1> ... <m7>]
+	mlanutl mlanX dyn_bw [n]
+	mlanutl mlanX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl uapX vhtcfg <j> <k> [l] [m] [n] [o]
+	mlanutl mlanX httxcfg [<m>] [<n>]
+	mlanutl mlanX htcapinfo [<m>] [<n>]
+        mlanutl mlanX 11axcfg [config/11axcfg.conf]
+	mlanutl mlanX 11axcmd <subcmd> <value>
+	mlanutl mlanX txratecfg [l] [m] [n] [o]
+	mlanutl uapX txratecfg [l] [m] [n] [o]
+
+DESCRIPTION
+	Those commands are used to send additional commands to the NXP MLAN
+	card via the Linux device driver.
+
+	The mlanX parameter specifies the network device that is to be used to
+	perform this command on. It could be mlan0, mlan1 etc.
+
+verext
+	Retrieve and display an extended version string from the firmware
+
+	Usage:
+		mlanutl mlanX verext [#]
+
+	where [#] is an optional argument to retrieve a specific version string,
+	omission of the argument retrieves the 0 indexed string.
+
+version
+	This is used to get the current version of the driver and the firmware.
+
+drvdbg
+	This command is used to set/get the bit masks of driver debug message control.
+
+	Usage:
+		mlanutl mlanX drvdbg [n]
+
+	Where the parameter <n> is the generic debug message control bit mask.
+	The following types of driver debug messages can be dynamically enabled or
+	disabled by setting or clearing the corresponding bits,
+		bit 0:  MMSG            PRINTM(MMSG,...)
+		bit 1:  MFATAL          PRINTM(MFATAL,...)
+		bit 2:  MERROR          PRINTM(MERROR,...)
+		bit 3:  MDATA           PRINTM(MDATA,...)
+		bit 4:  MCMND           PRINTM(MCMND,...)
+		bit 5:  MEVENT          PRINTM(MEVENT,...)
+		bit 6:  MINTR           PRINTM(MINTR,...)
+		bit 7:  MIOCTL          PRINTM(MIOCTL,...)
+		...
+		bit 16: MDAT_D          PRINTM(MDAT_D,...), DBG_HEXDUMP(MDAT_D,...)
+		bit 17: MCMD_D          PRINTM(MCMD_D,...), DBG_HEXDUMP(MCMD_D,...)
+		bit 18: MEVT_D          PRINTM(MEVT_D,...), DBG_HEXDUMP(MEVT_D,...)
+		bit 19: MFW_D           PRINTM(MFW_D,...),  DBG_HEXDUMP(MFW_D,...)
+		bit 20: MIF_D           PRINTM(MIF_D,...),  DBG_HEXDUMP(MIF_D,...)
+		...
+		bit 28: MENTRY          PRINTM(MENTRY,...), ENTER(), LEAVE()
+		bit 29: MWARN           PRINTM(MWARN,...)
+		bit 30: MINFO           PRINTM(MINFO,...)
+
+	If CONFIG_DEBUG=2, all kinds of debug messages can be configured.
+
+	If CONFIG_DEBUG=1, all kinds of debug messages can be configured except
+	for MENTRY, MWARN and MINFO. By default MMSG, MFATAL and MERROR are enabled.
+
+	Some special debug messages,
+		'*'             // MLAN driver ISR is called (bit 6 MINTR enabled)
+		'|'             // PS awake event is received (bit 5 MEVENT enabled)
+		'_'             // PS sleep event is received (bit 5 MEVENT enabled)
+		'+'             // PS sleep confirm is sent (bit 5 MEVENT enabled)
+
+	Examples:
+		mlanutl mlan0 drvdbg             : Get the current driver debug masks
+		mlanutl mlan0 drvdbg 0           : Disable all the debug messages
+		mlanutl mlan0 drvdbg 7           : Enable MMSG, MFATAL and MERROR messages
+		mlanutl mlan0 drvdbg 0x20037     : Enable MMSG, MFATAL, MEEROR,
+		                                   MCMND, MEVENT and MCMD_D messages
+		mlanutl mlan0 drvdbg -1          : Enable all the debug messages
+
+hostcmd generate_raw
+	This command is used to generate the raw data(hostcommand block) for
+	hostcommand in <conf_file> and write that to file <raw_data_file>
+
+	Usage:
+		mlanutl mlanX hostcmd <conf_file> generate_raw <raw_data_file>
+
+getdatarate
+	This command is used to get the data rate being used in last Tx
+	packet and last Rx packet.
+
+getlog
+	This command is used to get the statistics available in the station.
+	Following stats are displayed:-
+	dot11MulticastTransmittedFrameCount	Increments when the multicast bit is set in the destination
+						MAC address of a successfully transmitted MSDU
+
+	dot11FailedCount			Increments when an MSDU is not transmitted successfully
+
+	dot11RetryCount				Increments when an MSDU is successfully transmitted after one
+						or more retransmissions
+
+	dot11MultipleRetryCount			Increments when an MSDU is successfully transmitted after more
+						than one retransmission
+
+	dot11FrameDuplicateCount		Increments when a frame is received that the Sequence Control
+						field is indicating a duplicate count
+
+	dot11RTSSuccessCount			Increments when a CTS is received in response to an RTS
+
+	dot11RTSFailureCount			Increments when a CTS is not received in response to an RTS
+
+	dot11ACKFaliureCount			Increments when an ACK is not received when expected
+
+	dot11ReceivedFragmentCount		Increments for each successfully received MPDU of type Data or Management
+
+	dot11MulticastReceivedFrameCount	Increments when a MSDU is received with the multicast bit set in the destination MAC address
+
+	dot11FCSErrorCount			Increments when an FCS error is detected in a received MPDU
+
+	dot11TransmittedFrameCount		Increments for each successfully transmitted MSDU
+
+	dot11WeplcvErrCnt			Increment when WEP decryption error for key index 0.3
+
+	beaconReceivedCnt			Increments when received beacon
+
+	beaconMissedCnt				Increments when beacon missed
+
+	dot11TransmittedFrameCount		Increments for each successfully transmitted MSDU
+
+	dot11QosTransmittedFragmentCount	Increments when a corresponding UP's MPDU transmitted successfully
+
+	dot11QosFailedCount			Increments when a corresponding UP's MSDU not transmitted successfully
+
+	dot11QosRetryCount			Increment when a corresponding UP's MSDU transmitted successfully after one or more retransmission
+
+	dot11QosMultipleRetryCount		Increments when a corresponding UP's MSDU is successfully transmitted after more than one retransmission
+
+	dot11QosFrameDuplicateCount		Increments when a corresponding UP's frame is received that the Sequence
+						Control field is indicating a duplicate frame
+
+	dot11QosRTSSuccessCount			Increments when a CTS is received in response to an RTS, which is sent for a corresponding UP's Qos frame
+
+	dot11QosRTSFailureCount			Increments when a CTS is not received in response to an RTS, which is sent for a corresponding UP's
+						Qos frame
+
+	dot11QosACKFailureCount			Increments when an ACK is not received when expected for a corresponding UP's Qos frame
+
+	dot11QosReceivedFragmentCount		Increments when a corresponding UP's MPDU received
+
+	dot11QosTransmittedFrameCount		Increments when a corresponding UP's MSDU transmitted
+
+	dot11QosDiscardedFrameCount		Increments when a corresponding UP's MSDU not transmitted successfully
+
+	dot11QosMPDUsReceivedCount		Increments when a corresponding UP's MDPU received
+
+
+	dot11QosRetriesReceivedCount		Increments when a corresponding UP's MDPU received which retry bit is set
+
+	dot11RSNAStatsCMACICVErrors		Increment when a MPDU discard by CMAC integrity check
+
+	dot11RSNAStatsCMACReplays		Increments when a MPDU discarded by the CMAC replay error
+
+	dot11RSNAStatsRobustMgmtCCMPReplays	Increments when a robust management frame discarded by CCMP replay error
+
+	dot11RSNAStatsTKIPICVErrors		Increments when a MPDU discarded by TKIP ICV error
+
+	dot11RSNAStatsTKIPReplays		Increments when a MPDU discarded by TKIP replay error
+
+	dot11RSNAStatsCCMPDecryptErrors		Increments when a MPDU discarded by CCMP decryption error
+
+	dot11RSNAStatsCCMPReplays		Increments when a MPDU discarded by CCMP replay error
+
+	dot11TransmittedAMSDUCount		Increments when a A-MSDU transmitted successfully
+
+	dot11FailedAMSDUCount			Increments when a A-MSDU not transmitted successfully
+
+	dot11RetryAMSDUCount			Increments when a A-MSDU is successfully transmitted after one or more retransmissions
+
+	dot11MultipleRetryAMSDUCount		Increments when a A-MSDU is successfully transmitted after more than one retransmissions
+
+	dot11TransmittedOctetsInAMSDUCount	Increments by the number of octets in the frame body
+						of an A-MSDU frame when an A-MSDU frame is successfully transmitted
+
+	dot11AMSDUAckFailureCount		Increments when an acknowledgment to an A-MSDU is not received when expected.
+
+	dot11ReceivedAMSDUCount			Increments when a A-MSDU frame received
+
+	dot11ReceivedOctetsInAMSDUCount		Increments by the number of octets in the frame body
+						of an A-MSDU frame when an A-MSDU frame is received
+
+	dot11TransmittedAMPDUCount		Increments when an A-MPDU is transmitted
+
+	dot11TransmittedMPDUsInAMPDUCount	Increments by the number of MPDUs in the A-MPDU when an A-MPDU is transmitted
+
+	dot11TransmittedOctetsInAMPDUCount	Increments by the number of octets in the A-MPDU frame when an A-MPDU frame is transmitted
+
+	dot11AMPDUReceivedCount			Increments when the MAC receives an A-MPDU from the PHY
+
+	dot11MPDUInReceivedAMPDUCount		Increments by the number of MPDUs received in the
+						A-MPDU when an A-MPDU is received
+
+	dot11ReceivedOctetsInAMPDUCount		Increments by the number of octets in the A-MPDU
+						frame when an A-MPDU frame is received
+
+	dot11AMPDUDelimiterCRCErrorCount	Increments when an MPDU delimiter has a CRC error when this is the first
+						CRC error in the received A-MPDU or when the previous delimiter has been decoded correctly
+
+getsignal
+	This command gets the last and average value of RSSI, SNR and NF of
+	Beacon and Data.
+	Note: This command is available only when STA is connected.
+
+	where value of m is:
+		1   -- RSSI (Receive Signal Strength Indication)
+		2   -- SNR (Signal to Noise Ratio)
+		3   -- NF (Noise Floor)
+	where value of n is:
+		1   -- Beacon last
+		2   -- Beacon average
+		3   -- Data last
+		4   -- Data average
+
+	Examples:
+		mlanutl mlan0 getsignal 1        : Get the RSSI info (beacon last, beacon
+		                                  average, data last and data average)
+		mlanutl mlan0 getsignal 3 4      : Get the NF of data average
+		mlanutl mlan0 getsignal 2 1      : Get the SNR of beacon last
+		mlanutl mlan0 getsignal          : Get all of the signal info
+		mlan0     getsignal:-32  -33  -35  -36  67  59  63  56  -99  -92  -98  -92
+		RSSI info: beacon last -32, beacon average -33, data last -35, data average -36
+		SNR info: beacon last 67, beacon average 59, data last 63, data average 56
+		NF info: beacon last -99, beacon average -92, data last -98, data average -92
+
+getsignalext
+	This command gets the last and average value of RSSI, SNR and NF of
+	Beacon and Data of spectific antenna path.
+	Note: This command is available only when STA is connected.
+              Driver will enable signalext and collect signal information for one second
+
+	where value of m is:
+		1   -- PATH A
+		2   -- PATH B
+		3   -- PATH A+B
+
+	Examples:
+        	mlanutl mlan0 getsignalext          :Get All path's signal.
+        	mlanutl maln0 getsignalext 3        :Get path A+B signal
+        	mlanutl maln0 getsignalext 1        :Get path A signal
+		mlanutl mlan0 getsignalext 2        :Get path B signal
+
+        PATH A: -46 -46 -49 -49 65 45 39 42 -111 -91 -88 -91
+
+	PATH A: RSSI info: beacon last -46, beacon average -46, data last -49, data average -49
+		SNR info: beacon last 65, beacon average 45, data last 39, data average 42
+		NF info: beacon last -111, beacon average -91, data last -88, data average -91
+
+signalextcfg
+	This command is used to enable/disable signalext
+	Usage:
+    		mlanutl mlanX signalextcfg [m]
+	where the value of [m] is:
+		1 -- enable signalext in firmware
+		0 -- disable signalext in firmware
+	Examples:
+		mlanutl mlan0 signalextcfg 1 : Enable signalext in firmware
+		mlanutl mlan0 signalextcfg 0 : Disable signalext in firmware
+
+getsignalextv2
+	This command gets the last and average value of RSSI, SNR and NF of
+	Beacon and Data of spectific antenna path.
+	Note: This command is available only when STA is connected.
+              "mlanutl mlanX signalextcfg 1" command needs to be issued before issuing this command
+
+	where value of m is:
+		1   -- PATH A
+		2   -- PATH B
+		3   -- PATH A+B
+
+	Examples:
+        	mlanutl mlan0 getsignalextv2          :Get All path's signal.
+        	mlanutl maln0 getsignalextv2 3        :Get path A+B signal
+        	mlanutl maln0 getsignalextv2 1        :Get path A signal
+		mlanutl mlan0 getsignalextv2 2        :Get path B signal
+
+        PATH A: -46 -46 -49 -49 65 45 39 42 -111 -91 -88 -91
+
+	PATH A: RSSI info: beacon last -46, beacon average -46, data last -49, data average -49
+		SNR info: beacon last 65, beacon average 45, data last 39, data average 42
+		NF info: beacon last -111, beacon average -91, data last -88, data average -91
+
+get_txpwrlimit
+	This command is used to get the txpwrlimit table in FW
+Usage:
+ 	mlanutl mlanX get_txpwrlimit <n> [raw_data_file]
+	where <n>
+		0:      Get 2.4G txpwrlimit table
+		0x10:   Get 5G sub0 txpwrlimit table
+		0x11:   Get 5G sub1 txpwrlimit table
+		0x12    Get 5G sub2 txpwrlimit table
+		0x1f    Get all 5G txpwrlimit table
+		0xff    Get both 2G and 5G txpwrlimit table
+	<raw_data_file> driver will save fw raw data to this file.
+
+    Examples:
+		mlanutl mlan0 get_txpwrlimit 0                      : Get 2G txpwrlimit table.
+		mlanutl mlan0 get_txpwrlimit 0x10                   : Get 5G sub band0 txpwrlimit table
+		mlanutl mlan0 get_txpwrlimit 0xff txpwrlimit.bin    : Get both 2G/5G txpwrlimit table and save to txpwrlimit.bin
+
+aggrpriotbl
+	This command is used set/get the priority table for AMPDU/AMSDU traffic per tid.
+	This command can also be used to disable AMPDU/AMSDU for a given tid.
+	In case of AMPDU this priority table will be used to setup block ack (to make
+	sure the highest priority tid always uses AMPDU as we have limited AMPDU streams)
+
+	where <m0> <n0> <m1> <n1> ... <m7> <n7>
+
+	<mx> - This is priority for Tid0 for AMPDU packet. A priority could be any
+		   values between 0 - 7, 0xff to disable aggregation.
+	<nx> - This is priority for Tid0 for AMSDU packet. A priority could be any
+		   values between 0 - 7, 0xff to disable aggregation.
+
+	eg:
+	mlanutl mlanX aggrpriotbl - This command will get the current Priority table for AMPDU and AMSDU.
+						  <2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255>. This is read as
+						  <"Prio for AMPDU for Tid0" "Prio for AMSDU for Tid0"
+						   "Prio for AMPDU for Tid1" "Prio for AMSDU for Tid1" and so on
+	mlanutl mlanX aggrpriotbl 2 2 0 0 1 1 3 3 4 4 5 5 255 255 255 255 -
+						This will set the priority table for AMPDU and AMSDU
+						Priority for Tid0/AMPDU = 2, Tid0/AMSDU = 2, Tid1/AMPDU = 0, Tid1/AMSDU = 0
+						and so on. Aggregation for Tid6 and Tid7 are disabled.
+						Here higher the priority number, higher the priority (i.e. 7
+						has higher priority than 6). Similarly for AMSDU.
+	mlanutl mlanX aggrpriotbl 0xff 2 0xff 0 0xff 1 0xff 3 0xff 4 0xff 5 0xff 0xff 0xff 0xff - This will disable
+						AMPDU for all the TIDs but will still keep AMSDU enabled to Tid0 to Tid5
+
+	The default setting is 2 255 0 255 1 255 3 255 4 255 5 255 255 255 255 255.
+
+	A delBA should be seen in case a disable happens on a TID for which AMPDU stream
+	is currently setup.
+
+	Note:- This command should only be issue in disconnected state.
+
+addbapara
+	This command can be used to update the default ADDBA parameters.
+
+	where <m> is <timeout>
+	<timeout> - This is the block ack timeout for ADDBA request.
+		0 : Disable (recommended for throughput test)
+		1 - 65535 : Block Ack Timeout in TU
+
+	where <n> is <txwinsize>
+	<txwinsize> - Window size for ADDBA request. (16 is recommended and default value)
+
+	where <o> is <rxwinsize>
+	<rxwinsize> - Window size for ADDBA response. (48 is recommended and 32 is default value)
+	              (16 is recommended for IWNCOMM AP in WAPI throughput test)
+
+	Current window size limit for Tx as well as Rx is 1023.
+
+	where <p> is <txamsdu>
+	<txamsdu> - amsdu support for ADDBA request. (1 is default value)
+            0: disable amsdu in ADDBA request
+            1: enable amsdu in ADDBA request
+
+	where <q> is <rxamsdu>
+	<rxamsdu> - amsdu support for ADDBA response. (1 is default value)
+            0: disable amsdu in ADDBA response
+            1: enable amsdu in ADDBA response
+
+	eg:
+	mlanutl mlanX addbapara - This command will get the current addba params
+	mlanutl mlanX addbapara 1000 64 8 0 0 - This will change the ADDBA timeout to (1000 * 1024) us,
+			txwinsize to 64 and rxwinsize to 8 and disable amdsu in ADDBA request/response.
+
+	The default setting is 65535 16 32 1 1.
+
+	In case the ADDBA timeout value is updated then a ADDBA is sent for all streams
+	to update the timeout value.
+
+	In case txwinsize and/or rxwinsize is updated, the effect could only be seen on
+	next ADDBA request/response. The current streams will not be affected with this
+	change.
+
+	In case of txamsdu/rxamsdu is updated, the effect could only be seen on
+	next ADDBA request/response. The current streams will not be affected with this
+	change. AMSDU in AMPDU stream will be enabled when AP support this feature
+	and AMSDU is enabled in aggrpriotbl.
+
+addbareject
+	This command is used set/get the addbareject table for all the TIDs.
+	This command can also be used to enable rejection of ADDBA requests for a given tid.
+
+	where <m0> <m1> ... <m7>
+
+	<mX> - This can be 0/1 for TidX. 1 enables rejection of ADDBA request for TidX and
+		   0 would accept any ADDBAs for TidX.
+
+	eg:
+	mlanutl mlanX addbareject - This command will get the current table.
+	    [0 0 0 0 0 0 0 0]. ADDBA would be accepted for all TIDs. This is the default state.
+
+	mlanutl mlanX addbareject 0 0 1 1 0 0 0 0 - This command will accept ADDBA requests for
+		Tid [0,1,4,5,6,7] and reject ADDBA requests for Tid [2,3]
+
+	mlanutl mlanX addbareject 1 1 1 1 1 1 1 1 - This will enable rejection of ADDBA requests for
+		all Tids.
+
+	Note:- This command should only be issue in disconnected state.
+
+vhtcfg
+	This command is used to set and get various 11ac specific configuration
+	for transmission and reception. For the SET operation, all paramaters
+	may be applied. For the GET operation, only the first two parameters are applied.
+	The 6th argument "rx_mcs_set" can be used to disbale/enable 802.11ac.
+
+	where <j> is <band>
+	<band> - This is the band setting for the vhtcfg
+		0: Settings for both 2.4G and 5G bands (for SET operation, 11N BW only)
+		1: Settings for 2.4G band (for 11N BW only)
+		2: Settings for 5G band
+
+	where <k> is <txrx>
+	<txrx> - This parameter specifies the configuration of VHT operation for TX or/and VHT capabilities
+		0: Unspecified
+		1: configuration of VHT capabilities for Tx operations (STA only)
+		2: configuration of VHT capabilities for association (STA only)
+		3: configuration of VHT capabilities (uAP only)
+	Note: For the STA, the VHT capabilities configuration is applied in association,
+	      whereas the VHT operations configuration is actually used in Tx.
+
+	where [l] is <bwcfg>
+	<bwcfg> - This parameter specifies the bandwidth (BW) configuration
+		  applied to the vhtcfg.
+	If <txrx> is 1/3 (Tx operations),
+		0: Tx BW follows the BW (20/40 MHz) from 11N CFG
+		1: Tx BW follows the BW (80/160/80+80 MHz) from VHT Capabilities
+		   defined in <vhtcap> below for 5G band.
+	If <txrx> is 2 (association),
+		0: Rx BW follows the BW (20/40 MHz) from 11N CFG
+		1: Rx BW follows the BW (80/160/80+80 MHz) from VHT Capabilities
+		   defined in <vhtcap> below for 5G band.
+
+	where [m] is <vhtcap>
+	<vhtcap> - This parameter specifies the VHT capabilities info if <txrx> is 2 (association)
+		   or the VHT Tx operations if <txrx> is 1 (Tx operations).
+		   The VHT Tx operation should be a subset of VHT capabilities for association.
+		   It is a bitmap and should be used as follows:
+
+		Bit 31-30: Reserved and set to 0
+		Bit 29:    TX antenna pattern consistency
+			   1: antenna pattern does not change
+			   0: antenna pattern might change
+		Bit 28:    RX antenna pattern consistency
+			   1: antenna pattern does not change
+			   0: antenna pattern might change
+		Bit 27-26: VHT link adaptation capable
+			   0: no feedback of VHT MFB from the STA
+			   1: unsolicted feedback of VHT MFB from the STA
+			   2: both response and unsolicted feedback of VHT MFB
+			      from the STA
+			   3: reserved and set to 0
+		Bit 25-23: Maximum A-MPDU length exponent
+		Bit 22:    +HTC-VHT capable (1: enable. 0 disable)
+		Bit 21:    VHT TXOP PS
+		Bit 20:    MU beamformee capable (1: enable. 0 disable)
+		Bit 19:    MU beamformer capable (1: enable. 0 disable)
+		Bit 18-16: Number of sounding dimensions (set to maximum-1
+			   if Bit 11 is 1. Otherwise, reserved and set to 0)
+		Bit 15-13: Compressed steering number of beamformer
+			   antennas supported (set to maximum-1 if Bit 12 is 1.
+			   Otherwise, reserved and set to 0)
+		Bit 12:    SU beamformee capable (1: enable. 0 disable)
+		Bit 11:    SU beamformer capable (1: enable. 0 disable)
+		Bit 10-8:  Rx STBC
+			   0: no support
+			   1: support of 1 spatial stream
+			   2: support of 1-2 streams
+			   3: support of 1-3 spatial streams
+			   4: support of 1-4 spatial streams
+			   5-7: reserved and set to 0
+		Bit 7:     TX STBC (1: enable. 0 disable)
+		Bit 6:     Short GI for 160 and 80+80 MHz (1: enable. 0 disable)
+		Bit 5:     Short GI for 80 MHz (1: enable. 0 disable)
+		Bit 4:     Rx LDPC (1: enable. 0 disable)
+		Bit 3-2:   Supported channel width set.
+			   0: no support of either 160 or 80+80 MHz.
+			   1: support of 160 MHz
+			   2: support of both 160 and 80+80 MHz.
+			   3: reserved and set to 0.
+		Bit 1-0:   Maximum MPDU length
+			   0: 3895 octets.
+			   1: 7991 octets.
+			   2: 11454 octets.
+			   3: reserved and set to 0.
+
+	Note: for the STA, if <txrx> is 1 (Tx operations), the bitmap for <vhtcap> may be simplied as follows:
+		Bit 31-8: Reserved and set to 0
+		Bit 7:    Tx STBC (1: enable. 0 disable)
+		Bit 6:    Reserved and set to 0
+		Bit 5:    Short GI for 80 Mhz (1: enable. 0 disable)
+		Bit 4:    LDPC (1: enable. 0 disable)
+		Bit 3-0:  Reserved and set to 0
+
+	where [n] is <tx_mcs_map>,
+	<tx_mcs_map> - This parameter specifies the TX MCS map. It may not be used for the STA if <txrx> is 1 (Tx operations).
+		It is a bitmap and should be used as following
+		Bit 15-0:  MCS map, which is defined as folows:
+			Bit 15-14: Max MCS for 8 SS
+			Bit 13-12: Max MCS for 7 SS
+			Bit 11-10: Max MCS for 6 SS
+			Bit 9-8:   Max MCS for 5 SS
+			Bit 7-6:   Max MCS for 4 SS
+			Bit 5-4:   Max MCS for 3 SS
+			Bit 3-2:   Max MCS for 2 SS
+			Bit 1-0:   Max MCS for 1 SS
+
+	where [o] is <rx_mcs_map>.
+	<rx_mcs_map> - This parameter specifies the RX MCS map. It may not be used for the STA if <txrx> is 1 (Tx operations).
+		It is a bitmap with the same sructure as for <tx_mcs_map>
+		rx_mcs_map = 0xffff : FW will disable 802.11ac
+                rx_mcs_map = others : FW will enable 802.11ac
+
+	Note: The user setting of vhtcap may be overwritten by the driver
+	      if the setting of those fields is beyond the hardware capabilities.
+
+	Examples:
+		mlanutl mlan0 vhtcfg 2 1            : Get current VHT configuration in 5GHz for the STA.
+		mlanutl mlan0 vhtcfg 2 2            : Get maximum VHT configuration in 5GHz for the STA.
+		mlanutl mlan0 vhtcfg 2 1 1 0x000001f0
+		    : Set the Tx operations configuration in 5GHz for the STA,
+		      Tx BW follows the VHT Capabilities.
+		mlanutl mlan0 vhtcfg 2 2 0 0x000001f0 0xfff5 0xfffa
+		    : Set the VHT capabilities configuration in 5GHz for the STA,
+		      the Tx supports MCS 0-8 for both 1 and 2 spatial streams,
+		      while the Rx supports MCS 0-9 for both 1 and 2 spatial streams.
+		mlanutl uap0 vhtcfg 2 3 0 0x000001f0 0xfffa 0xfffa
+		    : Set the current/maximum VHT configuration in 5GHz for the uAP.
+		      Both Tx and Rx supports MCS 0-9 for both 1 and 2 spatial streams.
+		mlanutl uap0 vhtcfg 2 3 0 0x000001b0
+		    : Set the VHT capability information in 5GHz for the uAP, and keep the Tx/Rx MCS Map same as before.
+
+dyn_bw
+	This command is used to set/get dynamic bandwidth.
+
+	Usage:
+		mlanutl mlanX dyn_bw [n]
+
+	where <n>
+           [BIT0]
+                 0 = TxInfo Indicated BW Disable
+                 1 = TxInfo Indicated BW Enable
+           [BIT1]
+                 0 = TxInfo Dynamatic BW Disable
+                 1 = TxInfo Dynamatic BW Enable
+           [BIT2]
+                 0 = TxInfo Force send RTS Disable
+                 1 = TxInfo Force send RTS Enable
+           [BIT3]
+                 0 = Mac Dynamic BW Operation Mode Disable (Static BW Operation Mode)
+                 1 = Mac Dynamic BW Operation Mode Enable
+           other bits reserved.
+
+        If no parameter provided, get is performed.
+
+	Examples:
+		mlanutl mlan0 dyn_bw 0x1       : Enable TxInfo Indicated BW
+		mlanutl mlan0 dyn_bw           : get current setting
+
+httxcfg
+	This command is used to configure various 11n specific configuration
+	for transmit (such as Short GI, Channel BW and Green field support)
+
+	where <m> is <txcfg>
+	This is a bitmap and should be used as following
+		Bit 15-8: Reserved set to 0
+		Bit 7: STBC enable/disable
+		Bit 6: Short GI in 40 Mhz enable/disable
+		Bit 5: Short GI in 20 Mhz enable/disable
+		Bit 4: Green field enable/disable
+		Bit 3-2: Reserved set to 1
+		Bit 1: 20/40 Mhz enable disable.
+		Bit 0: LDPC enable/disable
+
+	When Bit 1 is set then firmware could transmit in 20Mhz or 40Mhz based
+	on rate adaptation. When this bit is reset then firmware will only
+	transmit in 20Mhz.
+
+	where <n> is <band>
+	<band> - This is the band info for <txcfg> settings.
+		0: Settings for both 2.4G and 5G bands
+		1: Settings for 2.4G band
+		2: Settings for 5G band
+
+	Example:
+		mlanutl mlanX httxcfg
+		This will display HT Tx configuration for 2.4G and 5G band.
+
+		mlanutl mlanX httxcfg 0x62
+		This will enable 20/40 and Short GI but will disable Green field for 2.4G and 5G band.
+
+		mlanutl mlanX httxcfg 0x30 1
+		This will enable Short GI 20 Mhz and Green field for 2.4G band.
+
+	The default value is 0x20 for 2.4G and 0x62 for 5G.
+
+	Note:- If 20/40 MHz support is disabled in htcapinfo, device will not transmit
+	in 40 MHz even 20/40 MHz is enabled in httxcfg.
+
+htcapinfo
+	This command is used to configure some of parameters in HTCapInfo IE
+	(such as Short GI, Channel BW, and Green field support)
+
+	where <m> is <capinfo>
+	<capinfo> - This is a bitmap and should be used as following
+		Bit 29: Green field enable/disable
+		Bit 26: Rx STBC Support enable/disable. (As we support
+			single spatial stream only 1 bit is used for Rx STBC)
+		Bit 25: Tx STBC support enable/disable.
+		Bit 24: Short GI in 40 Mhz enable/disable
+		Bit 23: Short GI in 20 Mhz enable/disable
+		Bit 22: Rx LDPC enable/disable
+		Bit 17: 20/40 Mhz enable disable.
+		Bit  8: Enable/disable 40Mhz Intolarent bit in ht capinfo.
+		        0 will reset this bit and 1 will set this bit in
+		        htcapinfo attached in assoc request.
+		All others are reserved and should be set to 0.
+
+	Setting of any other bits will return error.
+
+	where <n> is <band>
+	<band> - This is the band info for <capinfo> settings.
+		0: Settings for both 2.4G and 5G bands
+		1: Settings for 2.4G band
+		2: Settings for 5G band
+
+	Example:
+		mlanutl mlanX htcapinfo
+		This will display HT capabilties information.
+		If the information for 2.4G and 5G is different,
+		the first value is for 2.4G and the second value is for 5G.
+		Otherwise, it will display a single value for both bands.
+
+		mlanutl mlanX htcapinfo 0x1820000
+		This will enable Short GI, Channel BW to 20/40 and disable Green field support for 2.4G and 5G band.
+
+		mlanutl mlanX htcapinfo 0x800000 2
+		This will enable Short GI, Channel BW to 20 only, No Rx STBC support and disable Green field support for 5G band.
+
+	The default value is 0x4800000 for 2.4G and 0x5820000 for 5G.
+
+	Note:- This command can be issued any time but it will only come to effect from
+	next association. (as HTCapInfo is sent only during Association).
+
+11axcfg
+	This command is used to config 11ax HE capability using conf file.
+
+     Usage:
+             mlanutl mlanX 11axcfg [conf file]
+
+     Example:
+        mlanutl mlan0 11axcfg config/11axcfg.conf
+        mlanutl uap0  11axcfg config/11axcfg.conf
+
+11axcmd
+    This command is used to config 11ax HE capability using command.
+
+    Usage:
+            mlanutl <mlanX|uapX> 11axcmd <subcmd> [value_1] [value_2]
+            <subcmd = tx_omi > :     set/get omi value
+                                     used for OMI transmission in MAC header HTC+ field, please see 11ax spec for OMI definition
+                                     set OMI when [value_1 = <omi>], where <omi> is defined as:
+                                       Bit 0-2: Rx NSS
+                                       Bit 3-4: Channel Width
+                                       Bit 6  : Tx NSTS (applies to client mode only)
+                                       All other bits are not supported currently.
+                                     get OMI without value_1 and value_2
+
+            <subcmd = obssnbru_toltime> :  set/get OBSS narrow band RU tolerance time value in seconds
+                                           set tolerance time when [value_1 = <time>], where <time> indicates:
+                                           the minimum time that needs to pass since the reception of the last beacon frame from an OBSS AP that
+                                           did not indicate tolerance to narrow bandwidth RU in OFDMA before the STA transmits an HE TB PPDU in a
+                                           26-tine RU allocated by a trigger frame from the HE AP.
+                                           valid value range [1..3600] in seconds. Any value more than 3600 will disable this feature.
+                                           By default this feature is currently disabled.
+    Example :
+            mlanutl mlan0 11axcmd tx_omi 0x41            : set omi value to 0x41
+            mlanutl mlan0 11axcmd tx_omi                 : get omi value
+            mlanutl mlan0 11axcmd obssnbru_toltime 1800  : set OBSSNBRU tolerance time to 1800 seconds
+            mlanutl mlan0 11axcmd obssnbru_toltime 3601  : disable OBSSNBRU tolerance time
+            mlanutl mlan0 11axcmd obssnbru_toltime       : get OBSSNBRU tolerance time
+
+txratecfg
+	This command is used to set/get the transmit data rate.
+
+	Note:
+	1) The data rate can be set only after association.
+
+	2) If the reassoc is OFF driver reset the data rate to auto if the connection state is disconnected.
+	Please note that user has to re-issue the set data rate command if the driver is disconnected.
+
+	3) If the reassoc is ON driver remembers the data rate set by the user, if the driver is
+	disconnected user does not have to re-issue the set data rate again.
+
+	4) Parameter [o] is optional. If [o] is not given, it will be set as 0xffff.
+
+	Where
+	[l] is <format>
+	<format> - This parameter specifies the data rate format used in this command
+		0:    LG
+		1:    HT
+		2:    VHT
+		3:    HE
+		0xff: Auto
+
+	[m] is <index>
+	<index> - This parameter specifies the rate or MCS index
+	If <format> is 0 (LG),
+		0	1 Mbps
+		1	2 Mbps
+		2	5.5 Mbps
+		3	11 Mbps
+		4	6 Mbps
+		5	9 Mbps
+		6	12 Mbps
+		7	18 Mbps
+		8	24 Mbps
+		9	36 Mbps
+		10	48 Mbps
+		11	54 Mbps
+	If <format> is 1 (HT),
+		0	MCS0
+		1	MCS1
+		2	MCS2
+		3	MCS3
+		4	MCS4
+		5	MCS5
+		6	MCS6
+		7	MCS7
+		8	MCS8
+		9	MCS9
+		10	MCS10
+		11	MCS11
+		12	MCS12
+		13	MCS13
+		14	MCS14
+		15	MCS15
+	If <format> is 2 (VHT),
+		0	MCS0
+		1	MCS1
+		2	MCS2
+		3	MCS3
+		4	MCS4
+		5	MCS5
+		6	MCS6
+		7	MCS7
+		8	MCS8
+		9	MCS9
+	If <format> is 3 (HE),
+		0	MCS0
+		1	MCS1
+		2	MCS2
+		3	MCS3
+		4	MCS4
+		5	MCS5
+		6	MCS6
+		7	MCS7
+		8	MCS8
+		9	MCS9
+		10	MCS10
+		11	MCS11
+	[n] is <nss>
+	<nss> - This parameter specifies the NSS. It is valid for VHT
+	If <format> is 2 (VHT),
+		1	NSS1
+		2	NSS2
+	[n] is <nss>
+	<nss> - This parameter specifies the NSS. It is valid for HE
+	If <format> is 3 (HE),
+		1	NSS1
+		2	NSS2
+	[o] is <rate setting, only support 9098/9097/9xxx chips>
+        Bit0 - 1: indicate preambleType
+          For legacy 11b: preemble type
+             00    = long
+             01    = short
+             10/11  = reserved
+          For legacy 11g: reserved
+          For 11n: Green field PPDU indicator
+             00 = HT-mix
+             01 = HT-GF
+             10/11 = reserved.
+          For 11ac: reserved.
+          For 11ax:
+             00 = HE-SU
+             01 = HE-EXT-SU
+             others are reserved
+
+        Bit 2 - 4 : indicate BW:
+          For HE ER:
+            0 = 242-tone RU
+            1 =  upper frequency 106-tone RU within the primary 20 MHz
+          Otherwise:
+            0 = 20 MHz
+            1 = 40 MHz
+            2 = 80 MHz
+            3 = 160 MHz
+
+        Bit 5 -6: indicate LTF + GI size
+          For HT:
+            0 = normal
+            1 = Short GI
+          For VHT:
+            01 = Short GI
+            11 = Short GI and Nsym mod 10=9
+            00 = otherwise
+          For HE:
+            0 = 1xHELTF + GI0.8us
+            1 = 2xHELTF + GI0.8us
+            2 = 2xHELTF + GI1.6us
+            3 = 4xHELTF + GI0.8us if DCM = 1 and STBC = 1
+                4xHELTF + GI3.2us, otherwise.
+
+        Bit 7: Indicate  STBC:
+            0 = no STBC
+            1 = STBC
+
+        Bit 8: indicate DCM:
+            0 = no DCM
+            1 = DCM
+
+        Bit 9: indicate coding:
+            0 = BCC
+            1 = LDPC
+
+        Bit 10 - 11: reserved.
+
+        Bit 12 - 13: Indicate maxPE
+            Max packet extension
+            0 - 0 usec
+            1 - 8 usec
+            2 - 16 usec.
+
+        Bit 14 - 15: reserved.
+
+        0xffff: Auto
+
+	Examples:
+		mlanutl mlan0 txratecfg          : Read the current data rate setting
+		mlanutl mlan0 txratecfg 0 3      : Set fixed Tx rate to 11 Mbps
+		mlanutl mlan0 txratecfg 0 11     : Set fixed Tx rate to 54 Mbps
+		mlanutl mlan0 txratecfg 1 3      : Set fixed Tx rate to MCS3
+		mlanutl mlan0 txratecfg 2 3 2    : Set fixed Tx rate to MCS3 for NSS2
+		mlanutl mlan0 txratecfg 3 3 2    : Set 11AX fixed Tx rate to MCS3 for NSS2
+		mlanutl mlan0 txratecfg 3 5 2 0x2282   : Set 11AX fixed Tx rate to MCS5 for NSS2, and Preamble type is 2, BW is 0, LTF + GI size 0
+                                                         STBC is 1, DMC is 0, Coding is 1, maxPE is 2.
+		mlanutl mlan0 txratecfg 0xff     : Disable fixed rate and uses auto rate
+
diff --git a/wlan_sd8987/gpl-2.0.txt b/wlan_sd8987/gpl-2.0.txt
new file mode 100755
index 0000000..2c62266
--- /dev/null
+++ b/wlan_sd8987/gpl-2.0.txt
@@ -0,0 +1,339 @@
+              GNU GENERAL PUBLIC LICENSE
+ 		       Version 2, June 1991
+
+  Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  Everyone is permitted to copy and distribute verbatim copies
+  of this license document, but changing it is not allowed.
+
+ 			    Preamble
+
+   The licenses for most software are designed to take away your
+ freedom to share and change it.  By contrast, the GNU General Public
+ License is intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.  This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it.  (Some other Free Software Foundation software is covered by
+ the GNU Lesser General Public License instead.)  You can apply it to
+ your programs, too.
+
+   When we speak of free software, we are referring to freedom, not
+ price.  Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it
+ in new free programs; and that you know you can do these things.
+
+   To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.
+
+   For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have.  You must make sure that they, too, receive or can get the
+ source code.  And you must show them these terms so they know their
+ rights.
+
+   We protect your rights with two steps: (1) copyright the software, and
+ (2) offer you this license which gives you legal permission to copy,
+ distribute and/or modify the software.
+
+   Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software.  If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.
+
+   Finally, any free program is threatened constantly by software
+ patents.  We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary.  To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.
+
+   The precise terms and conditions for copying, distribution and
+ modification follow.
+
+ 		    GNU GENERAL PUBLIC LICENSE
+    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+   0. This License applies to any program or other work which contains
+ a notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License.  The "Program", below,
+ refers to any such program or work, and a "work based on the Program"
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language.  (Hereinafter, translation is included without limitation in
+ the term "modification".)  Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope.  The act of
+ running the Program is not restricted, and the output from the Program
+ is covered only if its contents constitute a work based on the
+ Program (independent of having been made by running the Program).
+ Whether that is true depends on what the Program does.
+
+   1. You may copy and distribute verbatim copies of the Program's
+ source code as you receive it, in any medium, provided that you
+ conspicuously and appropriately publish on each copy an appropriate
+ copyright notice and disclaimer of warranty; keep intact all the
+ notices that refer to this License and to the absence of any warranty;
+ and give any other recipients of the Program a copy of this License
+ along with the Program.
+
+ You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.
+
+   2. You may modify your copy or copies of the Program or any portion
+ of it, thus forming a work based on the Program, and copy and
+ distribute such modifications or work under the terms of Section 1
+ above, provided that you also meet all of these conditions:
+
+     a) You must cause the modified files to carry prominent notices
+     stating that you changed the files and the date of any change.
+
+     b) You must cause any work that you distribute or publish, that in
+     whole or in part contains or is derived from the Program or any
+     part thereof, to be licensed as a whole at no charge to all third
+     parties under the terms of this License.
+
+     c) If the modified program normally reads commands interactively
+     when run, you must cause it, when started running for such
+     interactive use in the most ordinary way, to print or display an
+     announcement including an appropriate copyright notice and a
+     notice that there is no warranty (or else, saying that you provide
+     a warranty) and that users may redistribute the program under
+     these conditions, and telling the user how to view a copy of this
+     License.  (Exception: if the Program itself is interactive but
+     does not normally print such an announcement, your work based on
+     the Program is not required to print an announcement.)
+
+ These requirements apply to the modified work as a whole.  If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works.  But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program
+ with the Program (or with a work based on the Program) on a volume of
+ a storage or distribution medium does not bring the other work under
+ the scope of this License.
+
+   3. You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+
+     a) Accompany it with the complete corresponding machine-readable
+     source code, which must be distributed under the terms of Sections
+     1 and 2 above on a medium customarily used for software interchange; or,
+
+     b) Accompany it with a written offer, valid for at least three
+     years, to give any third party, for a charge no more than your
+     cost of physically performing source distribution, a complete
+     machine-readable copy of the corresponding source code, to be
+     distributed under the terms of Sections 1 and 2 above on a medium
+     customarily used for software interchange; or,
+
+     c) Accompany it with the information you received as to the offer
+     to distribute corresponding source code.  (This alternative is
+     allowed only for noncommercial distribution and only if you
+     received the program in object code or executable form with such
+     an offer, in accord with Subsection b above.)
+
+ The source code for a work means the preferred form of the work for
+ making modifications to it.  For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to
+ control compilation and installation of the executable.  However, as a
+ special exception, the source code distributed need not include
+ anything that is normally distributed (in either source or binary
+ form) with the major components (compiler, kernel, and so on) of the
+ operating system on which the executable runs, unless that component
+ itself accompanies the executable.
+
+ If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent
+ access to copy the source code from the same place counts as
+ distribution of the source code, even though third parties are not
+ compelled to copy the source along with the object code.
+
+   4. You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License.  Any attempt
+ otherwise to copy, modify, sublicense or distribute the Program is
+ void, and will automatically terminate your rights under this License.
+ However, parties who have received copies, or rights, from you under
+ this License will not have their licenses terminated so long as such
+ parties remain in full compliance.
+
+   5. You are not required to accept this License, since you have not
+ signed it.  However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works.  These actions are
+ prohibited by law if you do not accept this License.  Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying
+ the Program or works based on it.
+
+   6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions.  You may not impose any further
+ restrictions on the recipients' exercise of the rights granted herein.
+ You are not responsible for enforcing compliance by third parties to
+ this License.
+
+   7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License.  If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all.  For example, if a patent
+ license would not permit royalty-free redistribution of the Program by
+ all those who receive copies directly or indirectly through you, then
+ the only way you could satisfy both it and this License would be to
+ refrain entirely from distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices.  Many people have made
+ generous contributions to the wide range of software distributed
+ through that system in reliance on consistent application of that
+ system; it is up to the author/donor to decide if he or she is willing
+ to distribute software through any other system and a licensee cannot
+ impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.
+
+   8. If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License
+ may add an explicit geographical distribution limitation excluding
+ those countries, so that distribution is permitted only in or among
+ countries not thus excluded.  In such case, this License incorporates
+ the limitation as if written in the body of this License.
+
+   9. The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time.  Such new versions will
+ be similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+
+ Each version is given a distinguishing version number.  If the Program
+ specifies a version number of this License which applies to it and "any
+ later version", you have the option of following the terms and conditions
+ either of that version or of any later version published by the Free
+ Software Foundation.  If the Program does not specify a version number of
+ this License, you may choose any version ever published by the Free Software
+ Foundation.
+
+   10. If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the author
+ to ask for permission.  For software which is copyrighted by the Free
+ Software Foundation, write to the Free Software Foundation; we sometimes
+ make exceptions for this.  Our decision will be guided by the two goals
+ of preserving the free status of all derivatives of our free software and
+ of promoting the sharing and reuse of software generally.
+
+ 			    NO WARRANTY
+
+   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+ REPAIR OR CORRECTION.
+
+   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGES.
+
+ 		     END OF TERMS AND CONDITIONS
+
+ 	    How to Apply These Terms to Your New Programs
+
+   If you develop a new program, and you want it to be of the greatest
+ possible use to the public, the best way to achieve this is to make it
+ free software which everyone can redistribute and change under these terms.
+
+   To do so, attach the following notices to the program.  It is safest
+ to attach them to the start of each source file to most effectively
+ convey the exclusion of warranty; and each file should have at least
+ the "copyright" line and a pointer to where the full notice is found.
+
+     <one line to give the program's name and a brief idea of what it does.>
+     Copyright (C) <year>  <name of author>
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; either version 2 of the License, or
+     (at your option) any later version.
+
+     This program is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+     GNU General Public License for more details.
+
+     You should have received a copy of the GNU General Public License along
+     with this program; if not, write to the Free Software Foundation, Inc.,
+     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Also add information on how to contact you by electronic and paper mail.
+
+ If the program is interactive, make it output a short notice like this
+ when it starts in an interactive mode:
+
+     Gnomovision version 69, Copyright (C) year name of author
+     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+     This is free software, and you are welcome to redistribute it
+     under certain conditions; type `show c' for details.
+
+ The hypothetical commands `show w' and `show c' should show the appropriate
+ parts of the General Public License.  Of course, the commands you use may
+ be called something other than `show w' and `show c'; they could even be
+ mouse-clicks or menu items--whatever suits your program.
+
+ You should also get your employer (if you work as a programmer) or your
+ school, if any, to sign a "copyright disclaimer" for the program, if
+ necessary.  Here is a sample; alter the names:
+
+   Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+   `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+   <signature of Ty Coon>, 1 April 1989
+   Ty Coon, President of Vice
+
+ This General Public License does not permit incorporating your program into
+ proprietary programs.  If your program is a subroutine library, you may
+ consider it more useful to permit linking proprietary applications with the
+ library.  If this is what you want to do, use the GNU Lesser General
+ Public License instead of this License.
diff --git a/wlan_sd8987/mlan/mlan.h b/wlan_sd8987/mlan/mlan.h
new file mode 100755
index 0000000..566ad50
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan.h
@@ -0,0 +1,37 @@
+/** @file mlan.h
+ *
+ *  @brief This file declares all APIs that will be called from MOAL module.
+ *  It also defines the data structures used for APIs between MLAN and MOAL.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+    11/07/2008: split mlan.h into mlan_decl.h & mlan_ioctl.h
+******************************************************/
+
+#ifndef _MLAN_H_
+#define _MLAN_H_
+
+#include "mlan_decl.h"
+#include "mlan_ioctl.h"
+#include "mlan_ieee.h"
+
+#endif /* !_MLAN_H_ */
diff --git a/wlan_sd8987/mlan/mlan_11ac.c b/wlan_sd8987/mlan/mlan_11ac.c
new file mode 100755
index 0000000..0478688
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11ac.c
@@ -0,0 +1,1479 @@
+/** @file mlan_11ac.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *
+ *  Copyright 2011-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u16 bands,
+				     t_u16 mcs_map);
+/**
+ *  @brief determine the center frquency center index for bandwidth
+ *         of 80 MHz and 160 MHz
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         band
+ *  @param pri_chan     primary channel
+ *  @param chan_bw      channel bandwidth
+ *
+ *  @return             channel center frequency center, if found; O, otherwise
+ */
+
+t_u8
+wlan_get_center_freq_idx(mlan_private *pmpriv, t_u16 band,
+			 t_u32 pri_chan, t_u8 chan_bw)
+{
+	t_u8 center_freq_idx = 0;
+
+	if (band & BAND_AAC) {
+		switch (pri_chan) {
+		case 36:
+		case 40:
+		case 44:
+		case 48:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 42;
+				break;
+			}
+			/* fall through */
+		case 52:
+		case 56:
+		case 60:
+		case 64:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 58;
+				break;
+			} else if (chan_bw == CHANNEL_BW_160MHZ) {
+				center_freq_idx = 50;
+				break;
+			}
+			/* fall through */
+		case 100:
+		case 104:
+		case 108:
+		case 112:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 106;
+				break;
+			}
+			/* fall through */
+		case 116:
+		case 120:
+		case 124:
+		case 128:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 122;
+				break;
+			} else if (chan_bw == CHANNEL_BW_160MHZ) {
+				center_freq_idx = 114;
+				break;
+			}
+			/* fall through */
+		case 132:
+		case 136:
+		case 140:
+		case 144:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 138;
+				break;
+			}
+			/* fall through */
+		case 149:
+		case 153:
+		case 157:
+		case 161:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 155;
+				break;
+			}
+			/* fall through */
+		case 165:
+		case 169:
+		case 173:
+		case 177:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 171;
+				break;
+			}
+			/* fall through */
+		case 184:
+		case 188:
+		case 192:
+		case 196:
+			if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 190;
+				break;
+			}
+			/* fall through */
+		default:	/* error. go to the default */
+			center_freq_idx = 42;
+		}
+	}
+	return center_freq_idx;
+}
+
+/**
+ *  @brief This function gets the bitmap of nss which supports VHT mcs
+ *
+ *  @param mcs_map_set  VHT mcs map
+ *
+ *  @return             The bitmap of supported nss
+ */
+static t_u8
+wlan_get_nss_vht_mcs(t_u16 mcs_map_set)
+{
+	t_u8 nss, nss_map = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+			nss_map |= 1 << (nss - 1);
+	}
+	PRINTM(MCMND, "Supported nss bit map:0x%02x\n", nss_map);
+	return nss_map;
+}
+
+/**
+ *  @brief This function gets the bitmap of nss which supports VHT mcs
+ *
+ *  @param mcs_map_set  VHT mcs map
+ *
+ *  @return             The bitmap of supported nss
+ */
+static t_u8
+wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)
+{
+	t_u8 nss, nss_num = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
+			nss_num++;
+	}
+	PRINTM(MCMND, "Supported nss:%d\n", nss_num);
+	return nss_num;
+}
+
+/**
+ *  @brief This function fills the cap info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11ac_dev_cap;
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_dot_11ac_dev_cap = priv->usr_dot_11ac_dev_cap_bg;
+
+	vht_cap->vht_cap_info = usr_dot_11ac_dev_cap;
+
+	RESET_VHTCAP_MAXMPDULEN(vht_cap->vht_cap_info);
+	LEAVE();
+}
+
+/**
+ *  @brief Set/get 11ac configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11ac_ioctl_vhtcfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11ac_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+	t_u32 usr_vht_cap_info = 0;
+	t_u32 cfg_value = 0;
+	t_u32 hw_value = 0;
+	t_u8 nss = 0;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	t_u16 rx_nss = 0;
+	t_u16 tx_nss = 0;
+#endif
+
+	ENTER();
+
+#define VHT_CAP_INFO_BIT_FIELDS                                                \
+	(MBIT(4) | MBIT(5) | MBIT(6) | MBIT(7) | MBIT(11) | MBIT(12) |         \
+	 MBIT(19) | MBIT(20) | MBIT(21) | MBIT(22) | MBIT(28) | MBIT(29))
+
+	cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		/** SET operation */
+		/** validate the user input and correct it if necessary */
+		if (pmpriv->bss_role == MLAN_BSS_ROLE_STA) {
+			if (cfg->param.vht_cfg.txrx == 3) {
+				PRINTM(MERROR,
+				       "Configuration of VHT capabilities for TX/RX 3 is not supported in STA mode!\n");
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+		if (pmpriv->bss_role == MLAN_BSS_ROLE_UAP) {
+			if (cfg->param.vht_cfg.txrx != 3) {
+				PRINTM(MERROR,
+				       "Configuration of VHT capabilities for TX/RX %d is not supported in UAP mode!\n",
+				       cfg->param.vht_cfg.txrx);
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+		/** set bit fileds */
+		usr_vht_cap_info = VHT_CAP_INFO_BIT_FIELDS &
+			cfg->param.vht_cfg.vht_cap_info &
+			pmadapter->hw_dot_11ac_dev_cap;
+		/** set MAX MPDU LEN field (bit 0 - bit 1) */
+		cfg_value =
+			GET_VHTCAP_MAXMPDULEN(cfg->param.vht_cfg.vht_cap_info);
+		hw_value =
+			GET_VHTCAP_MAXMPDULEN(pmadapter->hw_dot_11ac_dev_cap);
+		SET_VHTCAP_MAXMPDULEN(usr_vht_cap_info,
+				      MIN(cfg_value, hw_value));
+		/** set CHAN Width Set field (bit 2 - bit 3) */
+		cfg_value = GET_VHTCAP_CHWDSET(cfg->param.vht_cfg.vht_cap_info);
+		hw_value = GET_VHTCAP_CHWDSET(pmadapter->hw_dot_11ac_dev_cap);
+		SET_VHTCAP_CHWDSET(usr_vht_cap_info, MIN(cfg_value, hw_value));
+		/** set Rx STBC field (bit 8 - bit 10) */
+		cfg_value = GET_VHTCAP_RXSTBC(cfg->param.vht_cfg.vht_cap_info);
+		hw_value = GET_VHTCAP_RXSTBC(pmadapter->hw_dot_11ac_dev_cap);
+		SET_VHTCAP_RXSTBC(usr_vht_cap_info, MIN(cfg_value, hw_value));
+		/** set Steering Number of BFer Ant (bit 13 - bit 15) */
+		cfg_value =
+			GET_VHTCAP_SNBFERANT(cfg->param.vht_cfg.vht_cap_info);
+		hw_value = GET_VHTCAP_SNBFERANT(pmadapter->hw_dot_11ac_dev_cap);
+		SET_VHTCAP_SNBFERANT(usr_vht_cap_info,
+				     MIN(cfg_value, hw_value));
+		/** set Number of Sounding Dimension (bit 16 - bit 18) */
+		cfg_value =
+			GET_VHTCAP_NUMSNDDM(cfg->param.vht_cfg.vht_cap_info);
+		hw_value = GET_VHTCAP_NUMSNDDM(pmadapter->hw_dot_11ac_dev_cap);
+		SET_VHTCAP_NUMSNDDM(usr_vht_cap_info, MIN(cfg_value, hw_value));
+		/** set Number of Max AMPDU Length Exponent (bit 23 - bit 25) */
+		cfg_value =
+			GET_VHTCAP_MAXAMPDULENEXP(cfg->param.vht_cfg.
+						  vht_cap_info);
+		hw_value =
+			GET_VHTCAP_MAXAMPDULENEXP(pmadapter->
+						  hw_dot_11ac_dev_cap);
+		SET_VHTCAP_MAXAMPDULENEXP(usr_vht_cap_info,
+					  MIN(cfg_value, hw_value));
+		/** set VHT Link Adaptation Capable (bit 26 - bit 27) */
+		cfg_value =
+			GET_VHTCAP_LINKADPCAP(cfg->param.vht_cfg.vht_cap_info);
+		hw_value =
+			GET_VHTCAP_LINKADPCAP(pmadapter->hw_dot_11ac_dev_cap);
+		SET_VHTCAP_LINKADPCAP(usr_vht_cap_info,
+				      MIN(cfg_value, hw_value));
+		/** update the user setting if it is beyond the hw capabiliteis
+		 */
+		cfg->param.vht_cfg.vht_cap_info = usr_vht_cap_info;
+		PRINTM(MINFO, "Set: vht cap info  0x%x\n", usr_vht_cap_info);
+
+		/** update the RX MCS map */
+		if (cfg->param.vht_cfg.txrx & MLAN_RADIO_RX) {
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+			if (IS_CARD9098(pmadapter->card_type) ||
+			    IS_CARD9097(pmadapter->card_type)) {
+				if (cfg->param.vht_cfg.band == BAND_SELECT_A) {
+					rx_nss = GET_RXMCSSUPP(pmadapter->
+							       user_htstream >>
+							       8);
+					tx_nss = GET_TXMCSSUPP(pmadapter->
+							       user_htstream >>
+							       8) & 0x0f;
+				} else {
+					rx_nss = GET_RXMCSSUPP(pmadapter->
+							       user_htstream);
+					tx_nss = GET_TXMCSSUPP(pmadapter->
+							       user_htstream) &
+						0x0f;
+				}
+			}
+#endif
+			/* use the previous user value */
+			if (cfg->param.vht_cfg.vht_rx_mcs == 0xffffffff)
+				cfg->param.vht_cfg.vht_rx_mcs =
+					GET_VHTMCS(pmpriv->
+						   usr_dot_11ac_mcs_support);
+			for (nss = 1; nss <= 8; nss++) {
+				cfg_value =
+					GET_VHTNSSMCS(cfg->param.vht_cfg.
+						      vht_rx_mcs, nss);
+				hw_value =
+					GET_DEVNSSRXMCS(pmadapter->
+							hw_dot_11ac_mcs_support,
+							nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+				if ((rx_nss != 0) && (nss > rx_nss))
+					cfg_value = NO_NSS_SUPPORT;
+#endif
+				if ((hw_value == NO_NSS_SUPPORT) ||
+				    (cfg_value == NO_NSS_SUPPORT))
+					SET_VHTNSSMCS(cfg->param.vht_cfg.
+						      vht_rx_mcs, nss,
+						      NO_NSS_SUPPORT);
+				else
+					SET_VHTNSSMCS(cfg->param.vht_cfg.
+						      vht_rx_mcs, nss,
+						      MIN(cfg_value, hw_value));
+			}
+			PRINTM(MINFO, "Set: vht rx mcs set 0x%08x\n",
+			       cfg->param.vht_cfg.vht_rx_mcs);
+			/* use the previous user value */
+			if (cfg->param.vht_cfg.vht_tx_mcs == 0xffffffff)
+				cfg->param.vht_cfg.vht_tx_mcs =
+					GET_VHTMCS(pmpriv->
+						   usr_dot_11ac_mcs_support >>
+						   16);
+			for (nss = 1; nss <= 8; nss++) {
+				cfg_value =
+					GET_VHTNSSMCS(cfg->param.vht_cfg.
+						      vht_tx_mcs, nss);
+				hw_value =
+					GET_DEVNSSTXMCS(pmadapter->
+							hw_dot_11ac_mcs_support,
+							nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+				if ((tx_nss != 0) && (nss > tx_nss))
+					cfg_value = NO_NSS_SUPPORT;
+#endif
+				if ((hw_value == NO_NSS_SUPPORT) ||
+				    (cfg_value == NO_NSS_SUPPORT))
+					SET_VHTNSSMCS(cfg->param.vht_cfg.
+						      vht_tx_mcs, nss,
+						      NO_NSS_SUPPORT);
+				else
+					SET_VHTNSSMCS(cfg->param.vht_cfg.
+						      vht_tx_mcs, nss,
+						      MIN(cfg_value, hw_value));
+			}
+			PRINTM(MINFO, "Set: vht tx mcs set 0x%08x\n",
+			       cfg->param.vht_cfg.vht_tx_mcs);
+			if (!cfg->param.vht_cfg.skip_usr_11ac_mcs_cfg) {
+				RESET_DEVRXMCSMAP(pmpriv->
+						  usr_dot_11ac_mcs_support);
+				pmpriv->usr_dot_11ac_mcs_support |=
+					GET_VHTMCS(cfg->param.vht_cfg.
+						   vht_rx_mcs);
+				RESET_DEVTXMCSMAP(pmpriv->
+						  usr_dot_11ac_mcs_support);
+				pmpriv->usr_dot_11ac_mcs_support |=
+					(GET_VHTMCS
+					 (cfg->param.vht_cfg.vht_tx_mcs)
+					 << 16);
+				PRINTM(MINFO, "Set: vht mcs set 0x%08x\n",
+				       pmpriv->usr_dot_11ac_mcs_support);
+			} else {
+				PRINTM(MINFO,
+				       "Skipped user 11ac mcs configuration\n");
+				cfg->param.vht_cfg.skip_usr_11ac_mcs_cfg =
+					MFALSE;
+			}
+		}
+	}
+
+	if (pmpriv->bss_role == MLAN_BSS_ROLE_STA) {
+		if (cfg->param.vht_cfg.txrx & MLAN_RADIO_RX) {
+			/* maximum VHT configuration used in association */
+			if (pioctl_req->action == MLAN_ACT_SET) {
+				if (cfg->param.vht_cfg.band == BAND_SELECT_BG)
+					pmpriv->usr_dot_11ac_dev_cap_bg =
+						usr_vht_cap_info;
+				else if (cfg->param.vht_cfg.band ==
+					 BAND_SELECT_A)
+					pmpriv->usr_dot_11ac_dev_cap_a =
+						usr_vht_cap_info;
+				else {
+					pmpriv->usr_dot_11ac_dev_cap_bg =
+						usr_vht_cap_info;
+					pmpriv->usr_dot_11ac_dev_cap_a =
+						usr_vht_cap_info;
+				}
+				pmpriv->usr_dot_11ac_bw =
+					cfg->param.vht_cfg.bwcfg;
+
+			} else {
+				/** GET operation */
+				if (cfg->param.vht_cfg.band == BAND_SELECT_BG) {
+					cfg->param.vht_cfg.vht_cap_info =
+						pmpriv->usr_dot_11ac_dev_cap_bg;
+					PRINTM(MINFO,
+					       "Get: vht cap info for 2.4GHz 0x%x\n",
+					       pmpriv->usr_dot_11ac_dev_cap_bg);
+				} else if (cfg->param.vht_cfg.band ==
+					   BAND_SELECT_A) {
+					cfg->param.vht_cfg.vht_cap_info =
+						pmpriv->usr_dot_11ac_dev_cap_a;
+					PRINTM(MINFO,
+					       "Get: vht cap info for 5GHz 0x%x\n",
+					       pmpriv->usr_dot_11ac_dev_cap_a);
+				} else {
+					PRINTM(MINFO,
+					       "Get: invalid band selection for vht cap info\n");
+					ret = MLAN_STATUS_FAILURE;
+				}
+				cfg->param.vht_cfg.bwcfg =
+					pmpriv->usr_dot_11ac_bw;
+				cfg->param.vht_cfg.vht_rx_mcs =
+					GET_DEVRXMCSMAP(pmpriv->
+							usr_dot_11ac_mcs_support);
+				cfg->param.vht_cfg.vht_tx_mcs =
+					GET_DEVTXMCSMAP(pmpriv->
+							usr_dot_11ac_mcs_support);
+				cfg->param.vht_cfg.vht_rx_max_rate =
+					wlan_convert_mcsmap_to_maxrate(pmpriv,
+								       cfg->
+								       param.
+								       vht_cfg.
+								       band,
+								       cfg->
+								       param.
+								       vht_cfg.
+								       vht_rx_mcs);
+				cfg->param.vht_cfg.vht_tx_max_rate =
+					wlan_convert_mcsmap_to_maxrate(pmpriv,
+								       cfg->
+								       param.
+								       vht_cfg.
+								       band,
+								       cfg->
+								       param.
+								       vht_cfg.
+								       vht_tx_mcs);
+			}
+			LEAVE();
+			return ret;
+		}
+	}
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AC_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.vht_cfg);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set Operating Mode Notification cfg
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11ac_ioctl_opermodecfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11ac_cfg *cfg = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u8 hw_bw_160or8080 = 0;
+	t_u8 hw_rx_nss = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		cfg->param.opermode_cfg.bw = pmpriv->usr_dot_11ac_opermode_bw;
+		cfg->param.opermode_cfg.nss = pmpriv->usr_dot_11ac_opermode_nss;
+	} else if (pioctl_req->action == MLAN_ACT_SET) {
+		hw_bw_160or8080 =
+			GET_VHTCAP_CHWDSET(pmadapter->hw_dot_11ac_dev_cap);
+		hw_rx_nss =
+			wlan_get_nss_num_vht_mcs(GET_DEVRXMCSMAP
+						 (pmadapter->
+						  hw_dot_11ac_mcs_support));
+		if ((((cfg->param.opermode_cfg.bw - 1) > BW_80MHZ) &&
+		     !hw_bw_160or8080) ||
+		    (cfg->param.opermode_cfg.nss > hw_rx_nss)) {
+			PRINTM(MERROR,
+			       "bw or nss NOT supported. HW support bw_160or8080=%d rx_nss=%d.\n",
+			       hw_bw_160or8080, hw_rx_nss);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmpriv->usr_dot_11ac_opermode_bw = cfg->param.opermode_cfg.bw;
+		pmpriv->usr_dot_11ac_opermode_nss = cfg->param.opermode_cfg.nss;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get supported MCS set
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11ac_ioctl_supported_mcs_set(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req)
+{
+	/*mlan_ds_11ac_cfg *cfg= MNULL; */
+	/*int rx_mcs_supp; */
+	/*t_u8 mcs_set[NUM_MCS_SUPP]; */
+
+	ENTER();
+#if 0
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Set operation is not supported\n");
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	rx_mcs_supp = GET_11ACRXMCSSUPP(pmadapter->usr_dot_11ac_mcs_support);
+	/* Set MCS */
+	memset(pmadapter, (t_u8 *)mcs_set, 0xff, rx_mcs_supp);
+	/* Clear all the other values */
+	memset(pmadapter, (t_u8 *)&mcs_set[rx_mcs_supp], 0,
+	       NUM_MCS_FIELD - rx_mcs_supp);
+	/* Set MCS32 with 40MHz support */
+	if (ISSUPP_CHANWIDTH80(pmadapter->usr_dot_11ac_dev_cap_bg)
+	    || ISSUPP_CHANWIDTH80(pmadapter->usr_dot_11ac_dev_cap_a)
+		)
+		SETHT_MCS32(mcs_set);
+
+	cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+	memcpy_ext(pmadapter, cfg->param.supported_mcs_set, mcs_set,
+		   NUM_MCS_SUPP, sizeof(cfg->param.supported_mcs_set));
+
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prints the 802.11ac device capability
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *  @param cap           Capability value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+	ENTER();
+
+	switch (GET_VHTCAP_MAXMPDULEN(cap)) {
+	case 0x0:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MPDU length = 3895 octets\n");
+		break;
+	case 0x1:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MPDU length = 7991 octets\n");
+		break;
+	case 0x2:
+		PRINTM(MINFO,
+		       "GET_HW_SPEC: Maximum MPDU length = 11454 octets\n");
+		break;
+	default:
+		PRINTM(MINFO, "Unsupport value\n");
+		break;
+	}
+
+	PRINTM(MINFO, "GET_HW_SPEC: HTC-VHT %s\n",
+	       (ISSUPP_11ACVHTHTCVHT(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: VHT TXOP PS %s\n",
+	       (ISSUPP_11ACVHTTXOPPS(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU RX beamformee %s\n",
+	       (ISSUPP_11ACMURXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MU TX beamformee %s\n",
+	       (ISSUPP_11ACMUTXBEAMFORMEE(cap) ? "supported" :
+		"not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU RX Beamformee %s\n",
+	       (ISSUPP_11ACSUBEAMFORMEE(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: SU TX Beamformer %s\n",
+	       (ISSUPP_11ACSUBEAMFORMER(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+	       (ISSUPP_11ACRXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+	       (ISSUPP_11ACTXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 160MHz BW\n",
+	       (ISSUPP_11ACSGI160(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 80MHz BW\n",
+	       (ISSUPP_11ACSGI80(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: LDPC coding %s\n",
+	       (ISSUPP_11ACLDPC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160/80+80 MHz %s\n",
+	       (ISSUPP_11ACBW8080(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160 MHz %s\n",
+	       (ISSUPP_11ACBW160(cap) ? "supported" : "not supported"));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prints the 802.11ac device MCS
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param support   Support value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support)
+{
+	ENTER();
+
+	PRINTM(MINFO, "GET_HW_SPEC: MCSs for %2dx%2d MIMO\n",
+	       GET_DEVRXMCSMAP(support), GET_DEVTXMCSMAP(support));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function converts the 2-bit MCS map to the highest long GI
+ *  VHT PPDU data rate
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param bands        Supported bands
+ *  @param mcs_map      2-bit MCS map
+ *
+ *  @return             the max data rate for long GI
+ */
+t_u16
+wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u16 bands, t_u16 mcs_map)
+{
+	t_u8 i;
+	t_u8 nss;
+	t_u8 max_mcs;
+	t_u16 max_rate = 0;
+	t_u32 usr_vht_cap_info = 0;
+	t_u32 usr_dot_11n_dev_cap;
+
+	/* tables of the MCS map to the highest data rate (in Mbps)
+	 * supported for long GI */
+	t_u16 max_rate_lgi_20MHZ[8][3] = {
+		{0x41, 0x4E, 0x0},	/* NSS = 1 */
+		{0x82, 0x9C, 0x0},	/* NSS = 2 */
+		{0xC3, 0xEA, 0x104},	/* NSS = 3 */
+		{0x104, 0x138, 0x0},	/* NSS = 4 */
+		{0x145, 0x186, 0x0},	/* NSS = 5 */
+		{0x186, 0x1D4, 0x208},	/* NSS = 6 */
+		{0x1C7, 0x222, 0x0},	/* NSS = 7 */
+		{0x208, 0x270, 0x0}	/* NSS = 8 */
+	};
+
+	t_u16 max_rate_lgi_40MHZ[8][3] = {
+		{0x87, 0xA2, 0xB4},	/* NSS = 1 */
+		{0x10E, 0x144, 0x168},	/* NSS = 2 */
+		{0x195, 0x1E6, 0x21C},	/* NSS = 3 */
+		{0x21C, 0x288, 0x2D0},	/* NSS = 4 */
+		{0x2A3, 0x32A, 0x384},	/* NSS = 5 */
+		{0x32A, 0x3CC, 0x438},	/* NSS = 6 */
+		{0x3B1, 0x46E, 0x4EC},	/* NSS = 7 */
+		{0x438, 0x510, 0x5A0}	/* NSS = 8 */
+	};
+
+	t_u16 max_rate_lgi_80MHZ[8][3] = {
+		{0x124, 0x15F, 0x186},	/* NSS = 1 */
+		{0x249, 0x2BE, 0x30C},	/* NSS = 2 */
+		{0x36D, 0x41D, 0x492},	/* NSS = 3 */
+		{0x492, 0x57C, 0x618},	/* NSS = 4 */
+		{0x5B6, 0x6DB, 0x79E},	/* NSS = 5 */
+		{0x6DB, 0x83A, 0x0},	/* NSS = 6 */
+		{0x7FF, 0x999, 0xAAA},	/* NSS = 7 */
+		{0x924, 0xAF8, 0xC30}	/* NSS = 8 */
+	};
+	t_u16 max_rate_lgi_160MHZ[8][3] = {
+		{0x249, 0x2BE, 0x30C},	/* NSS = 1 */
+		{0x492, 0x57C, 0x618},	/* NSS = 2 */
+		{0x6DB, 0x83A, 0x0},	/* NSS = 3 */
+		{0x924, 0xAF8, 0xC30},	/* NSS = 4 */
+		{0xB6D, 0xDB6, 0xF3C},	/* NSS = 5 */
+		{0xDB6, 0x1074, 0x1248},	/* NSS = 6 */
+		{0xFFF, 0x1332, 0x1554},	/* NSS = 7 */
+		{0x1248, 0x15F0, 0x1860}	/* NSS = 8 */
+	};
+
+	if (bands & BAND_AAC) {
+		usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_a;
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	} else {
+		usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_bg;
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+	}
+
+	/* find the max NSS supported */
+	nss = 0;
+	for (i = 0; i < 8; i++) {
+		max_mcs = (mcs_map >> (2 * i)) & 0x3;
+		if (max_mcs < 3)
+			nss = i;
+	}
+
+	max_mcs = (mcs_map >> (2 * nss)) & 0x3;
+	/* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9 */
+	if (max_mcs >= 3)
+		max_mcs = 2;
+
+	if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
+		/* support 160 MHz */
+		max_rate = max_rate_lgi_160MHZ[nss][max_mcs];
+		if (max_mcs >= 1 && max_rate == 0)
+			/* MCS9 is not supported in NSS6 */
+			max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1];
+
+	} else {
+		if (priv->usr_dot_11ac_bw == BW_FOLLOW_VHTCAP) {
+			max_rate = max_rate_lgi_80MHZ[nss][max_mcs];
+			if (max_mcs >= 1 && max_rate == 0)
+				/* MCS9 is not supported in NSS3 */
+				max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1];
+		} else {
+			if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap)) {
+				max_rate = max_rate_lgi_40MHZ[nss][max_mcs];
+			} else {
+				max_rate = max_rate_lgi_20MHZ[nss][max_mcs];
+				/* MCS9 is not supported in NSS1/2/4/5/7/8 */
+				if (max_mcs >= 1 && max_rate == 0)
+					max_rate = max_rate_lgi_20MHZ[nss]
+						[max_mcs - 1];
+			}
+		}
+	}
+	PRINTM(MCMND, "max_rate=%dM\n", max_rate);
+	return max_rate;
+}
+
+/**
+ *  @brief This function fills the VHT cap tlv out put format is LE, not CPU
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pvht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *  @param flag         TREU--pvht_cap has the setting for resp
+ *                      MFALSE -- pvht_cap is clean
+ *  @param bw_80p80     TRUE -- enable 80p80
+ *  @return             N/A
+ */
+void
+wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+		      t_u16 bands, t_u8 flag, t_u8 bw_80p80)
+{
+	t_u16 mcs_map_user = 0;
+	t_u16 mcs_map_resp = 0;
+	t_u16 mcs_map_result = 0;
+	t_u16 mcs_user = 0;
+	t_u16 mcs_resp = 0;
+	t_u16 nss;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	t_u16 rx_nss = 0, tx_nss = 0;
+#endif
+	ENTER();
+
+	/* Fill VHT cap info */
+	wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+	/* clear 80p80 in vht_cap_info */
+	if (!bw_80p80)
+		pvht_cap->vht_cap.vht_cap_info &= ~(MBIT(2) | MBIT(3));
+	pvht_cap->vht_cap.vht_cap_info =
+		wlan_cpu_to_le32(pvht_cap->vht_cap.vht_cap_info);
+
+	/* Fill VHT MCS Set */
+	/* rx MCS Set, find the minimum of the user rx mcs and ap rx mcs */
+	mcs_map_resp = mcs_map_user =
+		GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
+	if (flag)
+		mcs_map_resp =
+			wlan_le16_to_cpu(pvht_cap->vht_cap.mcs_sets.rx_mcs_map);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	if (IS_CARD9098(priv->adapter->card_type) ||
+	    IS_CARD9097(priv->adapter->card_type)) {
+		if (bands & BAND_A) {
+			rx_nss = GET_RXMCSSUPP(priv->adapter->user_htstream >>
+					       8);
+			tx_nss = GET_TXMCSSUPP(priv->adapter->user_htstream >>
+					       8) & 0x0f;
+		} else {
+			rx_nss = GET_RXMCSSUPP(priv->adapter->user_htstream);
+			tx_nss = GET_TXMCSSUPP(priv->adapter->user_htstream) &
+				0x0f;
+		}
+		/** force 1x1 when enable 80P80 */
+		if (bw_80p80)
+			rx_nss = tx_nss = 1;
+	}
+#endif
+	mcs_map_result = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if ((rx_nss != 0) && (nss > rx_nss))
+			mcs_user = NO_NSS_SUPPORT;
+#endif
+		if ((mcs_user == NO_NSS_SUPPORT) ||
+		    (mcs_resp == NO_NSS_SUPPORT))
+			SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+		else
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      MIN(mcs_user, mcs_resp));
+	}
+	/* rx MCS map */
+	pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+		wlan_cpu_to_le16(mcs_map_result);
+
+	/* rx highest rate */
+	pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+		wlan_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
+	pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+		wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.rx_max_rate);
+
+	/* tx MCS Set find the minimum of the user tx mcs and ap tx mcs */
+	mcs_map_resp = mcs_map_user =
+		GET_DEVTXMCSMAP(priv->usr_dot_11ac_mcs_support);
+	if (flag)
+		mcs_map_resp =
+			wlan_le16_to_cpu(pvht_cap->vht_cap.mcs_sets.tx_mcs_map);
+	mcs_map_result = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if ((tx_nss != 0) && (nss > tx_nss))
+			mcs_user = NO_NSS_SUPPORT;
+#endif
+		if ((mcs_user == NO_NSS_SUPPORT) ||
+		    (mcs_resp == NO_NSS_SUPPORT))
+			SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+		else
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      MIN(mcs_user, mcs_resp));
+	}
+
+	/* tx MCS map */
+	pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+		wlan_cpu_to_le16(mcs_map_result);
+	/* tx highest rate */
+	pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+		wlan_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
+	pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+		wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.tx_max_rate);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function fills the VHT cap tlv out put format is CPU
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pvht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+		     t_u16 bands)
+{
+	ENTER();
+
+	pvht_cap->ieee_hdr.element_id = VHT_CAPABILITY;
+	pvht_cap->ieee_hdr.len = sizeof(VHT_capa_t);
+
+	/* Fill VHT cap info */
+	wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
+
+	/* rx MCS map */
+	pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
+		GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
+
+	/* rx highest rate */
+	pvht_cap->vht_cap.mcs_sets.rx_max_rate =
+		wlan_convert_mcsmap_to_maxrate(priv, bands,
+					       pvht_cap->vht_cap.mcs_sets.
+					       rx_mcs_map);
+
+	/* tx MCS map */
+	pvht_cap->vht_cap.mcs_sets.tx_mcs_map =
+		GET_DEVTXMCSMAP(priv->usr_dot_11ac_mcs_support);
+	/* tx highest rate */
+	pvht_cap->vht_cap.mcs_sets.tx_max_rate =
+		wlan_convert_mcsmap_to_maxrate(priv, bands,
+					       pvht_cap->vht_cap.mcs_sets.
+					       tx_mcs_map);
+
+	LEAVE();
+	return;
+}
+
+/*
+ *  @brief This function check if AP is in 11ac mode
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *
+ *  @return             MTRUE/MFALSE
+ */
+t_u8
+wlan_is_ap_in_11ac_mode(mlan_private *priv)
+{
+	BSSDescriptor_t *pbss_desc;
+	IEEEtypes_VHTOprat_t *vht_oprat = MNULL;
+	pbss_desc = &priv->curr_bss_params.bss_descriptor;
+	vht_oprat = pbss_desc->pvht_oprat;
+	if (!pbss_desc->pvht_cap)
+		return MFALSE;
+	if (vht_oprat && (vht_oprat->ieee_hdr.element_id == VHT_OPERATION)) {
+		if (vht_oprat->chan_width == VHT_OPER_CHWD_20_40MHZ)
+			return MFALSE;
+		else
+			return MTRUE;
+	} else
+		return MFALSE;
+}
+
+/**
+ *  @brief This function fills the VHTOperation ie out put format is CPU
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param vht_oprat    A pointer to IEEEtypes_VHTOprat_t structure
+ *  @param sta_ptr      A pointer to sta_node
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_tdls_vht_oprat_ie(mlan_private *priv,
+			    IEEEtypes_VHTOprat_t *vht_oprat, sta_node *sta_ptr)
+{
+	t_u8 supp_chwd_set;
+	t_u8 peer_supp_chwd_set;
+	t_u8 ap_supp_chwd_set;
+	t_u32 usr_vht_cap_info;
+
+	t_u16 mcs_map_user = 0;
+	t_u16 mcs_map_resp = 0;
+	t_u16 mcs_map_result = 0;
+	t_u16 mcs_user = 0;
+	t_u16 mcs_resp = 0;
+	t_u16 nss;
+	t_u8 chan_bw = 0;
+	BSSDescriptor_t *pbss_desc;
+	IEEEtypes_VHTCap_t *pvht_cap = &sta_ptr->vht_cap;
+	IEEEtypes_VHTCap_t *ap_vht_cap = MNULL;
+	ENTER();
+
+	pbss_desc = &priv->curr_bss_params.bss_descriptor;
+
+	/* Check if AP is in 11ac mode */
+	if (MFALSE == wlan_is_ap_in_11ac_mode(priv)) {
+		if (sta_ptr->ExtCap.ieee_hdr.element_id != EXT_CAPABILITY) {
+			PRINTM(MMSG, "No Peer's Ext_cap info\n");
+			return;
+		}
+		if (!ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH
+		    (sta_ptr->ExtCap.ext_cap)) {
+			PRINTM(MMSG,
+			       "Peer don't support Wider Bandwitch in Ext_cap\n");
+			return;
+		}
+	} else {
+		ap_vht_cap = pbss_desc->pvht_cap;
+	}
+
+	vht_oprat->ieee_hdr.element_id = VHT_OPERATION;
+	vht_oprat->ieee_hdr.len =
+		sizeof(IEEEtypes_VHTOprat_t) - sizeof(IEEEtypes_Header_t);
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_a;
+	else
+		usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_bg;
+
+	/* find the minmum bandwith between AP/TDLS peers */
+	supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
+	peer_supp_chwd_set = GET_VHTCAP_CHWDSET(pvht_cap->vht_cap.vht_cap_info);
+	supp_chwd_set = MIN(supp_chwd_set, peer_supp_chwd_set);
+
+	/* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
+	if (ap_vht_cap &&
+	    !ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(sta_ptr->ExtCap.ext_cap)) {
+		ap_supp_chwd_set =
+			GET_VHTCAP_CHWDSET(ap_vht_cap->vht_cap.vht_cap_info);
+		supp_chwd_set = MIN(supp_chwd_set, ap_supp_chwd_set);
+	}
+	switch (supp_chwd_set) {
+	case VHT_CAP_CHWD_80MHZ:
+		vht_oprat->chan_width = VHT_OPER_CHWD_80MHZ;
+		break;
+	case VHT_CAP_CHWD_160MHZ:
+		vht_oprat->chan_width = VHT_OPER_CHWD_160MHZ;
+		break;
+	case VHT_CAP_CHWD_80_80MHZ:
+		vht_oprat->chan_width = VHT_OPER_CHWD_80_80MHZ;
+		break;
+	}
+
+	/* Fill BASIC VHT MCS and NSS Set */
+	/* rx MCS Set, find the minimum of the user rx mcs and peer rx mcs */
+	mcs_map_user = GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
+	mcs_map_resp = pvht_cap->vht_cap.mcs_sets.rx_mcs_map;
+	mcs_map_result = 0;
+	for (nss = 1; nss <= 8; nss++) {
+		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
+		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
+		if ((mcs_user == NO_NSS_SUPPORT) ||
+		    (mcs_resp == NO_NSS_SUPPORT))
+			SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
+		else
+			SET_VHTNSSMCS(mcs_map_result, nss,
+				      MIN(mcs_user, mcs_resp));
+	}
+	/* Basic MCS map */
+	vht_oprat->basic_MCS_map = mcs_map_result;
+	switch (vht_oprat->chan_width) {
+	case VHT_OPER_CHWD_80MHZ:
+		chan_bw = CHANNEL_BW_80MHZ;
+		break;
+	case VHT_OPER_CHWD_160MHZ:
+		chan_bw = CHANNEL_BW_160MHZ;
+		break;
+	case VHT_OPER_CHWD_80_80MHZ:
+		chan_bw = CHANNEL_BW_80MHZ;
+		break;
+	}
+	vht_oprat->chan_center_freq_1 =
+		wlan_get_center_freq_idx(priv, BAND_AAC, pbss_desc->channel,
+					 chan_bw);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function would check whether support 80+80Mhz
+ *
+ *  @param pmpriv A pointer to mlan_private structure
+ *  @param pbss_desc   A pointer to BSSDescriptor_t structure
+ *
+ *  @return  ret  suport 80+80Mhz or not
+ */
+t_u8
+wlan_is_80_80_support(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+	t_u8 ret = MFALSE;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	t_u16 rx_nss = 0, tx_nss = 0;
+	IEEEtypes_VHTCap_t *pvht_cap = pbss_desc->pvht_cap;
+	MrvlIEtypes_He_cap_t *phecap = MNULL;
+	IEEEtypes_HECap_t *pBsshecap = MNULL;
+#endif
+
+	ENTER();
+
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	if (!IS_CARD9098(pmpriv->adapter->card_type) &&
+	    !IS_CARD9097(pmpriv->adapter->card_type))
+		return ret;
+	/** check band A */
+	if (!(pbss_desc->bss_band & BAND_A))
+		return ret;
+
+	/** check band A antenna setting */
+	rx_nss = GET_RXMCSSUPP(pmpriv->adapter->user_htstream >> 8);
+	tx_nss = GET_TXMCSSUPP(pmpriv->adapter->user_htstream >> 8) & 0x0f;
+	/** check if support 2*2 */
+	if (rx_nss != 2 || tx_nss != 2)
+		return ret;
+	/** check if AP support AC 80P80 */
+	if (ISSUPP_11ACBW8080(pmpriv->usr_dot_11ac_dev_cap_a) && pvht_cap &&
+	    ISSUPP_11ACBW8080(pvht_cap->vht_cap.vht_cap_info))
+		ret = MTRUE;
+	/** check if AP support AX 80P80 */
+	if (pbss_desc->phe_cap) {
+		pBsshecap = (IEEEtypes_HECap_t *) pbss_desc->phe_cap;
+		phecap = (MrvlIEtypes_He_cap_t *) pmpriv->user_he_cap;
+		if (ret && (phecap->he_phy_cap[0] & MBIT(4)) &&
+		    (pBsshecap->he_phy_cap[0] & MBIT(4)))
+			ret = MTRUE;
+		else
+			ret = MFALSE;
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function append the 802_11N tlv
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *  @param ppbuffer     A Pointer to command buffer pointer
+ *
+ *  @return bytes added to the buffer
+ */
+int
+wlan_cmd_append_11ac_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+			 t_u8 **ppbuffer)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIETypes_VHTCap_t *pvht_cap;
+	MrvlIETypes_OperModeNtf_t *pmrvl_oper_mode;
+	t_u16 mcs_map_user = 0;
+	t_u16 nss;
+	int ret_len = 0;
+	t_u8 bw_80p80 = MFALSE;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	t_u16 rx_nss = 0;
+#endif
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	/* VHT Capabilities IE */
+	if (pbss_desc->pvht_cap &&
+	    wlan_get_nss_vht_mcs(pbss_desc->pvht_cap->vht_cap.mcs_sets.
+				 rx_mcs_map)) {
+		pvht_cap = (MrvlIETypes_VHTCap_t *)*ppbuffer;
+		memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
+		pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
+		pvht_cap->header.len = sizeof(VHT_capa_t);
+		memcpy_ext(pmadapter,
+			   (t_u8 *)pvht_cap + sizeof(MrvlIEtypesHeader_t),
+			   (t_u8 *)pbss_desc->pvht_cap +
+			   sizeof(IEEEtypes_Header_t),
+			   pvht_cap->header.len, sizeof(VHT_capa_t));
+		bw_80p80 = wlan_is_80_80_support(pmpriv, pbss_desc);
+		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pbss_desc->bss_band,
+				      MTRUE, bw_80p80);
+
+		HEXDUMP("VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+			sizeof(MrvlIETypes_VHTCap_t));
+		*ppbuffer += sizeof(MrvlIETypes_VHTCap_t);
+		ret_len += sizeof(MrvlIETypes_VHTCap_t);
+		pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
+	} else {
+		LEAVE();
+		return 0;
+	}
+
+	/* Operating Mode Notification IE */
+	pmrvl_oper_mode = (MrvlIETypes_OperModeNtf_t *)*ppbuffer;
+	memset(pmadapter, pmrvl_oper_mode, 0,
+	       sizeof(MrvlIETypes_OperModeNtf_t));
+	pmrvl_oper_mode->header.type = wlan_cpu_to_le16(OPER_MODE_NTF);
+	pmrvl_oper_mode->header.len = sizeof(t_u8);
+
+	if (pmpriv->usr_dot_11ac_opermode_bw ||
+	    pmpriv->usr_dot_11ac_opermode_nss) {
+		pmrvl_oper_mode->oper_mode |=
+			(pmpriv->usr_dot_11ac_opermode_nss - 1) << 4;
+		pmrvl_oper_mode->oper_mode |=
+			pmpriv->usr_dot_11ac_opermode_bw - 1;
+		if (pbss_desc->bss_band & BAND_G) {
+			if (!(IS_OPER_MODE_20M(pmrvl_oper_mode->oper_mode))) {
+				if (pbss_desc->pht_cap->ht_cap.ht_cap_info &
+				    MBIT(1))
+					SET_OPER_MODE_40M(pmrvl_oper_mode->
+							  oper_mode);
+				else
+					SET_OPER_MODE_20M(pmrvl_oper_mode->
+							  oper_mode);
+			}
+		}
+	} else {
+		/** set default bandwidth:80M*/
+		SET_OPER_MODE_80M(pmrvl_oper_mode->oper_mode);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if (IS_CARD9098(pmadapter->card_type) ||
+		    IS_CARD9097(pmadapter->card_type)) {
+			if (pbss_desc->bss_band & BAND_A)
+				rx_nss = GET_RXMCSSUPP(pmadapter->
+						       user_htstream >> 8);
+			else
+				rx_nss = GET_RXMCSSUPP(pmadapter->
+						       user_htstream);
+		}
+#endif
+		mcs_map_user =
+			GET_DEVRXMCSMAP(pmpriv->usr_dot_11ac_mcs_support);
+		nss = wlan_get_nss_num_vht_mcs(mcs_map_user);
+
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if (IS_CARD9098(pmadapter->card_type) ||
+		    IS_CARD9097(pmadapter->card_type)) {
+			PRINTM(MCMND, "rx_nss=%d nss=%d\n", rx_nss, nss);
+			nss = MIN(rx_nss, nss);
+		}
+#endif
+
+		pmrvl_oper_mode->oper_mode |= (nss - 1) << 4;
+
+		switch (pbss_desc->curr_bandwidth) {
+		case BW_20MHZ:
+			SET_OPER_MODE_20M(pmrvl_oper_mode->oper_mode);
+			break;
+		case BW_40MHZ:
+			SET_OPER_MODE_40M(pmrvl_oper_mode->oper_mode);
+			break;
+		case BW_80MHZ:
+		default:
+			break;
+		}
+	}
+	HEXDUMP("OPER MODE NTF IE", (t_u8 *)pmrvl_oper_mode,
+		sizeof(MrvlIETypes_OperModeNtf_t));
+	*ppbuffer += sizeof(MrvlIETypes_OperModeNtf_t);
+	ret_len += sizeof(MrvlIETypes_OperModeNtf_t);
+	pmrvl_oper_mode->header.len =
+		wlan_cpu_to_le16(pmrvl_oper_mode->header.len);
+
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief 11ac configuration handler
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11ac_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11ac_cfg *cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11ac_cfg)) {
+		PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11ac_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
+	switch (cfg->sub_command) {
+	case MLAN_OID_11AC_VHT_CFG:
+		status = wlan_11ac_ioctl_vhtcfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11AC_CFG_SUPPORTED_MCS_SET:
+		status = wlan_11ac_ioctl_supported_mcs_set(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_11AC_OPERMODE_CFG:
+		status = wlan_11ac_ioctl_opermodecfg(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function prepares 11ac cfg command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11ac_cfg(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_11AC_CFG *vhtcfg = &cmd->params.vhtcfg;
+	mlan_ds_11ac_vht_cfg *vht_cfg = (mlan_ds_11ac_vht_cfg *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AC_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11AC_CFG) + S_DS_GEN);
+	vhtcfg->action = wlan_cpu_to_le16(cmd_action);
+	vhtcfg->band_config = vht_cfg->band & 0xFF;
+	// block user enable 80MHZ
+	if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+		vht_cfg->bwcfg = 0;
+
+	vhtcfg->misc_config = vht_cfg->txrx & 0x3;
+	if (vhtcfg->misc_config != 2)
+		vhtcfg->misc_config |= (vht_cfg->bwcfg << 2);
+
+	vhtcfg->vht_cap_info = wlan_cpu_to_le32(vht_cfg->vht_cap_info);
+	vht_cfg->vht_rx_mcs = wlan_cpu_to_le32(vht_cfg->vht_rx_mcs);
+	memcpy_ext(pmadapter, &vhtcfg->vht_supp_mcs_set[0],
+		   &vht_cfg->vht_rx_mcs, sizeof(t_u32), sizeof(t_u32));
+	vht_cfg->vht_tx_mcs = wlan_cpu_to_le32(vht_cfg->vht_tx_mcs);
+	memcpy_ext(pmadapter, &vhtcfg->vht_supp_mcs_set[4],
+		   &vht_cfg->vht_tx_mcs, sizeof(t_u32), sizeof(t_u32));
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11accfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11ac_cfg(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	mlan_ds_11ac_cfg *cfg = MNULL;
+	HostCmd_DS_11AC_CFG *vhtcfg = &resp->params.vhtcfg;
+
+	ENTER();
+	if (pioctl_buf &&
+	    (wlan_le16_to_cpu(vhtcfg->action) == HostCmd_ACT_GEN_GET)) {
+		cfg = (mlan_ds_11ac_cfg *)pioctl_buf->pbuf;
+		cfg->param.vht_cfg.band = vhtcfg->band_config;
+		cfg->param.vht_cfg.txrx = vhtcfg->misc_config & 0x03;
+		if (cfg->param.vht_cfg.txrx & 0x1)
+			cfg->param.vht_cfg.bwcfg =
+				(vhtcfg->misc_config & 0x04) >> 2;
+		else
+			cfg->param.vht_cfg.bwcfg = 0;
+
+		cfg->param.vht_cfg.vht_cap_info =
+			wlan_le32_to_cpu(vhtcfg->vht_cap_info);
+		memcpy_ext(pmadapter, &cfg->param.vht_cfg.vht_rx_mcs,
+			   &vhtcfg->vht_supp_mcs_set[0], sizeof(t_u32),
+			   sizeof(t_u32));
+		cfg->param.vht_cfg.vht_rx_mcs =
+			wlan_le32_to_cpu(cfg->param.vht_cfg.vht_rx_mcs);
+		memcpy_ext(pmadapter, &cfg->param.vht_cfg.vht_tx_mcs,
+			   &vhtcfg->vht_supp_mcs_set[4], sizeof(t_u32),
+			   sizeof(t_u32));
+		cfg->param.vht_cfg.vht_tx_mcs =
+			wlan_le32_to_cpu(cfg->param.vht_cfg.vht_tx_mcs);
+		cfg->param.vht_cfg.vht_rx_max_rate =
+			wlan_convert_mcsmap_to_maxrate(pmpriv,
+						       cfg->param.vht_cfg.band,
+						       cfg->param.vht_cfg.
+						       vht_rx_mcs);
+		cfg->param.vht_cfg.vht_tx_max_rate =
+			wlan_convert_mcsmap_to_maxrate(pmpriv,
+						       cfg->param.vht_cfg.band,
+						       cfg->param.vht_cfg.
+						       vht_tx_mcs);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+void
+wlan_update_11ac_cap(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	pmpriv->usr_dot_11ac_mcs_support = pmadapter->hw_dot_11ac_mcs_support;
+	pmpriv->usr_dot_11ac_dev_cap_bg =
+		pmadapter->hw_dot_11ac_dev_cap &
+		~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
+	pmpriv->usr_dot_11ac_dev_cap_a =
+		pmadapter->hw_dot_11ac_dev_cap &
+		~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
+	pmpriv->usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+}
+
+/**
+ *  @brief This function check if 11AC is allowed in bandcfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param bss_band     bss band
+ *
+ *  @return 0--not allowed, other value allowed
+ */
+t_u8
+wlan_11ac_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band)
+{
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if (bss_band & BAND_G)
+			return (pmpriv->adapter->adhoc_start_band & BAND_GAC);
+		else if (bss_band & BAND_A)
+			return (pmpriv->adapter->adhoc_start_band & BAND_AAC);
+	} else {
+		if (bss_band & BAND_G)
+			return (pmpriv->config_bands & BAND_GAC);
+		else if (bss_band & BAND_A)
+			return (pmpriv->config_bands & BAND_AAC);
+	}
+	return 0;
+}
diff --git a/wlan_sd8987/mlan/mlan_11ac.h b/wlan_sd8987/mlan/mlan_11ac.h
new file mode 100755
index 0000000..d143aeb
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11ac.h
@@ -0,0 +1,58 @@
+/** @file mlan_11ac.h
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *
+ *  Copyright 2011-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+#ifndef _MLAN_11AC_H_
+#define _MLAN_11AC_H_
+
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#include "mlan_wmm.h"
+
+void wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap);
+void wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support);
+t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u16 bands,
+				     t_u16 mcs_map);
+void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap,
+			   t_u16 bands, t_u8 flag, t_u8 bw_80p80);
+void wlan_fill_vht_cap_ie(mlan_private *priv, IEEEtypes_VHTCap_t *pvht_cap,
+			  t_u16 bands);
+void wlan_fill_tdls_vht_oprat_ie(mlan_private *priv,
+				 IEEEtypes_VHTOprat_t *vht_oprat,
+				 sta_node *sta_ptr);
+t_u8 wlan_is_ap_in_11ac_mode(mlan_private *priv);
+int wlan_cmd_append_11ac_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+			     t_u8 **ppbuffer);
+mlan_status wlan_11ac_cfg_ioctl(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req);
+void wlan_update_11ac_cap(mlan_private *pmpriv);
+t_u8 wlan_11ac_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band);
+t_u8 wlan_is_80_80_support(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc);
+
+mlan_status wlan_cmd_11ac_cfg(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			      t_void *pdata_buf);
+
+mlan_status wlan_ret_11ac_cfg(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AC_H_ */
diff --git a/wlan_sd8987/mlan/mlan_11ax.c b/wlan_sd8987/mlan/mlan_11ax.c
new file mode 100755
index 0000000..cb4bbfb
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11ax.c
@@ -0,0 +1,1021 @@
+/** @file mlan_11ax.c
+ *
+ *  @brief This file contains the functions for 11ax related features.
+ *
+ *
+ *  Copyright 2018-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_ioctl.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ax.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+#if 0
+/**
+ *  @brief This function prints the 802.11ax HE mac capability
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *  @param cap           Capability value
+ *
+ *  @return        N/A
+ */
+static void
+wlan_show_dot11axmaccap(pmlan_adapter pmadapter, t_u32 cap)
+{
+	ENTER();
+
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function check if AP support TWT Response.
+ *
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *
+ *  @return        MTRUE/MFALSE
+ */
+static t_u8
+wlan_check_ap_11ax_twt_supported(BSSDescriptor_t *pbss_desc)
+{
+	if (!pbss_desc->phe_cap)
+		return MFALSE;
+	if (!(pbss_desc->phe_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT))
+		return MFALSE;
+	if (!pbss_desc->pext_cap)
+		return MFALSE;
+	if (!ISSUPP_EXTCAP_EXT_TWT_RESP(pbss_desc->pext_cap->ext_cap))
+		return MFALSE;
+	return MTRUE;
+}
+
+/**
+ *  @brief This function check if we should enable TWT support
+ *
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *
+ *  @return        MTRUE/MFALSE
+ */
+t_u8
+wlan_check_11ax_twt_supported(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+	MrvlIEtypes_He_cap_t *phecap =
+		(MrvlIEtypes_He_cap_t *) & pmpriv->user_he_cap;
+	MrvlIEtypes_He_cap_t *hw_he_cap = (MrvlIEtypes_He_cap_t *)
+		& pmpriv->adapter->hw_he_cap;
+	if (pbss_desc && !wlan_check_ap_11ax_twt_supported(pbss_desc)) {
+		PRINTM(MINFO, "AP don't support twt feature\n");
+		return MFALSE;
+	}
+	if (pbss_desc) {
+		if (pbss_desc->bss_band & BAND_A) {
+			hw_he_cap = (MrvlIEtypes_He_cap_t *)
+				& pmpriv->adapter->hw_he_cap;
+			phecap = (MrvlIEtypes_He_cap_t *) & pmpriv->user_he_cap;
+		} else {
+			hw_he_cap = (MrvlIEtypes_He_cap_t *)
+				& pmpriv->adapter->hw_2g_he_cap;
+			phecap = (MrvlIEtypes_He_cap_t *)
+				& pmpriv->user_2g_he_cap;
+		}
+	}
+	if (!(hw_he_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT)) {
+		PRINTM(MINFO, "FW don't support TWT\n");
+		return MFALSE;
+	}
+	if (phecap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT)
+		return MTRUE;
+	PRINTM(MINFO, "USER HE_MAC_CAP don't support TWT\n");
+	return MFALSE;
+}
+
+#if 0
+/**
+ *  @brief This function prints the 802.11ax HE PHY cap
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param support   Support value
+ *
+ *  @return        N/A
+ */
+static void
+wlan_show_dot11axphycap(pmlan_adapter pmadapter, t_u32 support)
+{
+	ENTER();
+
+	LEAVE();
+	return;
+}
+#endif
+/**
+ *  @brief This function fills the HE cap tlv out put format is LE, not CPU
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param band         5G or 2.4 G
+ *  @param phe_cap      A pointer to MrvlIEtypes_Data_t structure
+ *  @param flag         TREU--pvht_cap has the setting for resp
+ *                            MFALSE -- pvht_cap is clean
+ *
+ *  @return bytes added to the phe_cap
+ */
+t_u16
+wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band,
+		     MrvlIEtypes_Extension_t * phe_cap, t_u8 flag)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u16 len = 0;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	t_u16 rx_nss = 0, tx_nss = 0;
+#endif
+	MrvlIEtypes_He_cap_t *phecap = MNULL;
+	t_u8 nss = 0;
+	t_u16 cfg_value = 0;
+	t_u16 hw_value = 0;
+	MrvlIEtypes_He_cap_t *phw_hecap = MNULL;
+
+	if (!phe_cap) {
+		LEAVE();
+		return 0;
+	}
+	if (band & BAND_A) {
+		memcpy_ext(pmadapter, (t_u8 *)phe_cap, pmpriv->user_he_cap,
+			   pmpriv->user_hecap_len,
+			   sizeof(MrvlIEtypes_He_cap_t));
+		len = pmpriv->user_hecap_len;
+		phw_hecap = (MrvlIEtypes_He_cap_t *) pmadapter->hw_he_cap;
+	} else {
+		memcpy_ext(pmadapter, (t_u8 *)phe_cap, pmpriv->user_2g_he_cap,
+			   pmpriv->user_2g_hecap_len,
+			   sizeof(MrvlIEtypes_He_cap_t));
+		len = pmpriv->user_2g_hecap_len;
+		phw_hecap = (MrvlIEtypes_He_cap_t *) pmadapter->hw_2g_he_cap;
+	}
+	phe_cap->type = wlan_cpu_to_le16(phe_cap->type);
+	phe_cap->len = wlan_cpu_to_le16(phe_cap->len);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	if (IS_CARD9098(pmpriv->adapter->card_type) ||
+	    IS_CARD9097(pmpriv->adapter->card_type)) {
+		if (band & BAND_A) {
+			rx_nss = GET_RXMCSSUPP(pmpriv->adapter->user_htstream >>
+					       8);
+			tx_nss = GET_TXMCSSUPP(pmpriv->adapter->user_htstream >>
+					       8) & 0x0f;
+		} else {
+			rx_nss = GET_RXMCSSUPP(pmpriv->adapter->user_htstream);
+			tx_nss = GET_TXMCSSUPP(pmpriv->adapter->user_htstream) &
+				0x0f;
+		}
+	}
+#endif
+	phecap = (MrvlIEtypes_He_cap_t *) phe_cap;
+	for (nss = 1; nss <= 8; nss++) {
+		cfg_value = GET_HE_NSSMCS(phecap->rx_mcs_80, nss);
+		hw_value = GET_HE_NSSMCS(phw_hecap->rx_mcs_80, nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if ((rx_nss != 0) && (nss > rx_nss))
+			cfg_value = NO_NSS_SUPPORT;
+#endif
+		if ((hw_value == NO_NSS_SUPPORT) ||
+		    (cfg_value == NO_NSS_SUPPORT))
+			SET_HE_NSSMCS(phecap->rx_mcs_80, nss, NO_NSS_SUPPORT);
+		else
+			SET_HE_NSSMCS(phecap->rx_mcs_80,
+				      nss, MIN(cfg_value, hw_value));
+	}
+	for (nss = 1; nss <= 8; nss++) {
+		cfg_value = GET_HE_NSSMCS(phecap->tx_mcs_80, nss);
+		hw_value = GET_HE_NSSMCS(phw_hecap->tx_mcs_80, nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if ((tx_nss != 0) && (nss > tx_nss))
+			cfg_value = NO_NSS_SUPPORT;
+#endif
+		if ((hw_value == NO_NSS_SUPPORT) ||
+		    (cfg_value == NO_NSS_SUPPORT))
+			SET_HE_NSSMCS(phecap->tx_mcs_80, nss, NO_NSS_SUPPORT);
+		else
+			SET_HE_NSSMCS(phecap->tx_mcs_80,
+				      nss, MIN(cfg_value, hw_value));
+	}
+	PRINTM(MCMND, "Set: HE rx mcs set 0x%08x tx mcs set 0x%08x\n",
+	       phecap->rx_mcs_80, phecap->tx_mcs_80);
+
+	DBG_HEXDUMP(MCMD_D, "fill_11ax_tlv", (t_u8 *)phecap, len);
+	LEAVE();
+	return len;
+}
+
+/**
+ *  @brief This function append the 802_11ax HE capability  tlv
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *  @param ppbuffer     A Pointer to command buffer pointer
+ *
+ *  @return bytes added to the buffer
+ */
+int
+wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+			 t_u8 **ppbuffer)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIEtypes_He_cap_t *phecap = MNULL;
+	int len = 0;
+	t_u8 bw_80p80 = MFALSE;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	t_u16 rx_nss = 0, tx_nss = 0;
+#endif
+	t_u8 nss = 0;
+	t_u16 cfg_value = 0;
+	t_u16 hw_value = 0;
+	MrvlIEtypes_He_cap_t *phw_hecap = MNULL;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	/** check if AP support HE, if not return right away */
+	if (!pbss_desc->phe_cap) {
+		LEAVE();
+		return 0;
+	}
+	bw_80p80 = wlan_is_80_80_support(pmpriv, pbss_desc);
+	phecap = (MrvlIEtypes_He_cap_t *) * ppbuffer;
+	if (pbss_desc->bss_band & BAND_A) {
+		memcpy_ext(pmadapter, *ppbuffer, pmpriv->user_he_cap,
+			   pmpriv->user_hecap_len, pmpriv->user_hecap_len);
+		*ppbuffer += pmpriv->user_hecap_len;
+		len = pmpriv->user_hecap_len;
+		phw_hecap = (MrvlIEtypes_He_cap_t *) pmadapter->hw_he_cap;
+	} else {
+		memcpy_ext(pmadapter, *ppbuffer, pmpriv->user_2g_he_cap,
+			   pmpriv->user_2g_hecap_len,
+			   pmpriv->user_2g_hecap_len);
+		*ppbuffer += pmpriv->user_2g_hecap_len;
+		len = pmpriv->user_2g_hecap_len;
+		phw_hecap = (MrvlIEtypes_He_cap_t *) pmadapter->hw_2g_he_cap;
+	}
+	phecap->type = wlan_cpu_to_le16(phecap->type);
+	phecap->len = wlan_cpu_to_le16(phecap->len);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	if (IS_CARD9098(pmpriv->adapter->card_type) ||
+	    IS_CARD9097(pmpriv->adapter->card_type)) {
+		if (pbss_desc->bss_band & BAND_A) {
+			rx_nss = GET_RXMCSSUPP(pmpriv->adapter->user_htstream >>
+					       8);
+			tx_nss = GET_TXMCSSUPP(pmpriv->adapter->user_htstream >>
+					       8) & 0x0f;
+		} else {
+			rx_nss = GET_RXMCSSUPP(pmpriv->adapter->user_htstream);
+			tx_nss = GET_TXMCSSUPP(pmpriv->adapter->user_htstream) &
+				0x0f;
+		}
+		/** force 1x1 when enable 80P80 */
+		if (bw_80p80)
+			rx_nss = tx_nss = 1;
+	}
+#endif
+	for (nss = 1; nss <= 8; nss++) {
+		cfg_value = GET_HE_NSSMCS(phecap->rx_mcs_80, nss);
+		hw_value = GET_HE_NSSMCS(phw_hecap->rx_mcs_80, nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if ((rx_nss != 0) && (nss > rx_nss))
+			cfg_value = NO_NSS_SUPPORT;
+#endif
+		if ((hw_value == NO_NSS_SUPPORT) ||
+		    (cfg_value == NO_NSS_SUPPORT))
+			SET_HE_NSSMCS(phecap->rx_mcs_80, nss, NO_NSS_SUPPORT);
+		else
+			SET_HE_NSSMCS(phecap->rx_mcs_80,
+				      nss, MIN(cfg_value, hw_value));
+	}
+	for (nss = 1; nss <= 8; nss++) {
+		cfg_value = GET_HE_NSSMCS(phecap->tx_mcs_80, nss);
+		hw_value = GET_HE_NSSMCS(phw_hecap->tx_mcs_80, nss);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if ((tx_nss != 0) && (nss > tx_nss))
+			cfg_value = NO_NSS_SUPPORT;
+#endif
+		if ((hw_value == NO_NSS_SUPPORT) ||
+		    (cfg_value == NO_NSS_SUPPORT))
+			SET_HE_NSSMCS(phecap->tx_mcs_80, nss, NO_NSS_SUPPORT);
+		else
+			SET_HE_NSSMCS(phecap->tx_mcs_80,
+				      nss, MIN(cfg_value, hw_value));
+	}
+	PRINTM(MCMND, "Set: HE rx mcs set 0x%08x tx mcs set 0x%08x\n",
+	       phecap->rx_mcs_80, phecap->tx_mcs_80);
+	if (!bw_80p80) {
+		/** reset BIT3 and BIT4 channel width ,not support 80 + 80*/
+		/** not support 160Mhz now, if support,not reset bit3 */
+		phecap->he_phy_cap[0] &= ~(MBIT(3) | MBIT(4));
+	}
+	DBG_HEXDUMP(MCMD_D, "append_11ax_tlv", (t_u8 *)phecap, len);
+
+	LEAVE();
+	return len;
+}
+
+/**
+ *  @brief This function save the 11ax cap from FW.
+ *
+ *  @param pmadapater   A pointer to mlan_adapter
+ *  @param hw_he_cap    A pointer to MrvlIEtypes_Extension_t
+ *
+ *  @return N/A
+ */
+void
+wlan_update_11ax_cap(mlan_adapter *pmadapter,
+		     MrvlIEtypes_Extension_t * hw_he_cap)
+{
+	MrvlIEtypes_He_cap_t *phe_cap = MNULL;
+	t_u8 i = 0;
+	t_u8 he_cap_2g = 0;
+
+	ENTER();
+	if ((hw_he_cap->len + sizeof(MrvlIEtypesHeader_t)) >
+	    sizeof(pmadapter->hw_he_cap)) {
+		PRINTM(MERROR, "hw_he_cap too big, len=%d\n", hw_he_cap->len);
+		LEAVE();
+		return;
+	}
+	phe_cap = (MrvlIEtypes_He_cap_t *) hw_he_cap;
+	if (phe_cap->he_phy_cap[0] &
+	    (AX_2G_40MHZ_SUPPORT | AX_2G_20MHZ_SUPPORT)) {
+		pmadapter->hw_2g_hecap_len =
+			hw_he_cap->len + sizeof(MrvlIEtypesHeader_t);
+		memcpy_ext(pmadapter, pmadapter->hw_2g_he_cap,
+			   (t_u8 *)hw_he_cap,
+			   hw_he_cap->len + sizeof(MrvlIEtypesHeader_t),
+			   sizeof(pmadapter->hw_2g_he_cap));
+		pmadapter->fw_bands |= BAND_GAX;
+		pmadapter->config_bands |= BAND_GAX;
+		he_cap_2g = MTRUE;
+		DBG_HEXDUMP(MCMD_D, "2.4G HE capability IE ",
+			    (t_u8 *)pmadapter->hw_2g_he_cap,
+			    pmadapter->hw_2g_hecap_len);
+	} else {
+		pmadapter->fw_bands |= BAND_AAX;
+		pmadapter->config_bands |= BAND_AAX;
+		pmadapter->hw_hecap_len =
+			hw_he_cap->len + sizeof(MrvlIEtypesHeader_t);
+		memcpy_ext(pmadapter, pmadapter->hw_he_cap, (t_u8 *)hw_he_cap,
+			   hw_he_cap->len + sizeof(MrvlIEtypesHeader_t),
+			   sizeof(pmadapter->hw_he_cap));
+		DBG_HEXDUMP(MCMD_D, "5G HE capability IE ",
+			    (t_u8 *)pmadapter->hw_he_cap,
+			    pmadapter->hw_hecap_len);
+	}
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			pmadapter->priv[i]->config_bands =
+				pmadapter->config_bands;
+			if (he_cap_2g) {
+				pmadapter->priv[i]->user_2g_hecap_len =
+					pmadapter->hw_2g_hecap_len;
+				memcpy_ext(pmadapter,
+					   pmadapter->priv[i]->user_2g_he_cap,
+					   pmadapter->hw_2g_he_cap,
+					   pmadapter->hw_2g_hecap_len,
+					   sizeof(pmadapter->priv[i]
+						  ->user_2g_he_cap));
+			} else {
+				pmadapter->priv[i]->user_hecap_len =
+					pmadapter->hw_hecap_len;
+				memcpy_ext(pmadapter,
+					   pmadapter->priv[i]->user_he_cap,
+					   pmadapter->hw_he_cap,
+					   pmadapter->hw_hecap_len,
+					   sizeof(pmadapter->priv[i]->
+						  user_he_cap));
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function check if 11AX is allowed in bandcfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param bss_band     bss band
+ *
+ *  @return 0--not allowed, other value allowed
+ */
+t_u16
+wlan_11ax_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band)
+{
+	if (!IS_FW_SUPPORT_11AX(pmpriv->adapter))
+		return MFALSE;
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if (bss_band & BAND_G)
+			return (pmpriv->adapter->adhoc_start_band & BAND_GAX);
+		else if (bss_band & BAND_A)
+			return (pmpriv->adapter->adhoc_start_band & BAND_AAX);
+	} else {
+		if (bss_band & BAND_G)
+			return (pmpriv->config_bands & BAND_GAX);
+		else if (bss_band & BAND_A)
+			return (pmpriv->config_bands & BAND_AAX);
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief Set 11ax configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11ax_ioctl_hecfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11ax_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11ax_cfg)) {
+		PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11ax_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	cfg = (mlan_ds_11ax_cfg *) pioctl_req->pbuf;
+
+	if ((cfg->param.he_cfg.band & MBIT(0)) &&
+	    !(pmadapter->fw_bands & BAND_GAX)) {
+		PRINTM(MERROR, "FW don't support 2.4G AX\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if ((cfg->param.he_cfg.band & MBIT(1)) &&
+	    !(pmadapter->fw_bands & BAND_AAX)) {
+		PRINTM(MERROR, "FW don't support 5G AX\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AX_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.he_cfg);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 11ax configuration handler
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11ax_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11ax_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11ax_cfg *) pioctl_req->pbuf;
+	switch (cfg->sub_command) {
+	case MLAN_OID_11AX_HE_CFG:
+		status = wlan_11ax_ioctl_hecfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11AX_CMD_CFG:
+		status = wlan_11ax_ioctl_cmd(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11AX_TWT_CFG:
+		status = wlan_11ax_ioctl_twtcfg(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function prepares 11ax cfg command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11ax_cfg(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_11AX_CFG *axcfg = &cmd->params.axcfg;
+	mlan_ds_11ax_he_cfg *hecfg = (mlan_ds_11ax_he_cfg *) pdata_buf;
+	MrvlIEtypes_Extension_t *tlv = MNULL;
+	t_u8 *pos = MNULL;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AX_CFG);
+	cmd->size = sizeof(HostCmd_DS_11AX_CFG) + S_DS_GEN;
+
+	axcfg->action = wlan_cpu_to_le16(cmd_action);
+	axcfg->band_config = hecfg->band & 0xFF;
+
+	pos = (t_u8 *)axcfg->val;
+	/**HE Capability */
+	if (hecfg->he_cap.len && (hecfg->he_cap.ext_id == HE_CAPABILITY)) {
+		tlv = (MrvlIEtypes_Extension_t *) pos;
+		tlv->type = wlan_cpu_to_le16(hecfg->he_cap.id);
+		tlv->len = wlan_cpu_to_le16(hecfg->he_cap.len);
+		memcpy_ext(pmadapter, &tlv->ext_id, &hecfg->he_cap.ext_id,
+			   hecfg->he_cap.len,
+			   MRVDRV_SIZE_OF_CMD_BUFFER - cmd->size);
+		cmd->size += hecfg->he_cap.len + sizeof(MrvlIEtypesHeader_t);
+		pos += hecfg->he_cap.len + sizeof(MrvlIEtypesHeader_t);
+	}
+
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11axcfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11ax_cfg(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	mlan_ds_11ax_cfg *cfg = MNULL;
+	mlan_ds_11ax_he_capa *hecap = MNULL;
+	HostCmd_DS_11AX_CFG *axcfg = &resp->params.axcfg;
+	MrvlIEtypes_Extension_t *tlv = MNULL;
+	t_u16 left_len = 0, tlv_type = 0, tlv_len = 0;
+
+	ENTER();
+
+	if (pioctl_buf == MNULL)
+		goto done;
+
+	cfg = (mlan_ds_11ax_cfg *) pioctl_buf->pbuf;
+	cfg->param.he_cfg.band = axcfg->band_config;
+	hecap = (mlan_ds_11ax_he_capa *) & cfg->param.he_cfg.he_cap;
+
+	/* TLV parse */
+	left_len = resp->size - sizeof(HostCmd_DS_11AX_CFG) - S_DS_GEN;
+	tlv = (MrvlIEtypes_Extension_t *) axcfg->val;
+
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if (tlv_type == EXTENSION) {
+			switch (tlv->ext_id) {
+			case HE_CAPABILITY:
+				hecap->id = tlv_type;
+				hecap->len = tlv_len;
+				memcpy_ext(pmadapter, (t_u8 *)&hecap->ext_id,
+					   (t_u8 *)&tlv->ext_id, tlv_len,
+					   sizeof(mlan_ds_11ax_he_capa) -
+					   sizeof(MrvlIEtypesHeader_t));
+				if (cfg->param.he_cfg.band & MBIT(1)) {
+					memcpy_ext(pmadapter,
+						   (t_u8 *)&pmpriv->user_he_cap,
+						   (t_u8 *)tlv,
+						   tlv_len +
+						   sizeof(MrvlIEtypesHeader_t),
+						   sizeof(pmpriv->user_he_cap));
+					pmpriv->user_hecap_len = MIN(tlv_len +
+								     sizeof
+								     (MrvlIEtypesHeader_t),
+								     sizeof
+								     (pmpriv->
+								      user_he_cap));
+					PRINTM(MCMND, "user_hecap_len=%d\n",
+					       pmpriv->user_hecap_len);
+				} else {
+					memcpy_ext(pmadapter,
+						   (t_u8 *)&pmpriv->
+						   user_2g_he_cap, (t_u8 *)tlv,
+						   tlv_len +
+						   sizeof(MrvlIEtypesHeader_t),
+						   sizeof(pmpriv->
+							  user_2g_he_cap));
+					pmpriv->user_2g_hecap_len =
+						MIN(tlv_len +
+						    sizeof(MrvlIEtypesHeader_t),
+						    sizeof(pmpriv->
+							   user_2g_he_cap));
+					PRINTM(MCMND, "user_2g_hecap_len=%d\n",
+					       pmpriv->user_2g_hecap_len);
+				}
+				break;
+			default:
+				break;
+			}
+		}
+
+		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypes_Extension_t *) ((t_u8 *)tlv + tlv_len +
+						   sizeof(MrvlIEtypesHeader_t));
+	}
+
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief 11ax command handler
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11ax_ioctl_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11ax_cmd_cfg *cfg = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11ax_cmd_cfg)) {
+		PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11ax_cmd_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	cfg = (mlan_ds_11ax_cmd_cfg *) pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	status = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AX_CMD, cmd_action, 0,
+				  (t_void *)pioctl_req, (t_void *)cfg);
+	if (status == MLAN_STATUS_SUCCESS)
+		status = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function prepares 11ax command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11ax_cmd(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_11AX_CMD_CFG *axcmd = &cmd->params.axcmd;
+	mlan_ds_11ax_cmd_cfg *ds_11ax_cmd = (mlan_ds_11ax_cmd_cfg *) pdata_buf;
+	mlan_ds_11ax_sr_cmd *sr_cmd =
+		(mlan_ds_11ax_sr_cmd *) & ds_11ax_cmd->param;
+	mlan_ds_11ax_beam_cmd *beam_cmd =
+		(mlan_ds_11ax_beam_cmd *) & ds_11ax_cmd->param;
+	mlan_ds_11ax_htc_cmd *htc_cmd =
+		(mlan_ds_11ax_htc_cmd *) & ds_11ax_cmd->param;
+	mlan_ds_11ax_txop_cmd *txop_cmd =
+		(mlan_ds_11ax_txop_cmd *) & ds_11ax_cmd->param;
+	mlan_ds_11ax_txomi_cmd *txomi_cmd =
+		(mlan_ds_11ax_txomi_cmd *) & ds_11ax_cmd->param;
+	mlan_ds_11ax_toltime_cmd *toltime_cmd =
+		(mlan_ds_11ax_toltime_cmd *) & ds_11ax_cmd->param;
+	MrvlIEtypes_Data_t *tlv = MNULL;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AX_CMD);
+	cmd->size = sizeof(HostCmd_DS_11AX_CMD_CFG) + S_DS_GEN;
+
+	axcmd->action = wlan_cpu_to_le16(cmd_action);
+	axcmd->sub_id = wlan_cpu_to_le16(ds_11ax_cmd->sub_id);
+	switch (ds_11ax_cmd->sub_id) {
+	case MLAN_11AXCMD_SR_SUBID:
+		tlv = (MrvlIEtypes_Data_t *)axcmd->val;
+		tlv->header.type = wlan_cpu_to_le16(sr_cmd->type);
+		tlv->header.len = wlan_cpu_to_le16(sr_cmd->len);
+		memcpy_ext(pmadapter, tlv->data,
+			   &sr_cmd->param.obss_pd_offset.offset, sr_cmd->len,
+			   sr_cmd->len);
+		cmd->size += sizeof(MrvlIEtypesHeader_t) + sr_cmd->len;
+		break;
+	case MLAN_11AXCMD_BEAM_SUBID:
+		axcmd->val[0] = beam_cmd->value;
+		cmd->size += sizeof(t_u8);
+		break;
+	case MLAN_11AXCMD_HTC_SUBID:
+		axcmd->val[0] = htc_cmd->value;
+		cmd->size += sizeof(t_u8);
+		break;
+	case MLAN_11AXCMD_TXOPRTS_SUBID:
+		memcpy_ext(pmadapter, axcmd->val, &txop_cmd->rts_thres,
+			   sizeof(t_u16), sizeof(t_u16));
+		cmd->size += sizeof(t_u16);
+		break;
+	case MLAN_11AXCMD_TXOMI_SUBID:
+		memcpy_ext(pmadapter, axcmd->val, &txomi_cmd->omi,
+			   sizeof(t_u16), sizeof(t_u16));
+		cmd->size += sizeof(t_u16);
+		break;
+	case MLAN_11AXCMD_OBSS_TOLTIME_SUBID:
+		memcpy_ext(pmadapter, axcmd->val, &toltime_cmd->tol_time,
+			   sizeof(t_u32), sizeof(t_u32));
+		cmd->size += sizeof(t_u32);
+		break;
+	default:
+		PRINTM(MERROR, "Unknown subcmd %x\n", ds_11ax_cmd->sub_id);
+		break;
+	}
+
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11axcmd
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11ax_cmd(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	mlan_ds_11ax_cmd_cfg *cfg = MNULL;
+	HostCmd_DS_11AX_CMD_CFG *axcmd = &resp->params.axcmd;
+	MrvlIEtypes_Data_t *tlv = MNULL;
+	t_s16 left_len = 0;
+	t_u16 tlv_len = 0;
+
+	ENTER();
+
+	if (pioctl_buf == MNULL)
+		goto done;
+
+	cfg = (mlan_ds_11ax_cmd_cfg *) pioctl_buf->pbuf;
+	cfg->sub_id = wlan_le16_to_cpu(axcmd->sub_id);
+
+	switch (axcmd->sub_id) {
+	case MLAN_11AXCMD_SR_SUBID:
+		/* TLV parse */
+		left_len =
+			resp->size - sizeof(HostCmd_DS_11AX_CMD_CFG) - S_DS_GEN;
+		// tlv = (MrvlIEtypes_Extension_t *)axcfg->val;
+		tlv = (MrvlIEtypes_Data_t *)axcmd->val;
+		while (left_len > (t_s16)sizeof(MrvlIEtypesHeader_t)) {
+			tlv_len = wlan_le16_to_cpu(tlv->header.len);
+			memcpy_ext(pmadapter,
+				   cfg->param.sr_cfg.param.obss_pd_offset.
+				   offset, tlv->data, tlv_len, tlv_len);
+			left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+			tlv = (MrvlIEtypes_Data_t
+			       *)((t_u8 *)tlv + tlv_len +
+				  sizeof(MrvlIEtypesHeader_t));
+		}
+		break;
+	case MLAN_11AXCMD_BEAM_SUBID:
+		cfg->param.beam_cfg.value = *axcmd->val;
+		break;
+	case MLAN_11AXCMD_HTC_SUBID:
+		cfg->param.htc_cfg.value = *axcmd->val;
+		break;
+	case MLAN_11AXCMD_TXOPRTS_SUBID:
+		memcpy_ext(pmadapter, &cfg->param.txop_cfg.rts_thres,
+			   axcmd->val, sizeof(t_u16), sizeof(t_u16));
+		break;
+	case MLAN_11AXCMD_TXOMI_SUBID:
+		memcpy_ext(pmadapter, &cfg->param.txomi_cfg.omi, axcmd->val,
+			   sizeof(t_u16), sizeof(t_u16));
+		break;
+	case MLAN_11AXCMD_OBSS_TOLTIME_SUBID:
+		memcpy_ext(pmadapter, &cfg->param.toltime_cfg.tol_time,
+			   axcmd->val, sizeof(t_u32), sizeof(t_u32));
+		break;
+	default:
+		PRINTM(MERROR, "Unknown subcmd %x\n", axcmd->sub_id);
+		break;
+	}
+
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief              This function prepares TWT cfg command to configure
+ * setup/teardown
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             Status returned
+ */
+mlan_status
+wlan_cmd_twt_cfg(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_TWT_CFG *hostcmd_twtcfg =
+		(HostCmd_DS_TWT_CFG *) & cmd->params.twtcfg;
+	mlan_ds_twtcfg *ds_twtcfg = (mlan_ds_twtcfg *) pdata_buf;
+	hostcmd_twt_setup *twt_setup_params = MNULL;
+	hostcmd_twt_teardown *twt_teardown_params = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TWT_CFG);
+
+	hostcmd_twtcfg->action = wlan_cpu_to_le16(cmd_action);
+	hostcmd_twtcfg->sub_id = wlan_cpu_to_le16(ds_twtcfg->sub_id);
+
+	cmd->size = S_DS_GEN + sizeof(hostcmd_twtcfg->action) +
+		sizeof(hostcmd_twtcfg->sub_id);
+
+	switch (hostcmd_twtcfg->sub_id) {
+	case MLAN_11AX_TWT_SETUP_SUBID:
+		twt_setup_params = &hostcmd_twtcfg->param.twt_setup;
+		memset(pmadapter, twt_setup_params, 0x00,
+		       sizeof(hostcmd_twtcfg->param.twt_setup));
+		twt_setup_params->implicit =
+			ds_twtcfg->param.twt_setup.implicit;
+		twt_setup_params->announced =
+			ds_twtcfg->param.twt_setup.announced;
+		twt_setup_params->trigger_enabled =
+			ds_twtcfg->param.twt_setup.trigger_enabled;
+		twt_setup_params->twt_info_disabled =
+			ds_twtcfg->param.twt_setup.twt_info_disabled;
+		twt_setup_params->negotiation_type =
+			ds_twtcfg->param.twt_setup.negotiation_type;
+		twt_setup_params->twt_wakeup_duration =
+			ds_twtcfg->param.twt_setup.twt_wakeup_duration;
+		twt_setup_params->flow_identifier =
+			ds_twtcfg->param.twt_setup.flow_identifier;
+		twt_setup_params->hard_constraint =
+			ds_twtcfg->param.twt_setup.hard_constraint;
+		twt_setup_params->twt_exponent =
+			ds_twtcfg->param.twt_setup.twt_exponent;
+		twt_setup_params->twt_mantissa =
+			wlan_cpu_to_le16(ds_twtcfg->param.twt_setup.
+					 twt_mantissa);
+		twt_setup_params->twt_request =
+			ds_twtcfg->param.twt_setup.twt_request;
+		cmd->size += sizeof(hostcmd_twtcfg->param.twt_setup);
+		break;
+	case MLAN_11AX_TWT_TEARDOWN_SUBID:
+		twt_teardown_params = &hostcmd_twtcfg->param.twt_teardown;
+		memset(pmadapter, twt_teardown_params, 0x00,
+		       sizeof(hostcmd_twtcfg->param.twt_teardown));
+		twt_teardown_params->flow_identifier =
+			ds_twtcfg->param.twt_teardown.flow_identifier;
+		twt_teardown_params->negotiation_type =
+			ds_twtcfg->param.twt_teardown.negotiation_type;
+		twt_teardown_params->teardown_all_twt =
+			ds_twtcfg->param.twt_teardown.teardown_all_twt;
+		cmd->size += sizeof(hostcmd_twtcfg->param.twt_teardown);
+		break;
+	default:
+		PRINTM(MERROR, "Unknown subcmd %x\n", ds_twtcfg->sub_id);
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief              TWT config command handler
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11ax_ioctl_twtcfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_twtcfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_twtcfg)) {
+		PRINTM(MERROR, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_twtcfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	cfg = (mlan_ds_twtcfg *) pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TWT_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req, (t_void *)cfg);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_11ax.h b/wlan_sd8987/mlan/mlan_11ax.h
new file mode 100755
index 0000000..4c16a70
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11ax.h
@@ -0,0 +1,73 @@
+/** @file mlan_11ax.h
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *
+ *  Copyright 2018-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+#ifndef _MLAN_11AX_H_
+#define _MLAN_11AX_H_
+
+/** device support 2.4G 40MHZ*/
+#define AX_2G_40MHZ_SUPPORT MBIT(1)
+/** device support 2.4G 242 tone RUs */
+#define AX_2G_20MHZ_SUPPORT MBIT(5)
+
+/*
+ * 0 indicates support for HE-MCS 0-7 for n spatial streams
+ * 1 indicates support for HE-MCS 0-9 for n spatial streams
+ * 2 indicates support for HE-MCS 0-11 for n spatial streams
+ * 3 indicates that n spatial streams is not supported for HE PPDUs
+ */
+#define GET_HE_NSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3)
+#define SET_HE_NSSMCS(MCSMapSet, nss, value)                                   \
+	(MCSMapSet |= (value & 0x3) << (2 * (nss - 1)))
+
+t_u8 wlan_check_11ax_twt_supported(mlan_private *pmpriv,
+				   BSSDescriptor_t *pbss_desc);
+mlan_status wlan_11ax_ioctl_twtcfg(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_twt_cfg(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			     t_void *pdata_buf);
+t_u16 wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band,
+			   MrvlIEtypes_Extension_t * phe_cap, t_u8 flag);
+void wlan_update_11ax_cap(mlan_adapter *pmadapter,
+			  MrvlIEtypes_Extension_t * hw_he_cap);
+int wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
+			     t_u8 **ppbuffer);
+t_u16 wlan_11ax_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band);
+mlan_status wlan_11ax_cfg_ioctl(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req);
+mlan_status wlan_11ax_ioctl_cmd(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_11ax_cfg(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			      t_void *pdata_buf);
+mlan_status wlan_ret_11ax_cfg(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_11ax_cmd(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			      t_void *pdata_buf);
+mlan_status wlan_ret_11ax_cmd(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf);
+
+#endif /* _MLAN_11AX_H_ */
diff --git a/wlan_sd8987/mlan/mlan_11d.c b/wlan_sd8987/mlan/mlan_11d.c
new file mode 100755
index 0000000..445d84f
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11d.c
@@ -0,0 +1,1634 @@
+/** @file mlan_11d.c
+ *
+ *  @brief This file contains functions for 802.11D.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_11h.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+#ifdef STA_SUPPORT
+/** Region code mapping */
+typedef struct _region_code_mapping {
+	/** Region */
+	t_u8 region[COUNTRY_CODE_LEN];
+	/** Code */
+	t_u8 code;
+} region_code_mapping_t;
+
+/** Region code mapping table */
+static region_code_mapping_t region_code_mapping[] = {
+	{"US ", 0x10},		/* US FCC      */
+	{"CA ", 0x20},		/* IC Canada   */
+	{"SG ", 0x10},		/* Singapore   */
+	{"EU ", 0x30},		/* ETSI        */
+	{"AU ", 0x30},		/* Australia   */
+	{"KR ", 0x30},		/* Republic Of Korea */
+	{"FR ", 0x32},		/* France      */
+	{"JP ", 0x40},		/* Japan       */
+	{"JP ", 0x41},		/* Japan       */
+	{"CN ", 0x50},		/* China       */
+	{"JP ", 0xFE},		/* Japan       */
+	{"JP ", 0xFF},		/* Japan special */
+	{"NE ", 0x30},		/* New Zeland  */
+};
+
+/** Universal region code */
+#define UNIVERSAL_REGION_CODE 0xff
+#endif
+
+/** Default Tx power */
+#define TX_PWR_DEFAULT 10
+
+/* Following two structures define the supported channels */
+/** Channels for 802.11b/g */
+static chan_freq_power_t channel_freq_power_UN_BG[] = {
+	{1, 2412, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, TX_PWR_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, TX_PWR_DEFAULT, MFALSE, {0x1d, 0, 0}},
+	{13, 2472, TX_PWR_DEFAULT, MFALSE, {0x1d, 0, 0}},
+	{14, 2484, TX_PWR_DEFAULT, MFALSE, {0x1d, 0, 0}},
+};
+
+/** Channels for 802.11a/j */
+static chan_freq_power_t channel_freq_power_UN_AJ[] = {
+	{8, 5040, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{12, 5060, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{16, 5080, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{34, 5170, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{36, 5180, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{38, 5190, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{42, 5210, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{46, 5230, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{120, 5600, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{124, 5620, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{128, 5640, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}
+	/*  {240, 4920, TX_PWR_DEFAULT},
+	   {244, 4940, TX_PWR_DEFAULT},
+	   {248, 4960, TX_PWR_DEFAULT},
+	   {252, 4980, TX_PWR_DEFAULT},
+	   channels for 11J JP 10M channel gap */
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function converts integer code to region string
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param code         Region code
+ *
+ *  @return             Region string
+ */
+static t_u8 *
+wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
+{
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(region_code_mapping); i++) {
+		if (region_code_mapping[i].code == code) {
+			LEAVE();
+			return region_code_mapping[i].region;
+		}
+	}
+
+	LEAVE();
+	/* Default is US */
+	return region_code_mapping[0].region;
+}
+
+/**
+ *  @brief This function Checks if channel txpwr is learned from AP/IBSS
+ *
+ *  @param pmadapter            A pointer to mlan_adapter structure
+ *  @param band                 Band number
+ *  @param chan                 Channel number
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MTRUE or MFALSE
+ */
+static t_u8
+wlan_11d_channel_known(pmlan_adapter pmadapter, t_u8 band,
+		       t_u8 chan, parsed_region_chan_11d_t *parsed_region_chan)
+{
+	chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 i = 0;
+	t_u8 ret = MFALSE;
+	mlan_private *pmpriv;
+
+	ENTER();
+
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)pchan_pwr,
+		sizeof(chan_power_11d_t) * no_of_chan);
+
+	/* Search channel */
+	for (i = 0; i < no_of_chan; i++) {
+		if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) {
+			PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan,
+			       band);
+			ret = MTRUE;
+
+			if (band & BAND_A) {
+				/* If chan is a DFS channel, we need to see an
+				 * AP on it */
+				pmpriv = wlan_get_priv(pmadapter,
+						       MLAN_BSS_ROLE_STA);
+				if (pmpriv &&
+				    wlan_11h_radar_detect_required(pmpriv,
+								   chan)) {
+					PRINTM(MINFO,
+					       "11H: DFS channel %d, and ap_seen=%d\n",
+					       chan, pchan_pwr[i].ap_seen);
+					ret = pchan_pwr[i].ap_seen;
+				}
+			}
+
+			LEAVE();
+			return ret;
+		}
+	}
+
+	PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function generates parsed_region_chan from Domain Info
+ *           learned from AP/IBSS
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param region_chan          Pointer to region_chan_t
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     N/A
+ */
+static t_void
+wlan_11d_generate_parsed_region_chan(pmlan_adapter pmadapter,
+				     region_chan_t *region_chan,
+				     parsed_region_chan_11d_t
+				     *parsed_region_chan)
+{
+	chan_freq_power_t *cfp;
+	t_u8 i;
+
+	ENTER();
+
+	/* Region channel must be provided */
+	if (!region_chan) {
+		PRINTM(MWARN, "11D: region_chan is MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Get channel-frequency-power trio */
+	cfp = region_chan->pcfp;
+	if (!cfp) {
+		PRINTM(MWARN, "11D: cfp equal MNULL\n");
+		LEAVE();
+		return;
+	}
+
+	/* Set channel, band and power */
+	for (i = 0; i < region_chan->num_cfp; i++, cfp++) {
+		parsed_region_chan->chan_pwr[i].chan = (t_u8)cfp->channel;
+		parsed_region_chan->chan_pwr[i].band = region_chan->band;
+		parsed_region_chan->chan_pwr[i].pwr = (t_u8)cfp->max_tx_power;
+		PRINTM(MINFO, "11D: Chan[%d] Band[%d] Pwr[%d]\n",
+		       parsed_region_chan->chan_pwr[i].chan,
+		       parsed_region_chan->chan_pwr[i].band,
+		       parsed_region_chan->chan_pwr[i].pwr);
+	}
+	parsed_region_chan->no_of_chan = region_chan->num_cfp;
+
+	PRINTM(MINFO, "11D: no_of_chan[%d]\n", parsed_region_chan->no_of_chan);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function generates domain_info from parsed_region_chan
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_generate_domain_info(pmlan_adapter pmadapter,
+			      parsed_region_chan_11d_t *parsed_region_chan)
+{
+	t_u8 no_of_sub_band = 0;
+	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
+	t_u8 no_of_parsed_chan = 0;
+	t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+	t_u8 i, flag = MFALSE;
+	wlan_802_11d_domain_reg_t *domain_info = &pmadapter->domain_reg;
+
+	ENTER();
+
+	/* Should be only place that clear domain_reg (besides init) */
+	memset(pmadapter, domain_info, 0, sizeof(wlan_802_11d_domain_reg_t));
+
+	/* Set country code */
+	memcpy_ext(pmadapter, domain_info->country_code,
+		   wlan_11d_code_2_region(pmadapter,
+					  (t_u8)pmadapter->region_code),
+		   COUNTRY_CODE_LEN, COUNTRY_CODE_LEN);
+
+	PRINTM(MINFO, "11D: Number of channel = %d\n", no_of_chan);
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan,
+		sizeof(parsed_region_chan_11d_t));
+
+	/* Set channel and power */
+	for (i = 0; i < no_of_chan; i++) {
+		if (!flag) {
+			flag = MTRUE;
+			next_chan = first_chan =
+				parsed_region_chan->chan_pwr[i].chan;
+			max_pwr = parsed_region_chan->chan_pwr[i].pwr;
+			no_of_parsed_chan = 1;
+			continue;
+		}
+
+		if (parsed_region_chan->chan_pwr[i].chan == next_chan + 1 &&
+		    parsed_region_chan->chan_pwr[i].pwr == max_pwr) {
+			next_chan++;
+			no_of_parsed_chan++;
+		} else {
+			domain_info->sub_band[no_of_sub_band].first_chan =
+				first_chan;
+			domain_info->sub_band[no_of_sub_band].no_of_chan =
+				no_of_parsed_chan;
+			domain_info->sub_band[no_of_sub_band].max_tx_pwr =
+				max_pwr;
+			no_of_sub_band++;
+			no_of_parsed_chan = 1;
+			next_chan = first_chan =
+				parsed_region_chan->chan_pwr[i].chan;
+			max_pwr = parsed_region_chan->chan_pwr[i].pwr;
+		}
+	}
+
+	if (flag) {
+		domain_info->sub_band[no_of_sub_band].first_chan = first_chan;
+		domain_info->sub_band[no_of_sub_band].no_of_chan =
+			no_of_parsed_chan;
+		domain_info->sub_band[no_of_sub_band].max_tx_pwr = max_pwr;
+		no_of_sub_band++;
+	}
+	domain_info->no_of_sub_band = no_of_sub_band;
+
+	PRINTM(MINFO, "11D: Number of sub-band =0x%x\n",
+	       domain_info->no_of_sub_band);
+	HEXDUMP("11D: domain_info", (t_u8 *)domain_info,
+		COUNTRY_CODE_LEN + 1 +
+		sizeof(IEEEtypes_SubbandSet_t) * no_of_sub_band);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function updates the channel power table with the channel
+ *            present in BSSDescriptor.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11d_update_chan_pwr_table(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	parsed_region_chan_11d_t *parsed_region_chan =
+		&pmadapter->parsed_region_chan;
+	t_u16 i;
+	t_u8 tx_power = 0;
+	t_u8 chan;
+
+	ENTER();
+
+	chan = pbss_desc->phy_param_set.ds_param_set.current_chan;
+
+	tx_power = wlan_get_txpwr_of_chan_from_cfp(pmpriv, chan);
+
+	if (!tx_power) {
+		PRINTM(MMSG, "11D: Invalid channel\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Check whether the channel already exists in channel power table of
+	   parsed region */
+	for (i = 0;
+	     ((i < parsed_region_chan->no_of_chan) && (i < MAX_NO_OF_CHAN));
+	     i++) {
+		if (parsed_region_chan->chan_pwr[i].chan == chan &&
+		    parsed_region_chan->chan_pwr[i].band ==
+		    pbss_desc->bss_band) {
+			/* Channel already exists, use minimum of existing and
+			   tx_power */
+			parsed_region_chan->chan_pwr[i].pwr =
+				MIN(parsed_region_chan->chan_pwr[i].pwr,
+				    tx_power);
+			parsed_region_chan->chan_pwr[i].ap_seen = MTRUE;
+			break;
+		}
+	}
+
+	if (i == parsed_region_chan->no_of_chan && i < MAX_NO_OF_CHAN) {
+		/* Channel not found. Update the channel in the channel-power
+		   table */
+		parsed_region_chan->chan_pwr[i].chan = chan;
+		parsed_region_chan->chan_pwr[i].band =
+			(t_u8)pbss_desc->bss_band;
+		parsed_region_chan->chan_pwr[i].pwr = tx_power;
+		parsed_region_chan->chan_pwr[i].ap_seen = MTRUE;
+		parsed_region_chan->no_of_chan++;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function finds the no_of_chan-th chan after the first_chan
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param band       Band
+ *  @param first_chan First channel number
+ *  @param no_of_chan Number of channels
+ *  @param chan       Pointer to the returned no_of_chan-th chan number
+ *
+ *  @return           MTRUE or MFALSE
+ */
+static t_u8
+wlan_11d_get_chan(pmlan_adapter pmadapter, t_u8 band,
+		  t_u8 first_chan, t_u8 no_of_chan, t_u8 *chan)
+{
+	chan_freq_power_t *cfp = MNULL;
+	t_u8 i;
+	t_u8 cfp_no = 0;
+
+	ENTER();
+	if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+		cfp = channel_freq_power_UN_BG;
+		cfp_no = NELEMENTS(channel_freq_power_UN_BG);
+	} else if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		cfp = channel_freq_power_UN_AJ;
+		cfp_no = NELEMENTS(channel_freq_power_UN_AJ);
+	} else {
+		PRINTM(MERROR, "11D: Wrong Band[%d]\n", band);
+		LEAVE();
+		return MFALSE;
+	}
+	/* Locate the first_chan */
+	for (i = 0; i < cfp_no; i++) {
+		if (cfp && ((cfp + i)->channel == first_chan)) {
+			PRINTM(MINFO, "11D: first_chan found\n");
+			break;
+		}
+	}
+
+	if (i < cfp_no) {
+		/* Check if beyond the boundary */
+		if (i + no_of_chan < cfp_no) {
+			/* Get first_chan + no_of_chan */
+			*chan = (t_u8)(cfp + i + no_of_chan)->channel;
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function processes the country info present in BSSDescriptor.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc     A pointer to BSSDescriptor_t
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11d_process_country_info(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	parsed_region_chan_11d_t region_chan;
+	parsed_region_chan_11d_t *parsed_region_chan =
+		&pmadapter->parsed_region_chan;
+	t_u16 i, j, num_chan_added = 0;
+
+	ENTER();
+
+	memset(pmadapter, &region_chan, 0, sizeof(parsed_region_chan_11d_t));
+
+	/* Parse 11D country info */
+	if (wlan_11d_parse_domain_info(pmadapter, &pbss_desc->country_info,
+				       (t_u8)pbss_desc->bss_band,
+				       &region_chan) != MLAN_STATUS_SUCCESS) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (parsed_region_chan->no_of_chan != 0) {
+		/*
+		 * Check if the channel number already exists in the
+		 * chan-power table of parsed_region_chan
+		 */
+		for (i = 0; (i < region_chan.no_of_chan && i < MAX_NO_OF_CHAN);
+		     i++) {
+			for (j = 0; (j < parsed_region_chan->no_of_chan &&
+				     j < MAX_NO_OF_CHAN); j++) {
+				/*
+				 * Channel already exists, update the tx power
+				 * with new tx power, since country IE is valid
+				 * here.
+				 */
+				if (region_chan.chan_pwr[i].chan ==
+				    parsed_region_chan->chan_pwr[j]
+				    .chan &&
+				    region_chan.chan_pwr[i].band ==
+				    parsed_region_chan->chan_pwr[j]
+				    .band) {
+					parsed_region_chan->chan_pwr[j].pwr =
+						region_chan.chan_pwr[i].pwr;
+					break;
+				}
+			}
+
+			if (j == parsed_region_chan->no_of_chan &&
+			    (j + num_chan_added) < MAX_NO_OF_CHAN) {
+				/*
+				 * Channel does not exist in the channel power
+				 * table, update this new chan and tx_power
+				 * to the channel power table
+				 */
+				parsed_region_chan->
+					chan_pwr[parsed_region_chan->
+						 no_of_chan + num_chan_added]
+					.chan = region_chan.chan_pwr[i].chan;
+				parsed_region_chan->
+					chan_pwr[parsed_region_chan->
+						 no_of_chan + num_chan_added]
+					.band = region_chan.chan_pwr[i].band;
+				parsed_region_chan->
+					chan_pwr[parsed_region_chan->
+						 no_of_chan + num_chan_added]
+					.pwr = region_chan.chan_pwr[i].pwr;
+				parsed_region_chan->
+					chan_pwr[parsed_region_chan->
+						 no_of_chan + num_chan_added]
+					.ap_seen = MFALSE;
+				num_chan_added++;
+			}
+		}
+		parsed_region_chan->no_of_chan += num_chan_added;
+	} else {
+		/* Parsed region is empty, copy the first one */
+		memcpy_ext(pmadapter, parsed_region_chan, &region_chan,
+			   sizeof(parsed_region_chan_11d_t),
+			   sizeof(parsed_region_chan_11d_t));
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This helper function copies chan_power_11d_t element
+ *
+ *  @param chan_dst   Pointer to destination of chan_power
+ *  @param chan_src   Pointer to source of chan_power
+ *
+ *  @return           N/A
+ */
+static t_void
+wlan_11d_copy_chan_power(chan_power_11d_t *chan_dst, chan_power_11d_t *chan_src)
+{
+	ENTER();
+
+	chan_dst->chan = chan_src->chan;
+	chan_dst->band = chan_src->band;
+	chan_dst->pwr = chan_src->pwr;
+	chan_dst->ap_seen = chan_src->ap_seen;
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function sorts parsed_region_chan in ascending
+ *  channel number.
+ *
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     N/A
+ */
+static t_void
+wlan_11d_sort_parsed_region_chan(parsed_region_chan_11d_t *parsed_region_chan)
+{
+	int i, j;
+	chan_power_11d_t temp;
+	chan_power_11d_t *pchan_power = parsed_region_chan->chan_pwr;
+
+	ENTER();
+
+	PRINTM(MINFO, "11D: Number of channel = %d\n",
+	       parsed_region_chan->no_of_chan);
+
+	/* Use insertion sort method */
+	for (i = 1; i < parsed_region_chan->no_of_chan; i++) {
+		wlan_11d_copy_chan_power(&temp, pchan_power + i);
+		for (j = i; j > 0 && (pchan_power + j - 1)->chan > temp.chan;
+		     j--)
+			wlan_11d_copy_chan_power(pchan_power + j,
+						 pchan_power + j - 1);
+		wlan_11d_copy_chan_power(pchan_power + j, &temp);
+	}
+
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan,
+		sizeof(parsed_region_chan_11d_t));
+
+	LEAVE();
+	return;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief This function sends domain info to FW
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11d_send_domain_info(mlan_private *pmpriv, t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send cmd to FW to set domain info */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11D_DOMAIN_INFO,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_buf,
+			       MNULL);
+	if (ret)
+		PRINTM(MERROR, "11D: Failed to download domain Info\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function overwrites domain_info
+ *
+ *  @param pmadapter        Pointer to mlan_adapter structure
+ *  @param band             Intended operating band
+ *  @param country_code     Intended country code
+ *  @param num_sub_band     Count of tuples in list below
+ *  @param sub_band_list    List of sub_band tuples
+ *
+ *  @return                 MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11d_set_domain_info(mlan_private *pmpriv, t_u8 band,
+			 t_u8 country_code[COUNTRY_CODE_LEN], t_u8 num_sub_band,
+			 IEEEtypes_SubbandSet_t *sub_band_list)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	wlan_802_11d_domain_reg_t *pdomain = &pmadapter->domain_reg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(pmadapter, pdomain, 0, sizeof(wlan_802_11d_domain_reg_t));
+	memcpy_ext(pmadapter, pdomain->country_code, country_code,
+		   COUNTRY_CODE_LEN, COUNTRY_CODE_LEN);
+	pdomain->band = band;
+	pdomain->no_of_sub_band = num_sub_band;
+	memcpy_ext(pmadapter, pdomain->sub_band, sub_band_list,
+		   num_sub_band * sizeof(IEEEtypes_SubbandSet_t),
+		   MRVDRV_MAX_SUBBAND_802_11D * sizeof(IEEEtypes_SubbandSet_t));
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global functions
+********************************************************/
+
+/**
+ *  @brief This function gets if priv is a station (STA)
+ *
+ *  @param pmpriv       Pointer to mlan_private structure
+ *
+ *  @return             MTRUE or MFALSE
+ */
+t_bool
+wlan_is_station(mlan_private *pmpriv)
+{
+	ENTER();
+	LEAVE();
+	return (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function gets if 11D is enabled
+ *
+ *  @param pmpriv       Pointer to mlan_private structure
+ *
+ *  @return             MTRUE or MFALSE
+ */
+t_bool
+wlan_11d_is_enabled(mlan_private *pmpriv)
+{
+	ENTER();
+	LEAVE();
+	return (pmpriv->state_11d.enable_11d == ENABLE_11D &&
+		pmpriv->state_11d.user_enable_11d == ENABLE_11D) ?
+		MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function gets if 11D is enabled in FW
+ *
+ *  @param pmpriv       Pointer to mlan_private structure
+ *
+ *  @return             MTRUE or MFALSE
+ */
+t_bool
+wlan_fw_11d_is_enabled(mlan_private *pmpriv)
+{
+	ENTER();
+	LEAVE();
+	return (pmpriv->state_11d.enable_11d == ENABLE_11D) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief Initialize interface variable for 11D
+ *
+ *  @param pmpriv       Pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_11d_priv_init(mlan_private *pmpriv)
+{
+	wlan_802_11d_state_t *state = &pmpriv->state_11d;
+
+	ENTER();
+
+	/* Start in disabled mode */
+	state->enable_11d = DISABLE_11D;
+	if (!pmpriv->adapter->init_para.cfg_11d)
+		state->user_enable_11d = DEFAULT_11D_STATE;
+	else
+		state->user_enable_11d = (pmpriv->adapter->init_para.cfg_11d ==
+					  MLAN_INIT_PARA_DISABLED) ?
+			DISABLE_11D : ENABLE_11D;
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Initialize device variable for 11D
+ *
+ *  @param pmadapter    Pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_11d_init(mlan_adapter *pmadapter)
+{
+	ENTER();
+
+#ifdef STA_SUPPORT
+	memset(pmadapter, &(pmadapter->parsed_region_chan), 0,
+	       sizeof(parsed_region_chan_11d_t));
+	memset(pmadapter, &(pmadapter->universal_channel), 0,
+	       sizeof(region_chan_t));
+#endif
+	memset(pmadapter, &(pmadapter->domain_reg), 0,
+	       sizeof(wlan_802_11d_domain_reg_t));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function enable/disable 11D
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param flag         11D status
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_enable(mlan_private *pmpriv, t_void *pioctl_buf, state_11d_t flag)
+{
+#ifdef STA_SUPPORT
+	mlan_adapter *pmadapter = pmpriv->adapter;
+#endif
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	state_11d_t enable = flag;
+
+	ENTER();
+
+	/* Send cmd to FW to enable/disable 11D function */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+			       HostCmd_ACT_GEN_SET, Dot11D_i,
+			       (t_void *)pioctl_buf, &enable);
+
+	if (ret) {
+		PRINTM(MERROR, "11D: Failed to %s 11D\n",
+		       (flag) ? "enable" : "disable");
+	}
+#ifdef STA_SUPPORT
+	else {
+		/* clear parsed table regardless of flag */
+		memset(pmadapter, &(pmadapter->parsed_region_chan), 0,
+		       sizeof(parsed_region_chan_11d_t));
+	}
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function implements command CMD_802_11D_DOMAIN_INFO
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure of
+ *                        command buffer
+ *  @param cmd_action   Command action
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11d_domain_info(mlan_private *pmpriv,
+			     HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11D_DOMAIN_INFO *pdomain_info =
+		&pcmd->params.domain_info;
+	MrvlIEtypes_DomainParamSet_t *domain = &pdomain_info->domain;
+	t_u8 no_of_sub_band = pmadapter->domain_reg.no_of_sub_band;
+	t_u8 i;
+
+	ENTER();
+	PRINTM(MCMND, "11D:Country=%c%c band=%d sub-band=5d\n",
+	       pmadapter->domain_reg.country_code[0],
+	       pmadapter->domain_reg.country_code[1],
+	       pmadapter->domain_reg.band, no_of_sub_band);
+	for (i = 0; i < no_of_sub_band; i++) {
+		PRINTM(MCMND,
+		       "11D: first chan=%d no_of_chan=%d, max_tx_pwr=%d\n",
+		       pmadapter->domain_reg.sub_band[i].first_chan,
+		       pmadapter->domain_reg.sub_band[i].no_of_chan,
+		       pmadapter->domain_reg.sub_band[i].max_tx_pwr);
+	}
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO);
+	pdomain_info->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		/* Dump domain info */
+		pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) +
+					      S_DS_GEN);
+		HEXDUMP("11D: 802_11D_DOMAIN_INFO", (t_u8 *)pcmd,
+			wlan_le16_to_cpu(pcmd->size));
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	/* Set domain info fields */
+	domain->header.type = wlan_cpu_to_le16(TLV_TYPE_DOMAIN);
+	memcpy_ext(pmadapter, domain->country_code,
+		   pmadapter->domain_reg.country_code,
+		   sizeof(domain->country_code), sizeof(domain->country_code));
+
+	domain->header.len =
+		((no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)) +
+		 sizeof(domain->country_code));
+
+	if (no_of_sub_band) {
+		memcpy_ext(pmadapter, domain->sub_band,
+			   pmadapter->domain_reg.sub_band,
+			   no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t),
+			   MRVDRV_MAX_SUBBAND_802_11D *
+			   sizeof(IEEEtypes_SubbandSet_t));
+
+		pcmd->size =
+			wlan_cpu_to_le16(sizeof(pdomain_info->action) +
+					 domain->header.len +
+					 sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN);
+	} else {
+		pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) +
+					      S_DS_GEN);
+	}
+	domain->header.len = wlan_cpu_to_le16(domain->header.len);
+
+	HEXDUMP("11D: 802_11D_DOMAIN_INFO", (t_u8 *)pcmd,
+		wlan_le16_to_cpu(pcmd->size));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle response of CMD_802_11D_DOMAIN_INFO
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         Pointer to command response buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11d_domain_info(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_802_11D_DOMAIN_INFO_RSP *domain_info =
+		&resp->params.domain_info_resp;
+	MrvlIEtypes_DomainParamSet_t *domain = &domain_info->domain;
+	t_u16 action = wlan_le16_to_cpu(domain_info->action);
+	t_u8 no_of_sub_band = 0;
+
+	ENTER();
+
+	/* Dump domain info response data */
+	HEXDUMP("11D: DOMAIN Info Rsp Data", (t_u8 *)resp, resp->size);
+
+	no_of_sub_band = (t_u8)((wlan_le16_to_cpu(domain->header.len) -
+				 COUNTRY_CODE_LEN) /
+				sizeof(IEEEtypes_SubbandSet_t));
+
+	PRINTM(MINFO, "11D Domain Info Resp: number of sub-band=%d\n",
+	       no_of_sub_band);
+
+	if (no_of_sub_band > MRVDRV_MAX_SUBBAND_802_11D) {
+		PRINTM(MWARN, "11D: Invalid number of subbands %d returned!!\n",
+		       no_of_sub_band);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	switch (action) {
+	case HostCmd_ACT_GEN_SET:	/* Proc Set Action */
+		break;
+	case HostCmd_ACT_GEN_GET:
+		break;
+	default:
+		PRINTM(MERROR, "11D: Invalid Action:%d\n", domain_info->action);
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function converts channel to frequency
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param chan         Channel number
+ *  @param band         Band
+ *
+ *  @return             Channel frequency
+ */
+t_u32
+wlan_11d_chan_2_freq(pmlan_adapter pmadapter, t_u8 chan, t_u8 band)
+{
+	chan_freq_power_t *cf;
+	t_u16 cnt;
+	t_u16 i;
+	t_u32 freq = 0;
+
+	ENTER();
+
+	/* Get channel-frequency-power trios */
+	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		cf = channel_freq_power_UN_AJ;
+		cnt = NELEMENTS(channel_freq_power_UN_AJ);
+	} else {
+		cf = channel_freq_power_UN_BG;
+		cnt = NELEMENTS(channel_freq_power_UN_BG);
+	}
+
+	/* Locate channel and return corresponding frequency */
+	for (i = 0; i < cnt; i++) {
+		if (chan == cf[i].channel)
+			freq = cf[i].freq;
+	}
+
+	LEAVE();
+	return freq;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function parses country information for region channel
+ *
+ *  @param pmadapter            Pointer to mlan_adapter structure
+ *  @param country_info         Country information
+ *  @param band                 Chan band
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_parse_domain_info(pmlan_adapter pmadapter,
+			   IEEEtypes_CountryInfoFullSet_t *country_info,
+			   t_u8 band,
+			   parsed_region_chan_11d_t *parsed_region_chan)
+{
+	t_u8 no_of_sub_band, no_of_chan;
+	t_u8 last_chan, first_chan, cur_chan = 0;
+	t_u8 idx = 0;
+	t_u8 j, i;
+
+	ENTER();
+
+	/*
+	 * Validation Rules:
+	 *    1. Valid Region Code
+	 *    2. First Chan increment
+	 *    3. Channel range no overlap
+	 *    4. Channel is valid?
+	 *    5. Channel is supported by Region?
+	 *    6. Others
+	 */
+
+	HEXDUMP("country_info", (t_u8 *)country_info, 30);
+
+	/* Step 1: Check region_code */
+	if (!(*(country_info->country_code)) ||
+	    (country_info->len <= COUNTRY_CODE_LEN)) {
+		/* No region info or wrong region info: treat as no 11D info */
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	no_of_sub_band = (country_info->len - COUNTRY_CODE_LEN) /
+		sizeof(IEEEtypes_SubbandSet_t);
+
+	for (j = 0, last_chan = 0; j < no_of_sub_band; j++) {
+		if (country_info->sub_band[j].first_chan <= last_chan) {
+			/* Step2&3: Check First Chan Num increment and no
+			 * overlap */
+			PRINTM(MINFO, "11D: Chan[%d>%d] Overlap\n",
+			       country_info->sub_band[j].first_chan, last_chan);
+			continue;
+		}
+
+		first_chan = country_info->sub_band[j].first_chan;
+		no_of_chan = country_info->sub_band[j].no_of_chan;
+
+		for (i = 0; idx < MAX_NO_OF_CHAN && i < no_of_chan; i++) {
+			/* Step 4 : Channel is supported? */
+			if (wlan_11d_get_chan(pmadapter, band, first_chan, i,
+					      &cur_chan) == MFALSE) {
+				/* Chan is not found in UN table */
+				PRINTM(MWARN,
+				       "11D: channel is not supported: %d\n",
+				       i);
+				break;
+			}
+
+			last_chan = cur_chan;
+
+			/* Step 5: We don't need to check if cur_chan is
+			   supported by mrvl in region */
+			parsed_region_chan->chan_pwr[idx].chan = cur_chan;
+			parsed_region_chan->chan_pwr[idx].band = band;
+			parsed_region_chan->chan_pwr[idx].pwr =
+				country_info->sub_band[j].max_tx_pwr;
+			idx++;
+		}
+
+		/* Step 6: Add other checking if any */
+	}
+
+	parsed_region_chan->no_of_chan = idx;
+
+	PRINTM(MINFO, "11D: number of channel=0x%x\n",
+	       parsed_region_chan->no_of_chan);
+	HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan->chan_pwr,
+		sizeof(chan_power_11d_t) * idx);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function setups scan channels
+ *
+ *  @param pmpriv       Pointer to mlan_private structure
+ *  @param band         Band
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_11d_set_universaltable(mlan_private *pmpriv, t_u8 band)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u16 i = 0;
+
+	ENTER();
+
+	memset(pmadapter, pmadapter->universal_channel, 0,
+	       sizeof(pmadapter->universal_channel));
+
+	if (band & (BAND_B | BAND_G | BAND_GN))
+		/* If band B, G or N */
+	{
+		/* Set channel-frequency-power */
+		pmadapter->universal_channel[i].num_cfp =
+			NELEMENTS(channel_freq_power_UN_BG);
+		PRINTM(MINFO, "11D: BG-band num_cfp=%d\n",
+		       pmadapter->universal_channel[i].num_cfp);
+
+		pmadapter->universal_channel[i].pcfp = channel_freq_power_UN_BG;
+		pmadapter->universal_channel[i].valid = MTRUE;
+
+		/* Set region code */
+		pmadapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
+
+		/* Set band */
+		if (band & BAND_GN)
+			pmadapter->universal_channel[i].band = BAND_G;
+		else
+			pmadapter->universal_channel[i].band =
+				(band & BAND_G) ? BAND_G : BAND_B;
+		i++;
+	}
+
+	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		/* If band A */
+
+		/* Set channel-frequency-power */
+		pmadapter->universal_channel[i].num_cfp =
+			NELEMENTS(channel_freq_power_UN_AJ);
+		PRINTM(MINFO, "11D: AJ-band num_cfp=%d\n",
+		       pmadapter->universal_channel[i].num_cfp);
+
+		pmadapter->universal_channel[i].pcfp = channel_freq_power_UN_AJ;
+
+		pmadapter->universal_channel[i].valid = MTRUE;
+
+		/* Set region code */
+		pmadapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
+
+		/* Set band */
+		pmadapter->universal_channel[i].band = BAND_A;
+		i++;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function calculates the scan type for channels
+ *
+ *  @param pmadapter            A pointer to mlan_adapter structure
+ *  @param band                 Band number
+ *  @param chan                 Chan number
+ *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
+ *
+ *  @return                     PASSIVE if chan is unknown; ACTIVE
+ *                              if chan is known
+ */
+t_u8
+wlan_11d_get_scan_type(pmlan_adapter pmadapter, t_u8 band, t_u8 chan,
+		       parsed_region_chan_11d_t *parsed_region_chan)
+{
+	t_u8 scan_type = MLAN_SCAN_TYPE_PASSIVE;
+
+	ENTER();
+
+	if (wlan_11d_channel_known(pmadapter, band, chan, parsed_region_chan)) {
+		/* Channel found */
+		PRINTM(MINFO, "11D: Channel found and doing Active Scan\n");
+		scan_type = MLAN_SCAN_TYPE_ACTIVE;
+	} else
+		PRINTM(MINFO,
+		       "11D: Channel not found and doing Passive Scan\n");
+
+	LEAVE();
+	return scan_type;
+}
+
+/**
+ *  @brief This function clears the parsed region table, if 11D is enabled
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_clear_parsedtable(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wlan_11d_is_enabled(pmpriv))
+		memset(pmadapter, &(pmadapter->parsed_region_chan), 0,
+		       sizeof(parsed_region_chan_11d_t));
+	else
+		ret = MLAN_STATUS_FAILURE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function generates 11D info from user specified regioncode
+ *         and download to FW
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         Band to create
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_create_dnld_countryinfo(mlan_private *pmpriv, t_u8 band)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	region_chan_t *region_chan;
+	parsed_region_chan_11d_t parsed_region_chan;
+	t_u8 j;
+
+	ENTER();
+
+	/* Only valid if 11D is enabled */
+	if (wlan_11d_is_enabled(pmpriv)) {
+		PRINTM(MINFO, "11D: Band[%d]\n", band);
+
+		/* Update parsed_region_chan; download domain info to FW */
+
+		/* Find region channel */
+		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
+			region_chan = &pmadapter->region_channel[j];
+
+			PRINTM(MINFO, "11D: [%d] region_chan->Band[%d]\n", j,
+			       region_chan->band);
+
+			if (!region_chan || !region_chan->valid ||
+			    !region_chan->pcfp)
+				continue;
+			switch (region_chan->band) {
+			case BAND_A:
+				switch (band) {
+				case BAND_A:
+				case BAND_AN:
+				case BAND_A | BAND_AN:
+				case BAND_A | BAND_AN | BAND_AAC:
+					break;
+				default:
+					continue;
+				}
+				break;
+			case BAND_B:
+			case BAND_G:
+				switch (band) {
+				case BAND_B:
+				case BAND_G:
+				case BAND_G | BAND_B:
+				case BAND_GN:
+				case BAND_G | BAND_GN:
+				case BAND_B | BAND_G | BAND_GN:
+				case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+					break;
+				default:
+					continue;
+				}
+				break;
+			default:
+				continue;
+			}
+			break;
+		}
+
+		/* Check if region channel found */
+		if (j >= MAX_REGION_CHANNEL_NUM) {
+			PRINTM(MERROR, "11D: region_chan not found. Band[%d]\n",
+			       band);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		/* Generate parsed region channel info from region channel */
+		memset(pmadapter, &parsed_region_chan, 0,
+		       sizeof(parsed_region_chan_11d_t));
+		wlan_11d_generate_parsed_region_chan(pmadapter, region_chan,
+						     &parsed_region_chan);
+
+		/* Generate domain info from parsed region channel info */
+		wlan_11d_generate_domain_info(pmadapter, &parsed_region_chan);
+
+		/* Set domain info */
+		ret = wlan_11d_send_domain_info(pmpriv, MNULL);
+		if (ret) {
+			PRINTM(MERROR,
+			       "11D: Error sending domain info to FW\n");
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function parses country info from AP and
+ *           download country info to FW
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc     A pointer to BSS descriptor
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_parse_dnld_countryinfo(mlan_private *pmpriv,
+				BSSDescriptor_t *pbss_desc)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	parsed_region_chan_11d_t region_chan;
+	parsed_region_chan_11d_t bssdesc_region_chan;
+	t_u32 i, j;
+
+	ENTER();
+
+	/* Only valid if 11D is enabled */
+	if (wlan_11d_is_enabled(pmpriv)) {
+		memset(pmadapter, &region_chan, 0,
+		       sizeof(parsed_region_chan_11d_t));
+		memset(pmadapter, &bssdesc_region_chan, 0,
+		       sizeof(parsed_region_chan_11d_t));
+
+		memcpy_ext(pmadapter, &region_chan,
+			   &pmadapter->parsed_region_chan,
+			   sizeof(parsed_region_chan_11d_t),
+			   sizeof(parsed_region_chan_11d_t));
+
+		if (pbss_desc) {
+			/* Parse domain info if available */
+			ret = wlan_11d_parse_domain_info(pmadapter,
+							 &pbss_desc->
+							 country_info,
+							 (t_u8)pbss_desc->
+							 bss_band,
+							 &bssdesc_region_chan);
+
+			if (ret == MLAN_STATUS_SUCCESS) {
+				/* Update the channel-power table */
+				for (i = 0;
+				     ((i < bssdesc_region_chan.no_of_chan) &&
+				      (i < MAX_NO_OF_CHAN)); i++) {
+					for (j = 0;
+					     ((j < region_chan.no_of_chan) &&
+					      (j < MAX_NO_OF_CHAN)); j++) {
+						/*
+						 * Channel already exists, use
+						 * minimum of existing tx power
+						 * and tx_power received from
+						 * country info of the current
+						 * AP
+						 */
+						if (region_chan.chan_pwr[i]
+						    .chan ==
+						    bssdesc_region_chan.
+						    chan_pwr[j]
+						    .chan &&
+						    region_chan.chan_pwr[i]
+						    .band ==
+						    bssdesc_region_chan.
+						    chan_pwr[j]
+						    .band) {
+							region_chan.chan_pwr[j]
+								.pwr =
+								MIN(region_chan.
+								    chan_pwr[j]
+								    .pwr,
+								    bssdesc_region_chan.
+								    chan_pwr[i]
+								    .pwr);
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		/* Generate domain info */
+		wlan_11d_generate_domain_info(pmadapter, &region_chan);
+
+		/* Set domain info */
+		ret = wlan_11d_send_domain_info(pmpriv, MNULL);
+		if (ret) {
+			PRINTM(MERROR,
+			       "11D: Error sending domain info to FW\n");
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares domain info from scan table and
+ *         downloads the domain info command to the FW.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_prepare_dnld_domain_info_cmd(mlan_private *pmpriv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	IEEEtypes_CountryInfoFullSet_t *pcountry_full = MNULL;
+	t_u32 idx;
+
+	ENTER();
+
+	/* Only valid if 11D is enabled */
+	if (wlan_11d_is_enabled(pmpriv) && pmadapter->num_in_scan_table != 0) {
+		for (idx = 0; idx < pmadapter->num_in_scan_table; idx++) {
+			pcountry_full =
+				&pmadapter->pscan_table[idx].country_info;
+
+			ret = wlan_11d_update_chan_pwr_table(pmpriv,
+							     &pmadapter->
+							     pscan_table[idx]);
+
+			if (*(pcountry_full->country_code) != 0 &&
+			    (pcountry_full->len > COUNTRY_CODE_LEN)) {
+				/* Country info found in the BSS Descriptor */
+				ret = wlan_11d_process_country_info(pmpriv,
+								    &pmadapter->
+								    pscan_table
+								    [idx]);
+			}
+		}
+
+		/* Sort parsed_region_chan in ascending channel number */
+		wlan_11d_sort_parsed_region_chan(&pmadapter->
+						 parsed_region_chan);
+
+		/* Check if connected */
+		if (pmpriv->media_connected == MTRUE) {
+			ret = wlan_11d_parse_dnld_countryinfo(pmpriv,
+							      &pmpriv->
+							      curr_bss_params.
+							      bss_descriptor);
+		} else {
+			ret = wlan_11d_parse_dnld_countryinfo(pmpriv, MNULL);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief This function checks country code and maps it when needed
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcountry_code Pointer to the country code string
+ *
+ *  @return             Pointer to the mapped country code string
+ */
+static t_u8 *
+wlan_11d_map_country_code(pmlan_adapter pmadapter, t_u8 *pcountry_code)
+{
+	/* Since firmware can only recognize EU as ETSI domain and there is no
+	 * memory left for some devices to convert it in firmware, driver need
+	 * to convert it before passing country code to firmware through tlv
+	 */
+
+	if (wlan_is_etsi_country(pmadapter, pcountry_code))
+		return ("EU ");
+	else
+		return pcountry_code;
+}
+
+/**
+ *  @brief This function sets up domain_reg and downloads CMD to FW
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_cfg_domain_info(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11d_domain_info *domain_info = MNULL;
+	mlan_ds_11d_cfg *cfg_11d = MNULL;
+	t_u8 cfp_bg = 0, cfp_a = 0;
+
+	ENTER();
+
+	if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+		PRINTM(MERROR,
+		       "ForceRegionRule is set in the on-chip OTP memory\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (!wlan_fw_11d_is_enabled(pmpriv))
+		wlan_11d_enable(pmpriv, MNULL, ENABLE_11D);
+
+	cfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+	domain_info = &cfg_11d->param.domain_info;
+	memcpy_ext(pmadapter, pmadapter->country_code,
+		   domain_info->country_code, COUNTRY_CODE_LEN,
+		   COUNTRY_CODE_LEN);
+	wlan_11d_set_domain_info(pmpriv, domain_info->band,
+				 wlan_11d_map_country_code(pmadapter,
+							   domain_info->
+							   country_code),
+				 domain_info->no_of_sub_band,
+				 (IEEEtypes_SubbandSet_t *)domain_info->
+				 sub_band);
+	ret = wlan_11d_send_domain_info(pmpriv, pioctl_req);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	/* Update region code and table based on country code */
+	if (wlan_misc_country_2_cfp_table_code
+	    (pmadapter, domain_info->country_code, &cfp_bg, &cfp_a)) {
+		PRINTM(MIOCTL, "Country code %c%c not found!\n",
+		       domain_info->country_code[0],
+		       domain_info->country_code[1]);
+		goto done;
+	}
+	pmadapter->cfp_code_bg = cfp_bg;
+	pmadapter->cfp_code_a = cfp_a;
+	if (cfp_a)
+		pmadapter->region_code = cfp_a;
+	else if (cfp_bg)
+		pmadapter->region_code = cfp_bg;
+	else
+		pmadapter->region_code = 0;
+	if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
+				 pmadapter->config_bands |
+				 pmadapter->adhoc_start_band)) {
+		PRINTM(MIOCTL, "Fail to set regiontabl\n");
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(UAP_SUPPORT)
+/**
+ *  @brief This function handles domain info data from UAP interface.
+ *         Checks conditions, sets up domain_reg, then downloads CMD.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         Band interface is operating on
+ *  @param domain_tlv   Pointer to domain_info tlv
+ *  @param pioctl_buf   Pointer to the IOCTL buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11d_handle_uap_domain_info(mlan_private *pmpriv, t_u8 band,
+				t_u8 *domain_tlv, t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	MrvlIEtypes_DomainParamSet_t *pdomain_tlv;
+	t_u8 num_sub_band = 0;
+	t_u8 cfp_bg = 0, cfp_a = 0;
+
+	ENTER();
+
+	pdomain_tlv = (MrvlIEtypes_DomainParamSet_t *)domain_tlv;
+
+	/* update region code & table based on country string */
+	if (wlan_misc_country_2_cfp_table_code
+	    (pmadapter, pdomain_tlv->country_code, &cfp_bg,
+	     &cfp_a) == MLAN_STATUS_SUCCESS) {
+		pmadapter->cfp_code_bg = cfp_bg;
+		pmadapter->cfp_code_a = cfp_a;
+		if (cfp_a)
+			pmadapter->region_code = cfp_a;
+		else if (cfp_bg)
+			pmadapter->region_code = cfp_bg;
+		else
+			pmadapter->region_code = 0;
+		if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
+					 pmadapter->config_bands |
+					 pmadapter->adhoc_start_band)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	memcpy_ext(pmadapter, pmadapter->country_code,
+		   pdomain_tlv->country_code, COUNTRY_CODE_LEN,
+		   COUNTRY_CODE_LEN);
+	num_sub_band = ((pdomain_tlv->header.len - COUNTRY_CODE_LEN) /
+			sizeof(IEEEtypes_SubbandSet_t));
+
+	/* TODO: don't just clobber pmadapter->domain_reg.
+	 *       Add some checking or merging between STA & UAP domain_info
+	 */
+	wlan_11d_set_domain_info(pmpriv, band, pdomain_tlv->country_code,
+				 num_sub_band, pdomain_tlv->sub_band);
+	ret = wlan_11d_send_domain_info(pmpriv, pioctl_buf);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
diff --git a/wlan_sd8987/mlan/mlan_11h.c b/wlan_sd8987/mlan/mlan_11h.c
new file mode 100755
index 0000000..838ece1
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11h.c
@@ -0,0 +1,4384 @@
+/** @file mlan_11h.c
+ *
+ *  @brief This file contains functions for 802.11H.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    03/26/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_11h.h"
+#include "mlan_11n.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** Default IBSS DFS recovery interval (in TBTTs); used for adhoc start */
+#define WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL 100
+
+/** Default 11h power constraint used to offset the maximum transmit power */
+#define WLAN_11H_TPC_POWERCONSTRAINT 0
+
+/** 11h TPC Power capability minimum setting, sent in TPC_INFO command to fw */
+#define WLAN_11H_TPC_POWERCAPABILITY_MIN 5
+
+/** 11h TPC Power capability maximum setting, sent in TPC_INFO command to fw */
+#define WLAN_11H_TPC_POWERCAPABILITY_MAX 20
+
+/** Regulatory requirement for the duration of a channel availability check */
+#define WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION 60000	/* in ms */
+
+/** Starting Frequency for 11A band */
+#define START_FREQ_11A_BAND 5000	/* in MHz */
+
+/** DFS Channel Move Time */
+#define DFS_CHAN_MOVE_TIME 10	/* in sec */
+
+/** Regulatory requirement for the duration of a non-occupancy period */
+#define WLAN_11H_NON_OCCUPANCY_PERIOD 1800	/* in sec (30mins) */
+
+/** Maximum allowable age (seconds) on DFS report data */
+#define MAX_DFS_REPORT_USABLE_AGE_SEC (120)	/* 2 minutes */
+
+/** Minimum delay for CHAN_SW IE to broadcast by FW */
+#define MIN_RDH_CHAN_SW_IE_PERIOD_MSEC (400)	/* 4 beacons @ 100ms */
+
+/** Maximum delay for CHAN_SW IE to broadcast by FW */
+#define MAX_RDH_CHAN_SW_IE_PERIOD_MSEC (3000)	/* 5 beacons @ 600ms */
+
+/** Maximum retries on selecting new random channel */
+#define MAX_RANDOM_CHANNEL_RETRIES (20)
+
+/** Maximum retries on selecting new random non-dfs channel */
+#define MAX_SWITCH_CHANNEL_RETRIES (30)
+
+/** Value for undetermined priv_curr_idx on first entry to new RDH stage */
+#define RDH_STAGE_FIRST_ENTRY_PRIV_IDX (0xff)
+
+/** Region codes 0x10, 0x20:  channels 1 thru 11 supported */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_FCC = { 1,
+	11
+};
+
+/** Region codes 0x30, 0x32, 0x41, 0x50:  channels 1 thru 13 supported */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_EU = { 1,
+	13
+};
+
+/** Region code 0x40:  only channel 14 supported */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_JPN40 = { 14,
+	1
+};
+
+/** JPN sub-band config : Start Channel = 8, NumChans = 3 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_JPN_bottom_band = { 8,
+	3
+};
+
+/** U-NII sub-band config : Start Channel = 36, NumChans = 4 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_lower_band = { 36,
+	4
+};
+
+/** U-NII sub-band config : Start Channel = 52, NumChans = 4 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_middle_band = { 52,
+	4
+};
+
+/** U-NII sub-band config : Start Channel = 100, NumChans = 11 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band = {
+	100, 11
+};
+
+/** U-NII sub-band config : Start Channel = 100, NumChans = 5 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band_0 = {
+	100, 5
+};
+
+/** U-NII sub-band config : Start Channel = 132, NumChans = 3 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band_1 = {
+	132, 3
+};
+
+/** U-NII sub-band config : Start Channel = 149, NumChans = 5 */
+static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_upper_band = { 149,
+	5
+};
+
+/** Internally passed structure used to send a CMD_802_11_TPC_INFO command */
+typedef struct {
+	t_u8 chan; /**< Channel to which the power constraint applies */
+	t_u8 power_constraint; /**< Local power constraint to send to firmware
+				*/
+} wlan_11h_tpc_info_param_t;
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Utility function to get a random number based on the underlying OS
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @return random integer
+ */
+static t_u32
+wlan_11h_get_random_num(pmlan_adapter pmadapter)
+{
+	t_u32 sec, usec;
+
+	ENTER();
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+						  &usec);
+	sec = (sec & 0xFFFF) + (sec >> 16);
+	usec = (usec & 0xFFFF) + (usec >> 16);
+
+	LEAVE();
+	return (usec << 16) | sec;
+}
+
+/**
+ *  @brief Convert an IEEE formatted IE to 16-bit ID/Len NXP
+ *         proprietary format
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @param pout_buf Output parameter: Buffer to output NXP formatted IE
+ *  @param pin_ie   Pointer to IEEE IE to be converted to NXP format
+ *
+ *  @return         Number of bytes output to pout_buf parameter return
+ */
+static t_u32
+wlan_11h_convert_ieee_to_mrvl_ie(mlan_adapter *pmadapter,
+				 t_u8 *pout_buf, const t_u8 *pin_ie)
+{
+	MrvlIEtypesHeader_t mrvl_ie_hdr;
+	t_u8 *ptmp_buf = pout_buf;
+
+	ENTER();
+	/* Assign the Element Id and Len to the NXP struct attributes */
+	mrvl_ie_hdr.type = wlan_cpu_to_le16(pin_ie[0]);
+	mrvl_ie_hdr.len = wlan_cpu_to_le16(pin_ie[1]);
+
+	/* If the element ID is zero, return without doing any copying */
+	if (!mrvl_ie_hdr.type) {
+		LEAVE();
+		return 0;
+	}
+
+	/* Copy the header to the buffer pointer */
+	memcpy_ext(pmadapter, ptmp_buf, &mrvl_ie_hdr, sizeof(mrvl_ie_hdr),
+		   sizeof(mrvl_ie_hdr));
+
+	/* Increment the temp buffer pointer by the size appended */
+	ptmp_buf += sizeof(mrvl_ie_hdr);
+
+	/* Append the data section of the IE; length given by the IEEE IE length
+	 */
+	memcpy_ext(pmadapter, ptmp_buf, pin_ie + 2, pin_ie[1], pin_ie[1]);
+
+	LEAVE();
+	/* Return the number of bytes appended to pout_buf */
+	return sizeof(mrvl_ie_hdr) + pin_ie[1];
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Setup the IBSS DFS element passed to the firmware in adhoc start
+ *         and join commands
+ *
+ *  The DFS Owner and recovery fields are set to be our MAC address and
+ *    a predetermined constant recovery value.  If we are joining an adhoc
+ *    network, these values are replaced with the existing IBSS values.
+ *    They are valid only when starting a new IBSS.
+ *
+ *  The IBSS DFS Element is variable in size based on the number of
+ *    channels supported in our current region.
+ *
+ *  @param priv Private driver information structure
+ *  @param pdfs Output parameter: Pointer to the IBSS DFS element setup by
+ *              this function.
+ *
+ *  @return
+ *    - Length of the returned element in pdfs output parameter
+ *    - 0 if returned element is not setup
+ */
+static t_u32
+wlan_11h_set_ibss_dfs_ie(mlan_private *priv, IEEEtypes_IBSS_DFS_t *pdfs)
+{
+	t_u8 num_chans = 0;
+	MeasRptBasicMap_t initial_map;
+	mlan_adapter *adapter = priv->adapter;
+
+	ENTER();
+
+	memset(adapter, pdfs, 0x00, sizeof(IEEEtypes_IBSS_DFS_t));
+
+	/*
+	 * A basic measurement report is included with each channel in the
+	 *   map field.  Initial value for the map for each supported channel
+	 *   is with only the unmeasured bit set.
+	 */
+	memset(adapter, &initial_map, 0x00, sizeof(initial_map));
+	initial_map.unmeasured = 1;
+
+	/* Set the DFS Owner and recovery interval fields */
+	memcpy_ext(adapter, pdfs->dfs_owner, priv->curr_addr,
+		   sizeof(pdfs->dfs_owner), sizeof(pdfs->dfs_owner));
+	pdfs->dfs_recovery_interval = WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL;
+
+	for (; (num_chans < adapter->parsed_region_chan.no_of_chan) &&
+	     (num_chans < WLAN_11H_MAX_IBSS_DFS_CHANNELS); num_chans++) {
+		pdfs->channel_map[num_chans].channel_number =
+			adapter->parsed_region_chan.chan_pwr[num_chans].chan;
+
+		/*
+		 * Set the initial map field with a basic measurement
+		 */
+		pdfs->channel_map[num_chans].rpt_map = initial_map;
+	}
+
+	/*
+	 * If we have an established channel map, include it and return
+	 *   a valid DFS element
+	 */
+	if (num_chans) {
+		PRINTM(MINFO, "11h: Added %d channels to IBSS DFS Map\n",
+		       num_chans);
+
+		pdfs->element_id = IBSS_DFS;
+		pdfs->len = (sizeof(pdfs->dfs_owner) +
+			     sizeof(pdfs->dfs_recovery_interval) +
+			     num_chans * sizeof(IEEEtypes_ChannelMap_t));
+
+		LEAVE();
+		return pdfs->len + sizeof(pdfs->len) + sizeof(pdfs->element_id);
+	}
+
+	/* Ensure the element is zeroed out for an invalid return */
+	memset(adapter, pdfs, 0x00, sizeof(IEEEtypes_IBSS_DFS_t));
+
+	LEAVE();
+	return 0;
+}
+#endif
+
+/**
+ *  @brief Setup the Supported Channel IE sent in association requests
+ *
+ *  The Supported Channels IE is required to be sent when the spectrum
+ *    management capability (11h) is enabled.  The element contains a
+ *    starting channel and number of channels tuple for each sub-band
+ *    the STA supports.  This information is based on the operating region.
+ *
+ *  @param priv      Private driver information structure
+ *  @param band      Band in use
+ *  @param psup_chan Output parameter: Pointer to the Supported Chan element
+ *                   setup by this function.
+ *
+ *  @return
+ *    - Length of the returned element in psup_chan output parameter
+ *    - 0 if returned element is not setup
+ */
+static t_u16
+wlan_11h_set_supp_channels_ie(mlan_private *priv, t_u8 band,
+			      IEEEtypes_SupportedChannels_t *psup_chan)
+{
+	t_u16 num_subbands = 0;
+	t_u16 ret_len = 0;
+	t_u8 cfp_bg, cfp_a;
+
+	ENTER();
+	memset(priv->adapter, psup_chan, 0x00,
+	       sizeof(IEEEtypes_SupportedChannels_t));
+
+	cfp_bg = cfp_a = priv->adapter->region_code;
+	if (!priv->adapter->region_code) {
+		/* Invalid region code, use CFP code */
+		cfp_bg = priv->adapter->cfp_code_bg;
+		cfp_a = priv->adapter->cfp_code_a;
+	}
+
+	if ((band & BAND_B) || (band & BAND_G)) {
+		/*
+		 * Channels are contiguous in 2.4GHz, usually only one subband.
+		 */
+		switch (cfp_bg) {
+		case 0x10:	/* USA FCC   */
+		case 0x20:	/* Canada IC */
+		default:
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_2_4G_region_FCC;
+			break;
+		case 0x30:	/* Europe ETSI */
+		case 0x41:	/* Japan  */
+		case 0x50:	/* China  */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_2_4G_region_EU;
+			break;
+		case 0x40:	/* Japan  */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_2_4G_region_JPN40;
+			break;
+		case 0xff:	/* Japan special */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_2_4G_region_EU;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_2_4G_region_JPN40;
+			break;
+		}
+	} else if (band & BAND_A) {
+		/*
+		 * Set the supported channel elements based on the region code,
+		 * incrementing num_subbands for each sub-band we append to the
+		 * element.
+		 */
+		switch (cfp_a) {
+		case 0x10:	/* USA FCC   */
+		case 0x20:	/* Canada IC */
+		case 0x30:	/* Europe ETSI */
+		default:
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_middle_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_mid_upper_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_upper_band;
+			break;
+		case 0x50:	/* China */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_middle_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_upper_band;
+			break;
+		case 0x40:	/* Japan */
+		case 0x41:	/* Japan */
+		case 0xff:	/* Japan special */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_JPN_bottom_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_middle_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_mid_upper_band;
+			break;
+		case 0x1:	/* Low band (5150-5250 MHz) channels */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			break;
+		case 0x2:	/* Lower middle band (5250-5350 MHz) channels */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_middle_band;
+			break;
+		case 0x3:	/* Upper middle band (5470-5725 MHz) channels */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_mid_upper_band;
+			break;
+		case 0x4:	/* High band (5725-5850 MHz) channels */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_upper_band;
+			break;
+		case 0x5:	/* Low band (5150-5250 MHz) and High band (5725-5850
+				   MHz) channels */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_upper_band;
+			break;
+		case 0x6:	/* Low band (5150-5250 MHz) and Lower middle band
+				   (5250-5350 MHz) and High band (5725-5850 MHz)
+				   channels */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_middle_band;
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_upper_band;
+			break;
+		case 0x7:
+			/* 36-48 */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_lower_band;
+			/* 52-64 */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_middle_band;
+			/* 100-116 */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_mid_upper_band_0;
+			/* 132-140 */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_mid_upper_band_1;
+			/* 149-165 */
+			psup_chan->subband[num_subbands++] =
+				wlan_11h_unii_upper_band;
+			break;
+		}
+	}
+
+	/*
+	 * If we have setup any supported subbands in the element, return a
+	 *    valid IE along with its size, else return 0.
+	 */
+	if (num_subbands) {
+		psup_chan->element_id = SUPPORTED_CHANNELS;
+		psup_chan->len =
+			num_subbands * sizeof(IEEEtypes_SupportChan_Subband_t);
+
+		ret_len = (t_u16)(psup_chan->len + sizeof(psup_chan->len) +
+				  sizeof(psup_chan->element_id));
+
+		HEXDUMP("11h: SupChan", (t_u8 *)psup_chan, ret_len);
+	}
+
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief Prepare CMD_802_11_TPC_ADAPT_REQ firmware command
+ *
+ *  @param priv      Private driver information structure
+ *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
+ *                   for the firmware
+ *  @param pinfo_buf HostCmd_DS_802_11_TPC_ADAPT_REQ passed as void data block
+ *
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11h_cmd_tpc_request(mlan_private *priv,
+			 HostCmd_DS_COMMAND *pcmd_ptr, const t_void *pinfo_buf)
+{
+	ENTER();
+
+	memcpy_ext(priv->adapter, &pcmd_ptr->params.tpc_req, pinfo_buf,
+		   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ),
+		   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ));
+
+	pcmd_ptr->params.tpc_req.req.timeout =
+		wlan_cpu_to_le16(pcmd_ptr->params.tpc_req.req.timeout);
+
+	/* Converted to little endian in wlan_11h_cmd_process */
+	pcmd_ptr->size = sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ) + S_DS_GEN;
+
+	HEXDUMP("11h: 11_TPC_ADAPT_REQ:", (t_u8 *)pcmd_ptr,
+		(t_u32)pcmd_ptr->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Prepare CMD_802_11_TPC_INFO firmware command
+ *
+ *  @param priv      Private driver information structure
+ *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
+ *                   for the firmware
+ *  @param pinfo_buf wlan_11h_tpc_info_param_t passed as void data block
+ *
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11h_cmd_tpc_info(mlan_private *priv,
+		      HostCmd_DS_COMMAND *pcmd_ptr, const t_void *pinfo_buf)
+{
+	HostCmd_DS_802_11_TPC_INFO *ptpc_info = &pcmd_ptr->params.tpc_info;
+	MrvlIEtypes_LocalPowerConstraint_t *pconstraint =
+		&ptpc_info->local_constraint;
+	MrvlIEtypes_PowerCapability_t *pcap = &ptpc_info->power_cap;
+
+	wlan_11h_device_state_t *pstate = &priv->adapter->state_11h;
+	const wlan_11h_tpc_info_param_t *ptpc_info_param =
+		(wlan_11h_tpc_info_param_t *)pinfo_buf;
+
+	ENTER();
+
+	pcap->min_power = pstate->min_tx_power_capability;
+	pcap->max_power = pstate->max_tx_power_capability;
+	pcap->header.len = wlan_cpu_to_le16(2);
+	pcap->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CAPABILITY);
+
+	pconstraint->chan = ptpc_info_param->chan;
+	pconstraint->constraint = ptpc_info_param->power_constraint;
+	pconstraint->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CONSTRAINT);
+	pconstraint->header.len = wlan_cpu_to_le16(2);
+
+	/* Converted to little endian in wlan_11h_cmd_process */
+	pcmd_ptr->size = sizeof(HostCmd_DS_802_11_TPC_INFO) + S_DS_GEN;
+
+	HEXDUMP("11h: TPC INFO", (t_u8 *)pcmd_ptr, (t_u32)pcmd_ptr->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Prepare CMD_802_11_CHAN_SW_ANN firmware command
+ *
+ *  @param priv      Private driver information structure
+ *  @param pcmd_ptr  Output parameter: Pointer to the command being
+ *                   prepared to for firmware
+ *  @param pinfo_buf HostCmd_DS_802_11_CHAN_SW_ANN passed as void data block
+ *
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11h_cmd_chan_sw_ann(mlan_private *priv,
+			 HostCmd_DS_COMMAND *pcmd_ptr, const t_void *pinfo_buf)
+{
+	const HostCmd_DS_802_11_CHAN_SW_ANN *pch_sw_ann =
+		(HostCmd_DS_802_11_CHAN_SW_ANN *)pinfo_buf;
+
+	ENTER();
+
+	/* Converted to little endian in wlan_11h_cmd_process */
+	pcmd_ptr->size = sizeof(HostCmd_DS_802_11_CHAN_SW_ANN) + S_DS_GEN;
+
+	memcpy_ext(priv->adapter, &pcmd_ptr->params.chan_sw_ann, pch_sw_ann,
+		   sizeof(HostCmd_DS_802_11_CHAN_SW_ANN),
+		   sizeof(HostCmd_DS_802_11_CHAN_SW_ANN));
+
+	PRINTM(MINFO, "11h: ChSwAnn: %#x-%u, Seq=%u, Ret=%u\n",
+	       pcmd_ptr->command, pcmd_ptr->size, pcmd_ptr->seq_num,
+	       pcmd_ptr->result);
+	PRINTM(MINFO, "11h: ChSwAnn: Ch=%d, Cnt=%d, Mode=%d\n",
+	       pch_sw_ann->new_chan, pch_sw_ann->switch_count,
+	       pch_sw_ann->switch_mode);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Prepare CMD_CHAN_REPORT_REQUEST firmware command
+ *
+ *  @param priv      Private driver information structure
+ *  @param pcmd_ptr  Output parameter: Pointer to the command being
+ *                   prepared to for firmware
+ *  @param pinfo_buf HostCmd_DS_CHAN_RPT_REQ passed as void data block
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
+ */
+static mlan_status
+wlan_11h_cmd_chan_rpt_req(mlan_private *priv,
+			  HostCmd_DS_COMMAND *pcmd_ptr, const t_void *pinfo_buf)
+{
+	HostCmd_DS_CHAN_RPT_REQ *pchan_rpt_req =
+		(HostCmd_DS_CHAN_RPT_REQ *)pinfo_buf;
+	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+	MrvlIEtypes_ChanRpt11hBasic_t *ptlv_basic;
+	t_bool is_cancel_req = MFALSE;
+	t_u8 dfs53cfg = priv->adapter->dfs53cfg;
+	MrvlIEtypes_DfsW53Cfg_t *ptlv_dfs53cfg;
+
+	ENTER();
+
+	/*
+	 * pchan_rpt_req->millisec_dwell_time would be zero if the chan_rpt_req
+	 * is to cancel current ongoing report
+	 */
+	if (pchan_rpt_req->millisec_dwell_time == 0)
+		is_cancel_req = MTRUE;
+
+	if (pstate_dfs->dfs_check_pending && !is_cancel_req) {
+		PRINTM(MERROR,
+		       "11h: ChanRptReq - previous CMD_CHAN_REPORT_REQUEST has"
+		       " not returned its result yet (as EVENT_CHANNEL_READY)."
+		       "  This command will be dropped.\n");
+		LEAVE();
+		return MLAN_STATUS_PENDING;
+	}
+
+	/* Converted to little endian in wlan_11h_cmd_process */
+	pcmd_ptr->size = sizeof(HostCmd_DS_CHAN_RPT_REQ) + S_DS_GEN;
+
+	memcpy_ext(priv->adapter, &pcmd_ptr->params.chan_rpt_req, pchan_rpt_req,
+		   sizeof(HostCmd_DS_CHAN_RPT_REQ),
+		   sizeof(HostCmd_DS_CHAN_RPT_REQ));
+	pcmd_ptr->params.chan_rpt_req.chan_desc.startFreq =
+		wlan_cpu_to_le16(pchan_rpt_req->chan_desc.startFreq);
+	pcmd_ptr->params.chan_rpt_req.millisec_dwell_time =
+		wlan_cpu_to_le32(pchan_rpt_req->millisec_dwell_time);
+
+	/* if DFS channel, add BASIC report TLV, and set radar bit */
+	if (!is_cancel_req &&
+	    wlan_11h_radar_detect_required(priv,
+					   pchan_rpt_req->chan_desc.chanNum)) {
+		ptlv_basic =
+			(MrvlIEtypes_ChanRpt11hBasic_t *)(((t_u8 *)(pcmd_ptr)) +
+							  pcmd_ptr->size);
+		ptlv_basic->Header.type =
+			wlan_cpu_to_le16(TLV_TYPE_CHANRPT_11H_BASIC);
+		ptlv_basic->Header.len =
+			wlan_cpu_to_le16(sizeof(MeasRptBasicMap_t));
+		memset(priv->adapter, &ptlv_basic->map, 0,
+		       sizeof(MeasRptBasicMap_t));
+		ptlv_basic->map.radar = 1;
+		pcmd_ptr->size += sizeof(MrvlIEtypes_ChanRpt11hBasic_t);
+	}
+
+	if ((priv->adapter->region_code == COUNTRY_CODE_JP_40 ||
+	     priv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
+	    (dfs53cfg != DFS_W53_DEFAULT_FW)) {
+		ptlv_dfs53cfg =
+			(MrvlIEtypes_DfsW53Cfg_t *) (((t_u8 *)(pcmd_ptr)) +
+						     pcmd_ptr->size);
+		ptlv_dfs53cfg->Header.type =
+			wlan_cpu_to_le16(TLV_TYPE_DFS_W53_CFG);
+		ptlv_dfs53cfg->Header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		ptlv_dfs53cfg->dfs53cfg = dfs53cfg;
+		pcmd_ptr->size += sizeof(MrvlIEtypes_DfsW53Cfg_t);
+	}
+
+	pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
+
+	/* update dfs sturcture.
+	 * dfs_check_pending is set when we receive CMD_RESP == SUCCESS */
+	pstate_dfs->dfs_check_pending = MFALSE;
+	pstate_dfs->dfs_radar_found = MFALSE;
+	pstate_dfs->dfs_check_priv = MNULL;
+
+	if (!is_cancel_req)
+		pstate_dfs->dfs_check_channel =
+			pchan_rpt_req->chan_desc.chanNum;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set the local power capability and constraint TLV
+ *
+ *  @param ppbuffer                The buffer to add these two TLVs
+ *  @param channel                 Channel to which the power constraint applies
+ *  @param power_constraint        Power constraint to be applied on the channel
+ *  @param min_tx_power_capability Min. Tx Power in Power Capability IE
+ *  @param max_tx_power_capability Max. Tx Power in Power Capability IE
+ *
+ *  @return                        The len increased
+ */
+static t_u32
+wlan_11h_set_local_power_constraint_tlv(t_u8 **ppbuffer, t_u8 channel,
+					t_u8 power_constraint,
+					t_u8 min_tx_power_capability,
+					t_u8 max_tx_power_capability)
+{
+	MrvlIEtypes_PowerCapability_t *pcap;
+	MrvlIEtypes_LocalPowerConstraint_t *pconstraint;
+	t_u8 *start_ptr = MNULL;
+
+	ENTER();
+
+	/* Null Checks */
+	if ((ppbuffer == MNULL) || (((t_u8 *)(*ppbuffer)) == MNULL)) {
+		LEAVE();
+		return 0;
+	}
+
+	start_ptr = (t_u8 *)(*ppbuffer);
+
+	PRINTM(MINFO,
+	       "11h: Set local power constraint = %d channel=%d min_tx_pwr=%d max_tx_pwr=%d\n",
+	       power_constraint, channel, min_tx_power_capability,
+	       max_tx_power_capability);
+
+	pcap = (MrvlIEtypes_PowerCapability_t *)*ppbuffer;
+	pcap->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CAPABILITY);
+	pcap->header.len = wlan_cpu_to_le16(2);
+	pcap->min_power = min_tx_power_capability;
+	pcap->max_power = max_tx_power_capability;
+	*ppbuffer += sizeof(MrvlIEtypesHeader_t) + 2;
+
+	pconstraint = (MrvlIEtypes_LocalPowerConstraint_t *)*ppbuffer;
+	pconstraint->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CONSTRAINT);
+	pconstraint->header.len = wlan_cpu_to_le16(2);
+	pconstraint->chan = channel;
+	pconstraint->constraint = power_constraint;
+	*ppbuffer += sizeof(MrvlIEtypesHeader_t) + 2;
+
+	LEAVE();
+	return (t_u32)(*ppbuffer - start_ptr);
+}
+
+/**
+ *  @brief  Utility function to process a join to an infrastructure BSS
+ *
+ *  @param priv          Private driver information structure
+ *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
+ *                       modified on return to point after the appended 11h TLVs
+ *  @param band          Band on which we are joining the BSS
+ *  @param channel       Channel on which we are joining the BSS
+ *  @param p11h_bss_info Pointer to the 11h BSS information for this network
+ *                       that was parsed out of the scan response.
+ *
+ *  @return              Integer number of bytes appended to the TLV output
+ *                       buffer (ppbuffer)
+ */
+static t_u32
+wlan_11h_process_infra_join(mlan_private *priv, t_u8 **ppbuffer,
+			    t_u8 band, t_u32 channel,
+			    wlan_11h_bss_info_t *p11h_bss_info)
+{
+	MrvlIEtypesHeader_t ie_header;
+	IEEEtypes_SupportedChannels_t sup_chan_ie;
+	t_u32 ret_len = 0;
+	t_u16 sup_chan_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if ((ppbuffer == MNULL) || (((t_u8 *)(*ppbuffer)) == MNULL)) {
+		LEAVE();
+		return 0;
+	}
+
+	ret_len +=
+		wlan_11h_set_local_power_constraint_tlv(ppbuffer, (t_u8)channel,
+							(t_u8)p11h_bss_info->
+							power_constraint.
+							local_constraint,
+							(t_u8)priv->adapter->
+							state_11h.
+							min_tx_power_capability,
+							(t_u8)priv->adapter->
+							state_11h.
+							max_tx_power_capability);
+
+	/* Setup the Supported Channels IE */
+	sup_chan_len = wlan_11h_set_supp_channels_ie(priv, band, &sup_chan_ie);
+
+	/*
+	 * If we returned a valid Supported Channels IE, wrap and append it
+	 */
+	if (sup_chan_len) {
+		/* Wrap the supported channels IE with a passthrough TLV type */
+		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+		ie_header.len = wlan_cpu_to_le16(sup_chan_len);
+		memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+			   sizeof(ie_header), sizeof(ie_header));
+
+		/*
+		 * Increment the return size and the return buffer
+		 * pointer param
+		 */
+		*ppbuffer += sizeof(ie_header);
+		ret_len += sizeof(ie_header);
+
+		/*
+		 * Copy the supported channels IE to the output buf,
+		 * advance pointer
+		 */
+		memcpy_ext(priv->adapter, *ppbuffer, &sup_chan_ie, sup_chan_len,
+			   sup_chan_len);
+		*ppbuffer += sup_chan_len;
+		ret_len += sup_chan_len;
+	}
+
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief Utility function to process a start or join to an adhoc network
+ *
+ *  Add the elements to the TLV buffer needed in the start/join adhoc commands:
+ *       - IBSS DFS IE
+ *       - Quiet IE
+ *
+ *  Also send the local constraint to the firmware in a TPC_INFO command.
+ *
+ *  @param priv          Private driver information structure
+ *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
+ *                       modified on return to point after the appended 11h TLVs
+ *  @param channel       Channel on which we are starting/joining the IBSS
+ *  @param p11h_bss_info Pointer to the 11h BSS information for this network
+ *                       that was parsed out of the scan response.  NULL
+ *                       indicates we are starting the adhoc network
+ *
+ *  @return              Integer number of bytes appended to the TLV output
+ *                       buffer (ppbuffer)
+ */
+static t_u32
+wlan_11h_process_adhoc(mlan_private *priv, t_u8 **ppbuffer,
+		       t_u32 channel, wlan_11h_bss_info_t *p11h_bss_info)
+{
+	IEEEtypes_IBSS_DFS_t dfs_elem;
+	t_u32 size_appended;
+	t_u32 ret_len = 0;
+	t_s8 local_constraint = 0;
+	mlan_adapter *adapter = priv->adapter;
+
+	ENTER();
+
+#ifdef STA_SUPPORT
+	/* Format our own IBSS DFS Element.  Include our channel map fields */
+	wlan_11h_set_ibss_dfs_ie(priv, &dfs_elem);
+#endif
+
+	if (p11h_bss_info) {
+		/*
+		 * Copy the DFS Owner/Recovery Interval from the BSS
+		 * we are joining
+		 */
+		memcpy_ext(adapter, dfs_elem.dfs_owner,
+			   p11h_bss_info->ibss_dfs.dfs_owner,
+			   sizeof(dfs_elem.dfs_owner),
+			   sizeof(dfs_elem.dfs_owner));
+		dfs_elem.dfs_recovery_interval =
+			p11h_bss_info->ibss_dfs.dfs_recovery_interval;
+	}
+
+	/* Append the dfs element to the TLV buffer */
+	size_appended =
+		wlan_11h_convert_ieee_to_mrvl_ie(adapter, (t_u8 *)*ppbuffer,
+						 (t_u8 *)&dfs_elem);
+
+	HEXDUMP("11h: IBSS-DFS", (t_u8 *)*ppbuffer, size_appended);
+	*ppbuffer += size_appended;
+	ret_len += size_appended;
+
+	/*
+	 * Check to see if we are joining a network.  Join is indicated by the
+	 *   BSS Info pointer being valid (not NULL)
+	 */
+	if (p11h_bss_info) {
+		/*
+		 * If there was a quiet element, include it in
+		 * adhoc join command
+		 */
+		if (p11h_bss_info->quiet.element_id == QUIET) {
+			size_appended =
+				wlan_11h_convert_ieee_to_mrvl_ie(adapter,
+								 (t_u8 *)
+								 *ppbuffer,
+								 (t_u8 *)
+								 &p11h_bss_info->
+								 quiet);
+			HEXDUMP("11h: Quiet", (t_u8 *)*ppbuffer, size_appended);
+			*ppbuffer += size_appended;
+			ret_len += size_appended;
+		}
+
+		/* Copy the local constraint from the network */
+		local_constraint =
+			p11h_bss_info->power_constraint.local_constraint;
+	} else {
+		/*
+		 * If we are the adhoc starter, we can add a quiet element
+		 */
+		if (adapter->state_11h.quiet_ie.quiet_period) {
+			size_appended =
+				wlan_11h_convert_ieee_to_mrvl_ie(adapter,
+								 (t_u8 *)
+								 *ppbuffer,
+								 (t_u8 *)
+								 &adapter->
+								 state_11h.
+								 quiet_ie);
+			HEXDUMP("11h: Quiet", (t_u8 *)*ppbuffer, size_appended);
+			*ppbuffer += size_appended;
+			ret_len += size_appended;
+		}
+		/* Use the local_constraint configured in the driver state */
+		local_constraint = adapter->state_11h.usr_def_power_constraint;
+	}
+
+	PRINTM(MINFO, "WEILIE 1: ppbuffer = %p\n", *ppbuffer);
+
+	ret_len +=
+		wlan_11h_set_local_power_constraint_tlv(ppbuffer, (t_u8)channel,
+							(t_u8)local_constraint,
+							(t_u8)priv->adapter->
+							state_11h.
+							min_tx_power_capability,
+							(t_u8)priv->adapter->
+							state_11h.
+							max_tx_power_capability);
+	PRINTM(MINFO, "WEILIE 2: ppbuffer = %p\n", *ppbuffer);
+
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief Return whether the driver has enabled 11h for the interface
+ *
+ *  Association/Join commands are dynamic in that they enable 11h in the
+ *    driver/firmware when they are detected in the existing BSS.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if 11h is enabled
+ *    - MFALSE otherwise
+ */
+static t_bool
+wlan_11h_is_enabled(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->intf_state_11h.is_11h_enabled;
+}
+
+/**
+ *  @brief Return whether the device has activated slave radar detection.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if slave radar detection is enabled in firmware
+ *    - MFALSE otherwise
+ */
+static t_bool
+wlan_11h_is_slave_radar_det_active(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->adapter->state_11h.is_slave_radar_det_active;
+}
+
+/**
+ *  @brief Return whether the slave interface is active, and on DFS channel.
+ *  priv is assumed to already be a dfs slave interface, doesn't check this.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if priv is slave, and meets both conditions
+ *    - MFALSE otherwise
+ */
+static t_bool
+wlan_11h_is_slave_active_on_dfs_chan(mlan_private *priv)
+{
+	t_bool ret = MFALSE;
+
+	ENTER();
+	if ((priv->media_connected == MTRUE) &&
+	    (priv->curr_bss_params.band & BAND_A) &&
+	    wlan_11h_radar_detect_required(priv,
+					   priv->curr_bss_params.bss_descriptor.
+					   channel))
+		ret = MTRUE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Return whether the master interface is active, and on DFS channel.
+ *  priv is assumed to already be a dfs master interface, doesn't check this.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if priv is master, and meets both conditions
+ *    - MFALSE otherwise
+ */
+static t_bool
+wlan_11h_is_master_active_on_dfs_chan(mlan_private *priv)
+{
+	t_bool ret = MFALSE;
+
+	ENTER();
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		/* Ad-hoc creator */
+		if (((priv->media_connected == MTRUE) ||
+		     (priv->adhoc_state == ADHOC_STARTING)) &&
+		    (priv->adapter->adhoc_start_band & BAND_A) &&
+		    wlan_11h_radar_detect_required(priv, priv->adhoc_channel))
+			ret = MTRUE;
+	} else if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		/* UAP */
+#ifdef UAP_SUPPORT
+		if ((priv->uap_bss_started == MTRUE) &&
+		    (priv->uap_state_chan_cb.bandcfg.chanBand == BAND_5GHZ) &&
+		    wlan_11h_radar_detect_required(priv,
+						   priv->uap_state_chan_cb.
+						   channel))
+			ret = MTRUE;
+#endif
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Determine if priv is DFS Master interface
+ *
+ *  @param priv Pointer to mlan_private
+ *
+ *  @return MTRUE or MFALSE
+ */
+static t_bool
+wlan_11h_is_dfs_master(mlan_private *priv)
+{
+	t_bool ret = MFALSE;
+
+	ENTER();
+	/* UAP: all are master */
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+		ret = MTRUE;
+
+	/* STA: only ad-hoc creator is master */
+	else if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+		 (priv->bss_mode == MLAN_BSS_MODE_IBSS) &&
+		 (priv->adhoc_state == ADHOC_STARTED ||
+		  priv->adhoc_state == ADHOC_STARTING))
+		ret = MTRUE;
+
+	/* all other cases = slave interface */
+	LEAVE();
+	return ret;
+}
+
+/* Need this as function to pass to wlan_count_priv_cond() */
+/**
+ *  @brief Determine if priv is DFS Slave interface
+ *
+ *  @param priv Pointer to mlan_private
+ *
+ *  @return MTRUE or MFALSE
+ */
+
+static t_bool
+wlan_11h_is_dfs_slave(mlan_private *priv)
+{
+	t_bool ret = MFALSE;
+	ENTER();
+	ret = !wlan_11h_is_dfs_master(priv);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if interface is active.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             MTRUE or MFALSE
+ */
+t_bool
+wlan_is_intf_active(mlan_private *pmpriv)
+{
+	t_bool ret = MFALSE;
+	ENTER();
+
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+		/*
+		 * NOTE: UAP's media_connected == true only after first STA
+		 * associated. Need different variable to tell if UAP
+		 * has been started.
+		 */
+		ret = pmpriv->uap_bss_started;
+	else
+#endif
+	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+		ret = pmpriv->media_connected;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets current radar detect flags
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             11H MIB setting for radar detect
+ */
+static t_u32
+wlan_11h_get_current_radar_detect_flags(mlan_adapter *pmadapter)
+{
+	t_u32 radar_det_flags = 0;
+
+	ENTER();
+	if (pmadapter->state_11h.is_master_radar_det_active)
+		radar_det_flags |= MASTER_RADAR_DET_MASK;
+	if (pmadapter->state_11h.is_slave_radar_det_active)
+		radar_det_flags |= SLAVE_RADAR_DET_MASK;
+
+	PRINTM(MINFO, "%s: radar_det_state_curr=0x%x\n", __func__,
+	       radar_det_flags);
+
+	LEAVE();
+	return radar_det_flags;
+}
+
+/**
+ *  @brief This function checks if radar detect flags have/should be changed.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pnew_state   Output param with new state, if return MTRUE.
+ *
+ *  @return             MTRUE (need update) or MFALSE (no change in flags)
+ */
+static t_bool
+wlan_11h_check_radar_det_state(mlan_adapter *pmadapter, t_u32 *pnew_state)
+{
+	t_u32 radar_det_state_new = 0;
+	t_bool ret;
+
+	ENTER();
+	PRINTM(MINFO,
+	       "%s: master_radar_det_pending=%d, "
+	       " slave_radar_det_pending=%d\n",
+	       __func__, pmadapter->state_11h.master_radar_det_enable_pending,
+	       pmadapter->state_11h.slave_radar_det_enable_pending);
+
+	/* new state comes from evaluating interface states & pending starts */
+	if (pmadapter->state_11h.master_radar_det_enable_pending ||
+	    (wlan_count_priv_cond(pmadapter,
+				  wlan_11h_is_master_active_on_dfs_chan,
+				  wlan_11h_is_dfs_master) > 0))
+		radar_det_state_new |= MASTER_RADAR_DET_MASK;
+	if (pmadapter->state_11h.slave_radar_det_enable_pending ||
+	    (wlan_count_priv_cond(pmadapter,
+				  wlan_11h_is_slave_active_on_dfs_chan,
+				  wlan_11h_is_dfs_slave) > 0))
+		radar_det_state_new |= SLAVE_RADAR_DET_MASK;
+
+	PRINTM(MINFO, "%s: radar_det_state_new=0x%x\n", __func__,
+	       radar_det_state_new);
+
+	/* now compare flags with current state */
+	ret = (wlan_11h_get_current_radar_detect_flags(pmadapter) !=
+	       radar_det_state_new) ? MTRUE : MFALSE;
+	if (ret)
+		*pnew_state = radar_det_state_new;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief generate the channel center frequency index
+ *
+ *  @param channel_num       channel number
+ *
+ *  @return                 frenquency index
+ */
+static t_u8
+wlan_11h_get_channel_freq_idx(t_u8 channel_num)
+{
+	t_u8 index;
+	t_u8 center_freq[] = { 42, 58, 106, 122, 138, 155 };
+	t_u8 chan_idx, ret = 0;
+
+	chan_idx = channel_num - 100;
+
+	for (index = 0; index < sizeof(center_freq); index++) {
+		if ((chan_idx >= (center_freq[index] - 6)) &&
+		    (chan_idx <= (center_freq[index] + 6))) {
+			ret = center_freq[index];
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Prepare ioctl for add/remove CHAN_SW IE - RADAR_DETECTED event
+ * handling
+ *
+ *  @param pmadapter        Pointer to mlan_adapter
+ *  @param pioctl_req       Pointer to completed mlan_ioctl_req (allocated
+ * inside)
+ *  @param ppcust_chansw_ie Poniter to customer ie
+ *  @param is_adding_ie     CHAN_SW IE is to be added (MTRUE), or removed
+ * (MFALSE)
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11h_prepare_custom_ie_chansw(mlan_adapter *pmadapter,
+				  mlan_ioctl_req **ppioctl_req,
+				  t_bool is_adding_ie)
+{
+	mlan_ioctl_req *pioctl_req = MNULL;
+	mlan_ds_misc_cfg *pds_misc_cfg = MNULL;
+	custom_ie *pcust_chansw_ie = MNULL;
+	IEEEtypes_ChanSwitchAnn_t *pchansw_ie = MNULL;
+	mlan_status ret;
+	IEEEtypes_Header_t *pChanSwWrap_ie = MNULL;
+	IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = MNULL;
+	IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = MNULL;
+	t_u8 index;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	if (pmadapter == MNULL || ppioctl_req == MNULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* allocate buffer for mlan_ioctl_req and mlan_ds_misc_cfg */
+	/* FYI - will be freed as part of cmd_response handler */
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_ioctl_req) +
+					       sizeof(mlan_ds_misc_cfg),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pioctl_req);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+		PRINTM(MERROR, "%s(): Could not allocate ioctl req\n",
+		       __func__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pds_misc_cfg = (mlan_ds_misc_cfg *)((t_u8 *)pioctl_req +
+					    sizeof(mlan_ioctl_req));
+
+	/* prepare mlan_ioctl_req */
+	memset(pmadapter, pioctl_req, 0x00, sizeof(mlan_ioctl_req));
+	pioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	pioctl_req->action = MLAN_ACT_SET;
+	pioctl_req->pbuf = (t_u8 *)pds_misc_cfg;
+	pioctl_req->buf_len = sizeof(mlan_ds_misc_cfg);
+
+	/* prepare mlan_ds_misc_cfg */
+	memset(pmadapter, pds_misc_cfg, 0x00, sizeof(mlan_ds_misc_cfg));
+	pds_misc_cfg->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	pds_misc_cfg->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+	pds_misc_cfg->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+	/* configure custom_ie api settings */
+	pcust_chansw_ie =
+		(custom_ie *)&pds_misc_cfg->param.cust_ie.ie_data_list[0];
+	pcust_chansw_ie->ie_index = 0xffff;	/* Auto index */
+	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = (is_adding_ie) ? MBIT(8) | MBIT(5)	/* add IE for BEACON |
+										   PROBE_RSP */
+		: 0;		/* remove IE */
+
+	/* prepare CHAN_SW IE inside ioctl */
+	pchansw_ie = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
+	pchansw_ie->element_id = CHANNEL_SWITCH_ANN;
+	pchansw_ie->len =
+		sizeof(IEEEtypes_ChanSwitchAnn_t) - sizeof(IEEEtypes_Header_t);
+	pchansw_ie->chan_switch_mode = 1;	/* STA should not transmit */
+	pchansw_ie->new_channel_num = pmadapter->state_rdh.new_channel;
+
+	pchansw_ie->chan_switch_count = pmadapter->dfs_cs_count;
+	PRINTM(MCMD_D, "New Channel = %d Channel switch count = %d\n",
+	       pmadapter->state_rdh.new_channel, pchansw_ie->chan_switch_count);
+
+	for (index = 0; index < pmadapter->state_rdh.priv_list_count; index++) {
+		pmpriv = pmadapter->state_rdh.priv_list[index];
+		/*find the first AP interface */
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			if (pmpriv->is_11ac_enabled) {
+				pChanSwWrap_ie =
+					(IEEEtypes_Header_t
+					 *)((t_u8 *)pchansw_ie +
+					    sizeof(IEEEtypes_ChanSwitchAnn_t));
+				pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
+				/*will have multiple sub IEs */
+				pChanSwWrap_ie->len = 0;
+
+				/* prepare the Wide Bandwidth Channel Switch IE
+				 * Channel Switch IE */
+				pbwchansw_ie =
+					(IEEEtypes_WideBWChanSwitch_t
+					 *)((t_u8 *)pChanSwWrap_ie +
+					    sizeof(IEEEtypes_Header_t));
+				pbwchansw_ie->ieee_hdr.element_id =
+					BW_CHANNEL_SWITCH;
+				pbwchansw_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_WideBWChanSwitch_t) -
+					sizeof(IEEEtypes_Header_t);
+				/*fix 80MHZ now */
+				pbwchansw_ie->new_channel_width =
+					VHT_OPER_CHWD_80MHZ;
+				pbwchansw_ie->new_channel_center_freq0 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pbwchansw_ie->new_channel_center_freq1 =
+					wlan_11h_get_channel_freq_idx
+					(pmadapter->state_rdh.new_channel);
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t);
+
+				/*prepare the VHT Transmit Power Envelope IE */
+				pvhttpcEnv_ie =
+					(IEEEtypes_VhtTpcEnvelope_t
+					 *)((t_u8 *)pChanSwWrap_ie +
+					    sizeof(IEEEtypes_Header_t) +
+					    sizeof
+					    (IEEEtypes_WideBWChanSwitch_t));
+				pvhttpcEnv_ie->ieee_hdr.element_id =
+					VHT_TX_POWER_ENV;
+				pvhttpcEnv_ie->ieee_hdr.len =
+					sizeof(IEEEtypes_VhtTpcEnvelope_t) -
+					sizeof(IEEEtypes_Header_t);
+				/* Local Max TX Power Count= 3,
+				 * Local TX Power Unit Inter=EIP(0) */
+				pvhttpcEnv_ie->tpc_info = 3;
+				pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
+				pvhttpcEnv_ie->local_max_tp_160mhz_80_80mhz =
+					0xff;
+				pChanSwWrap_ie->len +=
+					sizeof(IEEEtypes_VhtTpcEnvelope_t);
+
+				pcust_chansw_ie->ie_length +=
+					sizeof(IEEEtypes_WideBWChanSwitch_t) +
+					sizeof(IEEEtypes_VhtTpcEnvelope_t) +
+					sizeof(IEEEtypes_Header_t);
+
+				PRINTM(MINFO,
+				       "Append Wide Bandwidth Channel Switch IE\n");
+				break;
+			}
+		}
+	}
+
+	pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
+	DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
+		    (t_u8 *)pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
+
+	/* assign output pointer before returning */
+	*ppioctl_req = pioctl_req;
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief Check if start channel 165 is allowed to operate in
+ *  previous uAP channel's band config
+ *
+ *  @param priv          a pointer to mlan_private structure
+ *  @param start_chn     Random Start channel choosen after radar detection
+ *  @param uap_band_cfg  Private driver uAP band configuration information
+ * structure
+ *
+ *  @return MFALSE if the channel is not allowed in given band
+ */
+static t_bool
+wlan_11h_is_band_valid(mlan_private *priv, t_u8 start_chn,
+		       Band_Config_t uap_band_cfg)
+{
+	/* if band width is not 20MHZ (either 40 or 80MHz)
+	 * return MFALSE, 165 is not allowed in bands other than 20MHZ
+	 */
+	if (start_chn == 165) {
+		if (uap_band_cfg.chanWidth != CHAN_BW_20MHZ)
+			return MFALSE;
+	}
+	return MTRUE;
+}
+
+/**
+ *  @brief Retrieve a randomly selected starting channel if needed for 11h
+ *
+ *  If 11h is enabled and 5GHz band is selected in band_config
+ *    return a random channel in A band, else one from BG band.
+ *
+ *  @param priv          Private driver information structure
+ *  @param uap_band_cfg  Private driver information structure
+ *
+ *  @return      Starting channel
+ */
+static t_u8
+wlan_11h_get_uap_start_channel(mlan_private *priv, Band_Config_t uap_band_cfg)
+{
+	t_u8 start_chn;
+	mlan_adapter *adapter = priv->adapter;
+	t_u32 region;
+	t_u32 rand_entry;
+	region_chan_t *chn_tbl;
+	t_u8 rand_tries = 0;
+
+	/*TODO:  right now mostly a copy of wlan_11h_get_adhoc_start_channel.
+	 *       Improve to be more specfic to UAP, e.g.
+	 *       1. take into account COUNTRY_CODE -> region_code
+	 *       2. check domain_info for value channels
+	 */
+	ENTER();
+
+	/*
+	 * Set start_chn to the Default.
+	 * Used if 11h is disabled or the band
+	 * does not require 11h support.
+	 */
+	start_chn = DEFAULT_AD_HOC_CHANNEL;
+
+	/*
+	 * Check that we are looking for a channel in the A Band
+	 */
+	if (uap_band_cfg.chanBand == BAND_5GHZ) {
+		/*
+		 * Set default to the A Band default.
+		 * Used if random selection fails
+		 * or if 11h is not enabled
+		 */
+		start_chn = DEFAULT_AD_HOC_CHANNEL_A;
+
+		/*
+		 * Check that 11h is enabled in the driver
+		 */
+		if (wlan_11h_is_enabled(priv)) {
+			/*
+			 * Search the region_channel tables for a channel table
+			 * that is marked for the A Band.
+			 */
+			for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
+			     region++) {
+				chn_tbl = &adapter->region_channel[region];
+
+				/* Check if table is valid and marked for A Band
+				 */
+				if (chn_tbl->valid &&
+				    chn_tbl->region == adapter->region_code &&
+				    chn_tbl->band & BAND_A) {
+					/*
+					 * Set the start channel.  Get a random
+					 * number and use it to pick an entry
+					 * in the table between 0 and the number
+					 * of channels in the table (NumCFP).
+					 */
+					rand_entry =
+						wlan_11h_get_random_num(adapter)
+						% chn_tbl->num_cfp;
+					start_chn =
+						(t_u8)chn_tbl->pcfp[rand_entry]
+						.channel;
+					/* Loop until a non-dfs channel is found
+					 * with compatible band bounded by
+					 * chn_tbl->num_cfp entries in the
+					 * channel table
+					 */
+					while (((chn_tbl->pcfp[rand_entry]
+						 .dynamic.flags &
+						 NXP_CHANNEL_DISABLED) ||
+						(wlan_11h_is_channel_under_nop
+						 (adapter, start_chn) ||
+						 ((adapter->state_rdh.stage ==
+						   RDH_GET_INFO_CHANNEL) &&
+						  wlan_11h_radar_detect_required
+						  (priv, start_chn)) ||
+						 !(wlan_11h_is_band_valid
+						   (priv, start_chn,
+						    uap_band_cfg)))) &&
+					       (++rand_tries <
+						chn_tbl->num_cfp)) {
+						rand_entry++;
+						rand_entry = rand_entry %
+							chn_tbl->num_cfp;
+						start_chn =
+							(t_u8)chn_tbl->
+							pcfp[rand_entry]
+							.channel;
+						PRINTM(MINFO,
+						       "start chan=%d rand_entry=%d\n",
+						       start_chn, rand_entry);
+					}
+
+					if (rand_tries == chn_tbl->num_cfp) {
+						PRINTM(MERROR,
+						       "Failed to get UAP start channel\n");
+						start_chn = 0;
+					}
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMD_D, "11h: UAP Get Start Channel %d\n", start_chn);
+	LEAVE();
+	return start_chn;
+}
+#endif /* UAP_SUPPORT */
+
+#ifdef DEBUG_LEVEL1
+static const char *DFS_TS_REPR_STRINGS[] = { "", "NOP_start", "CAC_completed" };
+#endif
+
+/**
+ *  @brief Search for a dfs timestamp in the list with desired channel.
+ *
+ *  Assumes there will only be one timestamp per channel in the list.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param channel    Channel number
+ *
+ *  @return           Pointer to timestamp if found, or MNULL
+ */
+static wlan_dfs_timestamp_t *
+wlan_11h_find_dfs_timestamp(mlan_adapter *pmadapter, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pts = MNULL, *pts_found = MNULL;
+
+	ENTER();
+	pts = (wlan_dfs_timestamp_t *)util_peek_list(pmadapter->pmoal_handle,
+						     &pmadapter->state_dfs.
+						     dfs_ts_head, MNULL, MNULL);
+
+	while (pts &&
+	       pts !=
+	       (wlan_dfs_timestamp_t *)&pmadapter->state_dfs.dfs_ts_head) {
+		PRINTM(MINFO,
+		       "dfs_timestamp(@ %p) - chan=%d, repr=%d(%s),"
+		       " time(sec.usec)=%lu.%06lu\n", pts, pts->channel,
+		       pts->represents, DFS_TS_REPR_STRINGS[pts->represents],
+		       pts->ts_sec, pts->ts_usec);
+
+		if (pts->channel == channel) {
+			pts_found = pts;
+			break;
+		}
+		pts = pts->pnext;
+	}
+
+	LEAVE();
+	return pts_found;
+}
+
+/**
+ *  @brief Removes dfs timestamp from list.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param pdfs_ts    Pointer to dfs_timestamp to remove
+ */
+static t_void
+wlan_11h_remove_dfs_timestamp(mlan_adapter *pmadapter,
+			      wlan_dfs_timestamp_t *pdfs_ts)
+{
+	ENTER();
+	/* dequeue and delete timestamp */
+	util_unlink_list(pmadapter->pmoal_handle,
+			 &pmadapter->state_dfs.dfs_ts_head,
+			 (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pdfs_ts);
+	LEAVE();
+}
+
+/**
+ *  @brief Add a dfs timestamp to the list
+ *
+ *  Assumes there will only be one timestamp per channel in the list,
+ *  and that timestamp modes (represents) are mutually exclusive.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param repr       Timestamp 'represents' value (see _dfs_timestamp_repr_e)
+ *  @param channel    Channel number
+ *
+ *  @return           Pointer to timestamp if found, or MNULL
+ */
+static mlan_status
+wlan_11h_add_dfs_timestamp(mlan_adapter *pmadapter, t_u8 repr, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pdfs_ts = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
+
+	if (!pdfs_ts) {
+		/* need to allocate new timestamp */
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       sizeof
+						       (wlan_dfs_timestamp_t),
+						       MLAN_MEM_DEF,
+						       (t_u8 **)&pdfs_ts);
+		if ((ret != MLAN_STATUS_SUCCESS) || !pdfs_ts) {
+			PRINTM(MERROR, "%s(): Could not allocate dfs_ts\n",
+			       __func__);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		memset(pmadapter, (t_u8 *)pdfs_ts, 0,
+		       sizeof(wlan_dfs_timestamp_t));
+
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->state_dfs.dfs_ts_head,
+				       (pmlan_linked_list)pdfs_ts, MNULL,
+				       MNULL);
+		pdfs_ts->channel = channel;
+	}
+	/* (else, use existing timestamp for channel; see assumptions above) */
+
+	/* update params */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pdfs_ts->ts_sec,
+						  &pdfs_ts->ts_usec);
+	pdfs_ts->represents = repr;
+
+	PRINTM(MCMD_D,
+	       "11h: add/update dfs_timestamp - chan=%d, repr=%d(%s),"
+	       " time(sec.usec)=%lu.%06lu\n",
+	       pdfs_ts->channel, pdfs_ts->represents,
+	       DFS_TS_REPR_STRINGS[pdfs_ts->represents], pdfs_ts->ts_sec,
+	       pdfs_ts->ts_usec);
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global functions
+********************************************************/
+
+/**
+ *  @brief Return whether the device has activated master radar detection.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if master radar detection is enabled in firmware
+ *    - MFALSE otherwise
+ */
+t_bool
+wlan_11h_is_master_radar_det_active(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->adapter->state_11h.is_master_radar_det_active;
+}
+
+/**
+ *  @brief Configure master radar detection.
+ *  Call wlan_11h_check_update_radar_det_state() afterwards
+ *    to push this to firmware.
+ *
+ *  @param priv  Private driver information structure
+ *  @param enable Whether to enable or disable master radar detection
+ *
+ *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ *  @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status
+wlan_11h_config_master_radar_det(mlan_private *priv, t_bool enable)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	/* Force disable master radar detection on in-AP interfaces */
+	if (priv->adapter->dfs_repeater)
+		enable = MFALSE;
+
+	ENTER();
+	if (wlan_11h_is_dfs_master(priv) &&
+	    priv->adapter->init_para.dfs_master_radar_det_en) {
+		priv->adapter->state_11h.master_radar_det_enable_pending =
+			enable;
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure slave radar detection.
+ *  Call wlan_11h_check_update_radar_det_state() afterwards
+ *    to push this to firmware.
+ *
+ *  @param priv  Private driver information structure
+ *  @param enable Whether to enable or disable slave radar detection
+ *
+ *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ *  @sa wlan_11h_check_update_radar_det_state
+ */
+mlan_status
+wlan_11h_config_slave_radar_det(mlan_private *priv, t_bool enable)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	/* Force disable radar detection on STA interfaces */
+	if (priv->adapter->dfs_repeater)
+		enable = MFALSE;
+
+	ENTER();
+	if (wlan_11h_is_dfs_slave(priv) &&
+	    priv->adapter->init_para.dfs_slave_radar_det_en) {
+		priv->adapter->state_11h.slave_radar_det_enable_pending =
+			enable;
+		ret = MLAN_STATUS_SUCCESS;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Checks all interfaces and determines if radar_detect flag states
+ *         have/should be changed.  If so, sends SNMP_MIB 11H command to FW.
+ *         Call this function on any interface enable/disable/channel change.
+ *
+ *  @param pmpriv  Pointer to mlan_private structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS (update or not)
+ *              or MLAN_STATUS_FAILURE (cmd failure)
+ *
+ *  @sa    wlan_11h_check_radar_det_state
+ */
+mlan_status
+wlan_11h_check_update_radar_det_state(mlan_private *pmpriv)
+{
+	t_u32 new_radar_det_state = 0;
+	t_u32 mib_11h = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wlan_11h_check_radar_det_state(pmpriv->adapter,
+					   &new_radar_det_state)) {
+		PRINTM(MCMD_D, "%s: radar_det_state being updated.\n",
+		       __func__);
+
+		mib_11h |= new_radar_det_state;
+		/* keep priv's existing 11h state */
+		if (pmpriv->intf_state_11h.is_11h_active)
+			mib_11h |= ENABLE_11H_MASK;
+
+		/* Send cmd to FW to enable/disable 11h function in firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, Dot11H_i, MNULL,
+				       &mib_11h);
+		if (ret)
+			ret = MLAN_STATUS_FAILURE;
+	}
+
+	/* updated state sent OR no change, thus no longer pending */
+	pmpriv->adapter->state_11h.master_radar_det_enable_pending = MFALSE;
+	pmpriv->adapter->state_11h.slave_radar_det_enable_pending = MFALSE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Query 11h firmware enabled state.
+ *
+ *  Return whether the firmware currently has 11h extensions enabled
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return
+ *    - MTRUE if 11h has been activated in the firmware
+ *    - MFALSE otherwise
+ *
+ *  @sa wlan_11h_activate
+ */
+t_bool
+wlan_11h_is_active(mlan_private *priv)
+{
+	ENTER();
+	LEAVE();
+	return priv->intf_state_11h.is_11h_active;
+}
+
+/**
+ *  @brief Enable the transmit interface and record the state.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_tx_enable(mlan_private *priv)
+{
+	ENTER();
+	if (priv->intf_state_11h.tx_disabled) {
+		if (priv->media_connected == MTRUE) {
+			wlan_recv_event(priv, MLAN_EVENT_ID_FW_START_TX, MNULL);
+			priv->intf_state_11h.tx_disabled = MFALSE;
+		}
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Disable the transmit interface and record the state.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_tx_disable(mlan_private *priv)
+{
+	ENTER();
+	if (!priv->intf_state_11h.tx_disabled) {
+		if (priv->media_connected == MTRUE) {
+			priv->intf_state_11h.tx_disabled = MTRUE;
+			wlan_recv_event(priv, MLAN_EVENT_ID_FW_STOP_TX, MNULL);
+		}
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Enable or Disable the 11h extensions in the firmware
+ *
+ *  @param priv         Private driver information structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param flag         Enable 11h if MTRUE, disable otherwise
+ *
+ *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_activate(mlan_private *priv, t_void *pioctl_buf, t_bool flag)
+{
+	t_u32 enable = flag & ENABLE_11H_MASK;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* add bits for master/slave radar detect into enable. */
+	enable |= wlan_11h_get_current_radar_detect_flags(priv->adapter);
+
+	/* Whenever repeater mode is on make sure
+	 * we do not enable master or slave radar det mode.
+	 * HW will not detect radar in dfs_repeater mode.
+	 */
+	if (priv->adapter->dfs_repeater) {
+		enable &= ~(MASTER_RADAR_DET_MASK | SLAVE_RADAR_DET_MASK);
+	}
+
+	/*
+	 * Send cmd to FW to enable/disable 11h function in firmware
+	 */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+			       HostCmd_ACT_GEN_SET, Dot11H_i,
+			       (t_void *)pioctl_buf, &enable);
+	if (ret)
+		ret = MLAN_STATUS_FAILURE;
+	else
+		/* Set boolean flag in driver 11h state */
+		priv->intf_state_11h.is_11h_active = flag;
+
+	PRINTM(MINFO, "11h: %s\n", flag ? "Activate" : "Deactivate");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Initialize the 11h parameters and enable 11h when starting an IBSS
+ *
+ *  @param adapter mlan_adapter structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_init(mlan_adapter *adapter)
+{
+	wlan_11h_device_state_t *pstate_11h = &adapter->state_11h;
+	IEEEtypes_Quiet_t *pquiet = &adapter->state_11h.quiet_ie;
+	wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
+	wlan_radar_det_hndlg_state_t *pstate_rdh = &adapter->state_rdh;
+	wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
+
+	ENTER();
+
+	/* Initialize 11H struct */
+	pstate_11h->usr_def_power_constraint = WLAN_11H_TPC_POWERCONSTRAINT;
+	pstate_11h->min_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MIN;
+	pstate_11h->max_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MAX;
+
+	pstate_11h->recvd_chanswann_event = MFALSE;
+	pstate_11h->master_radar_det_enable_pending = MFALSE;
+	pstate_11h->slave_radar_det_enable_pending = MFALSE;
+	pstate_11h->is_master_radar_det_active = MFALSE;
+	pstate_11h->is_slave_radar_det_active = MFALSE;
+
+	/*Initialize quiet_ie */
+	memset(adapter, pquiet, 0, sizeof(IEEEtypes_Quiet_t));
+	pquiet->element_id = QUIET;
+	pquiet->len =
+		(sizeof(pquiet->quiet_count) + sizeof(pquiet->quiet_period) +
+		 sizeof(pquiet->quiet_duration) + sizeof(pquiet->quiet_offset));
+
+	/* Initialize DFS struct */
+	pstate_dfs->dfs_check_pending = MFALSE;
+	pstate_dfs->dfs_radar_found = MFALSE;
+	pstate_dfs->dfs_check_channel = 0;
+	pstate_dfs->dfs_report_time_sec = 0;
+	util_init_list((pmlan_linked_list)&pstate_dfs->dfs_ts_head);
+
+	/* Initialize RDH struct */
+	pstate_rdh->stage = RDH_OFF;
+	pstate_rdh->priv_list_count = 0;
+	pstate_rdh->priv_curr_idx = 0;
+	pstate_rdh->curr_channel = 0;
+	pstate_rdh->new_channel = 0;
+	memset(adapter, &(pstate_rdh->uap_band_cfg), 0,
+	       sizeof(pstate_rdh->uap_band_cfg));
+	pstate_rdh->max_bcn_dtim_ms = 0;
+	memset(adapter, pstate_rdh->priv_list, 0,
+	       sizeof(pstate_rdh->priv_list));
+
+	/* Initialize dfs channel switch count */
+#define DFS_CS_COUNT 5
+	adapter->dfs_cs_count = DFS_CS_COUNT;
+
+	/* Initialize DFS testing struct */
+	pdfs_test->user_cac_period_msec = 0;
+	pdfs_test->user_nop_period_sec = 0;
+	pdfs_test->no_channel_change_on_radar = MFALSE;
+	pdfs_test->fixed_new_channel_on_radar = 0;
+	pdfs_test->cac_restart = 0;
+	pdfs_test->millisec_dwell_time = 0;
+	adapter->dfs53cfg = adapter->init_para.dfs53cfg;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Cleanup for the 11h parameters that allocated memory, etc.
+ *
+ *  @param adapter mlan_adapter structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_cleanup(mlan_adapter *adapter)
+{
+	wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
+	wlan_dfs_timestamp_t *pdfs_ts;
+
+	ENTER();
+
+	/* cleanup dfs_timestamp list */
+	pdfs_ts =
+		(wlan_dfs_timestamp_t *)util_peek_list(adapter->pmoal_handle,
+						       &pstate_dfs->dfs_ts_head,
+						       MNULL, MNULL);
+	while (pdfs_ts) {
+		util_unlink_list(adapter->pmoal_handle,
+				 &pstate_dfs->dfs_ts_head,
+				 (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
+		adapter->callbacks.moal_mfree(adapter->pmoal_handle,
+					      (t_u8 *)pdfs_ts);
+
+		pdfs_ts =
+			(wlan_dfs_timestamp_t *)util_peek_list(adapter->
+							       pmoal_handle,
+							       &pstate_dfs->
+							       dfs_ts_head,
+							       MNULL, MNULL);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Initialize the 11h parameters and enable 11h when starting an IBSS
+ *
+ *  @param pmpriv Pointer to mlan_private structure
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_11h_priv_init(mlan_private *pmpriv)
+{
+	wlan_11h_interface_state_t *pistate_11h = &pmpriv->intf_state_11h;
+
+	ENTER();
+
+	pistate_11h->is_11h_enabled = MTRUE;
+	pistate_11h->is_11h_active = MFALSE;
+	pistate_11h->adhoc_auto_sel_chan = MTRUE;
+	pistate_11h->tx_disabled = MFALSE;
+	pistate_11h->dfs_slave_csa_chan = 0;
+	pistate_11h->dfs_slave_csa_expire_at_sec = 0;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Retrieve a randomly selected starting channel if needed for 11h
+ *
+ *  If 11h is enabled and an A-Band channel start band preference
+ *    configured in the driver, the start channel must be random in order
+ *    to meet with
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return      Starting channel
+ */
+t_u8
+wlan_11h_get_adhoc_start_channel(mlan_private *priv)
+{
+	t_u8 start_chn;
+	mlan_adapter *adapter = priv->adapter;
+	t_u32 region;
+	t_u32 rand_entry;
+	region_chan_t *chn_tbl;
+	t_u8 rand_tries = 0;
+
+	ENTER();
+
+	/*
+	 * Set start_chn to the Default.  Used if 11h is disabled or the band
+	 *   does not require 11h support.
+	 */
+	start_chn = DEFAULT_AD_HOC_CHANNEL;
+
+	/*
+	 * Check that we are looking for a channel in the A Band
+	 */
+	if ((adapter->adhoc_start_band & BAND_A)
+		) {
+		/*
+		 * Set default to the A Band default.
+		 * Used if random selection fails
+		 * or if 11h is not enabled
+		 */
+		start_chn = DEFAULT_AD_HOC_CHANNEL_A;
+
+		/*
+		 * Check that 11h is enabled in the driver
+		 */
+		if (wlan_11h_is_enabled(priv)) {
+			/*
+			 * Search the region_channel tables for a channel table
+			 *   that is marked for the A Band.
+			 */
+			for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
+			     region++) {
+				chn_tbl = &adapter->region_channel[region];
+
+				/* Check if table is valid and marked for A Band
+				 */
+				if (chn_tbl->valid &&
+				    chn_tbl->region == adapter->region_code &&
+				    chn_tbl->band & BAND_A) {
+					/*
+					 * Set the start channel.  Get a random
+					 * number and use it to pick an entry
+					 * in the table between 0 and the number
+					 * of channels in the table (NumCFP).
+					 */
+					do {
+						rand_entry =
+							wlan_11h_get_random_num
+							(adapter) %
+							chn_tbl->num_cfp;
+						start_chn =
+							(t_u8)chn_tbl->
+							pcfp[rand_entry]
+							.channel;
+					} while ((wlan_11h_is_channel_under_nop
+						  (adapter, start_chn) ||
+						  ((adapter->state_rdh.stage ==
+						    RDH_GET_INFO_CHANNEL) &&
+						   wlan_11h_radar_detect_required
+						   (priv, start_chn))) &&
+						 (++rand_tries <
+						  MAX_RANDOM_CHANNEL_RETRIES));
+				}
+			}
+		}
+	}
+
+	PRINTM(MINFO, "11h: %s: AdHoc Channel set to %u\n",
+	       wlan_11h_is_enabled(priv) ? "Enabled" : "Disabled", start_chn);
+
+	LEAVE();
+	return start_chn;
+}
+
+/**
+ *  @brief Retrieve channel closed for operation by Channel Switch Announcement
+ *
+ *  After receiving CSA, we must not transmit in any form on the original
+ *    channel for a certain duration.  This checks the time, and returns
+ *    the channel if valid.
+ *
+ *  @param priv  Private driver information structure
+ *
+ *  @return      Closed channel, else 0
+ */
+t_u8
+wlan_11h_get_csa_closed_channel(mlan_private *priv)
+{
+	t_u32 sec, usec;
+
+	ENTER();
+
+	if (!priv->intf_state_11h.dfs_slave_csa_chan) {
+		LEAVE();
+		return 0;
+	}
+
+	/* have csa channel, check if expired or not */
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+	if (sec > priv->intf_state_11h.dfs_slave_csa_expire_at_sec) {
+		/* expired:  remove channel from blacklist table, and clear vars
+		 */
+		wlan_set_chan_blacklist(priv, BAND_A,
+					priv->intf_state_11h.dfs_slave_csa_chan,
+					MFALSE);
+		priv->intf_state_11h.dfs_slave_csa_chan = 0;
+		priv->intf_state_11h.dfs_slave_csa_expire_at_sec = 0;
+	}
+
+	LEAVE();
+	return priv->intf_state_11h.dfs_slave_csa_chan;
+}
+
+/**
+ *  @brief Check if the current region's regulations require the input channel
+ *         to be scanned for radar.
+ *
+ *  Based on statically defined requirements for sub-bands per regulatory
+ *    agency requirements.
+ *
+ *  Used in adhoc start to determine if channel availability check is required
+ *
+ *  @param priv    Private driver information structure
+ *  @param channel Channel to determine radar detection requirements
+ *
+ *  @return
+ *    - MTRUE if radar detection is required
+ *    - MFALSE otherwise
+ */
+/**  @sa wlan_11h_issue_radar_detect
+ */
+t_bool
+wlan_11h_radar_detect_required(mlan_private *priv, t_u8 channel)
+{
+	t_bool required = MFALSE;
+
+	ENTER();
+
+	/*
+	 * No checks for 11h or measurement code being enabled is placed here
+	 * since regulatory requirements exist whether we support them or not.
+	 */
+
+	required = wlan_get_cfp_radar_detect(priv, channel);
+
+	if (!priv->adapter->region_code) {
+		PRINTM(MINFO,
+		       "11h: Radar detection in CFP code BG:%#x "
+		       ", A:%#x "
+		       "is %srequired for channel %d\n",
+		       priv->adapter->cfp_code_bg,
+		       priv->adapter->cfp_code_a,
+		       (required ? "" : "not "), channel);
+	} else
+		PRINTM(MINFO,
+		       "11h: Radar detection in region %#02x "
+		       "is %srequired for channel %d\n",
+		       priv->adapter->region_code, (required ? "" : "not "),
+		       channel);
+
+	if (required == MTRUE && priv->media_connected == MTRUE &&
+	    priv->curr_bss_params.bss_descriptor.channel == channel) {
+		required = MFALSE;
+
+		PRINTM(MINFO, "11h: Radar detection not required. "
+		       "Already operating on the channel\n");
+	}
+
+	LEAVE();
+	return required;
+}
+
+t_s32
+wlan_11h_cancel_radar_detect(mlan_private *priv)
+{
+	t_s32 ret;
+	HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+	memset(priv->adapter, &chan_rpt_req, 0x00, sizeof(chan_rpt_req));
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+			       HostCmd_ACT_GEN_SET, 0,
+			       (t_void *)MNULL, (t_void *)&chan_rpt_req);
+	return ret;
+}
+
+/**
+ *  @brief Perform a radar measurement if required on given channel
+ *
+ *  Check to see if the provided channel requires a channel availability
+ *    check (60 second radar detection measurement).  If required, perform
+ *    measurement, stalling calling thread until the measurement completes
+ *    and then report result.
+ *
+ *  Used when starting an adhoc or AP network.
+ *
+ *  @param priv         Private driver information structure
+ *  @param pioctl_req   Pointer to IOCTL request buffer
+ *  @param channel      Channel on which to perform radar measurement
+ *  @param bandcfg      Channel Band config structure
+ *
+ *  @return
+ *    - MTRUE  if radar measurement request was successfully issued
+ *    - MFALSE if radar detection is not required
+ *    - < 0 for error during radar detection (if performed)
+ *
+ *  @sa wlan_11h_radar_detect_required
+ */
+t_s32
+wlan_11h_issue_radar_detect(mlan_private *priv,
+			    pmlan_ioctl_req pioctl_req, t_u8 channel,
+			    Band_Config_t bandcfg)
+{
+	t_s32 ret;
+	HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+	mlan_adapter *pmadapter = priv->adapter;
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+
+	ENTER();
+
+	ret = wlan_11h_radar_detect_required(priv, channel);
+	if (ret) {
+		/* Prepare and issue CMD_CHAN_RPT_REQ. */
+		memset(priv->adapter, &chan_rpt_req, 0x00,
+		       sizeof(chan_rpt_req));
+
+		chan_rpt_req.chan_desc.startFreq = START_FREQ_11A_BAND;
+
+		if (pmadapter->chanrpt_param_bandcfg) {
+			chan_rpt_req.chan_desc.bandcfg = bandcfg;
+		} else {
+			*((t_u8 *)&chan_rpt_req.chan_desc.bandcfg) =
+				(t_u8)bandcfg.chanWidth;
+		}
+
+		chan_rpt_req.chan_desc.chanNum = channel;
+		chan_rpt_req.millisec_dwell_time =
+			WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION;
+
+		/* ETSI new requirement for ch 120, 124 and 128 */
+		if (wlan_is_etsi_country(pmadapter, pmadapter->country_code)) {
+			if (channel == 120 || channel == 124 || channel == 128) {
+				chan_rpt_req.millisec_dwell_time =
+					WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION *
+					10;
+			}
+			if (channel == 116 &&
+			    ((bandcfg.chanWidth == CHAN_BW_40MHZ)
+			     || (bandcfg.chanWidth == CHAN_BW_80MHZ)
+			    )) {
+				chan_rpt_req.millisec_dwell_time =
+					WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION *
+					10;
+			}
+		}
+
+		/* Save dwell time information to be used later in moal */
+		if (pioctl_req) {
+			ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+			if (!ds_11hcfg->param.chan_rpt_req.host_based) {
+				ds_11hcfg->param.chan_rpt_req.
+					millisec_dwell_time =
+					chan_rpt_req.millisec_dwell_time;
+			}
+		}
+
+		if (priv->adapter->dfs_test_params.user_cac_period_msec) {
+			PRINTM(MCMD_D,
+			       "dfs_testing - user CAC period=%d (msec)\n",
+			       priv->adapter->dfs_test_params.
+			       user_cac_period_msec);
+			chan_rpt_req.millisec_dwell_time =
+				priv->adapter->dfs_test_params.
+				user_cac_period_msec;
+		}
+		if (priv->adapter->dfs_test_params.cac_restart) {
+			priv->adapter->dfs_test_params.chan =
+				chan_rpt_req.chan_desc.chanNum;
+			if (chan_rpt_req.millisec_dwell_time)
+				priv->adapter->dfs_test_params.
+					millisec_dwell_time =
+					chan_rpt_req.millisec_dwell_time;
+			else
+				chan_rpt_req.millisec_dwell_time
+					=
+					priv->adapter->dfs_test_params.
+					millisec_dwell_time;
+			memcpy_ext(priv->adapter,
+				   &priv->adapter->dfs_test_params.bandcfg,
+				   &bandcfg, sizeof(bandcfg), sizeof(bandcfg));
+		}
+		PRINTM(MMSG,
+		       "11h: issuing DFS Radar check for channel=%d."
+		       "  Please wait for response...\n", channel);
+
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req,
+				       (t_void *)&chan_rpt_req);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Checks if a radar measurement was performed on channel,
+ *         and if so, whether radar was detected on it.
+ *
+ *  Used when starting an adhoc network.
+ *
+ *  @param priv         Private driver information structure
+ *  @param chan         Channel to check upon
+ *
+ *  @return
+ *    - MLAN_STATUS_SUCCESS if no radar on channel
+ *    - MLAN_STATUS_FAILURE if radar was found on channel
+ *    - (TBD??) MLAN_STATUS_PENDING if radar report NEEDS TO BE REISSUED
+ *
+ *  @sa wlan_11h_issue_radar_detect
+ *  @sa wlan_11h_process_start
+ */
+mlan_status
+wlan_11h_check_chan_report(mlan_private *priv, t_u8 chan)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+	t_u32 sec, usec;
+
+	ENTER();
+
+	/* check report we hold is valid or not */
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+
+	PRINTM(MINFO, "11h: %s()\n", __func__);
+	PRINTM(MINFO, "- sec_now=%d, sec_report=%d.\n", sec,
+	       pstate_dfs->dfs_report_time_sec);
+	PRINTM(MINFO, "- rpt_channel=%d, rpt_radar=%d.\n",
+	       pstate_dfs->dfs_check_channel, pstate_dfs->dfs_radar_found);
+
+	if ((!pstate_dfs->dfs_check_pending) &&
+	    (chan == pstate_dfs->dfs_check_channel) &&
+	    ((sec - pstate_dfs->dfs_report_time_sec) <
+	     MAX_DFS_REPORT_USABLE_AGE_SEC)) {
+		/* valid and not out-dated, check if radar */
+		if (pstate_dfs->dfs_radar_found) {
+			PRINTM(MMSG, "Radar was detected on channel %d.\n",
+			       chan);
+			ret = MLAN_STATUS_FAILURE;
+		}
+	} else {
+		/* When Cache is not valid. This is required during extending
+		 * cache validity during bss_stop
+		 */
+		pstate_dfs->dfs_check_channel = 0;
+
+		/*TODO:  reissue report request if not pending.
+		 *       BUT HOW to make the code wait for it???
+		 * For now, just fail since we don't have the info. */
+
+		ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Process an TLV buffer for a pending BSS Adhoc start command.
+ *
+ *  Activate 11h functionality in the firmware if driver has is enabled
+ *    for 11h (configured by the application via IOCTL).
+ *
+ *  @param priv          Private driver information structure
+ *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
+ *                       modified on return to point after the appended 11h TLVs
+ *  @param pcap_info     Pointer to the capability info for the BSS to join
+ *  @param channel       Channel on which we are starting the IBSS
+ *  @param p11h_bss_info Input/Output parameter: Pointer to the 11h BSS
+ *                       information for this network that we are establishing.
+ *                       11h sensed flag set on output if warranted.
+ *
+ *  @return
+ *      - MLAN_STATUS_SUCCESS if 11h is disabled
+ *      - Integer number of bytes appended to the TLV output buffer (ppbuffer)
+ *      - < 0 for error (e.g. radar detected on channel)
+ */
+t_s32
+wlan_11h_process_start(mlan_private *priv, t_u8 **ppbuffer,
+		       IEEEtypes_CapInfo_t *pcap_info, t_u32 channel,
+		       wlan_11h_bss_info_t *p11h_bss_info)
+{
+	mlan_adapter *adapter = priv->adapter;
+	t_s32 ret = MLAN_STATUS_SUCCESS;
+	t_bool is_dfs_chan = MFALSE;
+
+	ENTER();
+	if (wlan_11h_is_enabled(priv)
+	    && ((adapter->adhoc_start_band & BAND_A)
+	    )
+		) {
+		if (!wlan_fw_11d_is_enabled(priv)) {
+			/* No use having 11h enabled without 11d enabled */
+			wlan_11d_enable(priv, MNULL, ENABLE_11D);
+#ifdef STA_SUPPORT
+			wlan_11d_create_dnld_countryinfo(priv,
+							 adapter->
+							 adhoc_start_band);
+#endif
+		}
+
+		/*
+		 * Activate 11h functions in firmware,
+		 * turns on capability bit
+		 */
+		wlan_11h_activate(priv, MNULL, MTRUE);
+		pcap_info->spectrum_mgmt = MTRUE;
+
+		/* If using a DFS channel, enable radar detection. */
+		is_dfs_chan = wlan_11h_radar_detect_required(priv, channel);
+		if (is_dfs_chan) {
+			if (!wlan_11h_is_master_radar_det_active(priv))
+				wlan_11h_config_master_radar_det(priv, MTRUE);
+		}
+		wlan_11h_check_update_radar_det_state(priv);
+
+		/* Set flag indicating this BSS we are starting is using 11h */
+		p11h_bss_info->sensed_11h = MTRUE;
+
+		if (is_dfs_chan) {
+			/* check if this channel is under NOP */
+			if (wlan_11h_is_channel_under_nop(adapter, channel))
+				ret = MLAN_STATUS_FAILURE;
+			/* check last channel report, if this channel is free of
+			 * radar */
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = wlan_11h_check_chan_report(priv, channel);
+		}
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = wlan_11h_process_adhoc(priv, ppbuffer, channel,
+						     MNULL);
+		else
+			ret = MLAN_STATUS_FAILURE;
+	} else {
+		/* Deactivate 11h functions in the firmware */
+		wlan_11h_activate(priv, MNULL, MFALSE);
+		pcap_info->spectrum_mgmt = MFALSE;
+		wlan_11h_check_update_radar_det_state(priv);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Process an TLV buffer for a pending BSS Join command for
+ *         both adhoc and infra networks
+ *
+ *  The TLV command processing for a BSS join for either adhoc or
+ *    infrastructure network is performed with this function.  The
+ *    capability bits are inspected for the IBSS flag and the appropriate
+ *    local routines are called to setup the necessary TLVs.
+ *
+ *  Activate 11h functionality in the firmware if the spectrum management
+ *    capability bit is found in the network information for the BSS we are
+ *    joining.
+ *
+ *  @param priv          Private driver information structure
+ *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
+ *                       modified on return to point after the appended 11h TLVs
+ *  @param pcap_info     Pointer to the capability info for the BSS to join
+ *  @param band          Band on which we are joining the BSS
+ *  @param channel       Channel on which we are joining the BSS
+ *  @param p11h_bss_info Pointer to the 11h BSS information for this
+ *                       network that was parsed out of the scan response.
+ *
+ *  @return              Integer number of bytes appended to the TLV output
+ *                       buffer (ppbuffer), MLAN_STATUS_FAILURE (-1),
+ *                       or MLAN_STATUS_SUCCESS (0)
+ */
+t_s32
+wlan_11h_process_join(mlan_private *priv, t_u8 **ppbuffer,
+		      IEEEtypes_CapInfo_t *pcap_info, t_u8 band,
+		      t_u32 channel, wlan_11h_bss_info_t *p11h_bss_info)
+{
+	t_s32 ret = 0;
+
+	ENTER();
+
+	if (priv->media_connected == MTRUE) {
+		if (wlan_11h_is_active(priv) == p11h_bss_info->sensed_11h) {
+			/*
+			 * Assume DFS parameters are the same for roaming as
+			 * long as the current & next APs have the same spectrum
+			 * mgmt capability bit setting
+			 */
+			ret = MLAN_STATUS_SUCCESS;
+
+		} else {
+			/* No support for roaming between DFS/non-DFS yet */
+			ret = MLAN_STATUS_FAILURE;
+		}
+
+		LEAVE();
+		return ret;
+	}
+
+	if (p11h_bss_info->sensed_11h) {
+		if (!wlan_fw_11d_is_enabled(priv)) {
+			/* No use having 11h enabled without 11d enabled */
+			wlan_11d_enable(priv, MNULL, ENABLE_11D);
+#ifdef STA_SUPPORT
+			wlan_11d_parse_dnld_countryinfo(priv,
+							priv->
+							pattempted_bss_desc);
+#endif
+		}
+		/*
+		 * Activate 11h functions in firmware,
+		 * turns on capability bit
+		 */
+		wlan_11h_activate(priv, MNULL, MTRUE);
+		pcap_info->spectrum_mgmt = MTRUE;
+
+		/* If using a DFS channel, enable radar detection. */
+		if ((band & BAND_A) &&
+		    wlan_11h_radar_detect_required(priv, channel)) {
+			if (!wlan_11h_is_slave_radar_det_active(priv))
+				wlan_11h_config_slave_radar_det(priv, MTRUE);
+		}
+		wlan_11h_check_update_radar_det_state(priv);
+
+		if (pcap_info->ibss) {
+			PRINTM(MINFO, "11h: Adhoc join: Sensed\n");
+			ret = wlan_11h_process_adhoc(priv, ppbuffer, channel,
+						     p11h_bss_info);
+		} else {
+			PRINTM(MINFO, "11h: Infra join: Sensed\n");
+			ret = wlan_11h_process_infra_join(priv, ppbuffer, band,
+							  channel,
+							  p11h_bss_info);
+		}
+	} else {
+		/* Deactivate 11h functions in the firmware */
+		wlan_11h_activate(priv, MNULL, MFALSE);
+		pcap_info->spectrum_mgmt = MFALSE;
+		wlan_11h_check_update_radar_det_state(priv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *
+ *  @brief  Prepare the HostCmd_DS_Command structure for an 11h command.
+ *
+ *  Use the Command field to determine if the command being set up is for
+ *     11h and call one of the local command handlers accordingly for:
+ *
+ *        - HostCmd_CMD_802_11_TPC_ADAPT_REQ
+ *        - HostCmd_CMD_802_11_TPC_INFO
+ *        - HostCmd_CMD_802_11_CHAN_SW_ANN
+ */
+/**       - HostCmd_CMD_CHAN_REPORT_REQUEST
+ */
+/**
+ *  @param priv      Private driver information structure
+ *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
+ *                   for the firmware
+ *  @param pinfo_buf Void buffer pass through with data necessary for a
+ *                   specific command type
+ */
+/**  @return          MLAN_STATUS_SUCCESS, MLAN_STATUS_FAILURE
+ *                    or MLAN_STATUS_PENDING
+ */
+/**  @sa wlan_11h_cmd_tpc_request
+ *  @sa wlan_11h_cmd_tpc_info
+ *  @sa wlan_11h_cmd_chan_sw_ann
+ */
+/** @sa wlan_11h_cmd_chan_report_req
+ */
+mlan_status
+wlan_11h_cmd_process(mlan_private *priv,
+		     HostCmd_DS_COMMAND *pcmd_ptr, const t_void *pinfo_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	switch (pcmd_ptr->command) {
+	case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+		ret = wlan_11h_cmd_tpc_request(priv, pcmd_ptr, pinfo_buf);
+		break;
+	case HostCmd_CMD_802_11_TPC_INFO:
+		ret = wlan_11h_cmd_tpc_info(priv, pcmd_ptr, pinfo_buf);
+		break;
+	case HostCmd_CMD_802_11_CHAN_SW_ANN:
+		ret = wlan_11h_cmd_chan_sw_ann(priv, pcmd_ptr, pinfo_buf);
+		break;
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		ret = wlan_11h_cmd_chan_rpt_req(priv, pcmd_ptr, pinfo_buf);
+		break;
+	default:
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	pcmd_ptr->command = wlan_cpu_to_le16(pcmd_ptr->command);
+	pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle the command response from the firmware if from an 11h command
+ *
+ *  Use the Command field to determine if the command response being
+ *    is for 11h.  Call the local command response handler accordingly for:
+ *
+ *        - HostCmd_CMD_802_11_TPC_ADAPT_REQ
+ *        - HostCmd_CMD_802_11_TPC_INFO
+ *        - HostCmd_CMD_802_11_CHAN_SW_ANN
+ */
+/**       - HostCmd_CMD_CHAN_REPORT_REQUEST
+ */
+/**
+ *  @param priv  Private driver information structure
+ *  @param resp  HostCmd_DS_COMMAND struct returned from the firmware
+ *               command
+ *
+ *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_cmdresp_process(mlan_private *priv, const HostCmd_DS_COMMAND *resp)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	switch (resp->command) {
+	case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+		HEXDUMP("11h: TPC REQUEST Rsp:", (t_u8 *)resp,
+			(t_u32)resp->size);
+		memcpy_ext(priv->adapter, priv->adapter->curr_cmd->pdata_buf,
+			   &resp->params.tpc_req,
+			   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ),
+			   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ));
+		break;
+
+	case HostCmd_CMD_802_11_TPC_INFO:
+		HEXDUMP("11h: TPC INFO Rsp Data:", (t_u8 *)resp,
+			(t_u32)resp->size);
+		break;
+
+	case HostCmd_CMD_802_11_CHAN_SW_ANN:
+		PRINTM(MINFO, "11h: Ret ChSwAnn: Sz=%u, Seq=%u, Ret=%u\n",
+		       resp->size, resp->seq_num, resp->result);
+		break;
+
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		priv->adapter->state_dfs.dfs_check_priv = priv;
+		priv->adapter->state_dfs.dfs_check_pending = MTRUE;
+
+		if (resp->params.chan_rpt_req.millisec_dwell_time == 0) {
+			/* from wlan_11h_ioctl_dfs_chan_report */
+			priv->adapter->state_dfs.dfs_check_pending = MFALSE;
+			priv->adapter->state_dfs.dfs_check_priv = MNULL;
+			priv->adapter->state_dfs.dfs_check_channel = 0;
+			PRINTM(MINFO, "11h: Cancelling Chan Report \n");
+		} else {
+			PRINTM(MERROR,
+			       "11h: Ret ChanRptReq.  Set dfs_check_pending and wait"
+			       " for EVENT_CHANNEL_REPORT.\n");
+		}
+
+		break;
+
+	default:
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Process an element from a scan response, copy relevant info for 11h
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @param p11h_bss_info Output parameter: Pointer to the 11h BSS information
+ *                       for the network that is being processed
+ *  @param pelement      Pointer to the current IE we are inspecting for 11h
+ *                       relevance
+ *
+ *  @return              MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_process_bss_elem(mlan_adapter *pmadapter,
+			  wlan_11h_bss_info_t *p11h_bss_info,
+			  const t_u8 *pelement)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 element_len = *((t_u8 *)pelement + 1);
+
+	ENTER();
+	switch (*pelement) {
+	case POWER_CONSTRAINT:
+		PRINTM(MINFO, "11h: Power Constraint IE Found\n");
+		p11h_bss_info->sensed_11h = MTRUE;
+		memcpy_ext(pmadapter, &p11h_bss_info->power_constraint,
+			   pelement, element_len + sizeof(IEEEtypes_Header_t),
+			   sizeof(IEEEtypes_PowerConstraint_t));
+		p11h_bss_info->power_constraint.len =
+			MIN(element_len, (sizeof(IEEEtypes_PowerConstraint_t) -
+					  sizeof(IEEEtypes_Header_t)));
+		break;
+
+	case POWER_CAPABILITY:
+		PRINTM(MINFO, "11h: Power Capability IE Found\n");
+		p11h_bss_info->sensed_11h = MTRUE;
+		memcpy_ext(pmadapter, &p11h_bss_info->power_capability,
+			   pelement, element_len + sizeof(IEEEtypes_Header_t),
+			   sizeof(IEEEtypes_PowerCapability_t));
+		p11h_bss_info->power_capability.len =
+			MIN(element_len, (sizeof(IEEEtypes_PowerCapability_t) -
+					  sizeof(IEEEtypes_Header_t)));
+		break;
+
+	case TPC_REPORT:
+		PRINTM(MINFO, "11h: Tpc Report IE Found\n");
+		p11h_bss_info->sensed_11h = MTRUE;
+		memcpy_ext(pmadapter, &p11h_bss_info->tpc_report, pelement,
+			   element_len + sizeof(IEEEtypes_Header_t),
+			   sizeof(IEEEtypes_TPCReport_t));
+		p11h_bss_info->tpc_report.len =
+			MIN(element_len, (sizeof(IEEEtypes_TPCReport_t) -
+					  sizeof(IEEEtypes_Header_t)));
+		break;
+
+	case CHANNEL_SWITCH_ANN:
+		PRINTM(MINFO, "11h: Channel Switch Ann IE Found\n");
+		p11h_bss_info->sensed_11h = MTRUE;
+		memcpy_ext(pmadapter, &p11h_bss_info->chan_switch_ann, pelement,
+			   element_len + sizeof(IEEEtypes_Header_t),
+			   sizeof(IEEEtypes_ChanSwitchAnn_t));
+		p11h_bss_info->chan_switch_ann.len =
+			MIN(element_len, (sizeof(IEEEtypes_ChanSwitchAnn_t) -
+					  sizeof(IEEEtypes_Header_t)));
+		break;
+
+	case QUIET:
+		PRINTM(MINFO, "11h: Quiet IE Found\n");
+		p11h_bss_info->sensed_11h = MTRUE;
+		memcpy_ext(pmadapter, &p11h_bss_info->quiet, pelement,
+			   element_len + sizeof(IEEEtypes_Header_t),
+			   sizeof(IEEEtypes_Quiet_t));
+		p11h_bss_info->quiet.len =
+			MIN(element_len, (sizeof(IEEEtypes_Quiet_t) -
+					  sizeof(IEEEtypes_Header_t)));
+		break;
+
+	case IBSS_DFS:
+		PRINTM(MINFO, "11h: Ibss Dfs IE Found\n");
+		p11h_bss_info->sensed_11h = MTRUE;
+		memcpy_ext(pmadapter, &p11h_bss_info->ibss_dfs, pelement,
+			   element_len + sizeof(IEEEtypes_Header_t),
+			   sizeof(IEEEtypes_IBSS_DFS_t));
+		p11h_bss_info->ibss_dfs.len =
+			MIN(element_len, (sizeof(IEEEtypes_IBSS_DFS_t) -
+					  sizeof(IEEEtypes_Header_t)));
+		break;
+
+	case SUPPORTED_CHANNELS:
+	case TPC_REQUEST:
+		/*
+		 * These elements are not in beacons/probe responses.
+		 * Included here to cover set of enumerated 11h elements.
+		 */
+		break;
+
+	default:
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Driver handling for CHANNEL_SWITCH_ANN event
+ *
+ *  @param priv Pointer to mlan_private
+ *
+ *  @return MLAN_STATUS_SUCCESS, MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_handle_event_chanswann(mlan_private *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+	mlan_deauth_param deauth_param;
+#endif
+	t_u32 sec, usec;
+#ifdef UAP_SUPPORT
+	mlan_adapter *pmadapter = priv->adapter;
+	int i;
+	t_u8 radar_detected = MFALSE;
+	mlan_private *pmpriv = MNULL;
+#endif
+
+	ENTER();
+#ifdef UAP_SUPPORT
+	if (priv->adapter->state_11h.is_master_radar_det_active) {
+		for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM); i++) {
+			if (pmadapter->priv[i] &&
+			    (pmadapter->priv[i]->bss_role ==
+			     MLAN_BSS_ROLE_UAP) &&
+			    pmadapter->priv[i]->uap_bss_started &&
+			    (priv->curr_bss_params.bss_descriptor.channel ==
+			     pmadapter->priv[i]->uap_channel)) {
+				PRINTM(MCMND,
+				       "Receive channel switch Ann event on uap_channel=%d\n",
+				       pmadapter->priv[i]->uap_channel);
+				radar_detected = MTRUE;
+				pmpriv = pmadapter->priv[i];
+				break;
+			}
+		}
+		if (radar_detected) {
+			if (!pmpriv->intf_state_11h.is_11h_host) {
+				if (pmadapter->state_rdh.stage == RDH_OFF) {
+					pmadapter->state_rdh.stage =
+						RDH_CHK_INTFS;
+					wlan_11h_radar_detected_handling
+						(pmadapter, pmpriv);
+					if (pmpriv->uap_host_based)
+						wlan_recv_event(pmpriv,
+								MLAN_EVENT_ID_FW_RADAR_DETECTED,
+								MNULL);
+				} else {
+					PRINTM(MEVENT,
+					       "Ignore Event Radar Detected - handling already in progress.\n");
+				}
+			} else {
+				if (pmpriv->adapter->dfs_test_params.
+				    no_channel_change_on_radar ||
+				    pmpriv->adapter->dfs_test_params.
+				    fixed_new_channel_on_radar) {
+					if (pmadapter->state_rdh.stage ==
+					    RDH_OFF ||
+					    pmadapter->state_rdh.stage ==
+					    RDH_SET_CUSTOM_IE) {
+						pmadapter->state_rdh.stage =
+							RDH_CHK_INTFS;
+						wlan_11h_radar_detected_handling
+							(pmadapter, pmpriv);
+					} else
+						PRINTM(MEVENT,
+						       "Ignore Event Radar Detected - handling already in progress.\n");
+				} else {
+					pmpriv->intf_state_11h.tx_disabled =
+						MTRUE;
+					wlan_recv_event(pmpriv,
+							MLAN_EVENT_ID_FW_RADAR_DETECTED,
+							MNULL);
+				}
+			}
+		}
+	}
+	if (pmadapter->ecsa_enable) {
+		t_u8 stop_tx = *(t_u8 *)pmadapter->event_body;
+		if (stop_tx)
+			pmadapter->state_rdh.tx_block = MTRUE;
+		LEAVE();
+		return ret;
+	}
+#endif
+	priv->adapter->state_11h.recvd_chanswann_event = MTRUE;
+
+	/* unlikely:  clean up previous csa if still on-going */
+	if (priv->intf_state_11h.dfs_slave_csa_chan) {
+		wlan_set_chan_blacklist(priv, BAND_A,
+					priv->intf_state_11h.dfs_slave_csa_chan,
+					MFALSE);
+	}
+
+	/* record channel and time of occurence */
+	priv->intf_state_11h.dfs_slave_csa_chan =
+		priv->curr_bss_params.bss_descriptor.channel;
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+	priv->intf_state_11h.dfs_slave_csa_expire_at_sec =
+		sec + DFS_CHAN_MOVE_TIME;
+
+#ifdef STA_SUPPORT
+	/* do directed deauth.  recvd_chanswann_event flag will cause different
+	 * reason code */
+	PRINTM(MINFO, "11h: handle_event_chanswann() - sending deauth\n");
+	memcpy_ext(priv->adapter, deauth_param.mac_addr,
+		   &priv->curr_bss_params.bss_descriptor.mac_address,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	deauth_param.reason_code = DEF_DEAUTH_REASON_CODE;
+	ret = wlan_disconnect(priv, MNULL, &deauth_param);
+
+	/* clear region table so next scan will be all passive */
+	PRINTM(MINFO, "11h: handle_event_chanswann() - clear region table\n");
+	wlan_11d_clear_parsedtable(priv);
+
+	/* add channel to blacklist table */
+	PRINTM(MINFO,
+	       "11h: handle_event_chanswann() - scan blacklist csa channel\n");
+	wlan_set_chan_blacklist(priv, BAND_A,
+				priv->intf_state_11h.dfs_slave_csa_chan, MTRUE);
+#endif
+
+	priv->adapter->state_11h.recvd_chanswann_event = MFALSE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 802.11h DFS Testing configuration
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pioctl_req   Pointer to mlan_ioctl_req
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_ioctl_dfs_testing(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+	mlan_ds_11h_dfs_testing *dfs_test = MNULL;
+	wlan_dfs_testing_settings_t *pdfs_test_params = MNULL;
+
+	ENTER();
+
+	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+	dfs_test = &ds_11hcfg->param.dfs_testing;
+	pdfs_test_params = &pmadapter->dfs_test_params;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		dfs_test->usr_cac_period_msec =
+			pdfs_test_params->user_cac_period_msec;
+		dfs_test->usr_nop_period_sec =
+			pdfs_test_params->user_nop_period_sec;
+		dfs_test->usr_no_chan_change =
+			pdfs_test_params->no_channel_change_on_radar;
+		dfs_test->usr_fixed_new_chan =
+			pdfs_test_params->fixed_new_channel_on_radar;
+		dfs_test->usr_cac_restart = pdfs_test_params->cac_restart;
+	} else {
+		pdfs_test_params->user_cac_period_msec =
+			dfs_test->usr_cac_period_msec;
+		pdfs_test_params->user_nop_period_sec =
+			dfs_test->usr_nop_period_sec;
+		pdfs_test_params->no_channel_change_on_radar =
+			dfs_test->usr_no_chan_change;
+		pdfs_test_params->fixed_new_channel_on_radar =
+			dfs_test->usr_fixed_new_chan;
+		pdfs_test_params->cac_restart = dfs_test->usr_cac_restart;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief 802.11h IOCTL to handle channel NOP status check
+ *  @brief If given channel is under NOP, return a new non-dfs
+ *  @brief channel
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pioctl_req   Pointer to mlan_ioctl_req
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_ioctl_get_channel_nop_info(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+	t_s32 ret = MLAN_STATUS_FAILURE;
+	mlan_ds_11h_chan_nop_info *ch_nop_info = MNULL;
+
+	ENTER();
+
+	if (pioctl_req) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+		ch_nop_info = &ds_11hcfg->param.ch_nop_info;
+
+		if (pioctl_req->action == MLAN_ACT_GET) {
+			ch_nop_info->chan_under_nop =
+				wlan_11h_is_channel_under_nop(pmadapter,
+							      ch_nop_info->
+							      curr_chan);
+			if (ch_nop_info->chan_under_nop) {
+				wlan_11h_switch_non_dfs_chan(pmpriv,
+							     &ch_nop_info->
+							     new_chan.channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ ||
+				    ch_nop_info->chan_width == CHAN_BW_40MHZ)
+					wlan_11h_update_bandcfg(pmpriv,
+								&ch_nop_info->
+								new_chan.
+								bandcfg,
+								ch_nop_info->
+								new_chan.
+								channel);
+				if (ch_nop_info->chan_width == CHAN_BW_80MHZ)
+					ch_nop_info->new_chan.center_chan =
+						wlan_get_center_freq_idx(pmpriv,
+									 BAND_AAC,
+									 ch_nop_info->
+									 new_chan.
+									 channel,
+									 ch_nop_info->
+									 chan_width);
+			}
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 802.11h DFS Channel Switch Count Configuration
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pioctl_req   Pointer to mlan_ioctl_req
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_ioctl_chan_switch_count(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+	t_s32 ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+
+	if (pioctl_req) {
+		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+		if (pioctl_req->action == MLAN_ACT_GET) {
+			ds_11hcfg->param.cs_count = pmadapter->dfs_cs_count;
+		} else {
+			pmadapter->dfs_cs_count = ds_11hcfg->param.cs_count;
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 802.11h DFS chan report
+ *
+ *  @param priv         Pointer to mlan_private
+ *  @param pioctl_req   Pointer to mlan_ioctl_req
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_ioctl_dfs_chan_report(mlan_private *priv, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+	HostCmd_DS_CHAN_RPT_REQ *chan_rpt_req = MNULL;
+	t_s32 ret;
+
+	ENTER();
+
+	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+	chan_rpt_req =
+		(HostCmd_DS_CHAN_RPT_REQ *)&ds_11hcfg->param.chan_rpt_req;
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       (t_void *)chan_rpt_req);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check if channel is under NOP (Non-Occupancy Period)
+ *  If so, the channel should not be used until the period expires.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param channel    Channel number
+ *
+ *  @return MTRUE or MFALSE
+ */
+t_bool
+wlan_11h_is_channel_under_nop(mlan_adapter *pmadapter, t_u8 channel)
+{
+	wlan_dfs_timestamp_t *pdfs_ts = MNULL;
+	t_u32 now_sec, now_usec;
+	t_bool ret = MFALSE;
+	ENTER();
+	pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
+
+	if (pdfs_ts && (pdfs_ts->channel == channel) &&
+	    (pdfs_ts->represents == DFS_TS_REPR_NOP_START)) {
+		/* found NOP_start timestamp entry on channel */
+		pmadapter->callbacks.moal_get_system_time(pmadapter->
+							  pmoal_handle,
+							  &now_sec, &now_usec);
+		if (pmadapter->dfs_test_params.user_nop_period_sec) {
+			PRINTM(MCMD_D,
+			       "dfs_testing - user NOP period=%d (sec)\n",
+			       pmadapter->dfs_test_params.user_nop_period_sec);
+			if ((now_sec - pdfs_ts->ts_sec) <=
+			    pmadapter->dfs_test_params.user_nop_period_sec) {
+				ret = MTRUE;
+			}
+		} else {
+			if ((now_sec - pdfs_ts->ts_sec) <=
+			    WLAN_11H_NON_OCCUPANCY_PERIOD)
+				ret = MTRUE;
+		}
+
+		/* if entry is expired, remove it */
+		if (!ret) {
+			wlan_11h_remove_dfs_timestamp(pmadapter, pdfs_ts);
+		} else
+			PRINTM(MMSG,
+			       "11h: channel %d is under NOP - can't use.\n",
+			       channel);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Driver handling for CHANNEL_REPORT_RDY event
+ *  This event will have the channel report data appended.
+ *
+ *  @param priv     Pointer to mlan_private
+ *  @param pevent   Pointer to mlan_event
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_handle_event_chanrpt_ready(mlan_private *priv,
+				    mlan_event *pevent, t_u8 *radar_chan)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_CHAN_RPT_RSP *pchan_rpt_rsp;
+	MrvlIEtypes_Data_t *ptlv;
+	MeasRptBasicMap_t *pmeas_rpt_basic;
+	t_u8 *pbuffer;
+	t_s32 evt_len;
+	t_u16 tlv_len;
+	t_u32 sec, usec;
+	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+	t_u8 dfs_radar_found = MFALSE;
+	t_u8 dfs_check_channel = pstate_dfs->dfs_check_channel;
+
+	ENTER();
+	pchan_rpt_rsp = (HostCmd_DS_CHAN_RPT_RSP *)&pevent->event_buf;
+	DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
+		    (t_u8 *)pchan_rpt_rsp, pevent->event_len);
+
+	if (wlan_le32_to_cpu(pchan_rpt_rsp->cmd_result) ==
+	    MLAN_CMD_RESULT_SUCCESS) {
+		pbuffer = (t_u8 *)&pchan_rpt_rsp->tlv_buffer;
+		evt_len = pevent->event_len;
+		evt_len -= sizeof(HostCmd_DS_CHAN_RPT_RSP) -
+			sizeof(pchan_rpt_rsp->tlv_buffer);
+
+		while (evt_len >= (t_s32)sizeof(MrvlIEtypesHeader_t)) {
+			ptlv = (MrvlIEtypes_Data_t *)pbuffer;
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+
+			switch (wlan_le16_to_cpu(ptlv->header.type)) {
+			case TLV_TYPE_CHANRPT_11H_BASIC:
+				pmeas_rpt_basic =
+					(MeasRptBasicMap_t *)&ptlv->data;
+				if (pmeas_rpt_basic->radar)
+					dfs_radar_found = MTRUE;
+				break;
+			default:
+				break;
+			}
+
+			pbuffer += (tlv_len + sizeof(ptlv->header));
+			evt_len -= (tlv_len + sizeof(ptlv->header));
+			evt_len = (evt_len > 0) ? evt_len : 0;
+		}
+	} else {
+		ret = MLAN_STATUS_FAILURE;
+	}
+	if (dfs_radar_found) {
+		PRINTM(MMSG, "RADAR Detected on channel %d!\n",
+		       dfs_check_channel);
+		/* add channel to NOP list */
+		wlan_11h_add_dfs_timestamp(priv->adapter, DFS_TS_REPR_NOP_START,
+					   dfs_check_channel);
+	}
+	*radar_chan = dfs_check_channel;
+	pstate_dfs->dfs_radar_found = dfs_radar_found;
+	/* Update DFS structure. */
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &sec,
+						      &usec);
+	pstate_dfs->dfs_report_time_sec = sec;
+	pstate_dfs->dfs_check_pending = MFALSE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Print debug info in RADAR_DETECTED event
+ *  This event may have the dfs record data appended.
+ *
+ *  @param priv   		Pointer to mlan_private
+ *  @param pevent 		Pointer to mlan_event
+ *  @param radar_chan 	Pointer to radar channel
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_print_event_radar_detected(mlan_private *priv,
+				    mlan_event *pevent, t_u8 *radar_chan)
+{
+	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+	ENTER();
+	*radar_chan = pstate_dfs->dfs_check_channel;
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Check if RADAR_DETECTED handling is blocking data tx
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *
+ *  @return MTRUE or MFALSE
+ */
+t_bool
+wlan_11h_radar_detected_tx_blocked(mlan_adapter *pmadapter)
+{
+	if (pmadapter->state_rdh.tx_block)
+		return MTRUE;
+	switch (pmadapter->state_rdh.stage) {
+	case RDH_OFF:
+	case RDH_CHK_INTFS:
+	case RDH_STOP_TRAFFIC:
+		return MFALSE;
+	}
+	return MTRUE;
+}
+
+/**
+ *  @brief Callback for RADAR_DETECTED event driver handling
+ *
+ *  @param priv    Void pointer to mlan_private
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_radar_detected_callback(t_void *priv)
+{
+	mlan_status ret;
+	ENTER();
+	ret = wlan_11h_radar_detected_handling(((mlan_private *)(priv))->
+					       adapter, (mlan_private *)priv);
+	LEAVE();
+	return ret;
+}
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief Function for handling sta disconnect event in dfs_repeater mode
+ *
+ *  @param pmadapter	pointer to mlan_adapter
+ *
+ *  @return NONE
+ */
+void
+wlan_dfs_rep_disconnect(mlan_adapter *pmadapter)
+{
+	mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+	mlan_private *pmpriv = MNULL;
+	t_u8 pcount, i;
+
+	memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
+	pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+					priv_list);
+
+	/* Stop all the active BSSes */
+	for (i = 0; i < pcount; i++) {
+		pmpriv = priv_list[i];
+
+		if (GET_BSS_ROLE(pmpriv) != MLAN_BSS_ROLE_UAP)
+			continue;
+
+		if (wlan_11h_radar_detect_required(pmpriv,
+						   pmadapter->dfsr_channel)) {
+			wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
+					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+		}
+	}
+}
+
+/**
+ *  @brief Function for handling sta BW change event in dfs_repeater mode
+ *
+ *  @param pmadapter	pointer to mlan_adapter
+ *
+ *  @return NONE
+ */
+void
+wlan_dfs_rep_bw_change(mlan_adapter *pmadapter)
+{
+	mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+	mlan_private *pmpriv = MNULL;
+	t_u8 pcount, i;
+
+	memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
+	pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+					priv_list);
+	if (pcount == 1) {
+		pmpriv = priv_list[0];
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+			PRINTM(MMSG,
+			       "dfs-repeater: BW change detected\n"
+			       "no active priv's, skip event handling.\n");
+			return;
+		}
+	}
+
+	/* Stop all the active BSSes */
+	for (i = 0; i < pcount; i++) {
+		pmpriv = priv_list[i];
+
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			/* Check if uAPs running on non-dfs channel. If they do
+			 * then there is no need to restart the uAPs
+			 */
+			if (!wlan_11h_radar_detect_required
+			    (pmpriv, pmadapter->dfsr_channel))
+				return;
+
+			wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
+					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+		}
+	}
+
+	/* Start all old active BSSes */
+	for (i = 0; i < pcount; i++) {
+		pmpriv = priv_list[i];
+
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
+					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+		}
+	}
+}
+#endif
+
+/**
+ *  @brief Update band config for the new channel
+ *
+ *  @param uap_band_cfg  uap's old channel's band configuration
+ *  @param new_channel   new channel that the device is switching to
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+void
+wlan_11h_update_bandcfg(mlan_private *pmpriv, Band_Config_t *uap_band_cfg,
+			t_u8 new_channel)
+{
+	t_u8 chan_offset;
+	ENTER();
+
+	/* Update the channel offset for 20MHz, 40MHz and 80MHz
+	 * Clear the channel bandwidth for 20MHz
+	 * since channel switch could be happening from 40/80MHz to 20MHz
+	 */
+	chan_offset = wlan_get_second_channel_offset(pmpriv, new_channel);
+	uap_band_cfg->chan2Offset = chan_offset;
+
+	if (!chan_offset) {	/* 40MHz/80MHz */
+		PRINTM(MCMD_D, "20MHz channel, clear channel bandwidth\n");
+		uap_band_cfg->chanWidth = CHAN_BW_20MHZ;
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Get priv current index -- this is used to enter correct rdh_state
+ * during radar handling
+ *
+ * @param pmpriv           Pointer to mlan_private
+ * @param pstate_rdh       Pointer to radar detected state handler
+ *
+ * @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11h_get_priv_curr_idx(mlan_private *pmpriv,
+			   wlan_radar_det_hndlg_state_t *pstate_rdh)
+{
+	t_bool found = MFALSE;
+	ENTER();
+
+	PRINTM(MINFO, "%s:pmpriv =%p\n", __func__, pmpriv);
+	while ((++pstate_rdh->priv_curr_idx) < pstate_rdh->priv_list_count) {
+		if (pmpriv == pstate_rdh->priv_list[pstate_rdh->priv_curr_idx]) {
+			PRINTM(MINFO, "found matching priv: priv_idx=%d\n",
+			       pstate_rdh->priv_curr_idx);
+			found = MTRUE;
+			break;
+		}
+	}
+	return (found == MTRUE) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Driver handling for remove customeie
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pmpriv       Pointer to mlan_private
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_remove_custom_ie(mlan_adapter *pmadapter, mlan_private *pmpriv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+	mlan_ioctl_req *pioctl_req = MNULL;
+
+	ENTER();
+	if (pstate_rdh->stage == RDH_SET_CUSTOM_IE) {
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		PRINTM(MMSG, "Removing CHAN_SW IE from interfaces.\n");
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+			if (!wlan_11h_is_dfs_master(pmpriv))
+				continue;
+			ret = wlan_11h_prepare_custom_ie_chansw(pmadapter,
+								&pioctl_req,
+								MFALSE);
+			if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+				PRINTM(MERROR,
+				       "%s(): Error in preparing CHAN_SW IE.\n",
+				       __func__);
+				goto done;
+			}
+
+			pioctl_req->bss_index = pmpriv->bss_index;
+			ret = wlan_misc_ioctl_custom_ie_list(pmadapter,
+							     pioctl_req,
+							     MFALSE);
+			if (ret != MLAN_STATUS_SUCCESS &&
+			    ret != MLAN_STATUS_PENDING) {
+				PRINTM(MERROR,
+				       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+				       __func__, pmpriv, pmpriv->bss_index);
+				/* TODO: hiow to handle this error case??
+				 * ignore & continue? */
+			}
+			/* free ioctl buffer memory before we leave */
+			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+							(t_u8 *)pioctl_req);
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Driver handling for RADAR_DETECTED event
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pmpriv       Pointer to mlan_private
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_radar_detected_handling(mlan_adapter *pmadapter, mlan_private *pmpriv)
+{
+#ifdef DEBUG_LEVEL1
+	const char *rdh_stage_str[] = { "RDH_OFF",
+		"RDH_CHK_INTFS",
+		"RDH_STOP_TRAFFIC",
+		"RDH_GET_INFO_CHANNEL",
+		"RDH_GET_INFO_BEACON_DTIM",
+		"RDH_SET_CUSTOM_IE",
+		"RDH_REM_CUSTOM_IE",
+		"RDH_STOP_INTFS",
+		"RDH_SET_NEW_CHANNEL",
+		"RDH_RESTART_INTFS",
+		"RDH_RESTART_TRAFFIC"
+	};
+#endif
+
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 i;
+	wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
+
+	ENTER();
+
+	if (!pmpriv) {
+		PRINTM(MERROR, "Invalid radar priv -- Exit radar handling\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	switch (pstate_rdh->stage) {
+	case RDH_CHK_INTFS:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+
+		/* get active interfaces */
+		memset(pmadapter, pstate_rdh->priv_list, 0x00,
+		       sizeof(pstate_rdh->priv_list));
+		pstate_rdh->priv_list_count =
+			wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+					       pstate_rdh->priv_list);
+		PRINTM(MCMD_D, "%s():  priv_list_count = %d\n", __func__,
+		       pstate_rdh->priv_list_count);
+		for (i = 0; i < pstate_rdh->priv_list_count; i++)
+			PRINTM(MINFO, "%s():  priv_list[%d] = %p\n", __func__,
+			       i, pstate_rdh->priv_list[i]);
+
+		if (pstate_rdh->priv_list_count == 0) {
+			/* no interfaces active... nothing to do */
+			PRINTM(MMSG, "11h: Radar Detected - no active priv's,"
+			       " skip event handling.\n");
+			pstate_rdh->stage = RDH_OFF;
+			PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n",
+			       __func__, pstate_rdh->stage,
+			       rdh_stage_str[pstate_rdh->stage]);
+			break;	/* EXIT CASE */
+		}
+
+		/* else: start handling */
+		pstate_rdh->curr_channel = 0;
+		pstate_rdh->new_channel = 0;
+		memset(pmadapter, &(pstate_rdh->uap_band_cfg), 0,
+		       sizeof(pstate_rdh->uap_band_cfg));
+		pstate_rdh->max_bcn_dtim_ms = 0;
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_STOP_TRAFFIC;
+		/* fall through */
+
+	case RDH_STOP_TRAFFIC:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+
+		PRINTM(MMSG,
+		       "11h: Radar Detected - stopping host tx traffic.\n");
+		for (i = 0; i < pstate_rdh->priv_list_count; i++)
+			wlan_11h_tx_disable(pstate_rdh->priv_list[i]);
+
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_GET_INFO_CHANNEL;
+		/* fall through */
+
+	case RDH_GET_INFO_CHANNEL:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* here, prefer STA info over UAP info - one less CMD to send */
+		if (pstate_rdh->priv_curr_idx == RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+				ret = wlan_11h_get_priv_curr_idx(pmpriv,
+								 pstate_rdh);
+				if (ret != MLAN_STATUS_SUCCESS) {
+					PRINTM(MERROR,
+					       "Unable to locate pmpriv in current active priv_list\n");
+					break;	/* EXIT CASE */
+				}
+
+				/* send cmd to get first UAP's info */
+				pmpriv->uap_state_chan_cb.pioctl_req_curr =
+					MNULL;
+				pmpriv->uap_state_chan_cb.get_chan_callback =
+					wlan_11h_radar_detected_callback;
+				ret = wlan_uap_get_channel(pmpriv);
+				break;	/* EXIT CASE */
+			} else
+#endif
+			{
+				/* Assume all STAs on same channel, find first
+				 * STA */
+				MASSERT(pstate_rdh->priv_list_count > 0);
+				for (i = 0; i < pstate_rdh->priv_list_count;
+				     i++) {
+					pmpriv = pstate_rdh->priv_list[i];
+					if (GET_BSS_ROLE(pmpriv) ==
+					    MLAN_BSS_ROLE_STA)
+						break;
+				}
+				/* STA info kept in driver, just copy */
+				pstate_rdh->curr_channel =
+					pmpriv->curr_bss_params.bss_descriptor.
+					channel;
+			}
+		}
+#ifdef UAP_SUPPORT
+		else if (pstate_rdh->priv_curr_idx <
+			 pstate_rdh->priv_list_count) {
+			/* repeat entry: UAP return with info */
+			pstate_rdh->curr_channel =
+				pmpriv->uap_state_chan_cb.channel;
+			pstate_rdh->uap_band_cfg =
+				pmpriv->uap_state_chan_cb.bandcfg;
+			PRINTM(MCMD_D,
+			       "%s(): uap_band_cfg=0x%02x curr_chan=%d, curr_idx=%d bss_role=%d\n",
+			       __func__, pstate_rdh->uap_band_cfg,
+			       pstate_rdh->curr_channel,
+			       pstate_rdh->priv_curr_idx, GET_BSS_ROLE(pmpriv));
+		}
+#endif
+
+		/* add channel to NOP list */
+		wlan_11h_add_dfs_timestamp(pmadapter, DFS_TS_REPR_NOP_START,
+					   pstate_rdh->curr_channel);
+
+		/* choose new channel (!= curr channel) and move on */
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+			pstate_rdh->new_channel =
+				wlan_11h_get_uap_start_channel(pmpriv,
+							       pmpriv->
+							       uap_state_chan_cb.
+							       bandcfg);
+		else
+#endif
+			pstate_rdh->new_channel =
+				wlan_11h_get_adhoc_start_channel(pmpriv);
+
+		if (!pstate_rdh->new_channel || (pstate_rdh->new_channel == pstate_rdh->curr_channel)) {	/* report error */
+			PRINTM(MERROR,
+			       "%s():  ERROR - Failed to choose new_chan"
+			       " (!= curr_chan) !!\n", __func__);
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+				ret = wlan_prepare_cmd(pmpriv,
+						       HOST_CMD_APCMD_BSS_STOP,
+						       HostCmd_ACT_GEN_SET, 0,
+						       MNULL, MNULL);
+				PRINTM(MERROR,
+				       "STOP UAP and exit radar handling...\n");
+				pstate_rdh->stage = RDH_OFF;
+				break;	/* leads to exit case */
+			}
+#endif
+		}
+		if (!pmadapter->dfs_test_params.no_channel_change_on_radar &&
+		    pmadapter->dfs_test_params.fixed_new_channel_on_radar) {
+			PRINTM(MCMD_D, "dfs_testing - user fixed new_chan=%d\n",
+			       pmadapter->dfs_test_params.
+			       fixed_new_channel_on_radar);
+			pstate_rdh->new_channel =
+				pmadapter->dfs_test_params.
+				fixed_new_channel_on_radar;
+		}
+		/* applies to DFS with ECSA support */
+		if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
+			pstate_rdh->new_channel = pstate_rdh->curr_channel;
+		}
+		PRINTM(MCMD_D, "%s():  curr_chan=%d, new_chan=%d\n", __func__,
+		       pstate_rdh->curr_channel, pstate_rdh->new_channel);
+
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_GET_INFO_BEACON_DTIM;
+		/* fall through */
+
+	case RDH_GET_INFO_BEACON_DTIM:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+#ifdef UAP_SUPPORT
+		/* check all intfs in this stage to find longest period */
+		/* UAP intf callback returning with info */
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count) {
+			t_u16 bcn_dtim_msec;
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+			PRINTM(MCMD_D, "%s():  uap.bcn_pd=%d, uap.dtim_pd=%d\n",
+			       __func__,
+			       pmpriv->uap_state_chan_cb.beacon_period,
+			       pmpriv->uap_state_chan_cb.dtim_period);
+			bcn_dtim_msec =
+				(pmpriv->uap_state_chan_cb.beacon_period *
+				 pmpriv->uap_state_chan_cb.dtim_period);
+			if (bcn_dtim_msec > pstate_rdh->max_bcn_dtim_ms)
+				pstate_rdh->max_bcn_dtim_ms = bcn_dtim_msec;
+		}
+#endif
+
+		/* check next intf */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+				pmpriv->uap_state_chan_cb.pioctl_req_curr =
+					MNULL;
+				pmpriv->uap_state_chan_cb.get_chan_callback =
+					wlan_11h_radar_detected_callback;
+				ret = wlan_uap_get_beacon_dtim(pmpriv);
+				break;	/* leads to exit case */
+			} else
+#endif
+			{	/* get STA info from driver and compare here */
+				t_u16 bcn_pd_msec = 100;
+				t_u16 dtim_pd_msec = 1;
+				t_u16 bcn_dtim_msec;
+
+				/* adhoc creator */
+				if (wlan_11h_is_dfs_master(pmpriv)) {
+					bcn_pd_msec = pmpriv->beacon_period;
+				} else {
+					bcn_pd_msec =
+						pmpriv->curr_bss_params.
+						bss_descriptor.beacon_period;
+					/* if (priv->bss_mode !=
+					 * MLAN_BSS_MODE_IBSS) */
+					/* TODO: mlan_scan.c needs to parse TLV
+					 * 0x05 (TIM) for dtim_period */
+				}
+				PRINTM(MCMD_D,
+				       "%s():  sta.bcn_pd=%d, sta.dtim_pd=%d\n",
+				       __func__, bcn_pd_msec, dtim_pd_msec);
+				bcn_dtim_msec = (bcn_pd_msec * dtim_pd_msec);
+				if (bcn_dtim_msec > pstate_rdh->max_bcn_dtim_ms)
+					pstate_rdh->max_bcn_dtim_ms =
+						bcn_dtim_msec;
+			}
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count)
+			break;	/* EXIT CASE (for UAP) */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_SET_CUSTOM_IE;
+		/* fall through */
+
+	case RDH_SET_CUSTOM_IE:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* add CHAN_SW IE - Need apply on each interface */
+		if (pstate_rdh->priv_curr_idx == RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+			mlan_ioctl_req *pioctl_req = MNULL;
+			PRINTM(MMSG,
+			       "11h: Radar Detected - adding CHAN_SW IE to interfaces.\n");
+			while ((++pstate_rdh->priv_curr_idx) <
+			       pstate_rdh->priv_list_count) {
+				pmpriv = pstate_rdh->priv_list
+					[pstate_rdh->priv_curr_idx];
+				if (!wlan_11h_is_dfs_master(pmpriv))
+					continue;
+				ret = wlan_11h_prepare_custom_ie_chansw
+					(pmadapter, &pioctl_req, MTRUE);
+				if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+					PRINTM(MERROR,
+					       "%s(): Error in preparing CHAN_SW IE.\n",
+					       __func__);
+					break;	/* EXIT CASE */
+				}
+
+				pioctl_req->bss_index = pmpriv->bss_index;
+				ret = wlan_misc_ioctl_custom_ie_list(pmadapter,
+								     pioctl_req,
+								     MFALSE);
+				if (ret != MLAN_STATUS_SUCCESS &&
+				    ret != MLAN_STATUS_PENDING) {
+					PRINTM(MERROR,
+					       "%s(): Could not set IE for priv=%p [priv_bss_idx=%d]!\n",
+					       __func__, pmpriv,
+					       pmpriv->bss_index);
+					/* TODO: how to handle this error case??
+					 * ignore & continue? */
+				}
+				/* free ioctl buffer memory before we leave */
+				pmadapter->callbacks.moal_mfree(pmadapter->
+								pmoal_handle,
+								(t_u8 *)
+								pioctl_req);
+			}
+			break;	/* EXIT CASE */
+		}
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_REM_CUSTOM_IE;
+		/* fall through */
+
+	case RDH_REM_CUSTOM_IE:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* remove CHAN_SW IE - Need apply on each interface */
+		if (pstate_rdh->priv_curr_idx == RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
+			mlan_ioctl_req *pioctl_req = MNULL;
+			/*
+			 * first entry to this stage, do delay
+			 * DFS requires a minimum of 5 chances for clients to
+			 * hear this IE. Use delay:  5 beacons <=
+			 * (BCN_DTIM_MSEC*5) <= 3 seconds).
+			 */
+			t_u16 delay_ms = MAX(MIN_RDH_CHAN_SW_IE_PERIOD_MSEC,
+					     MIN((4 *
+						  pstate_rdh->max_bcn_dtim_ms),
+						 MAX_RDH_CHAN_SW_IE_PERIOD_MSEC));
+			PRINTM(MMSG,
+			       "11h: Radar Detected - delay %d ms for FW to"
+			       " broadcast CHAN_SW IE.\n", delay_ms);
+			wlan_mdelay(pmadapter, delay_ms);
+			PRINTM(MMSG,
+			       "11h: Radar Detected - delay over, removing"
+			       " CHAN_SW IE from interfaces.\n");
+			while ((++pstate_rdh->priv_curr_idx) <
+			       pstate_rdh->priv_list_count) {
+				pmpriv = pstate_rdh->priv_list
+					[pstate_rdh->priv_curr_idx];
+				if (!wlan_11h_is_dfs_master(pmpriv))
+					continue;
+				ret = wlan_11h_prepare_custom_ie_chansw
+					(pmadapter, &pioctl_req, MFALSE);
+				if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+					PRINTM(MERROR,
+					       "%s(): Error in preparing CHAN_SW IE.\n",
+					       __func__);
+					break;	/* EXIT CASE */
+				}
+
+				pioctl_req->bss_index = pmpriv->bss_index;
+				ret = wlan_misc_ioctl_custom_ie_list(pmadapter,
+								     pioctl_req,
+								     MFALSE);
+				if (ret != MLAN_STATUS_SUCCESS &&
+				    ret != MLAN_STATUS_PENDING) {
+					PRINTM(MERROR,
+					       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+					       __func__, pmpriv,
+					       pmpriv->bss_index);
+					/* TODO: hiow to handle this error
+					 * case??  ignore & continue? */
+				}
+				/* free ioctl buffer memory before we leave */
+				pmadapter->callbacks.moal_mfree(pmadapter->
+								pmoal_handle,
+								(t_u8 *)
+								pioctl_req);
+			}
+			break;	/* EXIT CASE */
+		}
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_STOP_INTFS;
+		/* fall through */
+
+	case RDH_STOP_INTFS:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* issues one cmd (DEAUTH/ADHOC_STOP/BSS_STOP) to each intf */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+				ret = wlan_prepare_cmd(pmpriv,
+						       HOST_CMD_APCMD_BSS_STOP,
+						       HostCmd_ACT_GEN_SET, 0,
+						       MNULL, MNULL);
+				break;	/* leads to exit case */
+			}
+#endif
+#ifdef STA_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+				if (wlan_11h_is_dfs_master(pmpriv)) {
+					/* Save ad-hoc creator state before stop
+					 * clears it */
+					pmpriv->adhoc_state_prev =
+						pmpriv->adhoc_state;
+				}
+				if (pmpriv->media_connected == MTRUE) {
+					wlan_disconnect(pmpriv, MNULL, MNULL);
+					break;	/* leads to exit case */
+				}
+			}
+#endif
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+		    ret == MLAN_STATUS_FAILURE)
+			break;	/* EXIT CASE */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_SET_NEW_CHANNEL;
+
+		if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
+			PRINTM(MCMD_D,
+			       "dfs_testing - no channel change on radar."
+			       "  Overwrite new_chan = curr_chan.\n");
+			pstate_rdh->new_channel = pstate_rdh->curr_channel;
+			pstate_rdh->priv_curr_idx =
+				RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+			pstate_rdh->stage = RDH_RESTART_INTFS;
+			goto rdh_restart_intfs;	/* skip next stage */
+		}
+		/* fall through */
+
+	case RDH_SET_NEW_CHANNEL:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* only set new channel for UAP intfs */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+				pmpriv->uap_state_chan_cb.pioctl_req_curr =
+					MNULL;
+				pmpriv->uap_state_chan_cb.get_chan_callback =
+					wlan_11h_radar_detected_callback;
+
+				/* DFS only in 5GHz */
+				wlan_11h_update_bandcfg(pmpriv,
+							&pstate_rdh->
+							uap_band_cfg,
+							pstate_rdh->
+							new_channel);
+				PRINTM(MCMD_D,
+				       "RDH_SET_NEW_CHANNEL: uAP band config = 0x%x channel=%d\n",
+				       pstate_rdh->uap_band_cfg,
+				       pstate_rdh->new_channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pstate_rdh->
+							   uap_band_cfg,
+							   pstate_rdh->
+							   new_channel);
+				break;	/* leads to exit case */
+			}
+#endif
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+		    ret == MLAN_STATUS_FAILURE)
+			break;	/* EXIT CASE (for UAP) */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_RESTART_INTFS;
+		/* fall through */
+
+	case RDH_RESTART_INTFS:
+rdh_restart_intfs:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
+		       pstate_rdh->priv_curr_idx);
+
+		/* can only restart master intfs */
+		while ((++pstate_rdh->priv_curr_idx) <
+		       pstate_rdh->priv_list_count) {
+			pmpriv = pstate_rdh->priv_list[pstate_rdh->
+						       priv_curr_idx];
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+				if (wlan_11h_radar_detect_required
+				    (pmpriv, pstate_rdh->new_channel)) {
+					/* Radar detection is required for this
+					   channel, make sure 11h is activated
+					   in the firmware */
+					ret = wlan_11h_activate(pmpriv, MNULL,
+								MTRUE);
+					ret = wlan_11h_config_master_radar_det
+						(pmpriv, MTRUE);
+					ret = wlan_11h_check_update_radar_det_state(pmpriv);
+				}
+				ret = wlan_prepare_cmd(pmpriv,
+						       HOST_CMD_APCMD_BSS_START,
+						       HostCmd_ACT_GEN_SET, 0,
+						       MNULL, MNULL);
+				break;	/* leads to exit case */
+			}
+#endif
+#ifdef STA_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+				/* Check previous state to find former
+				 * Ad-hoc creator interface. Set new
+				 * state to Starting, so it'll be seen
+				 * as a DFS master. */
+				if (pmpriv->adhoc_state_prev == ADHOC_STARTED) {
+					pmpriv->adhoc_state = ADHOC_STARTING;
+					pmpriv->adhoc_state_prev = ADHOC_IDLE;
+				}
+				if (wlan_11h_is_dfs_master(pmpriv)) {
+					/* set new adhoc channel here */
+					pmpriv->adhoc_channel =
+						pstate_rdh->new_channel;
+					if (wlan_11h_radar_detect_required
+					    (pmpriv, pstate_rdh->new_channel)) {
+						/* Radar detection is required
+						   for this channel, make sure
+						   11h is activated in the
+						   firmware */
+						ret = wlan_11h_activate(pmpriv,
+									MNULL,
+									MTRUE);
+						if (ret)
+							break;
+						ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+						if (ret)
+							break;
+						ret = wlan_11h_check_update_radar_det_state(pmpriv);
+						if (ret)
+							break;
+					}
+					ret = wlan_prepare_cmd(pmpriv,
+							       HostCmd_CMD_802_11_AD_HOC_START,
+							       HostCmd_ACT_GEN_SET,
+							       0, MNULL,
+							       &pmpriv->
+							       adhoc_last_start_ssid);
+					break;	/* leads to exit case */
+				}
+
+				/* NOTE:  DON'T reconnect slave STA intfs -
+				 * infra/adhoc_joiner Do we want to return to
+				 * same AP/network (on radar channel)? If want
+				 * to connect back, depend on either:
+				 *     1. driver's reassoc thread
+				 *     2. wpa_supplicant, or other user-space
+				 * app
+				 */
+			}
+#endif
+		}
+
+		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
+		    ret == MLAN_STATUS_FAILURE)
+			break;	/* EXIT CASE (for UAP) */
+		/* else */
+		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+		pstate_rdh->stage = RDH_RESTART_TRAFFIC;
+		/* fall through */
+
+	case RDH_RESTART_TRAFFIC:
+		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+		/* remove custome ie */
+		if (pmadapter->ecsa_enable) {
+			mlan_ioctl_req *pioctl_req = MNULL;
+			pstate_rdh->priv_curr_idx =
+				RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
+			while ((++pstate_rdh->priv_curr_idx) <
+			       pstate_rdh->priv_list_count) {
+				pmpriv = pstate_rdh->priv_list
+					[pstate_rdh->priv_curr_idx];
+				if (!wlan_11h_is_dfs_master(pmpriv))
+					continue;
+				ret = wlan_11h_prepare_custom_ie_chansw
+					(pmadapter, &pioctl_req, MFALSE);
+				if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
+					PRINTM(MERROR,
+					       "%s(): Error in preparing CHAN_SW IE.\n",
+					       __func__);
+					break;	/* EXIT CASE */
+				}
+
+				pioctl_req->bss_index = pmpriv->bss_index;
+
+				ret = wlan_misc_ioctl_custom_ie_list(pmadapter,
+								     pioctl_req,
+								     MFALSE);
+				if (ret != MLAN_STATUS_SUCCESS &&
+				    ret != MLAN_STATUS_PENDING) {
+					PRINTM(MERROR,
+					       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
+					       __func__, pmpriv,
+					       pmpriv->bss_index);
+					/* TODO: hiow to handle this error
+					 * case??  ignore & continue? */
+				}
+				/* free ioctl buffer memory before we leave */
+				pmadapter->callbacks.moal_mfree(pmadapter->
+								pmoal_handle,
+								(t_u8 *)
+								pioctl_req);
+			}
+		}
+		/* continue traffic for reactivated interfaces */
+		PRINTM(MMSG,
+		       "11h: Radar Detected - restarting host tx traffic.\n");
+		for (i = 0; i < pstate_rdh->priv_list_count; i++)
+			wlan_11h_tx_enable(pstate_rdh->priv_list[i]);
+
+		pstate_rdh->stage = RDH_OFF;	/* DONE! */
+		PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n", __func__,
+		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
+
+		break;
+
+	default:
+		pstate_rdh->stage = RDH_OFF;	/* cancel RDH to unblock Tx packets
+						 */
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief DFS Event Preprocessing.
+ *  Operates directly on pmadapter variables.
+ *
+ *  1. EVENT_RADAR_DETECTED comes from firmware without specific
+ *     bss_num/bss_type.  Find it an appropriate interface and
+ *     update event_cause field in event_buf.
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *
+ *  @return    MLAN_STATUS_SUCCESS (update successful)
+ *          or MLAN_STATUS_FAILURE (no change)
+ */
+mlan_status
+wlan_11h_dfs_event_preprocessing(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	mlan_private *pmpriv = MNULL;
+	mlan_private *priv_list[MLAN_MAX_BSS_NUM] = { MNULL };
+
+	ENTER();
+	switch (pmadapter->event_cause & EVENT_ID_MASK) {
+	case EVENT_RADAR_DETECTED:
+		/* find active intf:  prefer dfs_master over dfs_slave */
+		if (wlan_get_privs_by_two_cond
+		    (pmadapter, wlan_11h_is_master_active_on_dfs_chan,
+		     wlan_11h_is_dfs_master, MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_master priv=%p\n",
+			       __func__, pmpriv);
+		} else if (wlan_get_privs_by_two_cond(pmadapter,
+						      wlan_11h_is_slave_active_on_dfs_chan,
+						      wlan_11h_is_dfs_slave,
+						      MTRUE, priv_list)) {
+			pmpriv = priv_list[0];
+			PRINTM(MINFO, "%s: found dfs_slave priv=%p\n", __func__,
+			       pmpriv);
+		} else if (pmadapter->state_dfs.dfs_check_pending ||
+			   pmadapter->state_dfs.dfs_check_channel) {
+			pmpriv = (mlan_private *)(pmadapter->state_dfs.
+						  dfs_check_priv);
+			PRINTM(MINFO, "%s: found dfs priv=%p\n", __func__,
+			       pmpriv);
+		}
+
+		/* update event_cause if we found an appropriate priv */
+		if (pmpriv) {
+			pmlan_buffer pmevbuf = pmadapter->pmlan_buffer_event;
+			t_u32 new_event_cause =
+				pmadapter->event_cause & EVENT_ID_MASK;
+			new_event_cause |=
+				((GET_BSS_NUM(pmpriv) & 0xff) << 16) |
+				((pmpriv->bss_type & 0xff) << 24);
+			PRINTM(MINFO, "%s: priv - bss_num=%d, bss_type=%d\n",
+			       __func__, GET_BSS_NUM(pmpriv), pmpriv->bss_type);
+			memcpy_ext(pmadapter,
+				   pmevbuf->pbuf + pmevbuf->data_offset,
+				   &new_event_cause, sizeof(new_event_cause),
+				   sizeof(new_event_cause));
+			ret = MLAN_STATUS_SUCCESS;
+		} else {
+			PRINTM(MERROR,
+			       "Failed to find dfs master/slave priv\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief try to switch to a non-dfs channel
+ *
+ *  @param priv    Void pointer to mlan_private
+ *
+ *  @param chan    pointer to channel
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_11h_switch_non_dfs_chan(mlan_private *priv, t_u8 *chan)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u32 i;
+	t_u32 rand_entry;
+	t_u8 def_chan;
+	t_u8 rand_tries = 0;
+	region_chan_t *chn_tbl = MNULL;
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	if (!pmadapter->dfs_test_params.no_channel_change_on_radar &&
+	    pmadapter->dfs_test_params.fixed_new_channel_on_radar) {
+		PRINTM(MCMD_D, "dfs_testing - user fixed new_chan=%d\n",
+		       pmadapter->dfs_test_params.fixed_new_channel_on_radar);
+		*chan = pmadapter->dfs_test_params.fixed_new_channel_on_radar;
+
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	/*get the channel table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (pmadapter->region_channel[i].band == BAND_A &&
+		    pmadapter->region_channel[i].valid) {
+			chn_tbl = &pmadapter->region_channel[i];
+			break;
+		}
+	}
+
+	if (!chn_tbl || !chn_tbl->pcfp)
+		goto done;
+
+	do {
+		rand_entry =
+			wlan_11h_get_random_num(pmadapter) % chn_tbl->num_cfp;
+		def_chan = (t_u8)chn_tbl->pcfp[rand_entry].channel;
+		rand_tries++;
+	} while ((wlan_11h_is_channel_under_nop(pmadapter, def_chan) ||
+		  chn_tbl->pcfp[rand_entry].passive_scan_or_radar_detect ==
+		  MTRUE) && (rand_tries < MAX_SWITCH_CHANNEL_RETRIES));
+
+	/* meet max retries, use the lowest non-dfs channel */
+	if (rand_tries == MAX_SWITCH_CHANNEL_RETRIES) {
+		for (i = 0; i < chn_tbl->num_cfp; i++) {
+			if (chn_tbl->pcfp[i].passive_scan_or_radar_detect ==
+			    MFALSE &&
+			    !wlan_11h_is_channel_under_nop(pmadapter,
+							   (t_u8)chn_tbl->
+							   pcfp[i].channel)) {
+				def_chan = (t_u8)chn_tbl->pcfp[i].channel;
+				break;
+			}
+		}
+		if (i == chn_tbl->num_cfp)
+			goto done;
+	}
+
+	*chan = def_chan;
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set dfs check channel
+ *
+ *  @param priv    Void pointer to mlan_private
+ *
+ *  @param chan    pointer to channel
+ *
+ *  @return  N/A
+ */
+void
+wlan_11h_set_dfs_check_chan(mlan_private *priv, t_u8 chan)
+{
+	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
+	ENTER();
+	pstate_dfs->dfs_check_channel = chan;
+	PRINTM(MCMND, "Set dfs_check_channel=%d\n", chan);
+	LEAVE();
+}
+
+/**
+ *  @brief 802.11h DFS W53 configuration
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pioctl_req   Pointer to mlan_ioctl_req
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_11h_ioctl_dfs_w53_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+	mlan_ds_11h_dfs_w53_cfg *dfs_w53_cfg = MNULL;
+
+	ENTER();
+
+	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+	dfs_w53_cfg = &ds_11hcfg->param.dfs_w53_cfg;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		dfs_w53_cfg->dfs53cfg = pmadapter->dfs53cfg;
+	} else {
+		pmadapter->dfs53cfg = dfs_w53_cfg->dfs53cfg;
+	}
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8987/mlan/mlan_11h.h b/wlan_sd8987/mlan/mlan_11h.h
new file mode 100755
index 0000000..c49d324
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11h.h
@@ -0,0 +1,203 @@
+/** @file mlan_11h.h
+ *
+ *  @brief This header file contains data structures and
+ *  function declarations of 802.11h
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    03/26/2009: initial creation
+*************************************************************/
+
+#ifndef _MLAN_11H_
+#define _MLAN_11H_
+
+/** 11H OID bitmasks */
+#define ENABLE_11H_MASK MBIT(0)
+#define MASTER_RADAR_DET_MASK MBIT(1)
+#define SLAVE_RADAR_DET_MASK MBIT(2)
+
+/** DFS Master Radar Detect global enable */
+#define DFS_MASTER_RADAR_DETECT_EN (MTRUE)
+/** DFS Slave Radar Detect global enable */
+#define DFS_SLAVE_RADAR_DETECT_EN (MFALSE)
+
+#define CHANNEL_OFFSET_MASK 0x30
+#define CHANNEL_BANDWIDTH_MASK 0x0C
+
+/**
+ *  11H APIs
+ */
+
+/* Is master radar detection enabled in firmware? */
+extern t_bool wlan_11h_is_master_radar_det_active(mlan_private *priv);
+
+/** Configure master radar detection.
+ *  Need call wlan_11h_check_update_radar_det_state() after.
+ */
+extern mlan_status wlan_11h_config_master_radar_det(mlan_private *priv,
+						    t_bool enable);
+
+/** Configure slave radar detection.
+ *  Need call wlan_11h_check_update_radar_det_state() after.
+ */
+extern mlan_status wlan_11h_config_slave_radar_det(mlan_private *priv,
+						   t_bool enable);
+
+/** Checks all interfaces and updates radar detect flags if necessary */
+extern mlan_status wlan_11h_check_update_radar_det_state(mlan_private *pmpriv);
+
+/** Return 1 if 11h is active in the firmware, 0 if it is inactive */
+extern t_bool wlan_11h_is_active(mlan_private *priv);
+
+/** Enable the tx interface and record the new transmit state */
+extern void wlan_11h_tx_enable(mlan_private *priv);
+
+/** Disable the tx interface and record the new transmit state */
+extern void wlan_11h_tx_disable(mlan_private *priv);
+
+/** Activate 11h extensions in the firmware */
+extern mlan_status wlan_11h_activate(mlan_private *priv, t_void *pioctl_buf,
+				     t_bool flag);
+
+/** Initialize the 11h device structure */
+extern void wlan_11h_init(mlan_adapter *pmadapter);
+
+/** Cleanup for the 11h device structure */
+extern void wlan_11h_cleanup(mlan_adapter *pmadapter);
+
+/** Initialize the 11h interface structure */
+extern void wlan_11h_priv_init(mlan_private *pmpriv);
+
+/** Get an initial random channel to start an adhoc network on */
+extern t_u8 wlan_11h_get_adhoc_start_channel(mlan_private *priv);
+
+/** Get channel that has been closed via Channel Switch Announcement */
+extern t_u8 wlan_11h_get_csa_closed_channel(mlan_private *priv);
+
+/** Check if radar detection is required on the specified channel */
+extern t_bool wlan_11h_radar_detect_required(mlan_private *priv, t_u8 channel);
+
+/** Perform a standard availibility check on the specified channel */
+extern t_s32 wlan_11h_issue_radar_detect(mlan_private *priv,
+					 pmlan_ioctl_req pioctl_req,
+					 t_u8 channel, Band_Config_t bandcfg);
+
+/** Check previously issued radar report for a channel */
+extern mlan_status wlan_11h_check_chan_report(mlan_private *priv, t_u8 chan);
+
+/** Add any 11h TLVs necessary to complete an adhoc start command */
+extern t_s32 wlan_11h_process_start(mlan_private *priv, t_u8 **ppbuffer,
+				    IEEEtypes_CapInfo_t *pcap_info,
+				    t_u32 channel,
+				    wlan_11h_bss_info_t *p11h_bss_info);
+
+/** Add any 11h TLVs necessary to complete a join command (adhoc or infra) */
+extern t_s32 wlan_11h_process_join(mlan_private *priv, t_u8 **ppbuffer,
+				   IEEEtypes_CapInfo_t *pcap_info, t_u8 band,
+				   t_u32 channel,
+				   wlan_11h_bss_info_t *p11h_bss_info);
+
+/** Complete the firmware command preparation for an 11h command function */
+extern mlan_status wlan_11h_cmd_process(mlan_private *priv,
+					HostCmd_DS_COMMAND *pcmd_ptr,
+					const t_void *pinfo_buf);
+
+/** Process the response of an 11h firmware command */
+extern mlan_status wlan_11h_cmdresp_process(mlan_private *priv,
+					    const HostCmd_DS_COMMAND *resp);
+
+/** Receive IEs from scan processing and record any needed info for 11h */
+extern mlan_status wlan_11h_process_bss_elem(mlan_adapter *pmadapter,
+					     wlan_11h_bss_info_t *p11h_bss_info,
+					     const t_u8 *pelement);
+
+/** Handler for EVENT_CHANNEL_SWITCH_ANN */
+extern mlan_status wlan_11h_handle_event_chanswann(mlan_private *priv);
+
+/** Handler for EVENT_CHANNEL_REPORT_RDY */
+extern mlan_status wlan_11h_handle_event_chanrpt_ready(mlan_private *priv,
+						       mlan_event *pevent,
+						       t_u8 *radar_chan);
+
+/** Debug output for EVENT_RADAR_DETECTED */
+mlan_status wlan_11h_print_event_radar_detected(mlan_private *priv,
+						mlan_event *pevent,
+						t_u8 *radar_chan);
+
+t_s32 wlan_11h_cancel_radar_detect(mlan_private *priv);
+/** Handler for DFS_TESTING IOCTL */
+extern mlan_status wlan_11h_ioctl_dfs_testing(pmlan_adapter pmadapter,
+					      pmlan_ioctl_req pioctl_req);
+extern mlan_status
+
+wlan_11h_ioctl_get_channel_nop_info(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req);
+
+extern mlan_status
+ wlan_11h_ioctl_dfs_chan_report(mlan_private *priv, pmlan_ioctl_req pioctl_req);
+extern mlan_status wlan_11h_ioctl_chan_switch_count(pmlan_adapter pmadapter,
+						    pmlan_ioctl_req pioctl_req);
+
+/** get/set dfs w53 cfg */
+mlan_status wlan_11h_ioctl_dfs_w53_cfg(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req);
+
+/** Check if channel is under a NOP duration (should not be used) */
+extern t_bool wlan_11h_is_channel_under_nop(mlan_adapter *pmadapter,
+					    t_u8 channel);
+
+/** Check if RADAR_DETECTED handling is blocking data tx */
+extern t_bool wlan_11h_radar_detected_tx_blocked(mlan_adapter *pmadapter);
+
+/** Callback for RADAR_DETECTED (for UAP cmdresp) */
+extern mlan_status wlan_11h_radar_detected_callback(t_void *priv);
+/** set dfs check channel */
+void wlan_11h_set_dfs_check_chan(mlan_private *priv, t_u8 chan);
+
+#ifdef UAP_SUPPORT
+/** BW_change event Handler for dfs_repeater */
+void wlan_dfs_rep_bw_change(mlan_adapter *pmadapter);
+
+/** disconnect event Handler for dfs_repeater */
+void wlan_dfs_rep_disconnect(mlan_adapter *pmadapter);
+#endif
+
+/** Handler for RADAR_DETECTED */
+extern mlan_status wlan_11h_radar_detected_handling(mlan_adapter *pmadapter,
+						    mlan_private *priv);
+
+mlan_status wlan_11h_remove_custom_ie(mlan_adapter *pmadapter,
+				      mlan_private *pmpriv);
+
+/** DFS Event pre-processing */
+extern mlan_status wlan_11h_dfs_event_preprocessing(mlan_adapter *pmadapter);
+
+/** DFS switch to non-DFS channel */
+extern mlan_status wlan_11h_switch_non_dfs_chan(mlan_private *priv, t_u8 *chan);
+
+extern void wlan_11h_update_bandcfg(mlan_private *pmpriv,
+				    Band_Config_t *uap_band_cfg,
+				    t_u8 new_channel);
+
+/** function checks if interface is active. **/
+extern t_bool wlan_is_intf_active(mlan_private *pmpriv);
+
+#endif /*_MLAN_11H_ */
diff --git a/wlan_sd8987/mlan/mlan_11n.c b/wlan_sd8987/mlan/mlan_11n.c
new file mode 100755
index 0000000..d773af0
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n.c
@@ -0,0 +1,3258 @@
+/** @file mlan_11n.c
+ *
+ *  @brief This file contains functions for 11n handling.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *
+ *  @brief set/get max tx buf size
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return				MLAN_STATUS_SUCCESS --success, otherwise
+ * fail
+ */
+static mlan_status
+wlan_11n_ioctl_max_tx_buf_size(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	cfg->param.tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get htcapinfo configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return				MLAN_STATUS_SUCCESS --success, otherwise
+ * fail
+ */
+static mlan_status
+wlan_11n_ioctl_htusrcfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (((cfg->param.htcap_cfg.htcap & ~IGN_HW_DEV_CAP) &
+		     pmpriv->adapter->hw_dot_11n_dev_cap) !=
+		    (cfg->param.htcap_cfg.htcap & ~IGN_HW_DEV_CAP)) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+		} else {
+			if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BG) {
+				pmpriv->usr_dot_11n_dev_cap_bg =
+					cfg->param.htcap_cfg.htcap;
+				PRINTM(MINFO,
+				       "Set: UsrDot11nCap for 2.4GHz 0x%x\n",
+				       pmpriv->usr_dot_11n_dev_cap_bg);
+			}
+			if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
+				pmpriv->usr_dot_11n_dev_cap_a =
+					cfg->param.htcap_cfg.htcap;
+				PRINTM(MINFO,
+				       "Set: UsrDot11nCap for 5GHz 0x%x\n",
+				       pmpriv->usr_dot_11n_dev_cap_a);
+			}
+			if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BOTH) {
+				pmpriv->usr_dot_11n_dev_cap_bg =
+					cfg->param.htcap_cfg.htcap;
+				pmpriv->usr_dot_11n_dev_cap_a =
+					cfg->param.htcap_cfg.htcap;
+				PRINTM(MINFO,
+				       "Set: UsrDot11nCap for 2.4GHz and 5GHz 0x%x\n",
+				       cfg->param.htcap_cfg.htcap);
+			}
+		}
+	} else {
+		/* Hardware 11N device capability required */
+		if (cfg->param.htcap_cfg.hw_cap_req)
+			cfg->param.htcap_cfg.htcap =
+				pmadapter->hw_dot_11n_dev_cap;
+		else {
+			if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BG) {
+				cfg->param.htcap_cfg.htcap =
+					pmpriv->usr_dot_11n_dev_cap_bg;
+				PRINTM(MINFO,
+				       "Get: UsrDot11nCap for 2.4GHz 0x%x\n",
+				       cfg->param.htcap_cfg.htcap);
+			}
+			if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
+				cfg->param.htcap_cfg.htcap =
+					pmpriv->usr_dot_11n_dev_cap_a;
+				PRINTM(MINFO,
+				       "Get: UsrDot11nCap for 5GHz 0x%x\n",
+				       cfg->param.htcap_cfg.htcap);
+			}
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable/Disable AMSDU AGGR CTRL
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_amsdu_aggr_ctrl(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AMSDU_AGGR_CTRL, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.amsdu_aggr_ctrl);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get 11n configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_httxcfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.tx_cfg);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get TX beamforming capabilities
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_11n_ioctl_tx_bf_cap(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		pmpriv->tx_bf_cap = cfg->param.tx_bf_cap;
+	else
+		cfg->param.tx_bf_cap = pmpriv->tx_bf_cap;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get TX beamforming configurations
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_tx_bf_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_BF_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.tx_bf);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get HT stream configurations
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_stream_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_cfg *cfg = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		cfg->param.stream_cfg = pmpriv->usr_dev_mcs_support;
+	} else if (pioctl_req->action == MLAN_ACT_SET) {
+		switch (cfg->param.stream_cfg) {
+		case HT_STREAM_MODE_2X2:
+			if (pmadapter->hw_dev_mcs_support == HT_STREAM_MODE_1X1) {
+				PRINTM(MERROR,
+				       "HW does not support this mode\n");
+				ret = MLAN_STATUS_FAILURE;
+			} else
+				pmpriv->usr_dev_mcs_support =
+					cfg->param.stream_cfg;
+			break;
+		case HT_STREAM_MODE_1X1:
+			pmpriv->usr_dev_mcs_support = cfg->param.stream_cfg;
+			break;
+		default:
+			PRINTM(MERROR, "Invalid stream mode\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get control to coex RX window size configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_coex_rx_winsize(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cfg->param.coex_rx_winsize = pmadapter->coex_rx_winsize;
+	else if (pioctl_req->action == MLAN_ACT_SET)
+		pmadapter->coex_rx_winsize = (t_u8)cfg->param.coex_rx_winsize;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send delba request to
+ *          the peer in the TxBAStreamTbl
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ra       MAC Address to send DELBA
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_send_delba_to_peer(mlan_private *priv, t_u8 *ra)
+{
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+	wlan_request_ralist_lock(priv);
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (!memcmp(priv->adapter, ptx_tbl->ra, ra,
+			    MLAN_MAC_ADDR_LENGTH)) {
+			PRINTM(MIOCTL, "Tx:Send delba to tid=%d, " MACSTR "\n",
+			       ptx_tbl->tid, MAC2STR(ptx_tbl->ra));
+			wlan_send_delba(priv, MNULL, ptx_tbl->tid, ptx_tbl->ra,
+					1);
+		}
+		ptx_tbl = ptx_tbl->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+	/* Signal MOAL to trigger mlan_main_process */
+	wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/Get control to TX AMPDU configuration on infra link
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_txaggrctrl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_cfg *cfg = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cfg->param.txaggrctrl = pmpriv->txaggrctrl;
+	else if (pioctl_req->action == MLAN_ACT_SET)
+		pmpriv->txaggrctrl = (t_u8)cfg->param.txaggrctrl;
+
+	if (pmpriv->media_connected == MTRUE) {
+		if (pioctl_req->action == MLAN_ACT_SET && !pmpriv->txaggrctrl &&
+		    pmpriv->adapter->tdls_status != TDLS_NOT_SETUP)
+			wlan_11n_send_delba_to_peer(pmpriv,
+						    pmpriv->curr_bss_params.
+						    bss_descriptor.mac_address);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will resend addba request to all
+ *          the peer in the TxBAStreamTbl
+ *
+ *  @param priv     A pointer to mlan_private
+ *
+ *  @return         N/A
+ */
+static void
+wlan_11n_update_addba_request(mlan_private *priv)
+{
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		wlan_send_addba(priv, ptx_tbl->tid, ptx_tbl->ra);
+		ptx_tbl = ptx_tbl->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+	/* Signal MOAL to trigger mlan_main_process */
+	wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/get addba parameter
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return				MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_11n_ioctl_addba_param(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+	t_u32 timeout;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		cfg->param.addba_param.timeout = pmpriv->add_ba_param.timeout;
+		cfg->param.addba_param.txwinsize =
+			pmpriv->add_ba_param.tx_win_size;
+		cfg->param.addba_param.rxwinsize =
+			pmpriv->add_ba_param.rx_win_size;
+		cfg->param.addba_param.txamsdu = pmpriv->add_ba_param.tx_amsdu;
+		cfg->param.addba_param.rxamsdu = pmpriv->add_ba_param.rx_amsdu;
+	} else {
+		timeout = pmpriv->add_ba_param.timeout;
+		pmpriv->add_ba_param.timeout = cfg->param.addba_param.timeout;
+		pmpriv->add_ba_param.tx_win_size =
+			cfg->param.addba_param.txwinsize;
+
+		pmpriv->add_ba_param.rx_win_size =
+			cfg->param.addba_param.rxwinsize;
+		pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+		pmpriv->add_ba_param.tx_amsdu = cfg->param.addba_param.txamsdu;
+		pmpriv->add_ba_param.rx_amsdu = cfg->param.addba_param.rxamsdu;
+		if (timeout != pmpriv->add_ba_param.timeout)
+			wlan_11n_update_addba_request(pmpriv);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function send delba to specific tid
+ *
+ *  @param priv         A pointer to mlan_priv
+ *  @param tid          tid
+ *  @return             N/A
+ */
+void
+wlan_11n_delba(mlan_private *priv, int tid)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if (rx_reor_tbl_ptr->tid == tid) {
+			PRINTM(MIOCTL, "Send delba to tid=%d, " MACSTR "\n",
+			       tid, MAC2STR(rx_reor_tbl_ptr->ta));
+			wlan_send_delba(priv, MNULL, tid, rx_reor_tbl_ptr->ta,
+					0);
+			LEAVE();
+			return;
+		}
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/get addba reject set
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_addba_reject(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	int i = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		PRINTM(MINFO, "Get Addba reject\n");
+		memcpy_ext(pmadapter, cfg->param.addba_reject,
+			   pmpriv->addba_reject, MAX_NUM_TID, MAX_NUM_TID);
+	} else {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			/* For AMPDU */
+			if (cfg->param.addba_reject[i] >
+			    ADDBA_RSP_STATUS_REJECT) {
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+
+			pmpriv->addba_reject[i] = cfg->param.addba_reject[i];
+		}
+		if (pmpriv->media_connected == MTRUE) {
+			for (i = 0; i < MAX_NUM_TID; i++) {
+				if (cfg->param.addba_reject[i] ==
+				    ADDBA_RSP_STATUS_REJECT) {
+					PRINTM(MIOCTL,
+					       "Receive addba reject: tid=%d\n",
+					       i);
+					wlan_11n_delba(pmpriv, i);
+				}
+			}
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+					MNULL);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get ibss ampdu param
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_ibss_ampdu_param(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	int i = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		PRINTM(MINFO, "Get IBSS AMPDU param\n");
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			cfg->param.ibss_ampdu.ampdu[i] = pmpriv->ibss_ampdu[i];
+			cfg->param.ibss_ampdu.addba_reject[i] =
+				pmpriv->ibss_addba_reject[i];
+		}
+	} else {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			/* For AMPDU  RX */
+			if (cfg->param.ibss_ampdu.addba_reject[i] >
+			    ADDBA_RSP_STATUS_REJECT) {
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+			pmpriv->ibss_addba_reject[i] =
+				cfg->param.ibss_ampdu.addba_reject[i];
+			/* For AMPDU TX */
+			if ((cfg->param.ibss_ampdu.ampdu[i] > HIGH_PRIO_TID) &&
+			    (cfg->param.ibss_ampdu.ampdu[i] !=
+			     BA_STREAM_NOT_ALLOWED)) {
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+			pmpriv->ibss_ampdu[i] = cfg->param.ibss_ampdu.ampdu[i];
+		}
+		PRINTM(MMSG, "IBSS addba reject: %d %d %d %d %d %d %d %d\n",
+		       pmpriv->ibss_addba_reject[0],
+		       pmpriv->ibss_addba_reject[1],
+		       pmpriv->ibss_addba_reject[2],
+		       pmpriv->ibss_addba_reject[3],
+		       pmpriv->ibss_addba_reject[4],
+		       pmpriv->ibss_addba_reject[5],
+		       pmpriv->ibss_addba_reject[6],
+		       pmpriv->ibss_addba_reject[7]);
+		PRINTM(MMSG, "IBSS ampdu %d %d %d %d %d %d %d %d\n",
+		       pmpriv->ibss_ampdu[0], pmpriv->ibss_ampdu[1],
+		       pmpriv->ibss_ampdu[2], pmpriv->ibss_ampdu[3],
+		       pmpriv->ibss_ampdu[4], pmpriv->ibss_ampdu[5],
+		       pmpriv->ibss_ampdu[6], pmpriv->ibss_ampdu[7]);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Minimum BA Threshold
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_11n_ioctl_min_ba_threshold_cfg(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_cfg *cfg = MNULL;
+	ENTER();
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cfg->param.min_ba_threshold = pmadapter->min_ba_threshold;
+	else
+		pmadapter->min_ba_threshold = cfg->param.min_ba_threshold;
+	pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send DELBA to entries in the priv's
+ *          Tx BA stream table
+ *
+ *  @param priv                 A pointer to mlan_private
+ *  @param pioctl_req	        A pointer to ioctl request buffer
+ *  @param tid                  TID
+ *  @param peer_address         A pointer to peer address
+ *  @param last_tx_ba_to_delete A pointer to the last entry in TxBAStreamTbl
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
+ */
+static mlan_status
+wlan_send_delba_to_entry_in_txbastream_tbl(pmlan_private priv,
+					   pmlan_ioctl_req pioctl_req, t_u8 tid,
+					   t_u8 *peer_address,
+					   TxBAStreamTbl *last_tx_ba_to_delete)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	tx_ba_stream_tbl_ptr =
+		(TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+						&priv->tx_ba_stream_tbl_ptr,
+						MNULL, MNULL);
+	if (!tx_ba_stream_tbl_ptr) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return ret;
+	}
+
+	while (tx_ba_stream_tbl_ptr !=
+	       (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (tx_ba_stream_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+			if (((tid == DELBA_ALL_TIDS) ||
+			     (tid == tx_ba_stream_tbl_ptr->tid)) &&
+			    (!memcmp(pmadapter, peer_address, zero_mac,
+				     MLAN_MAC_ADDR_LENGTH) ||
+			     !memcmp(pmadapter, peer_address,
+				     tx_ba_stream_tbl_ptr->ra,
+				     MLAN_MAC_ADDR_LENGTH))) {
+				if (last_tx_ba_to_delete &&
+				    (tx_ba_stream_tbl_ptr ==
+				     last_tx_ba_to_delete))
+					ret = wlan_send_delba(priv, pioctl_req,
+							      tx_ba_stream_tbl_ptr->
+							      tid,
+							      tx_ba_stream_tbl_ptr->
+							      ra, 1);
+				else
+					ret = wlan_send_delba(priv, MNULL,
+							      tx_ba_stream_tbl_ptr->
+							      tid,
+							      tx_ba_stream_tbl_ptr->
+							      ra, 1);
+			}
+		}
+		tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send DELBA to entries in the priv's
+ *          rx reordering table
+ *
+ *  @param priv                 A pointer to mlan_private
+ *  @param pioctl_req	        A pointer to ioctl request buffer
+ *  @param tid                  TID
+ *  @param peer_address         A pointer to peer address
+ *  @param last_rx_ba_to_delete A pointer to the last entry in RxReorderTbl
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
+ */
+static mlan_status
+wlan_send_delba_to_entry_in_reorder_tbl(pmlan_private priv,
+					pmlan_ioctl_req pioctl_req, t_u8 tid,
+					t_u8 *peer_address,
+					RxReorderTbl *last_rx_ba_to_delete)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	RxReorderTbl *rx_reor_tbl_ptr;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(pmadapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       pmadapter->callbacks.
+					       moal_spin_lock,
+					       pmadapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return ret;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if (rx_reor_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+			if (((tid == DELBA_ALL_TIDS) ||
+			     (tid == rx_reor_tbl_ptr->tid)) &&
+			    (!memcmp(pmadapter, peer_address, zero_mac,
+				     MLAN_MAC_ADDR_LENGTH) ||
+			     !memcmp(pmadapter, peer_address,
+				     rx_reor_tbl_ptr->ta,
+				     MLAN_MAC_ADDR_LENGTH))) {
+				if (last_rx_ba_to_delete &&
+				    (rx_reor_tbl_ptr == last_rx_ba_to_delete))
+					ret = wlan_send_delba(priv, pioctl_req,
+							      rx_reor_tbl_ptr->
+							      tid,
+							      rx_reor_tbl_ptr->
+							      ta, 0);
+				else
+					ret = wlan_send_delba(priv, MNULL,
+							      rx_reor_tbl_ptr->
+							      tid,
+							      rx_reor_tbl_ptr->
+							      ta, 0);
+			}
+		}
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief IOCTL to delete BA
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_delba(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+	TxBAStreamTbl *tx_ba_stream_tbl_ptr, *last_tx_ba_to_delete = MNULL;
+	RxReorderTbl *rx_reor_tbl_ptr, *last_rx_ba_to_delete = MNULL;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+	t_u8 tid, *peer_address;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	tid = cfg->param.del_ba.tid;
+	peer_address = cfg->param.del_ba.peer_mac_addr;
+
+	PRINTM(MINFO, "DelBA: direction %d, TID %d, peer address " MACSTR "\n",
+	       cfg->param.del_ba.direction, tid, MAC2STR(peer_address));
+
+	if (cfg->param.del_ba.direction & DELBA_RX) {
+		rx_reor_tbl_ptr =
+			(RxReorderTbl *)util_peek_list(pmadapter->pmoal_handle,
+						       &pmpriv->
+						       rx_reorder_tbl_ptr,
+						       pmadapter->callbacks.
+						       moal_spin_lock,
+						       pmadapter->callbacks.
+						       moal_spin_unlock);
+
+		if (rx_reor_tbl_ptr) {
+			while (rx_reor_tbl_ptr !=
+			       (RxReorderTbl *)&pmpriv->rx_reorder_tbl_ptr) {
+				if (rx_reor_tbl_ptr->ba_status ==
+				    BA_STREAM_SETUP_COMPLETE) {
+					if (((tid == DELBA_ALL_TIDS) ||
+					     (tid == rx_reor_tbl_ptr->tid)) &&
+					    (!memcmp(pmadapter, peer_address,
+						     zero_mac,
+						     MLAN_MAC_ADDR_LENGTH) ||
+					     !memcmp(pmadapter, peer_address,
+						     rx_reor_tbl_ptr->ta,
+						     MLAN_MAC_ADDR_LENGTH))) {
+						/* Found RX BA to delete */
+						last_rx_ba_to_delete =
+							rx_reor_tbl_ptr;
+					}
+				}
+				rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+			}
+		}
+	}
+
+	if ((last_rx_ba_to_delete == MNULL) &&
+	    (cfg->param.del_ba.direction & DELBA_TX)) {
+		wlan_request_ralist_lock(pmpriv);
+		tx_ba_stream_tbl_ptr =
+			(TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+							&pmpriv->
+							tx_ba_stream_tbl_ptr,
+							MNULL, MNULL);
+
+		if (tx_ba_stream_tbl_ptr) {
+			while (tx_ba_stream_tbl_ptr !=
+			       (TxBAStreamTbl *)&pmpriv->tx_ba_stream_tbl_ptr) {
+				if (tx_ba_stream_tbl_ptr->ba_status ==
+				    BA_STREAM_SETUP_COMPLETE) {
+					if (((tid == DELBA_ALL_TIDS) ||
+					     (tid ==
+					      tx_ba_stream_tbl_ptr->tid)) &&
+					    (!memcmp(pmadapter, peer_address,
+						     zero_mac,
+						     MLAN_MAC_ADDR_LENGTH) ||
+					     !memcmp(pmadapter, peer_address,
+						     tx_ba_stream_tbl_ptr->ra,
+						     MLAN_MAC_ADDR_LENGTH))) {
+						/* Found TX BA to delete */
+						last_tx_ba_to_delete =
+							tx_ba_stream_tbl_ptr;
+					}
+				}
+				tx_ba_stream_tbl_ptr =
+					tx_ba_stream_tbl_ptr->pnext;
+			}
+		}
+		wlan_release_ralist_lock(pmpriv);
+	}
+
+	if (cfg->param.del_ba.direction & DELBA_TX) {
+		if (last_rx_ba_to_delete)
+			ret = wlan_send_delba_to_entry_in_txbastream_tbl(pmpriv,
+									 MNULL,
+									 tid,
+									 peer_address,
+									 MNULL);
+		else
+			ret = wlan_send_delba_to_entry_in_txbastream_tbl(pmpriv,
+									 pioctl_req,
+									 tid,
+									 peer_address,
+									 last_tx_ba_to_delete);
+	}
+	if (last_rx_ba_to_delete) {
+		ret = wlan_send_delba_to_entry_in_reorder_tbl(pmpriv,
+							      pioctl_req, tid,
+							      peer_address,
+							      last_rx_ba_to_delete);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief IOCTL to reject addba req
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_rejectaddbareq(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_REJECT_ADDBA_REQ, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       &cfg->param.reject_addba_req);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will send DELBA to entries in the priv's
+ *          Tx BA stream table
+ *
+ *  @param priv                 A pointer to mlan_private
+ *  @param tid                  TID
+ *
+ *  @return		 N/A
+ */
+static void
+wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	TxBAStreamTbl *tx_ba_stream_tbl_ptr;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	tx_ba_stream_tbl_ptr =
+		(TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+						&priv->tx_ba_stream_tbl_ptr,
+						MNULL, MNULL);
+	if (!tx_ba_stream_tbl_ptr) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return;
+	}
+
+	while (tx_ba_stream_tbl_ptr !=
+	       (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (tx_ba_stream_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
+			if (tid == tx_ba_stream_tbl_ptr->tid) {
+				PRINTM(MIOCTL,
+				       "Tx:Send delba to tid=%d, " MACSTR "\n",
+				       tid, MAC2STR(tx_ba_stream_tbl_ptr->ra));
+				wlan_release_ralist_lock(priv);
+				wlan_send_delba(priv, MNULL,
+						tx_ba_stream_tbl_ptr->tid,
+						tx_ba_stream_tbl_ptr->ra, 1);
+				LEAVE();
+				return;
+			}
+		}
+		tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
+	}
+	wlan_release_ralist_lock(priv);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief update station list for the new aggr_prio_tbl setting
+ *
+ *  @param priv 	A pointer to mlan_private structure
+ *
+ *
+ *  @return		N/A
+ */
+static void
+wlan_update_all_stations_ampdu(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	mlan_adapter *pmadapter = priv->adapter;
+	int i = 0;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	sta_ptr = (sta_node *)util_peek_list(pmadapter->pmoal_handle,
+					     &priv->sta_list, MNULL, MNULL);
+	if (!sta_ptr) {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			if (sta_ptr->is_11n_enabled)
+				sta_ptr->ampdu_sta[i] =
+					priv->aggr_prio_tbl[i].ampdu_user;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Set/get aggr_prio_tbl
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_aggr_prio_tbl(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	int i = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			cfg->param.aggr_prio_tbl.ampdu[i] =
+				pmpriv->aggr_prio_tbl[i].ampdu_user;
+			cfg->param.aggr_prio_tbl.amsdu[i] =
+				pmpriv->aggr_prio_tbl[i].amsdu;
+		}
+	} else {
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			/* For AMPDU */
+			if ((cfg->param.aggr_prio_tbl.ampdu[i] >
+			     HIGH_PRIO_TID)&&
+			    (cfg->param.aggr_prio_tbl.ampdu[i] !=
+			     BA_STREAM_NOT_ALLOWED)) {
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+
+			pmpriv->aggr_prio_tbl[i].ampdu_ap =
+				pmpriv->aggr_prio_tbl[i].ampdu_user =
+				cfg->param.aggr_prio_tbl.ampdu[i];
+
+			/* For AMSDU */
+			if ((cfg->param.aggr_prio_tbl.amsdu[i] >
+			     HIGH_PRIO_TID &&
+			     cfg->param.aggr_prio_tbl.amsdu[i] !=
+			     BA_STREAM_NOT_ALLOWED)) {
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			} else {
+				pmpriv->aggr_prio_tbl[i].amsdu =
+					cfg->param.aggr_prio_tbl.amsdu[i];
+			}
+		}
+		if (pmpriv->media_connected == MTRUE) {
+			for (i = 0; i < MAX_NUM_TID; i++) {
+				if (cfg->param.aggr_prio_tbl.ampdu[i] ==
+				    BA_STREAM_NOT_ALLOWED) {
+					PRINTM(MIOCTL,
+					       "Receive aggrpriotbl: BA not allowed tid=%d\n",
+					       i);
+					wlan_send_delba_txbastream_tbl(pmpriv,
+								       i);
+				}
+			}
+			wlan_update_all_stations_ampdu(pmpriv);
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+					MNULL);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function update all the tx_win_size
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *
+ *
+ *  @return             N/A
+ */
+void
+wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter)
+{
+	t_u8 i;
+	t_u32 tx_win_size = 0;
+	pmlan_private priv = MNULL;
+
+	ENTER();
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			tx_win_size = priv->add_ba_param.tx_win_size;
+#ifdef STA_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_STA)
+				priv->add_ba_param.tx_win_size =
+					MLAN_STA_AMPDU_DEF_TXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				priv->add_ba_param.tx_win_size =
+					MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+#endif
+#ifdef UAP_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_UAP)
+				priv->add_ba_param.tx_win_size =
+					MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+#endif
+			if (pmadapter->coex_win_size &&
+			    pmadapter->coex_tx_win_size)
+				priv->add_ba_param.tx_win_size =
+					pmadapter->coex_tx_win_size;
+
+			if (tx_win_size != priv->add_ba_param.tx_win_size) {
+				if (priv->media_connected == MTRUE) {
+					for (i = 0; i < MAX_NUM_TID; i++)
+						wlan_send_delba_txbastream_tbl
+							(priv, i);
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				}
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Get supported MCS set
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_11n_ioctl_supported_mcs_set(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11n_cfg *cfg = MNULL;
+	int rx_mcs_supp;
+	t_u8 mcs_set[NUM_MCS_FIELD];
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Set operation is not supported\n");
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	rx_mcs_supp = GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
+	/* Set MCS for 1x1/2x2 */
+	memset(pmadapter, (t_u8 *)mcs_set, 0xff, rx_mcs_supp);
+	/* Clear all the other values */
+	memset(pmadapter, (t_u8 *)&mcs_set[rx_mcs_supp], 0,
+	       NUM_MCS_FIELD - rx_mcs_supp);
+	/* Set MCS32 with 40MHz support */
+	if ((ISSUPP_CHANWIDTH40(pmpriv->usr_dot_11n_dev_cap_bg)
+	     || ISSUPP_CHANWIDTH40(pmpriv->usr_dot_11n_dev_cap_a)
+	    ) &&
+	    !(pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	      pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+		SETHT_MCS32(mcs_set);
+
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	memcpy_ext(pmadapter, cfg->param.supported_mcs_set, mcs_set,
+		   NUM_MCS_FIELD, NUM_MCS_FIELD);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the given pointer is valid entry of
+ *         Tx BA Stream table
+ *
+ *  @param priv         Pointer to mlan_private
+ *  @param ptxtblptr    Pointer to tx ba stream entry
+ *
+ *  @return             MTRUE or MFALSE
+ */
+static int
+wlan_is_txbastreamptr_valid(mlan_private *priv, TxBAStreamTbl *ptxtblptr)
+{
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		LEAVE();
+		return MFALSE;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (ptx_tbl == ptxtblptr) {
+			LEAVE();
+			return MTRUE;
+		}
+		ptx_tbl = ptx_tbl->pnext;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function will return the pointer to a entry in BA Stream
+ *          table which matches the ba_status requested
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param ba_status    Current status of the BA stream
+ *
+ *  @return             A pointer to first entry matching status in BA stream
+ *                      NULL if not found
+ */
+static TxBAStreamTbl *
+wlan_11n_get_txbastream_status(mlan_private *priv, baStatus_e ba_status)
+{
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		LEAVE();
+		return MNULL;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (ptx_tbl->ba_status == ba_status) {
+			LEAVE();
+			return ptx_tbl;
+		}
+		ptx_tbl = ptx_tbl->pnext;
+	}
+
+	LEAVE();
+	return MNULL;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function fills the cap info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_fill_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+		SETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+	else
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+	if (ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+		SETHT_GREENFIELD(ht_cap->ht_cap_info);
+	else
+		RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+	if (ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+		SETHT_SHORTGI20(ht_cap->ht_cap_info);
+	else
+		RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+	if (ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+		SETHT_SHORTGI40(ht_cap->ht_cap_info);
+	else
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+	if (ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+		SETHT_RXSTBC(ht_cap->ht_cap_info, 1);
+	else
+		RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+	if (ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+		SETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	else
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+	/** if current channel only allow 20Mhz, we should cler 40Mhz support */
+	if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	}
+	/* No user config for LDPC coding capability yet */
+	if (ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+		SETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+	else
+		RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+	/* No user config for TX STBC yet */
+	if (ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+		SETHT_TXSTBC(ht_cap->ht_cap_info);
+	else
+		RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+	/* No user config for Delayed BACK yet */
+	RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+
+	/* SM power save */
+	RESETHT_SM_POWERSAVE(ht_cap->ht_cap_info);	/* Clear to HT SMPS static mode */
+	if (ISSUPP_MIMOPS(usr_dot_11n_dev_cap)) {
+		if (ISSUPP_SMPS_DYNAMIC_MODE(usr_dot_11n_dev_cap))
+			SETHT_SMPS_DYNAMIC(ht_cap->ht_cap_info);	/* Set to HT SMPS dynamic mode */
+	} else {
+		SETHT_SMPS_DISABLE(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function clear the bit in cap info which we don't support
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+static void
+wlan_reset_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u8 bands)
+{
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
+		RESETHT_GREENFIELD(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI20(ht_cap->ht_cap_info);
+
+	if (!ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+	if (!ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_RXSTBC(ht_cap->ht_cap_info);
+
+	if (!ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+
+	/** if current channel only allow 20Mhz, we should cler 40Mhz support */
+	if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
+		RESETHT_SHORTGI40(ht_cap->ht_cap_info);
+		RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
+	}
+	/* No user config for LDPC coding capability yet */
+	if (!ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
+		RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
+
+	/* No user config for TX STBC yet */
+	if (!ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
+		RESETHT_TXSTBC(ht_cap->ht_cap_info);
+
+	/* No user config for Delayed BACK yet */
+	RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
+
+	/* Need change to support 8k AMSDU receive */
+	RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
+	/* SM power save */
+	if (!ISSUPP_MIMOPS(usr_dot_11n_dev_cap))
+		SETHT_SMPS_DISABLE(ht_cap->ht_cap_info);	/* Disable HT SMPS */
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function fills the HT cap tlv
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *  @param fill         A flag for fill the htcap info
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+		     t_u16 bands, t_u8 fill)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	int rx_mcs_supp;
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	/* Fill HT cap info */
+	if (fill)
+		wlan_fill_cap_info(priv, &pht_cap->ht_cap, bands);
+	else
+		wlan_reset_cap_info(priv, &pht_cap->ht_cap, bands);
+
+	pht_cap->ht_cap.ht_cap_info =
+		wlan_cpu_to_le16(pht_cap->ht_cap.ht_cap_info);
+
+	/* Set ampdu param */
+	SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K);
+	SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0);
+
+	rx_mcs_supp = GET_RXMCSSUPP(priv->usr_dev_mcs_support);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	if (IS_CARD9098(pmadapter->card_type) ||
+	    IS_CARD9097(pmadapter->card_type)) {
+		if (bands & BAND_A)
+			rx_mcs_supp = MIN(rx_mcs_supp,
+					  GET_RXMCSSUPP(pmadapter->
+							user_htstream >> 8));
+		else
+			rx_mcs_supp =
+				MIN(rx_mcs_supp,
+				    GET_RXMCSSUPP(pmadapter->user_htstream));
+	}
+#endif
+	memset(pmadapter, (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+	       rx_mcs_supp);
+	/* Clear all the other values to get the minimum mcs set btw STA and AP
+	 */
+	memset(pmadapter,
+	       (t_u8 *)&pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0,
+	       NUM_MCS_FIELD - rx_mcs_supp);
+	/* Set MCS32 with 40MHz support */
+	/* if current channel only support 20MHz, we should not set 40Mz
+	 * supprot*/
+	if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+	    !(priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	      priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+		SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set);
+
+	/* Clear RD responder bit */
+	RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap);
+	pht_cap->ht_cap.ht_ext_cap =
+		wlan_cpu_to_le16(pht_cap->ht_cap.ht_ext_cap);
+
+	/* Set Tx BF cap */
+	pht_cap->ht_cap.tx_bf_cap = wlan_cpu_to_le32(priv->tx_bf_cap);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function fills the HT cap ie
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pht_cap      A pointer to IEEEtypes_HTCap_t structure
+ *  @param bands        Band configuration
+ *
+ *  @return             N/A
+ */
+void
+wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap, t_u16 bands)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	int rx_mcs_supp;
+	t_u32 usr_dot_11n_dev_cap;
+
+	ENTER();
+
+	pht_cap->ieee_hdr.element_id = HT_CAPABILITY;
+	pht_cap->ieee_hdr.len = sizeof(HTCap_t);
+	if (bands & BAND_A)
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
+
+	/* Fill HT cap info */
+	wlan_fill_cap_info(priv, &pht_cap->ht_cap, bands);
+
+	/* Set ampdu param */
+	SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K);
+	SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0);
+
+	rx_mcs_supp = GET_RXMCSSUPP(priv->usr_dev_mcs_support);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	if (IS_CARD9098(pmadapter->card_type) ||
+	    IS_CARD9097(pmadapter->card_type)) {
+		if (bands & BAND_A)
+			rx_mcs_supp = MIN(rx_mcs_supp,
+					  GET_RXMCSSUPP(pmadapter->
+							user_htstream >> 8));
+		else
+			rx_mcs_supp =
+				MIN(rx_mcs_supp,
+				    GET_RXMCSSUPP(pmadapter->user_htstream));
+	}
+#endif
+	memset(pmadapter, (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
+	       rx_mcs_supp);
+	/* Clear all the other values to get the minimum mcs set btw STA and AP
+	 */
+	memset(pmadapter,
+	       (t_u8 *)&pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0,
+	       NUM_MCS_FIELD - rx_mcs_supp);
+	/* Set MCS32 with 40MHz support */
+	/* if current channel only support 20MHz, we should not set 40Mz
+	 * supprot*/
+	if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+	    !(priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	      priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS))
+		SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set);
+
+	/* Clear RD responder bit */
+	RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap);
+
+	/* Set Tx BF cap */
+	pht_cap->ht_cap.tx_bf_cap = priv->tx_bf_cap;
+
+	LEAVE();
+	return;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief This function prints the 802.11n device capability
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *  @param cap           Capability value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap)
+{
+	ENTER();
+
+	PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = %s octets\n",
+	       (ISSUPP_MAXAMSDU(cap) ? "7935" : "3839"));
+	PRINTM(MINFO, "GET_HW_SPEC: Beam forming %s\n",
+	       (ISSUPP_BEAMFORMING(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Greenfield preamble %s\n",
+	       (ISSUPP_GREENFIELD(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: AMPDU %s\n",
+	       (ISSUPP_AMPDU(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: MIMO Power Save %s\n",
+	       (ISSUPP_MIMOPS(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
+	       (ISSUPP_RXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
+	       (ISSUPP_TXSTBC(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI for 40 Mhz %s\n",
+	       (ISSUPP_SHORTGI40(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: Short GI for 20 Mhz %s\n",
+	       (ISSUPP_SHORTGI20(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: LDPC coded packet receive %s\n",
+	       (ISSUPP_RXLDPC(cap) ? "supported" : "not supported"));
+
+	PRINTM(MINFO, "GET_HW_SPEC: Number of Tx BA streams supported = %d\n",
+	       ISSUPP_GETTXBASTREAM(cap));
+	PRINTM(MINFO, "GET_HW_SPEC: 40 Mhz channel width %s\n",
+	       (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: 20 Mhz channel width %s\n",
+	       (ISSUPP_CHANWIDTH20(cap) ? "supported" : "not supported"));
+	PRINTM(MINFO, "GET_HW_SPEC: 10 Mhz channel width %s\n",
+	       (ISSUPP_CHANWIDTH10(cap) ? "supported" : "not supported"));
+
+	if (ISSUPP_RXANTENNAA(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna A\n");
+	if (ISSUPP_RXANTENNAB(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna B\n");
+	if (ISSUPP_RXANTENNAC(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna C\n");
+	if (ISSUPP_RXANTENNAD(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna D\n");
+	if (ISSUPP_TXANTENNAA(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna A\n");
+	if (ISSUPP_TXANTENNAB(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna B\n");
+	if (ISSUPP_TXANTENNAC(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna C\n");
+	if (ISSUPP_TXANTENNAD(cap))
+		PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna D\n");
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prints the 802.11n device MCS
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param support   Support value
+ *
+ *  @return        N/A
+ */
+void
+wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support)
+{
+	ENTER();
+
+	PRINTM(MINFO, "GET_HW_SPEC: MCSs for %dx%d MIMO\n",
+	       GET_RXMCSSUPP(support), GET_TXMCSSUPP(support));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *              delete a block ack request
+ *
+ *  @param priv    A pointer to mlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *resp)
+{
+	int tid;
+	TxBAStreamTbl *ptx_ba_tbl;
+	HostCmd_DS_11N_DELBA *pdel_ba =
+		(HostCmd_DS_11N_DELBA *)&resp->params.del_ba;
+
+	ENTER();
+
+	pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set);
+	pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code);
+
+	tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS;
+	if (pdel_ba->del_result == BA_RESULT_SUCCESS) {
+		mlan_11n_delete_bastream_tbl(priv, tid, pdel_ba->peer_mac_addr,
+					     TYPE_DELBA_SENT,
+					     INITIATOR_BIT(pdel_ba->
+							   del_ba_param_set),
+					     0);
+		wlan_request_ralist_lock(priv);
+		ptx_ba_tbl =
+			wlan_11n_get_txbastream_status(priv,
+						       BA_STREAM_SETUP_INPROGRESS);
+		wlan_release_ralist_lock(priv);
+		if (ptx_ba_tbl)
+			wlan_send_addba(priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra);
+	} else {		/*
+				 * In case of failure, recreate
+				 * the deleted stream in case
+				 * we initiated the ADDBA
+				 */
+		if (INITIATOR_BIT(pdel_ba->del_ba_param_set)) {
+			wlan_request_ralist_lock(priv);
+			if (!wlan_11n_get_txbastream_tbl
+			    (priv, tid, pdel_ba->peer_mac_addr, MFALSE))
+				wlan_11n_create_txbastream_tbl(priv,
+							       pdel_ba->
+							       peer_mac_addr,
+							       tid,
+							       BA_STREAM_SETUP_INPROGRESS);
+			ptx_ba_tbl =
+				wlan_11n_get_txbastream_status(priv,
+							       BA_STREAM_SETUP_INPROGRESS);
+			wlan_release_ralist_lock(priv);
+			if (ptx_ba_tbl) {
+				mlan_11n_delete_bastream_tbl(priv,
+							     ptx_ba_tbl->tid,
+							     ptx_ba_tbl->ra,
+							     TYPE_DELBA_SENT,
+							     MTRUE, 0);
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *              add a block ack request
+ *
+ *  @param priv    A pointer to mlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *resp)
+{
+	t_u8 tid;
+	HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
+		(HostCmd_DS_11N_ADDBA_RSP *)&resp->params.add_ba_rsp;
+	TxBAStreamTbl *ptx_ba_tbl;
+	raListTbl *ra_list = MNULL;
+	int tid_down;
+
+	ENTER();
+
+	padd_ba_rsp->block_ack_param_set =
+		wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set);
+	padd_ba_rsp->block_ack_tmo =
+		wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo);
+	padd_ba_rsp->ssn = (wlan_le16_to_cpu(padd_ba_rsp->ssn)) & SSN_MASK;
+	padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code);
+
+	tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
+		BLOCKACKPARAM_TID_POS;
+	tid_down = wlan_get_wmm_tid_down(priv, tid);
+	ra_list = wlan_wmm_get_ralist_node(priv, tid_down,
+					   padd_ba_rsp->peer_mac_addr);
+	if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) {
+		ptx_ba_tbl =
+			wlan_11n_get_txbastream_tbl(priv, tid,
+						    padd_ba_rsp->peer_mac_addr,
+						    MTRUE);
+		if (ptx_ba_tbl) {
+			PRINTM(MCMND,
+			       "ADDBA REQ: " MACSTR
+			       " tid=%d ssn=%d win_size=%d,amsdu=%d\n",
+			       MAC2STR(padd_ba_rsp->peer_mac_addr), tid,
+			       padd_ba_rsp->ssn,
+			       ((padd_ba_rsp->block_ack_param_set &
+				 BLOCKACKPARAM_WINSIZE_MASK) >>
+				BLOCKACKPARAM_WINSIZE_POS),
+			       padd_ba_rsp->block_ack_param_set &
+			       BLOCKACKPARAM_AMSDU_SUPP_MASK);
+			ptx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE;
+			if ((padd_ba_rsp->block_ack_param_set &
+			     BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
+			    priv->add_ba_param.tx_amsdu &&
+			    (priv->aggr_prio_tbl[tid].amsdu !=
+			     BA_STREAM_NOT_ALLOWED))
+				ptx_ba_tbl->amsdu = MTRUE;
+			else
+				ptx_ba_tbl->amsdu = MFALSE;
+			if (ra_list) {
+				ra_list->amsdu_in_ampdu = ptx_ba_tbl->amsdu;
+				ra_list->ba_status = BA_STREAM_SETUP_COMPLETE;
+			}
+		} else {
+			PRINTM(MERROR, "BA stream not created\n");
+		}
+	} else {
+		if (ra_list) {
+			ra_list->amsdu_in_ampdu = MFALSE;
+			ra_list->ba_status = BA_STREAM_NOT_SETUP;
+		}
+		mlan_11n_delete_bastream_tbl(priv, tid,
+					     padd_ba_rsp->peer_mac_addr,
+					     TYPE_DELBA_SENT, MTRUE, 0);
+		if (padd_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) {
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+				disable_station_ampdu(priv, tid,
+						      padd_ba_rsp->
+						      peer_mac_addr);
+#endif /* UAP_SUPPORT */
+			if (ra_list && ra_list->is_tdls_link)
+				disable_station_ampdu(priv, tid,
+						      padd_ba_rsp->
+						      peer_mac_addr);
+			priv->aggr_prio_tbl[tid].ampdu_ap =
+				BA_STREAM_NOT_ALLOWED;
+
+		} else {
+			if (ra_list) {
+				ra_list->packet_count = 0;
+				ra_list->ba_packet_threshold =
+					wlan_get_random_ba_threshold(priv->
+								     adapter);
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function restore tx_pause flag
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param flag         MTRUE/MFALSE;
+ *
+ *  @return             N/A
+ */
+void
+wlan_set_tx_pause_flag(mlan_private *priv, t_u8 flag)
+{
+	mlan_private *pmpriv = MNULL;
+	t_u8 i;
+	for (i = 0; i < priv->adapter->priv_num; i++) {
+		pmpriv = priv->adapter->priv[i];
+		if (pmpriv)
+			pmpriv->tx_pause = flag;
+	}
+}
+
+/**
+ *  @brief This function prepares command of reconfigure tx buf
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_recfg_tx_buf(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+		      int cmd_action, void *pdata_buf)
+{
+	HostCmd_DS_TXBUF_CFG *ptx_buf = &cmd->params.tx_buf;
+	t_u16 action = (t_u16)cmd_action;
+	t_u16 buf_size = *((t_u16 *)pdata_buf);
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TXBUF_CFG) + S_DS_GEN);
+	ptx_buf->action = wlan_cpu_to_le16(action);
+	switch (action) {
+	case HostCmd_ACT_GEN_SET:
+		PRINTM(MCMND, "set tx_buf = %d\n", buf_size);
+		ptx_buf->buff_size = wlan_cpu_to_le16(buf_size);
+		/** stop tx traffic */
+		wlan_set_tx_pause_flag(priv, MTRUE);
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		ptx_buf->buff_size = 0;
+		break;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of amsdu aggr control
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_amsdu_aggr_ctrl(mlan_private *priv,
+			 HostCmd_DS_COMMAND *cmd, int cmd_action,
+			 void *pdata_buf)
+{
+	HostCmd_DS_AMSDU_AGGR_CTRL *pamsdu_ctrl = &cmd->params.amsdu_aggr_ctrl;
+	t_u16 action = (t_u16)cmd_action;
+	mlan_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
+		(mlan_ds_11n_amsdu_aggr_ctrl *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_AMSDU_AGGR_CTRL) + S_DS_GEN);
+	pamsdu_ctrl->action = wlan_cpu_to_le16(action);
+	switch (action) {
+	case HostCmd_ACT_GEN_SET:
+		pamsdu_ctrl->enable = wlan_cpu_to_le16(aa_ctrl->enable);
+		pamsdu_ctrl->curr_buf_size = 0;
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		pamsdu_ctrl->curr_buf_size = 0;
+		break;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of amsdu aggr ctrl
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_11n_cfg *cfg = MNULL;
+	HostCmd_DS_AMSDU_AGGR_CTRL *amsdu_ctrl = &resp->params.amsdu_aggr_ctrl;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+		cfg->param.amsdu_aggr_ctrl.enable =
+			wlan_le16_to_cpu(amsdu_ctrl->enable);
+		cfg->param.amsdu_aggr_ctrl.curr_buf_size =
+			wlan_le16_to_cpu(amsdu_ctrl->curr_buf_size);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares 11n cfg command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11n_cfg(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_11N_CFG *htcfg = &cmd->params.htcfg;
+	mlan_ds_11n_tx_cfg *txcfg = (mlan_ds_11n_tx_cfg *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_CFG) + S_DS_GEN);
+	htcfg->action = wlan_cpu_to_le16(cmd_action);
+	htcfg->ht_tx_cap = wlan_cpu_to_le16(txcfg->httxcap);
+	htcfg->ht_tx_info = wlan_cpu_to_le16(txcfg->httxinfo);
+	htcfg->misc_config = wlan_cpu_to_le16(txcfg->misc_cfg);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of 11ncfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11n_cfg(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_11n_cfg *cfg = MNULL;
+	HostCmd_DS_11N_CFG *htcfg = &resp->params.htcfg;
+
+	ENTER();
+	if (pioctl_buf &&
+	    (wlan_le16_to_cpu(htcfg->action) == HostCmd_ACT_GEN_GET)) {
+		cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+		cfg->param.tx_cfg.httxcap = wlan_le16_to_cpu(htcfg->ht_tx_cap);
+		cfg->param.tx_cfg.httxinfo =
+			wlan_le16_to_cpu(htcfg->ht_tx_info);
+		cfg->param.tx_cfg.misc_cfg =
+			wlan_le16_to_cpu(htcfg->misc_config);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares reject addba req command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_reject_addba_req(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd,
+			  t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_REJECT_ADDBA_REQ *preject_addba_req =
+		&cmd->params.rejectaddbareq;
+	mlan_ds_reject_addba_req *prejaddbareq =
+		(mlan_ds_reject_addba_req *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_REJECT_ADDBA_REQ);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_REJECT_ADDBA_REQ) +
+				     S_DS_GEN);
+	preject_addba_req->action = wlan_cpu_to_le16(cmd_action);
+	preject_addba_req->conditions =
+		wlan_cpu_to_le32(prejaddbareq->conditions);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of reject addba req
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_reject_addba_req(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_11n_cfg *cfg = MNULL;
+	HostCmd_DS_REJECT_ADDBA_REQ *preject_addba_req =
+		&resp->params.rejectaddbareq;
+
+	ENTER();
+	if (pioctl_buf && (wlan_le16_to_cpu(preject_addba_req->action) ==
+			   HostCmd_ACT_GEN_GET)) {
+		cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+		cfg->param.reject_addba_req.conditions =
+			wlan_le32_to_cpu(preject_addba_req->conditions);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares TX BF configuration command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_tx_bf_cfg(pmlan_private pmpriv,
+		   HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_TX_BF_CFG *txbfcfg = &cmd->params.tx_bf_cfg;
+	mlan_ds_11n_tx_bf_cfg *txbf = (mlan_ds_11n_tx_bf_cfg *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_BF_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_BF_CFG) + S_DS_GEN);
+
+	if (txbf->bf_action == SET_GET_BF_PERIODICITY) {
+		memcpy_ext(pmadapter, txbfcfg->body.bf_periodicity.peer_mac,
+			   txbf->body.bf_periodicity[0].peer_mac,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	}
+	txbfcfg->action = wlan_cpu_to_le16(txbf->action);
+	txbfcfg->bf_action = wlan_cpu_to_le16(txbf->bf_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		switch (txbf->bf_action) {
+		case BF_GLOBAL_CONFIGURATION:
+			txbfcfg->body.bf_global_cfg.bf_enbl =
+				txbf->body.bf_global_cfg.bf_enbl;
+			txbfcfg->body.bf_global_cfg.sounding_enbl =
+				txbf->body.bf_global_cfg.sounding_enbl;
+			txbfcfg->body.bf_global_cfg.fb_type =
+				txbf->body.bf_global_cfg.fb_type;
+			txbfcfg->body.bf_global_cfg.snr_threshold =
+				txbf->body.bf_global_cfg.snr_threshold;
+			txbfcfg->body.bf_global_cfg.sounding_interval =
+				wlan_cpu_to_le16(txbf->body.bf_global_cfg.
+						 sounding_interval);
+			txbfcfg->body.bf_global_cfg.bf_mode =
+				txbf->body.bf_global_cfg.bf_mode;
+			break;
+		case TRIGGER_SOUNDING_FOR_PEER:
+			memcpy_ext(pmadapter,
+				   txbfcfg->body.bf_sound_args.peer_mac,
+				   txbf->body.bf_sound[0].peer_mac,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			break;
+		case SET_GET_BF_PERIODICITY:
+			txbfcfg->body.bf_periodicity.interval =
+				wlan_cpu_to_le16(txbf->body.bf_periodicity->
+						 interval);
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			memcpy_ext(pmadapter, txbfcfg->body.tx_bf_peer.peer_mac,
+				   txbf->body.tx_bf_peer[0].peer_mac,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			txbfcfg->body.tx_bf_peer.bf_enbl =
+				txbf->body.tx_bf_peer[0].bf_enbl;
+			txbfcfg->body.tx_bf_peer.sounding_enbl =
+				txbf->body.tx_bf_peer[0].sounding_enbl;
+			txbfcfg->body.tx_bf_peer.fb_type =
+				txbf->body.tx_bf_peer[0].fb_type;
+			break;
+		case SET_SNR_THR_PEER:
+			memcpy_ext(pmadapter, txbfcfg->body.bf_snr.peer_mac,
+				   txbf->body.bf_snr[0].peer_mac,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			txbfcfg->body.bf_snr.snr = txbf->body.bf_snr[0].snr;
+			break;
+		default:
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response
+ *  of TX BF configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_tx_bf_cfg(pmlan_private pmpriv,
+		   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_TX_BF_CFG *txbfcfg = &resp->params.tx_bf_cfg;
+	mlan_ds_11n_cfg *cfg_11n = MNULL;
+	mlan_ds_11n_tx_bf_cfg *txbf = MNULL;
+	bf_peer_args *tx_bf_peer;
+	bf_snr_thr_t *bf_snr;
+	int i;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		cfg_11n = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
+		txbf = (mlan_ds_11n_tx_bf_cfg *)&cfg_11n->param.tx_bf;
+		txbf->bf_action = wlan_le16_to_cpu(txbfcfg->bf_action);
+		switch (txbf->bf_action) {
+		case BF_GLOBAL_CONFIGURATION:
+			txbf->body.bf_global_cfg.bf_enbl =
+				txbfcfg->body.bf_global_cfg.bf_enbl;
+			txbf->body.bf_global_cfg.sounding_enbl =
+				txbfcfg->body.bf_global_cfg.sounding_enbl;
+			txbf->body.bf_global_cfg.fb_type =
+				txbfcfg->body.bf_global_cfg.fb_type;
+			txbf->body.bf_global_cfg.snr_threshold =
+				txbfcfg->body.bf_global_cfg.snr_threshold;
+			txbf->body.bf_global_cfg.sounding_interval =
+				wlan_le16_to_cpu(txbfcfg->body.bf_global_cfg.
+						 sounding_interval);
+			txbf->body.bf_global_cfg.bf_mode =
+				txbfcfg->body.bf_global_cfg.bf_mode;
+			break;
+		case TRIGGER_SOUNDING_FOR_PEER:
+			memcpy_ext(pmadapter, txbf->body.bf_sound[0].peer_mac,
+				   txbfcfg->body.bf_sound_args.peer_mac,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_sound[0].status =
+				txbfcfg->body.bf_sound_args.status;
+			break;
+		case SET_GET_BF_PERIODICITY:
+			memcpy_ext(pmadapter,
+				   txbf->body.bf_periodicity->peer_mac,
+				   txbfcfg->body.bf_periodicity.peer_mac,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			txbf->body.bf_periodicity->interval =
+				wlan_le16_to_cpu(txbfcfg->body.bf_periodicity.
+						 interval);
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			tx_bf_peer = (bf_peer_args *)((t_u8 *)&txbfcfg->body +
+						      sizeof(t_u8));
+			for (i = 0; i < (int)txbf->no_of_peers; i++) {
+				memcpy_ext(pmadapter,
+					   txbf->body.tx_bf_peer[i].peer_mac,
+					   (t_u8 *)tx_bf_peer->peer_mac,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				txbf->body.tx_bf_peer[i].bf_enbl =
+					tx_bf_peer->bf_enbl;
+				txbf->body.tx_bf_peer[i].sounding_enbl =
+					tx_bf_peer->sounding_enbl;
+				txbf->body.tx_bf_peer[i].fb_type =
+					tx_bf_peer->fb_type;
+				tx_bf_peer++;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
+			bf_snr = (bf_snr_thr_t *)((t_u8 *)&txbfcfg->body +
+						  sizeof(t_u8));
+			for (i = 0; i < (int)txbf->no_of_peers; i++) {
+				memcpy_ext(pmadapter,
+					   txbf->body.bf_snr[i].peer_mac,
+					   (t_u8 *)bf_snr->peer_mac,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				txbf->body.bf_snr[i].snr = bf_snr->snr;
+				bf_snr++;
+			}
+			break;
+		default:
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param chan            channel num
+ * @return                second channel offset
+ */
+t_u8
+wlan_get_second_channel_offset(mlan_private *priv, int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+
+	/* Special Case: 20Mhz-only Channel */
+	if (chan == 165)
+		return chan2Offset;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	}
+	return chan2Offset;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief validate the channel offset for Infra/Ad-hoc band configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param band         band
+ *  @param chan         primary channel
+ *  @param chan_bw      channel bandwidth
+ *
+ *  @return             channel offset (NO_SEC_CHANNEL, SEC_CHANNEL_ABOVE,
+ *                                      SEC_CHANNEL_BELOW)
+ */
+t_u8
+wlan_validate_chan_offset(mlan_private *pmpriv, t_u16 band,
+			  t_u32 chan, t_u8 chan_bw)
+{
+	t_u8 chan_offset;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	if (chan_bw == CHANNEL_BW_40MHZ_ABOVE)
+		chan_offset = SEC_CHAN_ABOVE;
+	else if (chan_bw == CHANNEL_BW_40MHZ_BELOW)
+		chan_offset = SEC_CHAN_BELOW;
+	else
+		chan_offset = SEC_CHAN_NONE;
+
+	/* validation */
+	if (chan_offset != SEC_CHAN_NONE) {
+		if (band & BAND_GN) {
+			if ((chan == 1) || (chan == 2) || (chan == 3) ||
+			    (chan == 4))
+				chan_offset = SEC_CHAN_ABOVE;
+			else if ((chan == 10) || (chan == 11) || (chan == 12) ||
+				 (chan == 13))
+				chan_offset = SEC_CHAN_BELOW;
+
+			/* check if channel 12 is supported in the region */
+			if (!wlan_find_cfp_by_band_and_channel(pmadapter, band,
+							       12))
+				if ((chan == 8) || (chan == 9))
+					chan_offset = SEC_CHAN_BELOW;
+		} else if (band & BAND_AN)
+			chan_offset =
+				wlan_get_second_channel_offset(pmpriv, chan);
+	}
+	return chan_offset;
+}
+
+/**
+ *  @brief This function check if ht40 is allowed in current region
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *
+ *  @return MTRUE/MFALSE
+ */
+static int
+wlan_check_chan_width_ht40_by_region(mlan_private *pmpriv,
+				     BSSDescriptor_t *pbss_desc)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	int i = 0;
+	int cover_pri_chan = MFALSE;
+	t_u8 pri_chan;
+	t_u8 chan_offset;
+	t_u8 num_cfp;
+
+	ENTER();
+
+	if (pbss_desc->pht_info == MNULL) {
+		PRINTM(MERROR, "ht_info pointer NULL, force use HT20\n");
+		LEAVE();
+		return MFALSE;
+	}
+	if (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
+	    pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
+		LEAVE();
+		return MFALSE;
+	}
+
+	pri_chan = pbss_desc->pht_info->ht_info.pri_chan;
+	chan_offset = GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info.field2);
+	if ((chan_offset == SEC_CHAN_ABOVE) &&
+	    (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS)) {
+		pmpriv->curr_chan_flags |=
+			CHAN_FLAGS_NO_HT40MINUS | CHAN_FLAGS_NO_80MHZ;
+		return MFALSE;
+	}
+	if ((chan_offset == SEC_CHAN_BELOW) &&
+	    (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS)) {
+		pmpriv->curr_chan_flags |=
+			CHAN_FLAGS_NO_HT40PLUS | CHAN_FLAGS_NO_80MHZ;
+		return MFALSE;
+	}
+	if (pmpriv->curr_chan_flags & CHAN_FLAGS_MAX)
+		return MTRUE;
+
+	num_cfp = pmadapter->region_channel[0].num_cfp;
+
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
+	    pmadapter->region_channel[0].valid) {
+		for (i = 0; i < num_cfp; i++) {
+			if (pri_chan ==
+			    pmadapter->region_channel[0].pcfp[i].channel) {
+				cover_pri_chan = MTRUE;
+				break;
+			}
+		}
+		if (!cover_pri_chan) {
+			PRINTM(MERROR, "Invalid channel, force use HT20\n");
+			LEAVE();
+			return MFALSE;
+		}
+
+		if (chan_offset == SEC_CHAN_ABOVE) {
+			if (pri_chan > num_cfp - 4) {
+				PRINTM(MERROR,
+				       "Invalid second channel offset, force use HT20\n");
+				LEAVE();
+				return MFALSE;
+			}
+		}
+	}
+	LEAVE();
+	return MTRUE;
+}
+
+/**
+ *  @brief This function append the 802_11N tlv
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_desc    A pointer to BSSDescriptor_t structure
+ *  @param ppbuffer     A Pointer to command buffer pointer
+ *
+ *  @return bytes added to the buffer
+ */
+int
+wlan_cmd_append_11n_tlv(mlan_private *pmpriv,
+			BSSDescriptor_t *pbss_desc, t_u8 **ppbuffer)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIETypes_HTCap_t *pht_cap;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list;
+	MrvlIETypes_2040BSSCo_t *p2040_bss_co;
+	MrvlIETypes_ExtCap_t *pext_cap;
+	t_u32 usr_dot_11n_dev_cap, orig_usr_dot_11n_dev_cap = 0;
+	t_u8 usr_dot_11ac_bw;
+	int ret_len = 0;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (pbss_desc == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	if (pbss_desc->bss_band & BAND_A)
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
+
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+		usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
+	else
+		usr_dot_11ac_bw = pmpriv->usr_dot_11ac_bw;
+	if ((pbss_desc->bss_band & (BAND_B | BAND_G | BAND_A)) &&
+	    ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+	    !wlan_check_chan_width_ht40_by_region(pmpriv, pbss_desc)) {
+		orig_usr_dot_11n_dev_cap = usr_dot_11n_dev_cap;
+		RESETSUPP_CHANWIDTH40(usr_dot_11n_dev_cap);
+		RESET_40MHZ_INTOLARENT(usr_dot_11n_dev_cap);
+		RESETSUPP_SHORTGI40(usr_dot_11n_dev_cap);
+		pmpriv->usr_dot_11n_dev_cap_bg = usr_dot_11n_dev_cap;
+		pbss_desc->curr_bandwidth = BW_20MHZ;
+	}
+	if (pbss_desc->pht_cap) {
+		pht_cap = (MrvlIETypes_HTCap_t *)*ppbuffer;
+		memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+		pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+		pht_cap->header.len = sizeof(HTCap_t);
+		memcpy_ext(pmadapter,
+			   (t_u8 *)pht_cap + sizeof(MrvlIEtypesHeader_t),
+			   (t_u8 *)pbss_desc->pht_cap +
+			   sizeof(IEEEtypes_Header_t),
+			   pht_cap->header.len, pht_cap->header.len);
+
+		pht_cap->ht_cap.ht_cap_info =
+			wlan_le16_to_cpu(pht_cap->ht_cap.ht_cap_info);
+		pht_cap->ht_cap.ht_ext_cap =
+			wlan_le16_to_cpu(pht_cap->ht_cap.ht_ext_cap);
+		wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pbss_desc->bss_band,
+				     MTRUE);
+
+		/** check if need support 80+80MHZ */
+		/** reset the 2 spatial stream rate for 80 + 80 Mhz */
+		if (wlan_is_80_80_support(pmpriv, pbss_desc))
+			pht_cap->ht_cap.supported_mcs_set[1] = 0;
+		HEXDUMP("HT_CAPABILITIES IE", (t_u8 *)pht_cap,
+			sizeof(MrvlIETypes_HTCap_t));
+		*ppbuffer += sizeof(MrvlIETypes_HTCap_t);
+		ret_len += sizeof(MrvlIETypes_HTCap_t);
+		pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
+	} else {
+		// AP don't support 11N
+		LEAVE();
+		return 0;
+	}
+
+	if (pbss_desc->pht_info) {
+
+		pchan_list = (MrvlIEtypes_ChanListParamSet_t *)*ppbuffer;
+		memset(pmadapter, pchan_list, 0,
+		       sizeof(MrvlIEtypes_ChanListParamSet_t));
+		pchan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_list->header.len =
+			sizeof(MrvlIEtypes_ChanListParamSet_t) -
+			sizeof(MrvlIEtypesHeader_t);
+		pchan_list->chan_scan_param[0].chan_number =
+			pbss_desc->pht_info->ht_info.pri_chan;
+		pchan_list->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+		/* support the VHT if the network to be join has the VHT
+		 * operation */
+		if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) &&
+		    (usr_dot_11ac_bw == BW_FOLLOW_VHTCAP) &&
+		    (!(pmpriv->curr_chan_flags & CHAN_FLAGS_NO_80MHZ)) &&
+		    wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band) &&
+		    pbss_desc->pvht_oprat &&
+		    pbss_desc->pvht_oprat->chan_width == VHT_OPER_CHWD_80MHZ) {
+			pchan_list->chan_scan_param[0].bandcfg.chanWidth =
+				CHAN_BW_80MHZ;
+			pchan_list->chan_scan_param[0].bandcfg.chan2Offset =
+				GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info.
+						  field2);
+			pbss_desc->curr_bandwidth = BW_80MHZ;
+		} else if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+			   ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.
+						 field2) &&
+			   wlan_check_chan_width_ht40_by_region(pmpriv,
+								pbss_desc)) {
+			pchan_list->chan_scan_param[0].bandcfg.chan2Offset =
+				GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info.
+						  field2);
+			pbss_desc->curr_bandwidth = BW_40MHZ;
+			pchan_list->chan_scan_param[0].bandcfg.chanWidth =
+				CHAN_BW_40MHZ;
+		}
+		pchan_list->chan_scan_param[0].bandcfg.scanMode =
+			SCAN_MODE_USER;
+		HEXDUMP("ChanList", (t_u8 *)pchan_list,
+			sizeof(MrvlIEtypes_ChanListParamSet_t));
+		HEXDUMP("pht_info", (t_u8 *)pbss_desc->pht_info,
+			sizeof(MrvlIETypes_HTInfo_t) - 2);
+		*ppbuffer += sizeof(MrvlIEtypes_ChanListParamSet_t);
+		ret_len += sizeof(MrvlIEtypes_ChanListParamSet_t);
+		pchan_list->header.len =
+			wlan_cpu_to_le16(pchan_list->header.len);
+	}
+
+	if (pbss_desc->pbss_co_2040) {
+		p2040_bss_co = (MrvlIETypes_2040BSSCo_t *)*ppbuffer;
+		memset(pmadapter, p2040_bss_co, 0,
+		       sizeof(MrvlIETypes_2040BSSCo_t));
+		p2040_bss_co->header.type = wlan_cpu_to_le16(BSSCO_2040);
+		p2040_bss_co->header.len = sizeof(BSSCo2040_t);
+
+		memcpy_ext(pmadapter,
+			   (t_u8 *)p2040_bss_co + sizeof(MrvlIEtypesHeader_t),
+			   (t_u8 *)pbss_desc->pbss_co_2040 +
+			   sizeof(IEEEtypes_Header_t),
+			   p2040_bss_co->header.len, p2040_bss_co->header.len);
+
+		HEXDUMP("20/40 BSS Coexistence IE", (t_u8 *)p2040_bss_co,
+			sizeof(MrvlIETypes_2040BSSCo_t));
+		*ppbuffer += sizeof(MrvlIETypes_2040BSSCo_t);
+		ret_len += sizeof(MrvlIETypes_2040BSSCo_t);
+		p2040_bss_co->header.len =
+			wlan_cpu_to_le16(p2040_bss_co->header.len);
+	}
+
+	if (pbss_desc->pext_cap) {
+		pext_cap = (MrvlIETypes_ExtCap_t *)*ppbuffer;
+		memset(pmadapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
+		pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
+		pext_cap->header.len = sizeof(ExtCap_t);
+
+		memcpy_ext(pmadapter,
+			   (t_u8 *)pext_cap + sizeof(MrvlIEtypesHeader_t),
+			   (t_u8 *)&pmpriv->ext_cap, sizeof(ExtCap_t),
+			   pext_cap->header.len);
+		if (pbss_desc && pbss_desc->multi_bssid_ap)
+			SET_EXTCAP_MULTI_BSSID(pext_cap->ext_cap);
+		if (!pmadapter->ecsa_enable)
+			RESET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
+		else
+			SET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
+
+		HEXDUMP("Extended Capabilities IE", (t_u8 *)pext_cap,
+			sizeof(MrvlIETypes_ExtCap_t));
+		*ppbuffer += sizeof(MrvlIETypes_ExtCap_t);
+		ret_len += sizeof(MrvlIETypes_ExtCap_t);
+		pext_cap->header.len = wlan_cpu_to_le16(pext_cap->header.len);
+	} else if (wlan_is_ext_capa_support(pmpriv) ||
+		   (pmpriv->config_bands & BAND_AAC)
+		) {
+		wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, ppbuffer);
+		ret_len += sizeof(MrvlIETypes_ExtCap_t);
+	}
+	PRINTM(MCMND, "curr_bandwidth=%d\n", pbss_desc->curr_bandwidth);
+	if (orig_usr_dot_11n_dev_cap)
+		pmpriv->usr_dot_11n_dev_cap_bg = orig_usr_dot_11n_dev_cap;
+
+	LEAVE();
+	return ret_len;
+}
+
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief 11n configuration handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11n_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_cfg *cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11n_cfg)) {
+		PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11n_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
+	switch (cfg->sub_command) {
+	case MLAN_OID_11N_CFG_TX:
+		status = wlan_11n_ioctl_httxcfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_HTCAP_CFG:
+		status = wlan_11n_ioctl_htusrcfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_AGGR_PRIO_TBL:
+		status = wlan_11n_ioctl_aggr_prio_tbl(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_ADDBA_REJECT:
+		status = wlan_11n_ioctl_addba_reject(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_ADDBA_PARAM:
+		status = wlan_11n_ioctl_addba_param(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_DELBA:
+		status = wlan_11n_ioctl_delba(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_REJECT_ADDBA_REQ:
+		status = wlan_11n_ioctl_rejectaddbareq(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE:
+		status = wlan_11n_ioctl_max_tx_buf_size(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL:
+		status = wlan_11n_ioctl_amsdu_aggr_ctrl(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_SUPPORTED_MCS_SET:
+		status = wlan_11n_ioctl_supported_mcs_set(pmadapter,
+							  pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_TX_BF_CAP:
+		status = wlan_11n_ioctl_tx_bf_cap(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_TX_BF_CFG:
+		status = wlan_11n_ioctl_tx_bf_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_STREAM_CFG:
+		status = wlan_11n_ioctl_stream_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_COEX_RX_WINSIZE:
+		status = wlan_11n_ioctl_coex_rx_winsize(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_TX_AGGR_CTRL:
+		status = wlan_11n_ioctl_txaggrctrl(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM:
+		status = wlan_11n_ioctl_ibss_ampdu_param(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11N_CFG_MIN_BA_THRESHOLD:
+		status = wlan_11n_ioctl_min_ba_threshold_cfg(pmadapter,
+							     pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function will delete the given entry in Tx BA Stream table
+ *
+ *  @param priv     Pointer to mlan_private
+ *  @param ptx_tbl  Pointer to tx ba stream entry to delete
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_delete_txbastream_tbl_entry(mlan_private *priv, TxBAStreamTbl *ptx_tbl)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	if (!ptx_tbl || !wlan_is_txbastreamptr_valid(priv, ptx_tbl))
+		goto exit;
+	PRINTM(MINFO, "Delete BA stream table entry: %p\n", ptx_tbl);
+	util_unlink_list(pmadapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr,
+			 (pmlan_linked_list)ptx_tbl, MNULL, MNULL);
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)ptx_tbl);
+exit:
+	LEAVE();
+}
+
+/**
+ *  @brief This function will delete all the entries in Tx BA Stream table
+ *
+ *  @param priv         A pointer to mlan_private
+ *
+ *  @return             N/A
+ */
+void
+wlan_11n_deleteall_txbastream_tbl(mlan_private *priv)
+{
+	int i;
+	TxBAStreamTbl *del_tbl_ptr = MNULL;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	while ((del_tbl_ptr =
+		(TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						&priv->tx_ba_stream_tbl_ptr,
+						MNULL, MNULL))) {
+		wlan_11n_delete_txbastream_tbl_entry(priv, del_tbl_ptr);
+	}
+
+	util_init_list((pmlan_linked_list)&priv->tx_ba_stream_tbl_ptr);
+	wlan_release_ralist_lock(priv);
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		priv->aggr_prio_tbl[i].ampdu_ap =
+			priv->aggr_prio_tbl[i].ampdu_user;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will return the pointer to an entry in BA Stream
+ *          table which matches the give RA/TID pair
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param tid     TID to find in reordering table
+ *  @param ra      RA to find in reordering table
+ *  @param lock    flag for request the spin_lock
+ *
+ *  @return        A pointer to first entry matching RA/TID in BA stream
+ *                 NULL if not found
+ */
+TxBAStreamTbl *
+wlan_11n_get_txbastream_tbl(mlan_private *priv, int tid, t_u8 *ra, int lock)
+{
+	TxBAStreamTbl *ptx_tbl;
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	if (lock)
+		wlan_request_ralist_lock(priv);
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		if (lock)
+			wlan_release_ralist_lock(priv);
+		LEAVE();
+		return MNULL;
+	}
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		PRINTM(MDAT_D, "get_txbastream_tbl TID %d\n", ptx_tbl->tid);
+		DBG_HEXDUMP(MDAT_D, "RA", ptx_tbl->ra, MLAN_MAC_ADDR_LENGTH);
+
+		if ((!memcmp(pmadapter, ptx_tbl->ra, ra,
+			     MLAN_MAC_ADDR_LENGTH)) && (ptx_tbl->tid == tid)) {
+			if (lock)
+				wlan_release_ralist_lock(priv);
+			LEAVE();
+			return ptx_tbl;
+		}
+
+		ptx_tbl = ptx_tbl->pnext;
+	}
+	if (lock)
+		wlan_release_ralist_lock(priv);
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function will create a entry in tx ba stream table for the
+ *          given RA/TID.
+ *
+ *  @param priv      A pointer to mlan_private
+ *  @param ra        RA to find in reordering table
+ *  @param tid       TID to find in reordering table
+ *  @param ba_status BA stream status to create the stream with
+ *
+ *  @return          N/A
+ */
+void
+wlan_11n_create_txbastream_tbl(mlan_private *priv, t_u8 *ra, int tid,
+			       baStatus_e ba_status)
+{
+	TxBAStreamTbl *new_node = MNULL;
+	pmlan_adapter pmadapter = priv->adapter;
+	raListTbl *ra_list = MNULL;
+	int tid_down;
+
+	ENTER();
+
+	PRINTM(MDAT_D, "create_txbastream_tbl TID %d\n", tid);
+	DBG_HEXDUMP(MDAT_D, "RA", ra, MLAN_MAC_ADDR_LENGTH);
+
+	if (pmadapter->callbacks.
+	    moal_malloc(pmadapter->pmoal_handle, sizeof(TxBAStreamTbl),
+			MLAN_MEM_DEF, (t_u8 **)&new_node)) {
+		PRINTM(MERROR,
+		       "wlan_11n_create_txbastream_tbl Failed to allocate new_node\n");
+		LEAVE();
+		return;
+	}
+	tid_down = wlan_get_wmm_tid_down(priv, tid);
+	ra_list = wlan_wmm_get_ralist_node(priv, tid_down, ra);
+	if (ra_list) {
+		ra_list->amsdu_in_ampdu = MFALSE;
+		ra_list->ba_status = ba_status;
+	}
+	util_init_list((pmlan_linked_list)new_node);
+
+	new_node->tid = tid;
+	new_node->ba_status = ba_status;
+	memcpy_ext(pmadapter, new_node->ra, ra, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &priv->tx_ba_stream_tbl_ptr,
+			       (pmlan_linked_list)new_node, MNULL, MNULL);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will send a block ack to given tid/ra
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid      TID to send the ADDBA
+ *  @param peer_mac MAC address to send the ADDBA
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+wlan_send_addba(mlan_private *priv, int tid, t_u8 *peer_mac)
+{
+	HostCmd_DS_11N_ADDBA_REQ add_ba_req;
+	static t_u8 dialog_tok;
+	mlan_status ret;
+
+	ENTER();
+
+	PRINTM(MCMND, "Send addba: TID %d\n", tid);
+	DBG_HEXDUMP(MCMD_D, "Send addba RA", peer_mac, MLAN_MAC_ADDR_LENGTH);
+
+	add_ba_req.block_ack_param_set = (t_u16)((tid << BLOCKACKPARAM_TID_POS)
+						 | (priv->add_ba_param.
+						    tx_win_size <<
+						    BLOCKACKPARAM_WINSIZE_POS) |
+						 IMMEDIATE_BLOCK_ACK);
+	/** enable AMSDU inside AMPDU */
+	if (priv->add_ba_param.tx_amsdu &&
+	    (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
+		add_ba_req.block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK;
+	add_ba_req.block_ack_tmo = (t_u16)priv->add_ba_param.timeout;
+
+	++dialog_tok;
+
+	if (dialog_tok == 0)
+		dialog_tok = 1;
+
+	add_ba_req.dialog_token = dialog_tok;
+	memcpy_ext(priv->adapter, &add_ba_req.peer_mac_addr, peer_mac,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+	/* We don't wait for the response of this command */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, 0, 0, MNULL,
+			       &add_ba_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will delete a block ack to given tid/ra
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *  @param tid          TID to send the ADDBA
+ *  @param peer_mac     MAC address to send the ADDBA
+ *  @param initiator    MTRUE if we have initiated ADDBA, MFALSE otherwise
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+int
+wlan_send_delba(mlan_private *priv, pmlan_ioctl_req pioctl_req, int tid,
+		t_u8 *peer_mac, int initiator)
+{
+	HostCmd_DS_11N_DELBA delba;
+	mlan_status ret;
+
+	ENTER();
+
+	memset(priv->adapter, &delba, 0, sizeof(delba));
+	delba.del_ba_param_set = (tid << DELBA_TID_POS);
+
+	if (initiator)
+		DELBA_INITIATOR(delba.del_ba_param_set);
+	else
+		DELBA_RECIPIENT(delba.del_ba_param_set);
+
+	memcpy_ext(priv->adapter, &delba.peer_mac_addr, peer_mac,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, HostCmd_ACT_GEN_SET,
+			       0, (t_void *)pioctl_req, (t_void *)&delba);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *          delete a block ack request
+ *
+ *  @param priv		A pointer to mlan_private structure
+ *  @param del_ba	A pointer to command response buffer
+ *
+ *  @return        N/A
+ */
+void
+wlan_11n_delete_bastream(mlan_private *priv, t_u8 *del_ba)
+{
+	HostCmd_DS_11N_DELBA *pdel_ba = (HostCmd_DS_11N_DELBA *)del_ba;
+	int tid;
+
+	ENTER();
+
+	DBG_HEXDUMP(MCMD_D, "Delba:", (t_u8 *)pdel_ba, 20);
+	pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set);
+	pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code);
+
+	tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS;
+
+	mlan_11n_delete_bastream_tbl(priv, tid, pdel_ba->peer_mac_addr,
+				     TYPE_DELBA_RECEIVE,
+				     INITIATOR_BIT(pdel_ba->del_ba_param_set),
+				     pdel_ba->reason_code);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Get Rx reordering table
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param buf          A pointer to rx_reorder_tbl structure
+ *  @return             number of rx reorder table entry
+ */
+int
+wlan_get_rxreorder_tbl(mlan_private *priv, rx_reorder_tbl *buf)
+{
+	int i;
+	rx_reorder_tbl *ptbl = buf;
+	RxReorderTbl *rx_reorder_tbl_ptr;
+	int count = 0;
+	ENTER();
+	priv->adapter->callbacks.moal_spin_lock(priv->adapter->pmoal_handle,
+						priv->rx_reorder_tbl_ptr.plock);
+	rx_reorder_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr, MNULL,
+					       MNULL);
+	if (!rx_reorder_tbl_ptr) {
+		priv->adapter->callbacks.moal_spin_unlock(priv->adapter->
+							  pmoal_handle,
+							  priv->
+							  rx_reorder_tbl_ptr.
+							  plock);
+		LEAVE();
+		return count;
+	}
+	while (rx_reorder_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		ptbl->tid = (t_u16)rx_reorder_tbl_ptr->tid;
+		memcpy_ext(priv->adapter, ptbl->ta, rx_reorder_tbl_ptr->ta,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		ptbl->start_win = rx_reorder_tbl_ptr->start_win;
+		ptbl->win_size = rx_reorder_tbl_ptr->win_size;
+
+		ptbl->amsdu = rx_reorder_tbl_ptr->amsdu;
+		for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) {
+			if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
+				ptbl->buffer[i] = MTRUE;
+			else
+				ptbl->buffer[i] = MFALSE;
+		}
+		rx_reorder_tbl_ptr = rx_reorder_tbl_ptr->pnext;
+		ptbl++;
+		count++;
+		if (count >= MLAN_MAX_RX_BASTREAM_SUPPORTED)
+			break;
+	}
+	priv->adapter->callbacks.moal_spin_unlock(priv->adapter->pmoal_handle,
+						  priv->rx_reorder_tbl_ptr.
+						  plock);
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief Get transmit BA stream table
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param buf          A pointer to tx_ba_stream_tbl structure
+ *  @return             number of ba stream table entry
+ */
+int
+wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf)
+{
+	TxBAStreamTbl *ptxtbl;
+	tx_ba_stream_tbl *ptbl = buf;
+	int count = 0;
+	t_u32 bastream_max = 0;
+
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	ptxtbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						 &priv->tx_ba_stream_tbl_ptr,
+						 MNULL, MNULL);
+	if (!ptxtbl) {
+		wlan_release_ralist_lock(priv);
+		LEAVE();
+		return count;
+	}
+	bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
+	if (bastream_max == 0)
+		bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
+
+	while (ptxtbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		ptbl->tid = (t_u16)ptxtbl->tid;
+		PRINTM(MINFO, "tid=%d\n", ptbl->tid);
+		memcpy_ext(priv->adapter, ptbl->ra, ptxtbl->ra,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		ptbl->amsdu = ptxtbl->amsdu;
+		ptxtbl = ptxtbl->pnext;
+		ptbl++;
+		count++;
+		if (count >= (int)bastream_max)
+			break;
+	}
+	wlan_release_ralist_lock(priv);
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief This function check if 11AC is allowed in bandcfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param bss_band     bss band
+ *
+ *  @return 0--not allowed, other value allowed
+ */
+t_u8
+wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u8 bss_band)
+{
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		if (bss_band & BAND_G)
+			return (pmpriv->adapter->adhoc_start_band & BAND_GN);
+		else if (bss_band & BAND_A)
+			return (pmpriv->adapter->adhoc_start_band & BAND_AN);
+	} else {
+		if (bss_band & BAND_G)
+			return (pmpriv->config_bands & BAND_GN);
+		else if (bss_band & BAND_A)
+			return (pmpriv->config_bands & BAND_AN);
+	}
+	return 0;
+}
+
+/**
+ *  @brief This function cleans up txbastream_tbl for specific station
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ra       RA to find in txbastream_tbl
+ *  @return         N/A
+ */
+void
+wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra)
+{
+	TxBAStreamTbl *ptx_tbl = MNULL;
+	t_u8 i;
+	ENTER();
+
+	wlan_request_ralist_lock(priv);
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ptx_tbl = wlan_11n_get_txbastream_tbl(priv, i, ra, MFALSE);
+		if (ptx_tbl)
+			wlan_11n_delete_txbastream_tbl_entry(priv, ptx_tbl);
+	}
+	wlan_release_ralist_lock(priv);
+	LEAVE();
+	return;
+}
+
+void
+wlan_update_11n_cap(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	pmpriv->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support;
+	pmpriv->usr_dot_11n_dev_cap_bg =
+		pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_BG;
+	pmpriv->usr_dot_11n_dev_cap_a =
+		pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_A;
+}
diff --git a/wlan_sd8987/mlan/mlan_11n.h b/wlan_sd8987/mlan/mlan_11n.h
new file mode 100755
index 0000000..601baa4
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n.h
@@ -0,0 +1,426 @@
+/** @file mlan_11n.h
+ *
+ *  @brief Interface for the 802.11n mlan_11n module implemented in mlan_11n.c
+ *
+ *  Driver interface functions and type declarations for the 11n module
+ *    implemented in mlan_11n.c.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    12/01/2008: initial version
+********************************************************/
+
+#ifndef _MLAN_11N_H_
+#define _MLAN_11N_H_
+
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#include "mlan_wmm.h"
+
+/** Print the 802.11n device capability */
+void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap);
+/** Print the 802.11n device MCS */
+void wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support);
+/** Handle the command response of a delete block ack request */
+mlan_status wlan_ret_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *resp);
+/** Handle the command response of an add block ack request */
+mlan_status wlan_ret_11n_addba_req(mlan_private *priv,
+				   HostCmd_DS_COMMAND *resp);
+/** Handle the command response of 11ncfg command */
+mlan_status wlan_ret_11n_cfg(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf);
+/** Prepare 11ncfg command */
+mlan_status wlan_cmd_11n_cfg(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			     t_void *pdata_buf);
+/** Prepare reject addba requst command */
+mlan_status wlan_cmd_reject_addba_req(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *cmd,
+				      t_u16 cmd_action, t_void *pdata_buf);
+/** Handle the command response of rejecting addba request */
+mlan_status wlan_ret_reject_addba_req(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf);
+/** Prepare TX BF configuration command */
+mlan_status wlan_cmd_tx_bf_cfg(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			       t_void *pdata_buf);
+/** Handle the command response TX BF configuration */
+mlan_status wlan_ret_tx_bf_cfg(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *resp,
+			       mlan_ioctl_req *pioctl_buf);
+#ifdef STA_SUPPORT
+t_u8 wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u8 bss_band);
+/** Append the 802_11N tlv */
+int wlan_cmd_append_11n_tlv(mlan_private *pmpriv,
+			    BSSDescriptor_t *pbss_desc, t_u8 **ppbuffer);
+/** wlan fill HT cap tlv */
+void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
+			  t_u16 band, t_u8 fill);
+/** wlan fill HT cap IE */
+void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
+			 t_u16 bands);
+#endif /* STA_SUPPORT */
+/** Miscellaneous configuration handler */
+mlan_status wlan_11n_cfg_ioctl(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req);
+/** Delete Tx BA stream table entry */
+void wlan_11n_delete_txbastream_tbl_entry(mlan_private *priv,
+					  TxBAStreamTbl *ptx_tbl);
+/** Delete all Tx BA stream table entries */
+void wlan_11n_deleteall_txbastream_tbl(mlan_private *priv);
+/** Get Tx BA stream table */
+TxBAStreamTbl *wlan_11n_get_txbastream_tbl(mlan_private *priv, int tid,
+					   t_u8 *ra, int lock);
+/** Create Tx BA stream table */
+void wlan_11n_create_txbastream_tbl(mlan_private *priv, t_u8 *ra, int tid,
+				    baStatus_e ba_status);
+/** Send ADD BA request */
+int wlan_send_addba(mlan_private *priv, int tid, t_u8 *peer_mac);
+/** Send DEL BA request */
+int wlan_send_delba(mlan_private *priv, pmlan_ioctl_req pioctl_req, int tid,
+		    t_u8 *peer_mac, int initiator);
+/** This function handles the command response of delete a block ack request*/
+void wlan_11n_delete_bastream(mlan_private *priv, t_u8 *del_ba);
+/** get rx reorder table */
+int wlan_get_rxreorder_tbl(mlan_private *priv, rx_reorder_tbl *buf);
+/** get tx ba stream table */
+int wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf);
+/** send delba */
+void wlan_11n_delba(mlan_private *priv, int tid);
+/** update amdpdu tx win size */
+void wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter);
+/** Minimum number of AMSDU */
+#define MIN_NUM_AMSDU 2
+/** AMSDU Aggr control cmd resp */
+mlan_status wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *resp,
+				     mlan_ioctl_req *pioctl_buf);
+void wlan_set_tx_pause_flag(mlan_private *priv, t_u8 flag);
+/** reconfigure tx buf size */
+mlan_status wlan_cmd_recfg_tx_buf(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+				  int cmd_action, void *pdata_buf);
+/** AMSDU aggr control cmd */
+mlan_status wlan_cmd_amsdu_aggr_ctrl(mlan_private *priv,
+				     HostCmd_DS_COMMAND *cmd, int cmd_action,
+				     void *pdata_buf);
+
+t_u8 wlan_validate_chan_offset(mlan_private *pmpriv, t_u16 band,
+			       t_u32 chan, t_u8 chan_bw);
+/** get channel offset */
+t_u8 wlan_get_second_channel_offset(mlan_private *priv, int chan);
+
+void wlan_update_11n_cap(mlan_private *pmpriv);
+
+/** clean up txbastream_tbl */
+void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra);
+/**
+ *  @brief This function checks whether a station has 11N enabled or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_11n_enabled(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
+	return MFALSE;
+}
+
+/**
+ *  @brief This function get station max amsdu size
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return         max amsdu size statio supported
+ */
+static INLINE t_u16
+get_station_max_amsdu_size(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return sta_ptr->max_amsdu;
+	return 0;
+}
+
+/**
+ *  @brief This function checks whether a station allows AMPDU or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+is_station_ampdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+	if (sta_ptr) {
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+		return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ?
+			MTRUE : MFALSE;
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief This function disable station ampdu for specific tid
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+disable_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
+	return;
+}
+
+/**
+ *  @brief This function reset station ampdu for specific id to user setting.
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param tid     tid index
+ *  @param ra      station mac address
+ *  @return        N/A
+ */
+static INLINE void
+reset_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		sta_ptr->ampdu_sta[tid] = priv->aggr_prio_tbl[tid].ampdu_user;
+	return;
+}
+
+#define IS_BG_RATE (priv->bitmap_rates[0] || priv->bitmap_rates[1])
+/**
+ *  @brief This function checks whether AMPDU is allowed or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+wlan_is_ampdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+	if (ptr->is_tdls_link)
+		return is_station_ampdu_allowed(priv, ptr, tid);
+	if (priv->adapter->tdls_status != TDLS_NOT_SETUP && !priv->txaggrctrl)
+		return MFALSE;
+
+	if ((!priv->is_data_rate_auto) && IS_BG_RATE)
+		return MFALSE;
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+		return is_station_ampdu_allowed(priv, ptr, tid);
+#endif /* UAP_SUPPORT */
+	if (priv->sec_info.wapi_enabled && !priv->sec_info.wapi_key_on)
+		return MFALSE;
+	return (priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)?
+		MTRUE : MFALSE;
+}
+
+#define BA_RSSI_HIGH_THRESHOLD -70
+
+static INLINE void
+wlan_update_station_del_ba_count(mlan_private *priv, raListTbl *ptr)
+{
+	sta_node *sta_ptr = MNULL;
+	t_s8 rssi;
+	sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+	if (sta_ptr) {
+		rssi = sta_ptr->snr - sta_ptr->nf;
+		if (rssi > BA_RSSI_HIGH_THRESHOLD)
+			ptr->del_ba_count = 0;
+	}
+	return;
+}
+
+static INLINE void
+wlan_update_del_ba_count(mlan_private *priv, raListTbl *ptr)
+{
+	t_s8 rssi;
+#ifdef UAP_802_11N
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+		return wlan_update_station_del_ba_count(priv, ptr);
+#endif /* UAP_SUPPORT */
+#endif /* UAP_802_11N */
+	if (ptr->is_tdls_link)
+		return wlan_update_station_del_ba_count(priv, ptr);
+	rssi = priv->snr - priv->nf;
+	if (rssi > BA_RSSI_HIGH_THRESHOLD)
+		ptr->del_ba_count = 0;
+}
+
+/**
+ *  @brief This function checks whether AMSDU is allowed or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param tid      TID value for ptr
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+wlan_is_amsdu_allowed(mlan_private *priv, raListTbl *ptr, int tid)
+{
+#ifdef UAP_SUPPORT
+	sta_node *sta_ptr = MNULL;
+#endif
+	if (priv->amsdu_disable)
+		return MFALSE;
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		sta_ptr = wlan_get_station_entry(priv, ptr->ra);
+		if (sta_ptr) {
+			if (priv->sec_info.wapi_enabled &&
+			    !sta_ptr->wapi_key_on)
+				return MFALSE;
+		}
+	}
+#endif /* UAP_SUPPORT */
+	if (ptr->is_tdls_link)
+		return (priv->aggr_prio_tbl[tid].amsdu !=
+			BA_STREAM_NOT_ALLOWED)? MTRUE : MFALSE;
+#define TXRATE_BITMAP_INDEX_MCS0_7 2
+	return ((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)&&
+		((priv->is_data_rate_auto) ||
+		 !(((priv->bitmap_rates[TXRATE_BITMAP_INDEX_MCS0_7]) & 0x03) ||
+		   IS_BG_RATE))) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function checks whether a BA stream is available or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+wlan_is_bastream_avail(mlan_private *priv)
+{
+	mlan_private *pmpriv = MNULL;
+	t_u8 i = 0;
+	t_u32 bastream_num = 0;
+	t_u32 bastream_max = 0;
+	for (i = 0; i < priv->adapter->priv_num; i++) {
+		pmpriv = priv->adapter->priv[i];
+		if (pmpriv)
+			bastream_num += wlan_wmm_list_len((pmlan_list_head)
+							  &pmpriv->
+							  tx_ba_stream_tbl_ptr);
+	}
+	bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
+	if (bastream_max == 0)
+		bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
+	return (bastream_num < bastream_max) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function finds the stream to delete
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *  @param ptr_tid  TID value of ptr
+ *  @param ptid     A pointer to TID of stream to delete, if return MTRUE
+ *  @param ra       RA of stream to delete, if return MTRUE
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE t_u8
+wlan_find_stream_to_delete(mlan_private *priv,
+			   raListTbl *ptr, int ptr_tid, int *ptid, t_u8 *ra)
+{
+	int tid;
+	t_u8 ret = MFALSE;
+	TxBAStreamTbl *ptx_tbl;
+
+	ENTER();
+
+	ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						  &priv->tx_ba_stream_tbl_ptr,
+						  MNULL, MNULL);
+	if (!ptx_tbl) {
+		LEAVE();
+		return ret;
+	}
+
+	tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
+
+	while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
+		if (tid > priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user) {
+			tid = priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user;
+			*ptid = ptx_tbl->tid;
+			memcpy_ext(priv->adapter, ra, ptx_tbl->ra,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			ret = MTRUE;
+		}
+
+		ptx_tbl = ptx_tbl->pnext;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks whether 11n is supported
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ra       Address of the receiver STA
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE int
+wlan_is_11n_enabled(mlan_private *priv, t_u8 *ra)
+{
+	int ret = MFALSE;
+	ENTER();
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		if ((!(ra[0] & 0x01)) && (priv->is_11n_enabled))
+			ret = is_station_11n_enabled(priv, ra);
+	}
+#endif /* UAP_SUPPORT */
+	LEAVE();
+	return ret;
+}
+#endif /* !_MLAN_11N_H_ */
diff --git a/wlan_sd8987/mlan/mlan_11n_aggr.c b/wlan_sd8987/mlan/mlan_11n_aggr.c
new file mode 100755
index 0000000..2bfdace
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_aggr.c
@@ -0,0 +1,706 @@
+/** @file mlan_11n_aggr.c
+ *
+ *  @brief This file contains functions for 11n Aggregation.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11n_aggr.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief Aggregate individual packets into one AMSDU packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param amsdu_buf A pointer to packet buffer
+ *  @param data      A pointer to aggregated data packet being formed
+ *  @param pkt_len   Length of current packet to aggregate
+ *  @param pad       Pad
+ *
+ *  @return         Final packet size
+ */
+static int
+wlan_11n_form_amsdu_pkt(pmlan_adapter pmadapter, t_u8 *amsdu_buf,
+			t_u8 *data, int pkt_len, int *pad)
+{
+	int dt_offset, amsdu_buf_offset;
+	Rfc1042Hdr_t snap = {
+		0xaa,		/* LLC DSAP */
+		0xaa,		/* LLC SSAP */
+		0x03,		/* LLC CTRL */
+		{0x00, 0x00, 0x00},	/* SNAP OUI */
+		0x0000		/* SNAP type */
+			/*
+			 * This field will be overwritten
+			 * later with ethertype
+			 */
+	};
+
+	ENTER();
+
+	memcpy_ext(pmadapter, amsdu_buf, data, (MLAN_MAC_ADDR_LENGTH) * 2,
+		   (MLAN_MAC_ADDR_LENGTH) * 2);
+	dt_offset = amsdu_buf_offset = (MLAN_MAC_ADDR_LENGTH) * 2;
+
+	snap.snap_type = *(t_u16 *)(data + dt_offset);
+	dt_offset += sizeof(t_u16);
+	*(t_u16 *)(amsdu_buf + amsdu_buf_offset) =
+		mlan_htons(pkt_len + LLC_SNAP_LEN -
+			   ((2 * MLAN_MAC_ADDR_LENGTH) + sizeof(t_u16)));
+	amsdu_buf_offset += sizeof(t_u16);
+	memcpy_ext(pmadapter, amsdu_buf + amsdu_buf_offset, &snap, LLC_SNAP_LEN,
+		   LLC_SNAP_LEN);
+	amsdu_buf_offset += LLC_SNAP_LEN;
+
+	memcpy_ext(pmadapter, amsdu_buf + amsdu_buf_offset, data + dt_offset,
+		   pkt_len - dt_offset, pkt_len - dt_offset);
+	*pad = (((pkt_len + LLC_SNAP_LEN) & 3)) ?
+		(4 - (((pkt_len + LLC_SNAP_LEN)) & 3)) : 0;
+
+	LEAVE();
+	return pkt_len + LLC_SNAP_LEN + *pad;
+}
+
+/**
+ *  @brief Add TxPD to AMSDU header
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param mbuf		Pointer to buffer where the TxPD will be formed
+ *
+ *  @return		N/A
+ */
+static void
+wlan_11n_form_amsdu_txpd(mlan_private *priv, mlan_buffer *mbuf)
+{
+	TxPD *ptx_pd;
+	mlan_adapter *pmadapter = priv->adapter;
+
+	ENTER();
+
+	ptx_pd = (TxPD *)mbuf->pbuf;
+	memset(pmadapter, ptx_pd, 0, sizeof(TxPD));
+
+	/*
+	 * Original priority has been overwritten
+	 */
+	ptx_pd->priority = (t_u8)mbuf->priority;
+	ptx_pd->pkt_delay_2ms =
+		wlan_wmm_compute_driver_packet_delay(priv, mbuf);
+	ptx_pd->bss_num = GET_BSS_NUM(priv);
+	ptx_pd->bss_type = priv->bss_type;
+	/* Always zero as the data is followed by TxPD */
+	ptx_pd->tx_pkt_offset = sizeof(TxPD);
+	ptx_pd->tx_pkt_type = PKT_TYPE_AMSDU;
+	if (mbuf->flags & MLAN_BUF_FLAG_TDLS)
+		ptx_pd->flags = MRVDRV_TxPD_FLAGS_TDLS_PACKET;
+	if (ptx_pd->tx_control == 0)
+		/* TxCtrl set by user or default */
+		ptx_pd->tx_control = priv->pkt_tx_ctrl;
+
+	endian_convert_TxPD(ptx_pd);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Update the TxPktLength field in TxPD after the complete AMSDU
+ *  packet is formed
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param mbuf     TxPD buffer
+ *
+ *  @return         N/A
+ */
+static INLINE void
+wlan_11n_update_pktlen_amsdu_txpd(mlan_private *priv, pmlan_buffer mbuf)
+{
+	TxPD *ptx_pd;
+	ENTER();
+
+	ptx_pd = (TxPD *)mbuf->pbuf;
+	ptx_pd->tx_pkt_length =
+		(t_u16)wlan_cpu_to_le16(mbuf->data_len - sizeof(TxPD));
+#ifdef STA_SUPPORT
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+	    (priv->adapter->pps_uapsd_mode)) {
+		if (MTRUE == wlan_check_last_packet_indication(priv)) {
+			priv->adapter->tx_lock_flag = MTRUE;
+			ptx_pd->flags |= MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
+		}
+	}
+#endif /* STA_SUPPORT */
+	LEAVE();
+}
+
+/**
+ *  @brief Get number of aggregated packets
+ *
+ *  @param data			A pointer to packet data
+ *  @param total_pkt_len	Total packet length
+ *
+ *  @return			Number of packets
+ */
+static int
+wlan_11n_get_num_aggrpkts(t_u8 *data, int total_pkt_len)
+{
+	int pkt_count = 0, pkt_len, pad;
+	t_u8 hdr_len = sizeof(Eth803Hdr_t);
+
+	ENTER();
+	while (total_pkt_len >= hdr_len) {
+		/* Length will be in network format, change it to host */
+		pkt_len = mlan_ntohs((*(t_u16 *)
+				      (data + (2 * MLAN_MAC_ADDR_LENGTH))));
+		if (pkt_len > total_pkt_len) {
+			PRINTM(MERROR, "Error in packet length.\n");
+			break;
+		}
+
+		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
+		data += pkt_len + pad + sizeof(Eth803Hdr_t);
+		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+		++pkt_count;
+	}
+	LEAVE();
+	return pkt_count;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Deaggregate the received AMSDU packet
+ *
+ *  @param priv		A pointer to mlan_private structure
+ *  @param pmbuf	A pointer to aggregated data packet
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf)
+{
+	t_u16 pkt_len;
+	int total_pkt_len;
+	t_u8 *data;
+	mlan_adapter *pmadapter = priv->adapter;
+	t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;
+	int pad;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	RxPacketHdr_t *prx_pkt;
+	mlan_buffer *daggr_mbuf = MNULL;
+	t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03,
+		0x00, 0x00, 0x00
+	};
+	t_u8 hdr_len = sizeof(Eth803Hdr_t);
+	t_u8 eapol_type[2] = { 0x88, 0x8e };
+	t_u8 tdls_action_type[2] = { 0x89, 0x0d };
+	t_u32 in_ts_sec, in_ts_usec;
+	t_u32 out_ts_sec, out_ts_usec;
+	t_u32 in_copy_ts_sec, in_copy_ts_usec;
+	t_u32 out_copy_ts_sec, out_copy_ts_usec;
+	t_u32 copy_delay = 0;
+	t_u32 delay = 0;
+
+	ENTER();
+
+	data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	total_pkt_len = pmbuf->data_len;
+
+	/* Sanity test */
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type) &&
+	    pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable) {
+		max_rx_data_size =
+			pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_max;
+		if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_mode ==
+		    MLAN_USB_AGGR_MODE_NUM) {
+			max_rx_data_size *=
+				MAX(MLAN_USB_MAX_PKT_SIZE,
+				    pmadapter->pcard_usb->usb_rx_deaggr.
+				    aggr_ctrl.aggr_align);
+			max_rx_data_size =
+				MAX(max_rx_data_size, MLAN_RX_DATA_BUF_SIZE);
+		}
+	}
+#endif
+	if (total_pkt_len > (int)max_rx_data_size) {
+		PRINTM(MERROR,
+		       "Total packet length greater than tx buffer"
+		       " size %d\n", total_pkt_len);
+		goto done;
+	}
+	if (pmadapter->tp_state_on)
+		pmadapter->callbacks.moal_get_system_time(pmadapter->
+							  pmoal_handle,
+							  &in_ts_sec,
+							  &in_ts_usec);
+	pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);
+
+	//rx_trace 7
+	if (pmadapter->tp_state_on) {
+		pmadapter->callbacks.moal_tp_accounting(pmadapter->pmoal_handle,
+							pmbuf,
+							7 /*RX_DROP_P3 */ );
+		pmadapter->callbacks.moal_tp_accounting_rx_param(pmadapter->
+								 pmoal_handle,
+								 4,
+								 pmbuf->
+								 use_count);
+	}
+	if (pmadapter->tp_state_drop_point == 7 /*RX_DROP_P3 */ )
+		goto done;
+	prx_pkt = (RxPacketHdr_t *)data;
+	if (pmbuf->pdesc && !memcmp(pmadapter, prx_pkt->eth803_hdr.dest_addr,
+				    priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
+		if (pmadapter->callbacks.moal_recv_amsdu_packet) {
+			ret = pmadapter->callbacks.
+				moal_recv_amsdu_packet(pmadapter->pmoal_handle,
+						       pmbuf);
+			if (ret == MLAN_STATUS_PENDING) {
+				priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count;
+				priv->amsdu_rx_cnt++;
+				return ret;
+			}
+			goto done;
+		}
+	}
+	while (total_pkt_len >= hdr_len) {
+		prx_pkt = (RxPacketHdr_t *)data;
+		/* Length will be in network format, change it to host */
+		pkt_len = mlan_ntohs((*(t_u16 *)
+				      (data + (2 * MLAN_MAC_ADDR_LENGTH))));
+		if (pkt_len > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
+			       total_pkt_len, pkt_len);
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
+			(4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
+
+		total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);
+
+		if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr,
+			   sizeof(rfc1042_eth_hdr)) == 0) {
+			memmove(pmadapter, data + LLC_SNAP_LEN, data,
+				(2 * MLAN_MAC_ADDR_LENGTH));
+			data += LLC_SNAP_LEN;
+			pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
+		} else {
+			*(t_u16 *)(data + (2 * MLAN_MAC_ADDR_LENGTH)) =
+				(t_u16)0;
+			pkt_len += sizeof(Eth803Hdr_t);
+		}
+		daggr_mbuf = wlan_alloc_mlan_buffer(pmadapter,
+						    pkt_len + MLAN_NET_IP_ALIGN,
+						    0, MOAL_ALLOC_MLAN_BUFFER);
+		if (daggr_mbuf == MNULL) {
+			PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		daggr_mbuf->data_offset += MLAN_NET_IP_ALIGN;
+		daggr_mbuf->bss_index = pmbuf->bss_index;
+		daggr_mbuf->buf_type = pmbuf->buf_type;
+		daggr_mbuf->data_len = pkt_len;
+		daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
+		daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
+		daggr_mbuf->extra_ts_sec = pmbuf->extra_ts_sec;
+		daggr_mbuf->extra_ts_usec = pmbuf->extra_ts_usec;
+		daggr_mbuf->pparent = pmbuf;
+		daggr_mbuf->priority = pmbuf->priority;
+		if (pmadapter->tp_state_on)
+			pmadapter->callbacks.moal_get_system_time(pmadapter->
+								  pmoal_handle,
+								  &in_copy_ts_sec,
+								  &in_copy_ts_usec);
+		memcpy_ext(pmadapter,
+			   daggr_mbuf->pbuf + daggr_mbuf->data_offset, data,
+			   pkt_len, daggr_mbuf->data_len);
+		if (pmadapter->tp_state_on) {
+			pmadapter->callbacks.moal_get_system_time(pmadapter->
+								  pmoal_handle,
+								  &out_copy_ts_sec,
+								  &out_copy_ts_usec);
+			copy_delay +=
+				(t_s32)(out_copy_ts_sec -
+					in_copy_ts_sec) * 1000000;
+			copy_delay +=
+				(t_s32)(out_copy_ts_usec - in_copy_ts_usec);
+		}
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			ret = wlan_uap_recv_packet(priv, daggr_mbuf);
+		} else {
+#endif /* UAP_SUPPORT */
+			/** send EAPOL from AMSDU pkt to firmware */
+			if (priv->sec_info.ewpa_enabled &&
+			    (!memcmp(pmadapter,
+				     daggr_mbuf->pbuf +
+				     daggr_mbuf->data_offset +
+				     MLAN_ETHER_PKT_TYPE_OFFSET,
+				     eapol_type, sizeof(eapol_type)))) {
+				ret = wlan_prepare_cmd(priv,
+						       HostCmd_CMD_802_11_EAPOL_PKT,
+						       0, 0, MNULL, daggr_mbuf);
+				if (ret == MLAN_STATUS_SUCCESS)
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				wlan_free_mlan_buffer(pmadapter, daggr_mbuf);
+				data += pkt_len + pad;
+				continue;
+			}
+			/**process tdls packet*/
+			if (!memcmp(pmadapter,
+				    daggr_mbuf->pbuf + daggr_mbuf->data_offset +
+				    MLAN_ETHER_PKT_TYPE_OFFSET,
+				    tdls_action_type,
+				    sizeof(tdls_action_type))) {
+				PRINTM(MEVENT,
+				       "Recevie AMSDU TDLS action frame\n");
+				wlan_process_tdls_action_frame(priv,
+							       daggr_mbuf->
+							       pbuf +
+							       daggr_mbuf->
+							       data_offset,
+							       daggr_mbuf->
+							       data_len);
+			}
+
+			ret = pmadapter->callbacks.moal_recv_packet(pmadapter->
+								    pmoal_handle,
+								    daggr_mbuf);
+#ifdef UAP_SUPPORT
+		}
+#endif /* UAP_SUPPORT */
+		switch (ret) {
+		case MLAN_STATUS_PENDING:
+			break;
+		case MLAN_STATUS_FAILURE:
+			PRINTM(MERROR, "Deaggr, send to moal failed\n");
+			daggr_mbuf->status_code = MLAN_ERROR_PKT_INVALID;
+			/* fall through */
+		case MLAN_STATUS_SUCCESS:
+			wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
+			break;
+		default:
+			break;
+		}
+
+		data += pkt_len + pad;
+	}
+	if (pmadapter->tp_state_on) {
+		pmadapter->callbacks.moal_get_system_time(pmadapter->
+							  pmoal_handle,
+							  &out_ts_sec,
+							  &out_ts_usec);
+		delay += (t_s32)(out_ts_sec - in_ts_sec) * 1000000;
+		delay += (t_s32)(out_ts_usec - in_ts_usec);
+		pmadapter->callbacks.moal_amsdu_tp_accounting(pmadapter->
+							      pmoal_handle,
+							      delay,
+							      copy_delay);
+	}
+
+done:
+	priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count;
+	priv->amsdu_rx_cnt++;
+	/** we should free the aggr buffer after deaggr */
+	pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Aggregate multiple packets into one single AMSDU packet
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param pra_list Pointer to the RA List table containing the pointers
+ *                  to packets.
+ *  @param headroom Any interface specific headroom that may be need. TxPD
+ *                  will be formed leaving this headroom.
+ *  @param ptrindex Pointer index
+ *
+ *  @return     Final packet size or MLAN_STATUS_FAILURE
+ */
+int
+wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
+		       int headroom, int ptrindex)
+{
+	int pkt_size = 0;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_buffer *pmbuf_aggr, *pmbuf_src;
+	t_u8 *data;
+	int pad = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	mlan_tx_param tx_param;
+#ifdef STA_SUPPORT
+	TxPD *ptx_pd = MNULL;
+#endif
+	t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size);
+	t_u32 msdu_in_tx_amsdu_cnt = 0;
+	ENTER();
+
+	PRINTM(MDAT_D, "Handling Aggr packet\n");
+
+	pmbuf_src =
+		(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					     &pra_list->buf_head, MNULL, MNULL);
+	if (pmbuf_src) {
+		pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
+						    pmadapter->tx_buf_size, 0,
+						    MOAL_MALLOC_BUFFER);
+		if (!pmbuf_aggr) {
+			PRINTM(MERROR, "Error allocating mlan_buffer\n");
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		data = pmbuf_aggr->pbuf + headroom;
+		pmbuf_aggr->bss_index = pmbuf_src->bss_index;
+		pmbuf_aggr->buf_type = pmbuf_src->buf_type;
+		pmbuf_aggr->priority = pmbuf_src->priority;
+		pmbuf_aggr->pbuf = data;
+		pmbuf_aggr->data_offset = 0;
+		pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec;
+		pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec;
+		if (pmbuf_src->flags & MLAN_BUF_FLAG_TDLS)
+			pmbuf_aggr->flags |= MLAN_BUF_FLAG_TDLS;
+		if (pmbuf_src->flags & MLAN_BUF_FLAG_TCP_ACK)
+			pmbuf_aggr->flags |= MLAN_BUF_FLAG_TCP_ACK;
+
+		/* Form AMSDU */
+		wlan_11n_form_amsdu_txpd(priv, pmbuf_aggr);
+		pkt_size = sizeof(TxPD);
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+			ptx_pd = (TxPD *)pmbuf_aggr->pbuf;
+#endif
+		priv->msdu_in_tx_amsdu_cnt++;
+	} else {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		goto exit;
+	}
+
+	while (pmbuf_src && ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN) +
+			      headroom) <= max_amsdu_size)) {
+		pmbuf_src =
+			(pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+							&pra_list->buf_head,
+							MNULL, MNULL);
+		/* Collects TP statistics */
+		if (pmadapter->tp_state_on && (pkt_size > sizeof(TxPD)))
+			pmadapter->callbacks.moal_tp_accounting(pmadapter->
+								pmoal_handle,
+								pmbuf_src->
+								pdesc, 3);
+		pra_list->total_pkts--;
+
+		/* decrement for every PDU taken from the list */
+		priv->wmm.pkts_queued[ptrindex]--;
+		util_scalar_decrement(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+
+		if (pmbuf_src) {
+			pkt_size +=
+				wlan_11n_form_amsdu_pkt(pmadapter,
+							(data + pkt_size),
+							pmbuf_src->pbuf +
+							pmbuf_src->data_offset,
+							pmbuf_src->data_len,
+							&pad);
+
+			DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src,
+				    sizeof(mlan_buffer));
+			wlan_write_data_complete(pmadapter, pmbuf_src,
+						 MLAN_STATUS_SUCCESS);
+		}
+
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+
+		if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmbuf_src =
+			(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &pra_list->buf_head, MNULL,
+						     MNULL);
+		priv->msdu_in_tx_amsdu_cnt++;
+		msdu_in_tx_amsdu_cnt++;
+	}
+
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	/* Last AMSDU packet does not need padding */
+	pkt_size -= pad;
+	pmbuf_aggr->data_len = pkt_size;
+	wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr);
+	pmbuf_aggr->data_len += headroom;
+	pmbuf_aggr->pbuf = data - headroom;
+	tx_param.next_pkt_len =
+		((pmbuf_src) ? pmbuf_src->data_len + sizeof(TxPD) : 0);
+	/* Collects TP statistics */
+	if (pmadapter->tp_state_on) {
+		pmadapter->callbacks.moal_tp_accounting(pmadapter->pmoal_handle,
+							pmbuf_aggr, 4);
+		pmadapter->callbacks.moal_tp_accounting_rx_param(pmadapter->
+								 pmoal_handle,
+								 5,
+								 msdu_in_tx_amsdu_cnt);
+	}
+
+	/* Drop Tx packets at drop point 4 */
+	if (pmadapter->tp_state_drop_point == 4) {
+		wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+		goto exit;
+	} else
+		ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA,
+						  pmbuf_aggr, &tx_param);
+	switch (ret) {
+#ifdef USB
+	case MLAN_STATUS_PRESOURCE:
+		PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+		break;
+#endif
+	case MLAN_STATUS_RESOURCE:
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+
+		if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID;
+			wlan_write_data_complete(pmadapter, pmbuf_aggr,
+						 MLAN_STATUS_FAILURE);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#ifdef STA_SUPPORT
+		/* reset tx_lock_flag */
+		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+		    pmadapter->pps_uapsd_mode &&
+		    (pmadapter->tx_lock_flag == MTRUE)) {
+			pmadapter->tx_lock_flag = MFALSE;
+			if (ptx_pd != MNULL)
+				ptx_pd->flags = 0;
+		}
+#endif
+		util_enqueue_list_head(pmadapter->pmoal_handle,
+				       &pra_list->buf_head,
+				       (pmlan_linked_list)pmbuf_aggr, MNULL,
+				       MNULL);
+
+		pra_list->total_pkts++;
+
+		/* add back only one: aggregated packet is requeued as one */
+		priv->wmm.pkts_queued[ptrindex]++;
+		util_scalar_increment(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		pmbuf_aggr->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+		pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID;
+		break;
+	case MLAN_STATUS_FAILURE:
+		pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
+		pmadapter->dbg.num_tx_host_to_card_failure++;
+		wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+		goto exit;
+	case MLAN_STATUS_PENDING:
+		break;
+	case MLAN_STATUS_SUCCESS:
+		wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+		break;
+	default:
+		break;
+	}
+	if (ret != MLAN_STATUS_RESOURCE) {
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+		if (wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
+			priv->wmm.packets_out[ptrindex]++;
+			priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
+		}
+		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+			pmadapter->bssprio_tbl[priv->bss_priority]
+			.bssprio_cur->pnext;
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+	}
+	PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec);
+	priv->amsdu_tx_cnt++;
+
+exit:
+	LEAVE();
+	return pkt_size + headroom;
+}
diff --git a/wlan_sd8987/mlan/mlan_11n_aggr.h b/wlan_sd8987/mlan/mlan_11n_aggr.h
new file mode 100755
index 0000000..b7aca6b
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_aggr.h
@@ -0,0 +1,38 @@
+/** @file mlan_11n_aggr.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n aggregation functionalities
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    11/10/2008: initial version
+********************************************************/
+
+#ifndef _MLAN_11N_AGGR_H_
+#define _MLAN_11N_AGGR_H_
+
+/** Aggregate 11N packets */
+mlan_status wlan_11n_deaggregate_pkt(pmlan_private priv, pmlan_buffer pmbuf);
+/** Deaggregate 11N packets */
+int wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *ptr, int headroom,
+			   int ptrindex);
+
+#endif /* !_MLAN_11N_AGGR_H_ */
diff --git a/wlan_sd8987/mlan/mlan_11n_rxreorder.c b/wlan_sd8987/mlan/mlan_11n_rxreorder.c
new file mode 100755
index 0000000..441270f
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_rxreorder.c
@@ -0,0 +1,1560 @@
+/** @file mlan_11n_rxreorder.c
+ *
+ *  @brief This file contains the handling of RxReordering in wlan
+ *  driver.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    11/10/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11n_rxreorder.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function will dispatch amsdu packet and
+ *         forward it to kernel/upper layer
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param pmbuf    A pointer to the received buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11n_dispatch_amsdu_pkt(mlan_private *priv, pmlan_buffer pmbuf)
+{
+	RxPD *prx_pd;
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+	ENTER();
+	if (prx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
+		pmbuf->data_len = prx_pd->rx_pkt_length;
+		pmbuf->data_offset += prx_pd->rx_pkt_offset;
+		wlan_11n_deaggregate_pkt(priv, pmbuf);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function will process the rx packet and
+ *         forward it to kernel/upper layer
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param payload  A pointer to rx packet payload
+ *  @param rx_reor_tbl_ptr       pointer to RxReorderTbl
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_11n_dispatch_pkt(t_void *priv, t_void *payload,
+		      RxReorderTbl *rx_reor_tbl_ptr)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+	pmlan_adapter pmadapter = ((pmlan_private)priv)->adapter;
+#endif
+	ENTER();
+	if (payload == (t_void *)RX_PKT_DROPPED_IN_FW) {
+		LEAVE();
+		return ret;
+	}
+
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE((mlan_private *)priv) == MLAN_BSS_ROLE_UAP) {
+		if (MLAN_STATUS_SUCCESS ==
+		    wlan_11n_dispatch_amsdu_pkt((mlan_private *)priv,
+						(pmlan_buffer)payload)) {
+			LEAVE();
+			return ret;
+		}
+		ret = wlan_process_uap_rx_packet(priv, (pmlan_buffer)payload);
+		LEAVE();
+		return ret;
+	}
+#endif /* UAP_SUPPORT */
+
+#ifdef STA_SUPPORT
+	if (MLAN_STATUS_SUCCESS ==
+	    wlan_11n_dispatch_amsdu_pkt((mlan_private *)priv,
+					(pmlan_buffer)payload)) {
+		LEAVE();
+		return ret;
+	}
+	ret = wlan_process_rx_packet(pmadapter, (pmlan_buffer)payload);
+#endif /* STA_SUPPORT */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function restarts the reordering timeout timer
+ *
+ *  @param pmadapter        A pointer to mlan_adapter
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *
+ *  @return                 N/A
+ */
+static void
+mlan_11n_rxreorder_timer_restart(pmlan_adapter pmadapter,
+				 RxReorderTbl *rx_reor_tbl_ptr)
+{
+	t_u16 min_flush_time = 0;
+	ENTER();
+
+	if (rx_reor_tbl_ptr->win_size >= 32)
+		min_flush_time = MIN_FLUSH_TIMER_15_MS;
+	else
+		min_flush_time = MIN_FLUSH_TIMER_MS;
+
+	if (rx_reor_tbl_ptr->timer_context.timer_is_set)
+		pmadapter->callbacks.moal_stop_timer(pmadapter->pmoal_handle,
+						     rx_reor_tbl_ptr->
+						     timer_context.timer);
+
+	pmadapter->callbacks.moal_start_timer(pmadapter->pmoal_handle,
+					      rx_reor_tbl_ptr->timer_context.
+					      timer, MFALSE,
+					      (rx_reor_tbl_ptr->win_size *
+					       min_flush_time));
+
+	rx_reor_tbl_ptr->timer_context.timer_is_set = MTRUE;
+	LEAVE();
+}
+
+/**
+ *  @brief This function dispatches all the packets in the buffer.
+ *         There could be holes in the buffer.
+ *
+ *  @param priv             A pointer to mlan_private
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *  @param start_win        Start window
+ *
+ *  @return                 MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11n_dispatch_pkt_until_start_win(t_void *priv,
+				      RxReorderTbl *rx_reor_tbl_ptr,
+				      int start_win)
+{
+	int no_pkt_to_send, i, xchg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	void *rx_tmp_ptr = MNULL;
+	mlan_private *pmpriv = (mlan_private *)priv;
+
+	ENTER();
+
+	no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ?
+		MIN((start_win - rx_reor_tbl_ptr->start_win),
+		    rx_reor_tbl_ptr->win_size) : rx_reor_tbl_ptr->win_size;
+
+	for (i = 0; i < no_pkt_to_send; ++i) {
+		pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->
+							  pmoal_handle,
+							  pmpriv->rx_pkt_lock);
+		rx_tmp_ptr = MNULL;
+		if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+			rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
+			rx_reor_tbl_ptr->rx_reorder_ptr[i] = MNULL;
+		}
+		pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+							    pmoal_handle,
+							    pmpriv->
+							    rx_pkt_lock);
+		if (rx_tmp_ptr)
+			wlan_11n_dispatch_pkt(priv, rx_tmp_ptr,
+					      rx_reor_tbl_ptr);
+	}
+
+	pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->pmoal_handle,
+						  pmpriv->rx_pkt_lock);
+	/*
+	 * We don't have a circular buffer, hence use rotation to simulate
+	 * circular buffer
+	 */
+	xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send;
+	for (i = 0; i < xchg; ++i) {
+		rx_reor_tbl_ptr->rx_reorder_ptr[i] =
+			rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i];
+		rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = MNULL;
+	}
+
+	rx_reor_tbl_ptr->start_win = start_win;
+	pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+						    pmoal_handle,
+						    pmpriv->rx_pkt_lock);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will display the rxReorder table
+ *
+ *  @param pmadapter          A pointer to mlan_adapter structure
+ *  @param rx_reor_tbl_ptr    A pointer to structure RxReorderTbl
+ *
+ *  @return                   N/A
+ */
+static t_void
+wlan_11n_display_tbl_ptr(pmlan_adapter pmadapter, RxReorderTbl *rx_reor_tbl_ptr)
+{
+	ENTER();
+
+	DBG_HEXDUMP(MDAT_D, "Reorder ptr", rx_reor_tbl_ptr->rx_reorder_ptr,
+		    sizeof(t_void *) * rx_reor_tbl_ptr->win_size);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will dispatch all packets sequentially
+ *          from start_win until a hole is found and adjust the
+ *          start_win appropriately
+ *
+ *  @param priv             A pointer to mlan_private
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *
+ *  @return                 MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11n_scan_and_dispatch(t_void *priv, RxReorderTbl *rx_reor_tbl_ptr)
+{
+	int i, j, xchg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	void *rx_tmp_ptr = MNULL;
+	mlan_private *pmpriv = (mlan_private *)priv;
+
+	ENTER();
+
+	for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) {
+		pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->
+							  pmoal_handle,
+							  pmpriv->rx_pkt_lock);
+		if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+			pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->
+								    adapter->
+								    pmoal_handle,
+								    pmpriv->
+								    rx_pkt_lock);
+			break;
+		}
+		rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
+		rx_reor_tbl_ptr->rx_reorder_ptr[i] = MNULL;
+		pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+							    pmoal_handle,
+							    pmpriv->
+							    rx_pkt_lock);
+		wlan_11n_dispatch_pkt(priv, rx_tmp_ptr, rx_reor_tbl_ptr);
+	}
+
+	pmpriv->adapter->callbacks.moal_spin_lock(pmpriv->adapter->pmoal_handle,
+						  pmpriv->rx_pkt_lock);
+	/*
+	 * We don't have a circular buffer, hence use rotation to simulate
+	 * circular buffer
+	 */
+	if (i > 0) {
+		xchg = rx_reor_tbl_ptr->win_size - i;
+		for (j = 0; j < xchg; ++j) {
+			rx_reor_tbl_ptr->rx_reorder_ptr[j] =
+				rx_reor_tbl_ptr->rx_reorder_ptr[i + j];
+			rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = MNULL;
+		}
+	}
+
+	rx_reor_tbl_ptr->start_win =
+		(rx_reor_tbl_ptr->start_win + i) & (MAX_TID_VALUE - 1);
+
+	pmpriv->adapter->callbacks.moal_spin_unlock(pmpriv->adapter->
+						    pmoal_handle,
+						    pmpriv->rx_pkt_lock);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function delete rxreorder table's entry
+ *          and free the memory
+ *
+ *  @param priv             A pointer to mlan_private
+ *  @param rx_reor_tbl_ptr  A pointer to structure RxReorderTbl
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_11n_delete_rxreorder_tbl_entry(mlan_private *priv,
+				    RxReorderTbl *rx_reor_tbl_ptr)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+	mlan_block_rx_process(pmadapter, MTRUE);
+
+	wlan_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr,
+					      (rx_reor_tbl_ptr->start_win +
+					       rx_reor_tbl_ptr->
+					       win_size) & (MAX_TID_VALUE - 1));
+
+	if (rx_reor_tbl_ptr->timer_context.timer) {
+		if (rx_reor_tbl_ptr->timer_context.timer_is_set) {
+			priv->adapter->callbacks.moal_stop_timer(pmadapter->
+								 pmoal_handle,
+								 rx_reor_tbl_ptr->
+								 timer_context.
+								 timer);
+			rx_reor_tbl_ptr->timer_context.timer_is_set = MFALSE;
+		}
+		priv->adapter->callbacks.moal_free_timer(pmadapter->
+							 pmoal_handle,
+							 rx_reor_tbl_ptr->
+							 timer_context.timer);
+		rx_reor_tbl_ptr->timer_context.timer = MNULL;
+	}
+
+	PRINTM(MDAT_D, "Delete rx_reor_tbl_ptr: %p\n", rx_reor_tbl_ptr);
+	util_unlink_list(pmadapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
+			 (pmlan_linked_list)rx_reor_tbl_ptr,
+			 pmadapter->callbacks.moal_spin_lock,
+			 pmadapter->callbacks.moal_spin_unlock);
+
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)rx_reor_tbl_ptr->
+					rx_reorder_ptr);
+	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)rx_reor_tbl_ptr);
+	mlan_block_rx_process(pmadapter, MFALSE);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function returns the last used sequence number
+ *
+ *  @param rx_reorder_tbl_ptr   A pointer to structure RxReorderTbl
+ *
+ *  @return                     Last used sequence number
+ */
+static int
+wlan_11n_find_last_seqnum(RxReorderTbl *rx_reorder_tbl_ptr)
+{
+	int i;
+
+	ENTER();
+	for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) {
+		if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
+			LEAVE();
+			return i;
+		}
+	}
+	LEAVE();
+	return -1;
+}
+
+/**
+ *  @brief This function flushes all data
+ *
+ *  @param priv          A pointer to  mlan_private structure
+ *  @param rx_reor_tbl_ptr  A pointer to RxReorderTbl
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_start_flush_data(mlan_private *priv, RxReorderTbl *rx_reor_tbl_ptr)
+{
+	int startWin;
+
+	ENTER();
+	wlan_11n_display_tbl_ptr(priv->adapter, rx_reor_tbl_ptr);
+
+	startWin = wlan_11n_find_last_seqnum(rx_reor_tbl_ptr);
+	if (startWin >= 0) {
+		PRINTM(MINFO, "Flush data %d\n", startWin);
+		wlan_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr,
+						      ((rx_reor_tbl_ptr->
+							start_win + startWin +
+							1) & (MAX_TID_VALUE -
+							      1)));
+	}
+	wlan_11n_display_tbl_ptr(priv->adapter, rx_reor_tbl_ptr);
+	LEAVE();
+}
+
+/**
+ *  @brief This function set the flag to flushes data
+ *
+ *  @param context      Reorder context pointer
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_flush_data(t_void *context)
+{
+	reorder_tmr_cnxt_t *reorder_cnxt = (reorder_tmr_cnxt_t *)context;
+	ENTER();
+	/* Set the flag to flush data */
+	reorder_cnxt->priv->adapter->flush_data = MTRUE;
+	reorder_cnxt->ptr->flush_data = MTRUE;
+	reorder_cnxt->timer_is_set = MFALSE;
+	wlan_recv_event(reorder_cnxt->priv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK,
+			MNULL);
+	LEAVE();
+}
+
+/**
+ *  @brief This function will create a entry in rx reordering table for the
+ *          given ta/tid and will initialize it with seq_num, win_size
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ta       ta to find in reordering table
+ *  @param tid      tid to find in reordering table
+ *  @param win_size win_size for the give ta/tid pair.
+ *  @param seq_num  Starting sequence number for current entry.
+ *
+ *  @return         N/A
+ */
+static t_void
+wlan_11n_create_rxreorder_tbl(mlan_private *priv, t_u8 *ta,
+			      int tid, int win_size, int seq_num)
+{
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	RxReorderTbl *rx_reor_tbl_ptr, *new_node;
+	sta_node *sta_ptr = MNULL;
+	t_u16 last_seq = 0;
+
+	ENTER();
+
+	/*
+	 * If we get a TID, ta pair which is already present dispatch all the
+	 * the packets and move the window size until the ssn
+	 */
+	rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, ta);
+	if (rx_reor_tbl_ptr) {
+		PRINTM(MCMND, "%s: delete %p old_size=%d, win_size=%d\n",
+		       __func__, rx_reor_tbl_ptr, rx_reor_tbl_ptr->win_size,
+		       win_size);
+		wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+	}
+	mlan_block_rx_process(pmadapter, MTRUE);
+	PRINTM(MCMND, "%s: seq_num %d, tid %d, ta " MACSTR ", win_size %d\n",
+	       __func__, seq_num, tid, MAC2STR(ta), win_size);
+	if (pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					     sizeof(RxReorderTbl), MLAN_MEM_DEF,
+					     (t_u8 **)&new_node)) {
+		PRINTM(MERROR, "Rx reorder memory allocation failed\n");
+		mlan_block_rx_process(pmadapter, MFALSE);
+		LEAVE();
+		return;
+	}
+
+	util_init_list((pmlan_linked_list)new_node);
+	if (pmadapter->callbacks.
+	    moal_malloc(pmadapter->pmoal_handle,
+			sizeof(pmlan_buffer) * win_size, MLAN_MEM_DEF,
+			(t_u8 **)&new_node->rx_reorder_ptr)) {
+		PRINTM(MERROR, "Rx reorder table memory allocation" "failed\n");
+		pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+						(t_u8 *)new_node);
+		mlan_block_rx_process(pmadapter, MFALSE);
+		LEAVE();
+		return;
+	}
+	PRINTM(MDAT_D, "Create ReorderPtr: %p start_win=%d last_seq=%d\n",
+	       new_node, new_node->start_win, last_seq);
+	new_node->timer_context.ptr = new_node;
+	new_node->timer_context.priv = priv;
+	new_node->timer_context.timer_is_set = MFALSE;
+	pmadapter->callbacks.moal_init_timer(pmadapter->pmoal_handle,
+					     &new_node->timer_context.timer,
+					     wlan_flush_data,
+					     &new_node->timer_context);
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &priv->rx_reorder_tbl_ptr,
+			       (pmlan_linked_list)new_node,
+			       pmadapter->callbacks.moal_spin_lock,
+			       pmadapter->callbacks.moal_spin_unlock);
+	new_node->tid = tid;
+	memcpy_ext(pmadapter, new_node->ta, ta, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+	new_node->start_win = seq_num;
+	new_node->pkt_count = 0;
+	if (queuing_ra_based(priv)) {
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			sta_ptr = wlan_get_station_entry(priv, ta);
+			if (sta_ptr)
+				last_seq = sta_ptr->rx_seq[tid];
+		}
+		PRINTM(MINFO, "UAP/ADHOC:last_seq=%d start_win=%d\n", last_seq,
+		       new_node->start_win);
+	} else {
+		sta_ptr = wlan_get_station_entry(priv, ta);
+		if (sta_ptr)
+			last_seq = sta_ptr->rx_seq[tid];
+		else
+			last_seq = priv->rx_seq[tid];
+	}
+	new_node->last_seq = last_seq;
+	new_node->win_size = win_size;
+	new_node->force_no_drop = MFALSE;
+	new_node->check_start_win = MTRUE;
+	new_node->ba_status = BA_STREAM_SETUP_INPROGRESS;
+	for (i = 0; i < win_size; ++i)
+		new_node->rx_reorder_ptr[i] = MNULL;
+
+	mlan_block_rx_process(pmadapter, MFALSE);
+	LEAVE();
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function will return the pointer to a entry in rx reordering
+ *          table which matches the give TA/TID pair
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param ta      ta to find in reordering table
+ *  @param tid     tid to find in reordering table
+ *
+ *  @return        A pointer to structure RxReorderTbl
+ */
+RxReorderTbl *
+wlan_11n_get_rxreorder_tbl(mlan_private *priv, int tid, t_u8 *ta)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr, MNULL,
+					       MNULL);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return MNULL;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if ((!memcmp(priv->adapter, rx_reor_tbl_ptr->ta, ta,
+			     MLAN_MAC_ADDR_LENGTH)) &&
+		    (rx_reor_tbl_ptr->tid == tid)) {
+			LEAVE();
+			return rx_reor_tbl_ptr;
+		}
+
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function prepares command for adding a block ack
+ *          request.
+ *
+ *  @param priv        A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf   A pointer to data buffer
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+		       t_void *pdata_buf)
+{
+	HostCmd_DS_11N_ADDBA_REQ *padd_ba_req =
+		(HostCmd_DS_11N_ADDBA_REQ *)&cmd->params.add_ba_req;
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_ADDBA_REQ) + S_DS_GEN);
+
+	memcpy_ext(priv->adapter, padd_ba_req, pdata_buf,
+		   sizeof(HostCmd_DS_11N_ADDBA_REQ),
+		   sizeof(HostCmd_DS_11N_ADDBA_REQ));
+	padd_ba_req->block_ack_param_set =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_param_set);
+	padd_ba_req->block_ack_tmo =
+		wlan_cpu_to_le16(padd_ba_req->block_ack_tmo);
+	padd_ba_req->ssn = wlan_cpu_to_le16(padd_ba_req->ssn);
+	padd_ba_req->add_req_result = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function check if AMPDU Rx allowed
+ *
+ *  @param priv        A pointer to mlan_private structure
+ *  @param tid         TID
+ *
+ *  @return            MTRUE/MFALSE
+ */
+static t_u8
+wlan_is_addba_reject(mlan_private *priv, t_u8 tid)
+{
+#ifdef STA_SUPPORT
+#endif
+	return priv->addba_reject[tid];
+}
+
+/**
+ *  @brief This function prepares command for adding a block ack
+ *          response.
+ *
+ *  @param priv        A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf   A pointer to data buffer
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11n_addba_rspgen(mlan_private *priv,
+			  HostCmd_DS_COMMAND *cmd, void *pdata_buf)
+{
+	HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
+		(HostCmd_DS_11N_ADDBA_RSP *)&cmd->params.add_ba_rsp;
+	HostCmd_DS_11N_ADDBA_REQ *pevt_addba_req =
+		(HostCmd_DS_11N_ADDBA_REQ *)pdata_buf;
+	t_u8 tid = 0;
+	int win_size = 0;
+
+	ENTER();
+
+	pevt_addba_req->block_ack_param_set =
+		wlan_le16_to_cpu(pevt_addba_req->block_ack_param_set);
+	pevt_addba_req->block_ack_tmo =
+		wlan_le16_to_cpu(pevt_addba_req->block_ack_tmo);
+	pevt_addba_req->ssn = wlan_le16_to_cpu(pevt_addba_req->ssn);
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_ADDBA_RSP) + S_DS_GEN);
+
+	memcpy_ext(priv->adapter, padd_ba_rsp->peer_mac_addr,
+		   pevt_addba_req->peer_mac_addr, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+	padd_ba_rsp->dialog_token = pevt_addba_req->dialog_token;
+	padd_ba_rsp->block_ack_tmo =
+		wlan_cpu_to_le16(pevt_addba_req->block_ack_tmo);
+	padd_ba_rsp->ssn = wlan_cpu_to_le16(pevt_addba_req->ssn);
+	padd_ba_rsp->add_rsp_result = 0;
+
+	padd_ba_rsp->block_ack_param_set = pevt_addba_req->block_ack_param_set;
+	tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
+		BLOCKACKPARAM_TID_POS;
+	if (wlan_is_addba_reject(priv, tid)
+#ifdef STA_SUPPORT
+	    || ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+		priv->wps.session_enable)
+#endif
+#ifdef UAP_SUPPORT
+	    || ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+		(util_scalar_read(priv->adapter->pmoal_handle,
+				  &priv->adapter->pending_bridge_pkts,
+				  priv->adapter->callbacks.moal_spin_lock,
+				  priv->adapter->callbacks.moal_spin_unlock) >
+		 RX_LOW_THRESHOLD))
+#endif
+		)
+		padd_ba_rsp->status_code =
+			wlan_cpu_to_le16(ADDBA_RSP_STATUS_DECLINED);
+	else
+		padd_ba_rsp->status_code =
+			wlan_cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
+	padd_ba_rsp->block_ack_param_set &= ~BLOCKACKPARAM_WINSIZE_MASK;
+	if (!priv->add_ba_param.rx_amsdu)
+		/* We do not support AMSDU inside AMPDU, hence reset the bit */
+		padd_ba_rsp->block_ack_param_set &=
+			~BLOCKACKPARAM_AMSDU_SUPP_MASK;
+
+	padd_ba_rsp->block_ack_param_set |=
+		(priv->add_ba_param.rx_win_size << BLOCKACKPARAM_WINSIZE_POS);
+	win_size = (padd_ba_rsp->block_ack_param_set &
+		    BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS;
+
+	if (win_size == 0)
+		padd_ba_rsp->status_code =
+			wlan_cpu_to_le16(ADDBA_RSP_STATUS_DECLINED);
+
+	padd_ba_rsp->block_ack_param_set =
+		wlan_cpu_to_le16(padd_ba_rsp->block_ack_param_set);
+
+	if (padd_ba_rsp->status_code ==
+	    wlan_cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT))
+		wlan_11n_create_rxreorder_tbl(priv,
+					      pevt_addba_req->peer_mac_addr,
+					      tid, win_size,
+					      pevt_addba_req->ssn);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command for deleting a block ack
+ *          request.
+ *
+ *  @param priv       A pointer to mlan_private structure
+ *  @param cmd        A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf  A pointer to data buffer
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *cmd, void *pdata_buf)
+{
+	HostCmd_DS_11N_DELBA *pdel_ba =
+		(HostCmd_DS_11N_DELBA *)&cmd->params.del_ba;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_DELBA);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_DELBA) + S_DS_GEN);
+
+	memcpy_ext(priv->adapter, pdel_ba, pdata_buf,
+		   sizeof(HostCmd_DS_11N_DELBA), sizeof(HostCmd_DS_11N_DELBA));
+	pdel_ba->del_ba_param_set = wlan_cpu_to_le16(pdel_ba->del_ba_param_set);
+	pdel_ba->reason_code = wlan_cpu_to_le16(pdel_ba->reason_code);
+	pdel_ba->del_result = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function will identify if RxReodering is needed for the packet
+ *          and will do the reordering if required before sending it to kernel
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param seq_num  Seqence number of the current packet
+ *  @param tid      Tid of the current packet
+ *  @param ta       Transmiter address of the current packet
+ *  @param pkt_type Packetype for the current packet (to identify if its a BAR)
+ *  @param payload  Pointer to the payload
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+mlan_11n_rxreorder_pkt(void *priv, t_u16 seq_num, t_u16 tid,
+		       t_u8 *ta, t_u8 pkt_type, void *payload)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+	int prev_start_win, start_win, end_win, win_size;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_adapter pmadapter = ((mlan_private *)priv)->adapter;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		wlan_11n_get_rxreorder_tbl((mlan_private *)priv, tid, ta);
+	if (!rx_reor_tbl_ptr || rx_reor_tbl_ptr->win_size <= 1) {
+		if (pkt_type != PKT_TYPE_BAR)
+			wlan_11n_dispatch_pkt(priv, payload, rx_reor_tbl_ptr);
+
+		LEAVE();
+		return ret;
+
+	} else {
+		if (rx_reor_tbl_ptr->flush_data) {
+			rx_reor_tbl_ptr->flush_data = MFALSE;
+			wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+		}
+		if ((pkt_type == PKT_TYPE_AMSDU) && !rx_reor_tbl_ptr->amsdu) {
+			wlan_11n_dispatch_pkt(priv, payload, rx_reor_tbl_ptr);
+			LEAVE();
+			return ret;
+		}
+		if (pkt_type == PKT_TYPE_BAR)
+			PRINTM(MDAT_D, "BAR ");
+		if (pkt_type == PKT_TYPE_AMSDU)
+			PRINTM(MDAT_D, "AMSDU ");
+
+		if (rx_reor_tbl_ptr->check_start_win) {
+			if (seq_num == rx_reor_tbl_ptr->start_win)
+				rx_reor_tbl_ptr->check_start_win = MFALSE;
+			else {
+				rx_reor_tbl_ptr->pkt_count++;
+				if (rx_reor_tbl_ptr->pkt_count <
+				    (rx_reor_tbl_ptr->win_size / 2)) {
+					if (rx_reor_tbl_ptr->last_seq ==
+					    seq_num) {
+						/** drop duplicate packet */
+						ret = MLAN_STATUS_FAILURE;
+					} else {
+						/** forward the packet to kernel
+						 */
+						rx_reor_tbl_ptr->last_seq =
+							seq_num;
+						if (pkt_type != PKT_TYPE_BAR)
+							wlan_11n_dispatch_pkt
+								(priv, payload,
+								 rx_reor_tbl_ptr);
+					}
+					LEAVE();
+					return ret;
+				}
+				rx_reor_tbl_ptr->check_start_win = MFALSE;
+				if ((seq_num != rx_reor_tbl_ptr->start_win) &&
+				    (rx_reor_tbl_ptr->last_seq !=
+				     DEFAULT_SEQ_NUM)) {
+					end_win = (rx_reor_tbl_ptr->start_win +
+						   rx_reor_tbl_ptr->win_size -
+						   1) & (MAX_TID_VALUE - 1);
+					if (((end_win >
+					      rx_reor_tbl_ptr->start_win) &&
+					     (rx_reor_tbl_ptr->last_seq >=
+					      rx_reor_tbl_ptr->start_win) &&
+					     (rx_reor_tbl_ptr->last_seq <
+					      end_win)) ||
+					    ((end_win <
+					      rx_reor_tbl_ptr->start_win) &&
+					     ((rx_reor_tbl_ptr->last_seq >=
+					       rx_reor_tbl_ptr->start_win) ||
+					      (rx_reor_tbl_ptr->last_seq <
+					       end_win)))) {
+						PRINTM(MDAT_D,
+						       "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n",
+						       rx_reor_tbl_ptr->
+						       last_seq,
+						       rx_reor_tbl_ptr->
+						       start_win, seq_num);
+						rx_reor_tbl_ptr->start_win =
+							rx_reor_tbl_ptr->
+							last_seq + 1;
+					} else if ((seq_num <
+						    rx_reor_tbl_ptr->start_win)
+						   && (seq_num >
+						       rx_reor_tbl_ptr->
+						       last_seq)) {
+						PRINTM(MDAT_D,
+						       "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n",
+						       rx_reor_tbl_ptr->
+						       last_seq,
+						       rx_reor_tbl_ptr->
+						       start_win, seq_num);
+						rx_reor_tbl_ptr->start_win =
+							rx_reor_tbl_ptr->
+							last_seq + 1;
+					}
+				}
+			}
+		}
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			wlan_11n_dispatch_pkt_until_start_win(priv,
+							      rx_reor_tbl_ptr,
+							      (rx_reor_tbl_ptr->
+							       start_win +
+							       rx_reor_tbl_ptr->
+							       win_size) &
+							      (MAX_TID_VALUE -
+							       1));
+			if (pkt_type != PKT_TYPE_BAR)
+				rx_reor_tbl_ptr->start_win = seq_num;
+			mlan_11n_rxreorder_timer_restart(pmadapter,
+							 rx_reor_tbl_ptr);
+		}
+
+		prev_start_win = start_win = rx_reor_tbl_ptr->start_win;
+		win_size = rx_reor_tbl_ptr->win_size;
+		end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
+
+		PRINTM(MDAT_D, "TID %d, TA " MACSTR "\n", tid, MAC2STR(ta));
+		PRINTM(MDAT_D,
+		       "1:seq_num %d start_win %d win_size %d end_win %d\n",
+		       seq_num, start_win, win_size, end_win);
+		/*
+		 * If seq_num is less then starting win then ignore and drop
+		 * the packet
+		 */
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			PRINTM(MDAT_D, "No drop packet\n");
+			rx_reor_tbl_ptr->force_no_drop = MFALSE;
+		} else {
+			/* Wrap */
+			if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
+				if (seq_num >= ((start_win + (TWOPOW11)) &
+						(MAX_TID_VALUE - 1)) &&
+				    (seq_num < start_win)) {
+					if (pkt_type == PKT_TYPE_BAR)
+						PRINTM(MDAT_D,
+						       "BAR: start_win=%d, end_win=%d, seq_num=%d\n",
+						       start_win, end_win,
+						       seq_num);
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			} else if ((seq_num < start_win) ||
+				   (seq_num >= (start_win + (TWOPOW11)))) {
+				if (pkt_type == PKT_TYPE_BAR)
+					PRINTM(MDAT_D,
+					       "BAR: start_win=%d, end_win=%d, seq_num=%d\n",
+					       start_win, end_win, seq_num);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+
+		/*
+		 * If this packet is a BAR we adjust seq_num as
+		 * WinStart = seq_num
+		 */
+		if (pkt_type == PKT_TYPE_BAR)
+			seq_num = ((seq_num + win_size) - 1) &
+				(MAX_TID_VALUE - 1);
+
+		PRINTM(MDAT_D,
+		       "2:seq_num %d start_win %d win_size %d end_win %d\n",
+		       seq_num, start_win, win_size, end_win);
+
+		if (((end_win < start_win) && (seq_num < start_win) &&
+		     (seq_num > end_win)) ||
+		    ((end_win > start_win) &&
+		     ((seq_num > end_win) || (seq_num < start_win)))) {
+			end_win = seq_num;
+			if (((seq_num - win_size) + 1) >= 0)
+				start_win = (end_win - win_size) + 1;
+			else
+				start_win =
+					(MAX_TID_VALUE - (win_size - seq_num)) +
+					1;
+			ret = wlan_11n_dispatch_pkt_until_start_win(priv,
+								    rx_reor_tbl_ptr,
+								    start_win);
+			if (ret)
+				goto done;
+		}
+
+		PRINTM(MDAT_D,
+		       "3:seq_num %d start_win %d win_size %d"
+		       " end_win %d\n", seq_num, start_win, win_size, end_win);
+		if (pkt_type != PKT_TYPE_BAR) {
+			if (seq_num >= start_win) {
+				if (rx_reor_tbl_ptr->rx_reorder_ptr[seq_num -
+								    start_win])
+				{
+					PRINTM(MDAT_D, "Drop Duplicate Pkt\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+				rx_reor_tbl_ptr->rx_reorder_ptr[seq_num -
+								start_win] =
+					payload;
+			} else {	/* Wrap condition */
+				if (rx_reor_tbl_ptr->rx_reorder_ptr[(seq_num +
+								     (MAX_TID_VALUE))
+								    -
+								    start_win])
+				{
+					PRINTM(MDAT_D, "Drop Duplicate Pkt\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+				rx_reor_tbl_ptr->rx_reorder_ptr[(seq_num +
+								 (MAX_TID_VALUE))
+								- start_win] =
+					payload;
+			}
+		}
+
+		wlan_11n_display_tbl_ptr(pmadapter, rx_reor_tbl_ptr);
+
+		/*
+		 * Dispatch all packets sequentially from start_win until a
+		 * hole is found and adjust the start_win appropriately
+		 */
+		ret = wlan_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr);
+
+		wlan_11n_display_tbl_ptr(pmadapter, rx_reor_tbl_ptr);
+	}
+
+done:
+	if (!rx_reor_tbl_ptr->timer_context.timer_is_set ||
+	    (prev_start_win != rx_reor_tbl_ptr->start_win)) {
+		mlan_11n_rxreorder_timer_restart(pmadapter, rx_reor_tbl_ptr);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will delete an entry for a given tid/ta pair. tid/ta
+ *          are taken from delba_event body
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param tid          tid to send delba
+ *  @param peer_mac     MAC address to send delba
+ *  @param type         TYPE_DELBA_SENT	or TYPE_DELBA_RECEIVE
+ *  @param initiator    MTRUE if we are initiator of ADDBA, MFALSE otherwise
+ *  @param reason_code  delete ba reason
+ *
+ *  @return             N/A
+ */
+void
+mlan_11n_delete_bastream_tbl(mlan_private *priv, int tid, t_u8 *peer_mac,
+			     t_u8 type, int initiator, t_u16 reason_code)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+	TxBAStreamTbl *ptxtbl;
+	t_u8 cleanup_rx_reorder_tbl;
+	raListTbl *ra_list = MNULL;
+	int tid_down;
+
+	ENTER();
+
+	if (type == TYPE_DELBA_RECEIVE)
+		cleanup_rx_reorder_tbl = (initiator) ? MTRUE : MFALSE;
+	else
+		cleanup_rx_reorder_tbl = (initiator) ? MFALSE : MTRUE;
+
+	PRINTM(MEVENT,
+	       "delete_bastream_tbl: " MACSTR " tid=%d, type=%d"
+	       "initiator=%d reason=%d\n",
+	       MAC2STR(peer_mac), tid, type, initiator, reason_code);
+
+	if (cleanup_rx_reorder_tbl) {
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tid, peer_mac);
+		if (!rx_reor_tbl_ptr) {
+			PRINTM(MWARN, "TID, TA not found in table!\n");
+			LEAVE();
+			return;
+		}
+		wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr);
+	} else {
+		wlan_request_ralist_lock(priv);
+		ptxtbl = wlan_11n_get_txbastream_tbl(priv, tid, peer_mac,
+						     MFALSE);
+		if (!ptxtbl) {
+			PRINTM(MWARN, "TID, RA not found in table!\n");
+			wlan_release_ralist_lock(priv);
+			LEAVE();
+			return;
+		}
+		wlan_11n_delete_txbastream_tbl_entry(priv, ptxtbl);
+		wlan_release_ralist_lock(priv);
+		tid_down = wlan_get_wmm_tid_down(priv, tid);
+		ra_list = wlan_wmm_get_ralist_node(priv, tid_down, peer_mac);
+		if (ra_list) {
+			ra_list->amsdu_in_ampdu = MFALSE;
+			ra_list->ba_status = BA_STREAM_NOT_SETUP;
+			if (type == TYPE_DELBA_RECEIVE) {
+				if (reason_code == REASON_CODE_STA_TIMEOUT)
+					ra_list->del_ba_count = 0;
+				else
+					ra_list->del_ba_count++;
+				ra_list->packet_count = 0;
+/** after delba, we will try to set up BA again after sending 1k packets*/
+#define MIN_BA_SETUP_PACKET_REQIRED 1024
+				ra_list->ba_packet_threshold =
+					MIN_BA_SETUP_PACKET_REQIRED +
+					wlan_get_random_ba_threshold(priv->
+								     adapter);
+			}
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the command response of
+ *          a block ack response
+ *
+ *  @param priv    A pointer to mlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_11n_addba_resp(mlan_private *priv, HostCmd_DS_COMMAND *resp)
+{
+	HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
+		(HostCmd_DS_11N_ADDBA_RSP *)&resp->params.add_ba_rsp;
+	int tid;
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+
+	ENTER();
+
+	padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code);
+	padd_ba_rsp->block_ack_param_set =
+		wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set);
+	padd_ba_rsp->block_ack_tmo =
+		wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo);
+	padd_ba_rsp->ssn = wlan_le16_to_cpu(padd_ba_rsp->ssn);
+
+	tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
+		BLOCKACKPARAM_TID_POS;
+	/* Check  if we had rejected the ADDBA, if yes then do not create the
+	 * stream
+	 */
+	if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) {
+		PRINTM(MCMND,
+		       "ADDBA RSP: " MACSTR
+		       " tid=%d ssn=%d win_size=%d,amsdu=%d\n",
+		       MAC2STR(padd_ba_rsp->peer_mac_addr), tid,
+		       padd_ba_rsp->ssn,
+		       ((padd_ba_rsp->block_ack_param_set &
+			 BLOCKACKPARAM_WINSIZE_MASK) >>
+			BLOCKACKPARAM_WINSIZE_POS),
+		       padd_ba_rsp->block_ack_param_set &
+		       BLOCKACKPARAM_AMSDU_SUPP_MASK);
+
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tid,
+						   padd_ba_rsp->peer_mac_addr);
+		if (rx_reor_tbl_ptr) {
+			rx_reor_tbl_ptr->ba_status = BA_STREAM_SETUP_COMPLETE;
+			if ((padd_ba_rsp->block_ack_param_set &
+			     BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
+			    priv->add_ba_param.rx_amsdu)
+				rx_reor_tbl_ptr->amsdu = MTRUE;
+			else
+				rx_reor_tbl_ptr->amsdu = MFALSE;
+		}
+	} else {
+		PRINTM(MCMND, "ADDBA RSP: Failed(" MACSTR " tid=%d)\n",
+		       MAC2STR(padd_ba_rsp->peer_mac_addr), tid);
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tid,
+						   padd_ba_rsp->peer_mac_addr);
+		if (rx_reor_tbl_ptr)
+			wlan_11n_delete_rxreorder_tbl_entry(priv,
+							    rx_reor_tbl_ptr);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles ba_stream_timeout event
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param event    A pointer to structure HostCmd_DS_11N_BATIMEOUT
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_ba_stream_timeout(mlan_private *priv, HostCmd_DS_11N_BATIMEOUT *event)
+{
+	HostCmd_DS_11N_DELBA delba;
+
+	ENTER();
+
+	DBG_HEXDUMP(MCMD_D, "Event:", (t_u8 *)event, 20);
+
+	memset(priv->adapter, &delba, 0, sizeof(HostCmd_DS_11N_DELBA));
+	memcpy_ext(priv->adapter, delba.peer_mac_addr, event->peer_mac_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+	delba.del_ba_param_set |= (t_u16)event->tid << DELBA_TID_POS;
+	delba.del_ba_param_set |= (t_u16)event->origninator
+		<< DELBA_INITIATOR_POS;
+	delba.reason_code = REASON_CODE_STA_TIMEOUT;
+	wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, MNULL, &delba);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl
+ *
+ *  @param priv     A pointer to mlan_private
+ *
+ *  @return         N/A
+ */
+void
+wlan_11n_cleanup_reorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *del_tbl_ptr;
+
+	ENTER();
+
+	while ((del_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock))) {
+		wlan_11n_delete_rxreorder_tbl_entry(priv, del_tbl_ptr);
+	}
+
+	util_init_list((pmlan_linked_list)&priv->rx_reorder_tbl_ptr);
+
+	memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+	LEAVE();
+}
+
+/**
+ *  @brief This function handle the rxba_sync event
+ *
+ *  @param priv       A pointer to mlan_private
+ *  @param event_buf  A pointer to event buf
+ *  @param len        event_buf length
+ *  @return           N/A
+ */
+void
+wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len)
+{
+	MrvlIEtypes_RxBaSync_t *tlv_rxba = (MrvlIEtypes_RxBaSync_t *)event_buf;
+	t_u16 tlv_type, tlv_len;
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i, j;
+	t_u16 seq_num = 0;
+	int tlv_buf_left = len;
+	ENTER();
+
+	DBG_HEXDUMP(MEVT_D, "RXBA_SYNC_EVT", event_buf, len);
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypes_RxBaSync_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv_rxba->header.type);
+		tlv_len = wlan_le16_to_cpu(tlv_rxba->header.len);
+		if (tlv_type != TLV_TYPE_RXBA_SYNC) {
+			PRINTM(MERROR, "Wrong TLV id=0x%x\n", tlv_type);
+			goto done;
+		}
+		tlv_rxba->seq_num = wlan_le16_to_cpu(tlv_rxba->seq_num);
+		tlv_rxba->bitmap_len = wlan_le16_to_cpu(tlv_rxba->bitmap_len);
+		PRINTM(MEVENT, MACSTR " tid=%d seq_num=%d bitmap_len=%d\n",
+		       MAC2STR(tlv_rxba->mac), tlv_rxba->tid, tlv_rxba->seq_num,
+		       tlv_rxba->bitmap_len);
+		rx_reor_tbl_ptr =
+			wlan_11n_get_rxreorder_tbl(priv, tlv_rxba->tid,
+						   tlv_rxba->mac);
+		if (!rx_reor_tbl_ptr) {
+			PRINTM(MEVENT, "Can not find rx_reorder_tbl\n");
+			goto done;
+		}
+		if (rx_reor_tbl_ptr->force_no_drop) {
+			PRINTM(MEVENT, "Ignore RXBA_SYNC_EVT in resume\n");
+			goto done;
+		}
+		for (i = 0; i < tlv_rxba->bitmap_len; i++) {
+			for (j = 0; j < 8; j++) {
+				if (tlv_rxba->bitmap[i] & (1 << j)) {
+					seq_num = (tlv_rxba->seq_num + i * 8 +
+						   j) & (MAX_TID_VALUE - 1);
+					PRINTM(MEVENT,
+					       "Fw dropped packet, seq=%d start_win=%d, win_size=%d\n",
+					       seq_num,
+					       rx_reor_tbl_ptr->start_win,
+					       rx_reor_tbl_ptr->win_size);
+					if (MLAN_STATUS_SUCCESS !=
+					    mlan_11n_rxreorder_pkt(priv,
+								   seq_num,
+								   tlv_rxba->
+								   tid,
+								   tlv_rxba->
+								   mac, 0,
+								   (t_void *)
+								   RX_PKT_DROPPED_IN_FW)) {
+						PRINTM(MERROR,
+						       "Fail to handle dropped packet, seq=%d\n",
+						       seq_num);
+					}
+				}
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv_rxba =
+			(MrvlIEtypes_RxBaSync_t *)((t_u8 *)tlv_rxba + tlv_len +
+						   sizeof(MrvlIEtypesHeader_t));
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function cleans up reorder tbl for specific station
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ta       ta to find in reordering table
+ *  @return         N/A
+ */
+void
+wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta)
+{
+	RxReorderTbl *rx_reor_tbl_ptr = MNULL;
+	t_u8 i;
+	ENTER();
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, i, ta);
+		if (rx_reor_tbl_ptr)
+			wlan_11n_delete_rxreorder_tbl_entry(priv,
+							    rx_reor_tbl_ptr);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function will set force_no_drop flag in rxreorder_tbl.
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param flag    MTRUE/MFALSE
+ *
+ *  @return        N/A
+ */
+static void
+wlan_set_rxreorder_tbl_no_drop_flag(mlan_private *priv, t_u8 flag)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		rx_reor_tbl_ptr->force_no_drop = flag;
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param flag         MTRUE/MFALSE
+ *  @return             N/A
+ */
+void
+wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_set_rxreorder_tbl_no_drop_flag(priv, flag);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function will flush the data  in rxreorder_tbl.
+ *  	   which has flush_data flag on.
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return        N/A
+ */
+static void
+wlan_flush_priv_rxreorder_tbl(mlan_private *priv)
+{
+	RxReorderTbl *rx_reor_tbl_ptr;
+
+	ENTER();
+
+	rx_reor_tbl_ptr =
+		(RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					       &priv->rx_reorder_tbl_ptr,
+					       priv->adapter->callbacks.
+					       moal_spin_lock,
+					       priv->adapter->callbacks.
+					       moal_spin_unlock);
+	if (!rx_reor_tbl_ptr) {
+		LEAVE();
+		return;
+	}
+
+	while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
+		if (rx_reor_tbl_ptr->flush_data) {
+			rx_reor_tbl_ptr->flush_data = MFALSE;
+			wlan_start_flush_data(priv, rx_reor_tbl_ptr);
+		}
+		rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_reorder_tbl's force_no_drop flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @return             N/A
+ */
+void
+wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			wlan_flush_priv_rxreorder_tbl(priv);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function update all the rx_win_size based on coex flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param coex_flag    coex flag
+ *
+ *  @return             N/A
+ */
+static void
+wlan_update_ampdu_rxwinsize(pmlan_adapter pmadapter, t_u8 coex_flag)
+{
+	t_u8 i;
+	t_u32 rx_win_size = 0;
+	pmlan_private priv = MNULL;
+
+	ENTER();
+	if (!pmadapter->coex_rx_winsize) {
+		LEAVE();
+		return;
+	}
+	PRINTM(MEVENT, "Update rxwinsize %d\n", coex_flag);
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			rx_win_size = priv->add_ba_param.rx_win_size;
+			if (coex_flag == MTRUE) {
+#ifdef STA_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_STA)
+					priv->add_ba_param.rx_win_size =
+						MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+					priv->add_ba_param.rx_win_size =
+						MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+#ifdef UAP_SUPPORT
+				if (priv->bss_type == MLAN_BSS_TYPE_UAP)
+					priv->add_ba_param.rx_win_size =
+						MLAN_UAP_COEX_AMPDU_DEF_RXWINSIZE;
+#endif
+
+			} else {
+				priv->add_ba_param.rx_win_size =
+					priv->user_rxwinsize;
+			}
+			if (pmadapter->coex_win_size &&
+			    pmadapter->coex_rx_win_size)
+				priv->add_ba_param.rx_win_size =
+					pmadapter->coex_rx_win_size;
+			if (rx_win_size != priv->add_ba_param.rx_win_size) {
+				if (priv->media_connected == MTRUE) {
+					for (i = 0; i < MAX_NUM_TID; i++)
+						wlan_11n_delba(priv, i);
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+							MNULL);
+				}
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief check coex for
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *
+ *  @return             N/A
+ */
+void
+wlan_coex_ampdu_rxwinsize(pmlan_adapter pmadapter)
+{
+	t_u8 i;
+	pmlan_private priv = MNULL;
+	t_u8 count = 0;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+#ifdef STA_SUPPORT
+			if (GET_BSS_ROLE((mlan_private *)priv) ==
+			    MLAN_BSS_ROLE_STA) {
+				if (priv->media_connected == MTRUE)
+					count++;
+			}
+#endif
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE((mlan_private *)priv) ==
+			    MLAN_BSS_ROLE_UAP) {
+				if (priv->uap_bss_started)
+					count++;
+			}
+#endif
+		}
+		if (count >= 2)
+			break;
+	}
+	if (count >= 2)
+		wlan_update_ampdu_rxwinsize(pmadapter, MTRUE);
+	else
+		wlan_update_ampdu_rxwinsize(pmadapter, MFALSE);
+	return;
+}
diff --git a/wlan_sd8987/mlan/mlan_11n_rxreorder.h b/wlan_sd8987/mlan/mlan_11n_rxreorder.h
new file mode 100755
index 0000000..2aae43e
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_11n_rxreorder.h
@@ -0,0 +1,104 @@
+/** @file mlan_11n_rxreorder.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of 11n RxReordering functionalities
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    11/10/2008: initial version
+********************************************************/
+
+#ifndef _MLAN_11N_RXREORDER_H_
+#define _MLAN_11N_RXREORDER_H_
+
+/** Max value a TID can take = 2^12 = 4096 */
+#define MAX_TID_VALUE (2 << 11)
+/** 2^11 = 2048 */
+#define TWOPOW11 (2 << 10)
+
+/** Tid Mask used for extracting TID from BlockAckParamSet */
+#define BLOCKACKPARAM_TID_MASK 0x3C
+/** Tid position in BlockAckParamSet */
+#define BLOCKACKPARAM_TID_POS 2
+/** WinSize Mask used for extracting WinSize from BlockAckParamSet */
+#define BLOCKACKPARAM_WINSIZE_MASK 0xffc0
+/** WinSize Mask used for extracting WinSize from BlockAckParamSet */
+#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1
+/** WinSize position in BlockAckParamSet */
+#define BLOCKACKPARAM_WINSIZE_POS 6
+/** Position of TID in DelBA Param set */
+#define DELBA_TID_POS 12
+/** Position of INITIATOR in DelBA Param set */
+#define DELBA_INITIATOR_POS 11
+/** Reason code: Requested from peer STA as it does not want to
+ * use the mechanism */
+#define REASON_CODE_STA_DONT_WANT 37
+/** Reason code: Requested from peer STA due to timeout*/
+#define REASON_CODE_STA_TIMEOUT 39
+/** Type: send delba command */
+#define TYPE_DELBA_SENT 1
+/** Type: recieve delba command */
+#define TYPE_DELBA_RECEIVE 2
+/** Set Initiator Bit */
+#define DELBA_INITIATOR(paramset) (paramset = (paramset | (1 << 11)))
+/** Reset Initiator Bit for recipient */
+#define DELBA_RECIPIENT(paramset) (paramset = (paramset & ~(1 << 11)))
+/** Immediate block ack */
+#define IMMEDIATE_BLOCK_ACK 0x2
+
+/** The request has been declined */
+#define ADDBA_RSP_STATUS_DECLINED 37
+/** ADDBA response status : Reject */
+#define ADDBA_RSP_STATUS_REJECT 1
+/** ADDBA response status : Accept */
+#define ADDBA_RSP_STATUS_ACCEPT 0
+
+/** DEFAULT SEQ NUM */
+#define DEFAULT_SEQ_NUM 0xffff
+
+/** Indicate packet has been dropped in FW */
+#define RX_PKT_DROPPED_IN_FW 0xffffffff
+
+mlan_status mlan_11n_rxreorder_pkt(void *priv, t_u16 seqNum, t_u16 tid,
+				   t_u8 *ta, t_u8 pkttype, void *payload);
+void mlan_11n_delete_bastream_tbl(mlan_private *priv, int tid,
+				  t_u8 *PeerMACAddr, t_u8 type, int initiator,
+				  t_u16 reason_code);
+void wlan_11n_ba_stream_timeout(mlan_private *priv,
+				HostCmd_DS_11N_BATIMEOUT *event);
+mlan_status wlan_ret_11n_addba_resp(mlan_private *priv,
+				    HostCmd_DS_COMMAND *resp);
+mlan_status wlan_cmd_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+			       void *pdata_buf);
+mlan_status wlan_cmd_11n_addba_rspgen(mlan_private *priv,
+				      HostCmd_DS_COMMAND *cmd, void *pdata_buf);
+mlan_status wlan_cmd_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
+				   void *pdata_buf);
+void wlan_11n_cleanup_reorder_tbl(mlan_private *priv);
+RxReorderTbl *wlan_11n_get_rxreorder_tbl(mlan_private *priv, int tid, t_u8 *ta);
+void wlan_11n_rxba_sync_event(mlan_private *priv, t_u8 *event_buf, t_u16 len);
+void wlan_update_rxreorder_tbl(pmlan_adapter pmadapter, t_u8 flag);
+void wlan_flush_rxreorder_tbl(pmlan_adapter pmadapter);
+void wlan_coex_ampdu_rxwinsize(pmlan_adapter pmadapter);
+
+/** clean up reorder_tbl */
+void wlan_cleanup_reorder_tbl(mlan_private *priv, t_u8 *ta);
+#endif /* _MLAN_11N_RXREORDER_H_ */
diff --git a/wlan_sd8987/mlan/mlan_cfp.c b/wlan_sd8987/mlan/mlan_cfp.c
new file mode 100755
index 0000000..702d610
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_cfp.c
@@ -0,0 +1,3850 @@
+/**
+ * @file mlan_cfp.c
+ *
+ *  @brief This file contains WLAN client mode channel, frequency and power
+ *  related code
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+ * Change Log:
+ *	04/16/2009: initial version
+ ************************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_join.h"
+#include "mlan_main.h"
+
+/********************************************************
+ *			Local Variables
+ ********************************************************/
+
+/** 100mW */
+#define WLAN_TX_PWR_DEFAULT 20
+/** 100mW */
+#define WLAN_TX_PWR_00_DEFAULT 20
+/** 100mW */
+#define WLAN_TX_PWR_US_DEFAULT 20
+/** 100mW */
+#define WLAN_TX_PWR_JP_BG_DEFAULT 20
+/** 200mW */
+#define WLAN_TX_PWR_JP_A_DEFAULT 23
+/** 100mW */
+#define WLAN_TX_PWR_EMEA_DEFAULT 20
+/** 2000mW */
+#define WLAN_TX_PWR_CN_2000MW 33
+/** 200mW */
+#define WLAN_TX_PWR_200MW 23
+/** 1000mW */
+#define WLAN_TX_PWR_1000MW 30
+/** 250mW */
+#define WLAN_TX_PWR_250MW 24
+
+/** Region code mapping */
+typedef struct _country_code_mapping {
+	/** Region */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Code for B/G CFP table */
+	t_u8 cfp_code_bg;
+	/** Code for A CFP table */
+	t_u8 cfp_code_a;
+} country_code_mapping_t;
+
+#define EU_CFP_CODE_BG 0x30
+#define EU_CFP_CODE_A 0x30
+
+/** Region code mapping table */
+static country_code_mapping_t country_code_mapping[] = {
+	{"WW", 0x00, 0x00},	/* World       */
+	{"US", 0x10, 0x10},	/* US FCC      */
+	{"CA", 0x10, 0x20},	/* IC Canada   */
+	{"SG", 0x10, 0x10},	/* Singapore   */
+	{"EU", 0x30, 0x30},	/* ETSI        */
+	{"AU", 0x30, 0x30},	/* Australia   */
+	{"KR", 0x30, 0x30},	/* Republic Of Korea */
+	{"JP", 0xFF, 0x40},	/* Japan       */
+	{"CN", 0x30, 0x50},	/* China       */
+	{"BR", 0x01, 0x09},	/* Brazil      */
+	{"RU", 0x30, 0x0f},	/* Russia      */
+	{"IN", 0x10, 0x06},	/* India       */
+	{"MY", 0x30, 0x06},	/* Malaysia    */
+	{"NZ", 0x30, 0x30},	/* New Zeland  */
+	{"MX", 0x10, 0x07},	/* Mexico */
+};
+
+/** Country code for ETSI */
+static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
+	"AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY", "CZ", "DK",
+	"EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "KR", "LV",
+	"LI", "LT", "LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "RU",
+	"SM", "RS", "SI", "SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NZ"
+};
+
+/**
+ * The structure for Channel-Frequency-Power table
+ */
+typedef struct _cfp_table {
+	/** Region or Code */
+	t_u8 code;
+	/** Frequency/Power */
+	chan_freq_power_t *cfp;
+	/** No of CFP flag */
+	int cfp_no;
+} cfp_table_t;
+
+/* Format { Channel, Frequency (MHz), MaxTxPower } */
+/** Band : 'B/G', Region: World Wide Safe */
+static chan_freq_power_t channel_freq_power_00_BG[] = {
+	{1, 2412, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1d, 0, 0}},
+	{13, 2472, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1d, 0, 0}}
+};
+
+/* Format { Channel, Frequency (MHz), MaxTxPower } */
+/** Band: 'B/G', Region: USA FCC/Canada IC */
+static chan_freq_power_t channel_freq_power_US_BG[] = {
+	{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}}
+};
+
+/** Band: 'B/G', Region: Europe ETSI/China */
+static chan_freq_power_t channel_freq_power_EU_BG[] = {
+	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1d, 0, 0}},
+	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1d, 0, 0}}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}}
+};
+
+/** Band: 'B/G', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE, {0x1d, 0, 0}},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE, {0x1d, 0, 0}}
+};
+
+/** Band : 'B/G', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR_BG[] = {
+	{1, 2412, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, WLAN_TX_PWR_1000MW, MFALSE, {0x1d, 0, 0}},
+	{13, 2472, WLAN_TX_PWR_1000MW, MFALSE, {0x1d, 0, 0}}
+};
+
+/** Band : 'B/G', Region: Special */
+static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
+	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}},
+	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}},
+	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}}
+};
+
+/**
+ * The 2.4GHz CFP tables
+ */
+static cfp_table_t cfp_table_BG[] = {
+	{
+	 0x01,			/* Brazil */
+	 channel_freq_power_BR_BG,
+	 NELEMENTS(channel_freq_power_BR_BG),
+	 },
+	{
+	 0x00,			/* World FCC */
+	 channel_freq_power_00_BG,
+	 NELEMENTS(channel_freq_power_00_BG),
+	 },
+	{
+	 0x10,			/* US FCC */
+	 channel_freq_power_US_BG,
+	 NELEMENTS(channel_freq_power_US_BG),
+	 },
+	{
+	 0x20,			/* CANADA IC */
+	 channel_freq_power_US_BG,
+	 NELEMENTS(channel_freq_power_US_BG),
+	 },
+	{
+	 0x30,			/* EU */
+	 channel_freq_power_EU_BG,
+	 NELEMENTS(channel_freq_power_EU_BG),
+	 },
+	{
+	 0x40,			/* JAPAN */
+	 channel_freq_power_JPN40_BG,
+	 NELEMENTS(channel_freq_power_JPN40_BG),
+	 },
+	{
+	 0x41,			/* JAPAN */
+	 channel_freq_power_JPN41_BG,
+	 NELEMENTS(channel_freq_power_JPN41_BG),
+	 },
+	{
+	 0x50,			/* China */
+	 channel_freq_power_EU_BG,
+	 NELEMENTS(channel_freq_power_EU_BG),
+	 },
+	{
+	 0xfe,			/* JAPAN */
+	 channel_freq_power_JPNFE_BG,
+	 NELEMENTS(channel_freq_power_JPNFE_BG),
+	 },
+	{
+	 0xff,			/* Special */
+	 channel_freq_power_SPECIAL_BG,
+	 NELEMENTS(channel_freq_power_SPECIAL_BG),
+	 },
+	/* Add new region here */
+};
+
+/** Number of the CFP tables for 2.4GHz */
+#define MLAN_CFP_TABLE_SIZE_BG (NELEMENTS(cfp_table_BG))
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: World Wide Safe */
+static chan_freq_power_t channel_freq_power_00_A[] = {
+	{36, 5180, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{120, 5600, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{124, 5620, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{128, 5640, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{144, 5720, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
+/** Band: 'A', Region: USA FCC */
+static chan_freq_power_t channel_freq_power_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Region: Canada IC */
+static chan_freq_power_t channel_freq_power_CAN_A[] = {
+	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Region: Europe ETSI */
+static chan_freq_power_t channel_freq_power_EU_A[] = {
+	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Region: Japan */
+static chan_freq_power_t channel_freq_power_JPN_A[] = {
+	{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{144, 5720, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}}
+};
+
+/** Band: 'A', Region: China */
+static chan_freq_power_t channel_freq_power_CN_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', NULL */
+static chan_freq_power_t channel_freq_power_NULL_A[] = { };
+
+/** Band: 'A', Region: Spain/Austria/Brazil */
+static chan_freq_power_t channel_freq_power_SPN2_A[] = {
+	{36, 5180, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}}
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR1_A[] = {
+	{100, 5500, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{120, 5600, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{124, 5620, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{128, 5640, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}}
+};
+
+/** Band: 'A', Region: Brazil */
+static chan_freq_power_t channel_freq_power_BR2_A[] = {
+	{149, 5745, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Region: Russia */
+static chan_freq_power_t channel_freq_power_RU_A[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Region: Mexico */
+static chan_freq_power_t channel_freq_power_MX_A[] = {
+	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
+static chan_freq_power_t channel_freq_power_low_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
+static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}}
+};
+
+/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
+static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
+	{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}}
+};
+
+/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
+static chan_freq_power_t channel_freq_power_high_band[] = {
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
+ *  High band (5725-5850 MHz) channels
+ */
+static chan_freq_power_t channel_freq_power_low_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
+ *  mid low (5260-5320) and High band (5725-5850 MHz) channels
+ */
+static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
+	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
+	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}
+};
+
+/**
+ * The 5GHz CFP tables
+ */
+static cfp_table_t cfp_table_A[] = {
+	{0x1,			/* Low band (5150-5250 MHz) channels */
+	 channel_freq_power_low_band, NELEMENTS(channel_freq_power_low_band)},
+	{0x2,			/* Lower middle band (5250-5350 MHz) channels */
+	 channel_freq_power_lower_middle_band,
+	 NELEMENTS(channel_freq_power_lower_middle_band)},
+	{0x3,			/* Upper middle band (5470-5725 MHz) channels */
+	 channel_freq_power_upper_middle_band,
+	 NELEMENTS(channel_freq_power_upper_middle_band)},
+	{0x4,			/* High band (5725-5850 MHz) channels */
+	 channel_freq_power_high_band, NELEMENTS(channel_freq_power_high_band)},
+	{0x5,			/* Low band (5150-5250 MHz) and
+				 * High band (5725-5850 MHz) channels
+				 */
+	 channel_freq_power_low_high_band,
+	 NELEMENTS(channel_freq_power_low_high_band)},
+	{0x6,			/* Low band (5150-5250 MHz)
+				 * Mid band (5260-5320) and
+				 * High band (5725-5850 MHz) channels
+				 */
+	 channel_freq_power_low_middle_high_band,
+	 NELEMENTS(channel_freq_power_low_middle_high_band)},
+	{
+	 0x07,			/* Mexico */
+	 channel_freq_power_MX_A,
+	 NELEMENTS(channel_freq_power_MX_A),
+	 },
+
+	{
+	 0x09,			/* SPAIN/Austria/Brazil */
+	 channel_freq_power_SPN2_A,
+	 NELEMENTS(channel_freq_power_SPN2_A),
+	 },
+	{
+	 0x0c,			/* Brazil */
+	 channel_freq_power_BR1_A,
+	 NELEMENTS(channel_freq_power_BR1_A),
+	 },
+	{
+	 0x0e,			/* Brazil */
+	 channel_freq_power_BR2_A,
+	 NELEMENTS(channel_freq_power_BR2_A),
+	 },
+	{
+	 0x0f,			/* Russia */
+	 channel_freq_power_RU_A,
+	 NELEMENTS(channel_freq_power_RU_A),
+	 },
+	{
+	 0x00,			/* World */
+	 channel_freq_power_00_A,
+	 NELEMENTS(channel_freq_power_00_A),
+	 },
+	{
+	 0x10,			/* US FCC */
+	 channel_freq_power_A,
+	 NELEMENTS(channel_freq_power_A),
+	 },
+	{
+	 0x20,			/* CANADA IC */
+	 channel_freq_power_CAN_A,
+	 NELEMENTS(channel_freq_power_CAN_A),
+	 },
+	{
+	 0x30,			/* EU */
+	 channel_freq_power_EU_A,
+	 NELEMENTS(channel_freq_power_EU_A),
+	 },
+	{
+	 0x40,			/* JAPAN */
+	 channel_freq_power_JPN_A,
+	 NELEMENTS(channel_freq_power_JPN_A),
+	 },
+	{
+	 0x41,			/* JAPAN */
+	 channel_freq_power_JPN_A,
+	 NELEMENTS(channel_freq_power_JPN_A),
+	 },
+	{
+	 0x50,			/* China */
+	 channel_freq_power_CN_A,
+	 NELEMENTS(channel_freq_power_CN_A),
+	 },
+	{
+	 0xfe,			/* JAPAN */
+	 channel_freq_power_NULL_A,
+	 NELEMENTS(channel_freq_power_NULL_A),
+	 },
+	{
+	 0xff,			/* Special */
+	 channel_freq_power_JPN_A,
+	 NELEMENTS(channel_freq_power_JPN_A),
+	 },
+	/* Add new region here */
+};
+
+/** Number of the CFP tables for 5GHz */
+#define MLAN_CFP_TABLE_SIZE_A (NELEMENTS(cfp_table_A))
+
+enum {
+	RATEID_DBPSK1Mbps,	//(0)
+	RATEID_DQPSK2Mbps,	//(1)
+	RATEID_CCK5_5Mbps,	//(2)
+	RATEID_CCK11Mbps,	//(3)
+	RATEID_CCK22Mbps,	//(4)
+	RATEID_OFDM6Mbps,	//(5)
+	RATEID_OFDM9Mbps,	//(6)
+	RATEID_OFDM12Mbps,	//(7)
+	RATEID_OFDM18Mbps,	//(8)
+	RATEID_OFDM24Mbps,	//(9)
+	RATEID_OFDM36Mbps,	//(10)
+	RATEID_OFDM48Mbps,	//(11)
+	RATEID_OFDM54Mbps,	//(12)
+	RATEID_OFDM72Mbps,	//(13)
+};
+
+static const t_u8 rateUnit_500Kbps[] = {
+	(10 / 5),		/* 1Mbps */
+	(20 / 5),		/* 2Mbps */
+
+	(55 / 5),		/* 5.5Mbps */
+	(110 / 5),		/* 11Mbps */
+	(10 / 5),		/* 22Mbps, intentionally set to 1Mbps
+				 * because it's not available
+				 */
+
+	(60 / 5),		/* 6Mbps */
+	(90 / 5),		/* 9Mbps */
+	(120 / 5),		/* 12Mbps */
+	(180 / 5),		/* 18Mbps */
+	(240 / 5),		/* 24Mbps */
+	(360 / 5),		/* 36Mbps */
+	(480 / 5),		/* 48Mbps */
+	(540 / 5),		/* 54Mbps */
+	(60 / 5),		/* 72Mbps, intentionally set to 6Mbps
+				 * because it's not available
+				 */
+};
+
+typedef struct _rate_map {
+	/** Rate, in 0.5Mbps */
+	t_u32 rate;
+	/** Mrvl rate id, refer to RATEID_XXX in FW */
+	t_u32 id;
+	/** nss: 0-nss1, 1-nss2 */
+	t_u8 nss;
+} rate_map;
+
+/** If user configure to 1x1 or we found peer device only support 1x1,
+ * then we need skip the nss1 part when map to Mrvl rate.
+ */
+static const rate_map rate_map_table_2x2[] = {
+	/* LG <--> Mrvl rate idx */
+	{2, 0, 0},		// RATEID_DBPSK1Mbps
+	{4, 1, 0},		// RATEID_DQPSK2Mbps
+	{11, 2, 0},		// RATEID_CCK5_5Mbps
+	{22, 3, 0},		// RATEID_CCK11Mbps
+	{44, 4, 0},		// RATEID_CCK22Mbps
+	{12, 5, 0},		// RATEID_OFDM6Mbps
+	{18, 6, 0},		// RATEID_OFDM9Mbps
+	{24, 7, 0},		// RATEID_OFDM12Mbps
+	{36, 8, 0},		// RATEID_OFDM18Mbps
+	{48, 9, 0},		// RATEID_OFDM24Mbps
+	{72, 10, 0},		// RATEID_OFDM36Mbps
+	{96, 11, 0},		// RATEID_OFDM48Mbps
+	{108, 12, 0},		// RATEID_OFDM54Mbps
+	{144, 13, 0},		// RATEID_OFDM72Mbps
+
+	/* HT bw20 <--> Mrvl rate idx - nss2 */
+	{26, 22, 1},		// RATEID_MCS8_13Mbps
+	{52, 23, 1},		// RATEID_MCS9_26Mbps
+	{78, 24, 1},		// RATEID_MCS10_39Mbps
+	{104, 25, 1},		// RATEID_MCS11_52Mbps
+	{156, 26, 1},		// RATEID_MCS12_78Mbps
+	{208, 27, 1},		// RATEID_MCS13_104Mbps
+	{234, 28, 1},		// RATEID_MCS14_117Mbps
+	{260, 29, 1},		// RATEID_MCS15_130Mbps
+	/* HT bw20 <--> Mrvl rate idx - nss1 */
+	{13, 14, 0},		// RATEID_MCS0_6d5Mbps
+	{26, 15, 0},		// RATEID_MCS1_13Mbps
+	{39, 16, 0},		// RATEID_MCS2_19d5Mbps
+	{52, 17, 0},		// RATEID_MCS3_26Mbps
+	{78, 18, 0},		// RATEID_MCS4_39Mbps
+	{104, 19, 0},		// RATEID_MCS5_52Mbps
+	{117, 20, 0},		// RATEID_MCS6_58d5Mbps
+	{130, 21, 0},		// RATEID_MCS7_65Mbps
+
+	/* HT bw40<--> Mrvl rate idx - nss2 */
+	{54, 39, 1},		// RATEID_MCS8BW40_27Mbps
+	{108, 40, 1},		// RATEID_MCS9BW40_54Mbps
+	{162, 41, 1},		// RATEID_MCS10BW40_81Mbps
+	{216, 42, 1},		// RATEID_MCS11BW40_108Mbps
+	{324, 43, 1},		// RATEID_MCS12BW40_162Mbps
+	{432, 44, 1},		// RATEID_MCS13BW40_216Mbps
+	{486, 45, 1},		// RATEID_MCS14BW40_243Mbps
+	{540, 46, 1},		// RATEID_MCS15BW40_270Mbps
+	/* HT bw40<--> Mrvl rate idx - nss1 */
+	{12, 30, 0},		// RATEID_MCS32BW40_6Mbps
+	{27, 31, 0},		// RATEID_MCS0BW40_13d5Mbps
+	{54, 32, 0},		// RATEID_MCS1BW40_27Mbps
+	{81, 33, 0},		// RATEID_MCS2BW40_40d5Mbps
+	{108, 34, 0},		// RATEID_MCS3BW40_54Mbps
+	{162, 35, 0},		// RATEID_MCS4BW40_81Mbps
+	{216, 36, 0},		// RATEID_MCS5BW40_108Mbps
+	{243, 37, 0},		// RATEID_MCS6BW40_121d5Mbps
+	{270, 38, 0},		// RATEID_MCS7BW40_135Mbps
+
+	/* VHT bw20<--> Mrvl rate idx - nss2 */
+	{26, 57, 1},		// RATEID_VHT_MCS0_2SS_BW20   13    Mbps
+	{52, 58, 1},		// RATEID_VHT_MCS1_2SS_BW20   26    Mbps
+	{78, 59, 1},		// RATEID_VHT_MCS2_2SS_BW20   39    Mbps
+	{104, 60, 1},		// RATEID_VHT_MCS3_2SS_BW20   52    Mbps
+	{156, 61, 1},		// RATEID_VHT_MCS4_2SS_BW20   78    Mbps
+	{208, 62, 1},		// RATEID_VHT_MCS5_2SS_BW20   104   Mbps
+	{234, 63, 1},		// RATEID_VHT_MCS6_2SS_BW20   117   Mbps
+	{260, 64, 1},		// RATEID_VHT_MCS7_2SS_BW20   130   Mbps
+	{312, 65, 1},		// RATEID_VHT_MCS8_2SS_BW20   156   Mbps
+	{0, 66, 1},		// RATEID_VHT_MCS9_2SS_BW20   173.3 Mbps(INVALID)
+	/* VHT bw20<--> Mrvl rate idx - nss1 */
+	{13, 47, 0},		// RATEID_VHT_MCS0_1SS_BW20   6.5  Mbps
+	{26, 48, 0},		// RATEID_VHT_MCS1_1SS_BW20   13   Mbps
+	{39, 49, 0},		// RATEID_VHT_MCS2_1SS_BW20   19.5 Mbps
+	{52, 50, 0},		// RATEID_VHT_MCS3_1SS_BW20   26   Mbps
+	{78, 51, 0},		// RATEID_VHT_MCS4_1SS_BW20   39   Mbps
+	{104, 52, 0},		// RATEID_VHT_MCS5_1SS_BW20   52   Mbps
+	{117, 53, 0},		// RATEID_VHT_MCS6_1SS_BW20   58.5 Mbps
+	{130, 54, 0},		// RATEID_VHT_MCS7_1SS_BW20   65   Mbps
+	{156, 55, 0},		// RATEID_VHT_MCS8_1SS_BW20   78   Mbps
+	{0, 56, 0},		// RATEID_VHT_MCS9_1SS_BW20   86.7 Mbps(INVALID)
+
+	/* VHT bw40<--> Mrvl rate idx - nss2 */
+	{54, 77, 1},		// RATEID_VHT_MCS0_2SS_BW40   27  Mbps
+	{108, 78, 1},		// RATEID_VHT_MCS1_2SS_BW40   54  Mbps
+	{162, 79, 1},		// RATEID_VHT_MCS2_2SS_BW40   81  Mbps
+	{216, 80, 1},		// RATEID_VHT_MCS3_2SS_BW40   108 Mbps
+	{324, 81, 1},		// RATEID_VHT_MCS4_2SS_BW40   162 Mbps
+	{432, 82, 1},		// RATEID_VHT_MCS5_2SS_BW40   216 Mbps
+	{486, 83, 1},		// RATEID_VHT_MCS6_2SS_BW40   243 Mbps
+	{540, 84, 1},		// RATEID_VHT_MCS7_2SS_BW40   270 Mbps
+	{648, 85, 1},		// RATEID_VHT_MCS8_2SS_BW40   324 Mbps
+	{720, 86, 1},		// RATEID_VHT_MCS9_2SS_BW40   360 Mbps
+	/* VHT bw40<--> Mrvl rate idx - nss1 */
+	{27, 67, 0},		// RATEID_VHT_MCS0_1SS_BW40   13.5  Mbps
+	{54, 68, 0},		// RATEID_VHT_MCS1_1SS_BW40   27    Mbps
+	{81, 69, 0},		// RATEID_VHT_MCS2_1SS_BW40   40.5  Mbps
+	{108, 70, 0},		// RATEID_VHT_MCS3_1SS_BW40   54    Mbps
+	{162, 71, 0},		// RATEID_VHT_MCS4_1SS_BW40   81    Mbps
+	{216, 72, 0},		// RATEID_VHT_MCS5_1SS_BW40   108   Mbps
+	{243, 73, 0},		// RATEID_VHT_MCS6_1SS_BW40   121.5 Mbps
+	{270, 74, 0},		// RATEID_VHT_MCS7_1SS_BW40   135   Mbps
+	{324, 75, 0},		// RATEID_VHT_MCS8_1SS_BW40   162   Mbps
+	{360, 76, 0},		// RATEID_VHT_MCS9_1SS_BW40   180   Mbps
+
+	/* VHT bw80<--> Mrvl rate idx - nss2 */
+	{117, 97, 1},		// RATEID_VHT_MCS0_2SS_BW80   58.5  Mbps
+	{234, 98, 1},		// RATEID_VHT_MCS1_2SS_BW80   117   Mbps
+	{350, 99, 1},		// RATEID_VHT_MCS2_2SS_BW80   175   Mbps
+	{468, 100, 1},		// RATEID_VHT_MCS3_2SS_BW80   234   Mbps
+	{702, 101, 1},		// RATEID_VHT_MCS4_2SS_BW80   351   Mbps
+	{936, 102, 1},		// RATEID_VHT_MCS5_2SS_BW80   468   Mbps
+	{1053, 103, 1},		// RATEID_VHT_MCS6_2SS_BW80   526.5 Mbps
+	{1170, 104, 1},		// RATEID_VHT_MCS7_2SS_BW80   585   Mbps
+	{1404, 105, 1},		// RATEID_VHT_MCS8_2SS_BW80   702   Mbps
+	{1560, 106, 1},		// RATEID_VHT_MCS9_2SS_BW80   780   Mbps
+	/* VHT bw80<--> Mrvl rate idx - nss1 */
+	{58, 87, 0},		// RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could
+	// correspond to 58
+	{59, 87, 0},		// RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3*2 could
+	// correspond to 59 too
+	{117, 88, 0},		// RATEID_VHT_MCS1_1SS_BW80   58.5  Mbps
+	{175, 89, 0},		// RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
+	// correspond to 175
+	{176, 89, 0},		// RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
+	// correspond to 176 too
+	{234, 90, 0},		// RATEID_VHT_MCS3_1SS_BW80   117   Mbps
+	{351, 91, 0},		// RATEID_VHT_MCS4_1SS_BW80   175.5 Mbps
+	{468, 92, 0},		// RATEID_VHT_MCS5_1SS_BW80   234   Mbps
+	{526, 93, 0},		// RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
+	// correspond to 526
+	{527, 93, 0},		// RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
+	// correspond to 527 too
+	{585, 94, 0},		// RATEID_VHT_MCS7_1SS_BW80   292.5 Mbps
+	{702, 95, 0},		// RATEID_VHT_MCS8_1SS_BW80   351   Mbps
+	{780, 96, 0},		// RATEID_VHT_MCS9_1SS_BW80   390   Mbps
+};
+
+/** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
+ * For the chip who only support 1x1, Mrvl rate idx define is different with 2x2
+ * in FW We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
+ */
+static const rate_map rate_map_table_1x1[] = {
+	/* LG <--> Mrvl rate idx */
+	{2, 0, 0},		// RATEID_DBPSK1Mbps
+	{4, 1, 0},		// RATEID_DQPSK2Mbps
+	{11, 2, 0},		// RATEID_CCK5_5Mbps
+	{22, 3, 0},		// RATEID_CCK11Mbps
+	{44, 4, 0},		// RATEID_CCK22Mbps
+	{12, 5, 0},		// RATEID_OFDM6Mbps
+	{18, 6, 0},		// RATEID_OFDM9Mbps
+	{24, 7, 0},		// RATEID_OFDM12Mbps
+	{36, 8, 0},		// RATEID_OFDM18Mbps
+	{48, 9, 0},		// RATEID_OFDM24Mbps
+	{72, 10, 0},		// RATEID_OFDM36Mbps
+	{96, 11, 0},		// RATEID_OFDM48Mbps
+	{108, 12, 0},		// RATEID_OFDM54Mbps
+	{144, 13, 0},		// RATEID_OFDM72Mbps
+
+	/* HT bw20 <--> Mrvl rate idx */
+	{13, 14, 0},		// RATEID_MCS0_6d5Mbps
+	{26, 15, 0},		// RATEID_MCS1_13Mbps
+	{39, 16, 0},		// RATEID_MCS2_19d5Mbps
+	{52, 17, 0},		// RATEID_MCS3_26Mbps
+	{78, 18, 0},		// RATEID_MCS4_39Mbps
+	{104, 19, 0},		// RATEID_MCS5_52Mbps
+	{117, 20, 0},		// RATEID_MCS6_58d5Mbps
+	{130, 21, 0},		// RATEID_MCS7_65Mbps
+
+	/* HT bw40<--> Mrvl rate idx */
+	{12, 22, 0},		// RATEID_MCS32BW40_6Mbps,   for 1x1 start from 22
+	{27, 23, 0},		// RATEID_MCS0BW40_13d5Mbps
+	{54, 24, 0},		// RATEID_MCS1BW40_27Mbps
+	{81, 25, 0},		// RATEID_MCS2BW40_40d5Mbps
+	{108, 26, 0},		// RATEID_MCS3BW40_54Mbps
+	{162, 27, 0},		// RATEID_MCS4BW40_81Mbps
+	{216, 28, 0},		// RATEID_MCS5BW40_108Mbps
+	{243, 29, 0},		// RATEID_MCS6BW40_121d5Mbps
+	{270, 30, 0},		// RATEID_MCS7BW40_135Mbps
+
+	/* VHT bw20<--> Mrvl rate idx */
+	{13, 31, 0},		// RATEID_VHT_MCS0_1SS_BW20   6.5  Mbps
+	{26, 32, 0},		// RATEID_VHT_MCS1_1SS_BW20   13   Mbps
+	{39, 33, 0},		// RATEID_VHT_MCS2_1SS_BW20   19.5 Mbps
+	{52, 34, 0},		// RATEID_VHT_MCS3_1SS_BW20   26   Mbps
+	{78, 35, 0},		// RATEID_VHT_MCS4_1SS_BW20   39   Mbps
+	{104, 36, 0},		// RATEID_VHT_MCS5_1SS_BW20   52   Mbps
+	{117, 37, 0},		// RATEID_VHT_MCS6_1SS_BW20   58.5 Mbps
+	{130, 38, 0},		// RATEID_VHT_MCS7_1SS_BW20   65   Mbps
+	{156, 39, 0},		// RATEID_VHT_MCS8_1SS_BW20   78   Mbps
+	{0, 40, 0},		// RATEID_VHT_MCS9_1SS_BW20   86.7 Mbps(INVALID)
+
+	/* VHT bw40<--> Mrvl rate idx */
+	{27, 41, 0},		// RATEID_VHT_MCS0_1SS_BW40   13.5  Mbps
+	{54, 42, 0},		// RATEID_VHT_MCS1_1SS_BW40   27    Mbps
+	{81, 43, 0},		// RATEID_VHT_MCS2_1SS_BW40   40.5  Mbps
+	{108, 44, 0},		// RATEID_VHT_MCS3_1SS_BW40   54    Mbps
+	{162, 45, 0},		// RATEID_VHT_MCS4_1SS_BW40   81    Mbps
+	{216, 46, 0},		// RATEID_VHT_MCS5_1SS_BW40   108   Mbps
+	{243, 47, 0},		// RATEID_VHT_MCS6_1SS_BW40   121.5 Mbps
+	{270, 48, 0},		// RATEID_VHT_MCS7_1SS_BW40   135   Mbps
+	{324, 49, 0},		// RATEID_VHT_MCS8_1SS_BW40   162   Mbps
+	{360, 50, 0},		// RATEID_VHT_MCS9_1SS_BW40   180   Mbps
+
+	/* VHT bw80<--> Mrvl rate idx */
+	{58, 51, 0},		// RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could
+	// correspond to 58
+	{59, 51, 0},		// RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could
+	// correspond to 59 too
+	{117, 52, 0},		// RATEID_VHT_MCS1_1SS_BW80   58.5  Mbps
+	{175, 53, 0},		// RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
+	// correspond to 175
+	{176, 53, 0},		// RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
+	// correspond to 176 too
+	{234, 54, 0},		// RATEID_VHT_MCS3_1SS_BW80   117   Mbps
+	{351, 55, 0},		// RATEID_VHT_MCS4_1SS_BW80   175.5 Mbps
+	{468, 56, 0},		// RATEID_VHT_MCS5_1SS_BW80   234   Mbps
+	{526, 57, 0},		// RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
+	// correspond to 526
+	{527, 57, 0},		// RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
+	// correspond to 527 too
+	{585, 58, 0},		// RATEID_VHT_MCS7_1SS_BW80   292.5 Mbps
+	{702, 59, 0},		// RATEID_VHT_MCS8_1SS_BW80   351   Mbps
+	{780, 60, 0},		// RATEID_VHT_MCS9_1SS_BW80   390   Mbps
+};
+
+/********************************************************
+ *			Global Variables
+ ********************************************************/
+/**
+ * The table to keep region code
+ */
+
+t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] =
+	{ 0x00, 0x10, 0x20, 0x30, 0x40,
+	0x41, 0x50, 0xfe, 0xff
+};
+
+/** The table to keep CFP code for BG */
+t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { };
+
+/** The table to keep CFP code for A */
+t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
+
+/**
+ * The rates supported for ad-hoc B mode
+ */
+t_u8 AdhocRates_B[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
+
+/**
+ * The rates supported for ad-hoc G mode
+ */
+t_u8 AdhocRates_G[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, 0xb0,
+	0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported for ad-hoc BG mode
+ */
+t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0x0c,
+	0x12, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode for ad-hoc
+ */
+t_u8 AdhocRates_A[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, 0xb0,
+	0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in A mode (used for BAND_A)
+ */
+t_u8 SupportedRates_A[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, 0xb0,
+	0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported by the card
+ */
+static t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
+	0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6C, 0x90, 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82,
+	0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00
+};
+
+/**
+ * The rates supported in B mode
+ */
+t_u8 SupportedRates_B[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0x00 };
+
+/**
+ * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_G[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, 0x30,
+	0x48, 0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
+ */
+t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c, 0x12,
+	0x16, 0x18, 0x24, 0x30, 0x48,
+	0x60, 0x6c, 0x00
+};
+
+/**
+ * The rates supported in N mode
+ */
+t_u8 SupportedRates_N[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+
+#define MCS_NUM_AX 12
+// for MCS0/MCS1/MCS3/MCS4 have 4 additional DCM=1 value
+// note: the value in the table is 2 multiplier of the actual rate
+static t_u16 ax_mcs_rate_nss1[12][MCS_NUM_AX + 4] = {
+	{0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
+	 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962},	/*SG 160M */
+	{0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
+	 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC},	/*MG 160M */
+	{0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
+	 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9},	/*LG 160M */
+	{0x48, 0x24, 0x90, 0x48, 0xD8, 0x120, 0x90, 0x1B0, 0xD8, 0x240, 0x288,
+	 0x2D0, 0x360, 0x3C0, 0x438, 0x4B0},	/*SG 80M */
+	{0x44, 0x22, 0x88, 0x44, 0xCC, 0x110, 0x88, 0x198, 0xCC, 0x220, 0x264,
+	 0x2A8, 0x330, 0x38B, 0x3FC, 0x46E},	/*MG 80M */
+	{0x3D, 0x1E, 0x7A, 0x3D, 0xB7, 0xF5, 0x7A, 0x16F, 0xB7, 0x1EA, 0x227,
+	 0x264, 0x2DF, 0x330, 0x396, 0x3FC},	/*LG 80M */
+	{0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
+	 0x158, 0x19D, 0x1CA, 0x204, 0x23D},	/*SG 40M */
+	{0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
+	 0x145, 0x186, 0x1B1, 0x1E7, 0x21D},	/*MG 40M */
+	{0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
+	 0x124, 0x15F, 0x186, 0x1B6, 0x1E7},	/*LG 40M */
+	{0x11, 0x8, 0x22, 0x11, 0x33, 0x44, 0x22, 0x67, 0x33, 0x89, 0x9A, 0xAC,
+	 0xCE, 0xE5, 0x102, 0x11E},	/*SG 20M */
+	{0x10, 0x8, 0x20, 0x10, 0x30, 0x41, 0x20, 0x61, 0x30, 0x82, 0x92, 0xA2,
+	 0xC3, 0xD8, 0xF3, 0x10E},	/*MG 20M */
+	{0xE, 0x7, 0x1D, 0xE, 0x2B, 0x3A, 0x1D, 0x57, 0x2B, 0x75, 0x83, 0x92,
+	 0xAF, 0xC3, 0xDB, 0xF3}	/*LG 20M */
+};
+
+#if 0
+// note: the value in the table is 2 multiplier of the actual rate
+t_u16 ax_tone_ru_rate_nss1[9][MCS_NUM_AX + 4] = {
+	{0x8, 0x4, 0xF, 0x8, 0x17, 0x1E, 0xF, 0x2D, 0x17, 0x3C, 0x44, 0x4B,
+	 0x5A, 0x64, 0x71, 0x7D},	/*SG 106-tone */
+	{0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2B, 0x16, 0x39, 0x40, 0x47,
+	 0x55, 0x5F, 0x6B, 0x76},	/*MG 106-tone */
+	{0x7, 0x3, 0xD, 0x6, 0x14, 0x1A, 0xD, 0x27, 0x14, 0x33, 0x3A, 0x40,
+	 0x4D, 0x55, 0x60, 0x6B},	/*LG 106-tone */
+	{0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
+	 0x2F, 0x35, 0x3B},	/*SG 52-tone */
+	{0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
+	 0x2D, 0x32, 0x38},	/*MG 52-tone */
+	{0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
+	 0x28, 0x2D, 0x32},	/*LG 52-tone */
+	{0x2, 0x1, 0x4, 0x2, 0x6, 0x7, 0x4, 0xB, 0x5, 0xE, 0x10, 0x12, 0x15,
+	 0x18, 0x1A, 0x1D},	/*SG 26-tone */
+	{0x2, 0x1, 0x4, 0x2, 0x5, 0x6, 0x4, 0xA, 0x5, 0xD, 0xF, 0x11, 0x14,
+	 0x16, 0x19, 0x1C},	/*MG 26-tone */
+	{0x2, 0x1, 0x3, 0x2, 0x5, 0x6, 0x3, 0x9, 0x4, 0xC, 0xE, 0xF, 0x12, 0x14,
+	 0x17, 0x19}		/*LG 26-tone */
+};
+#endif
+
+// note: the value in the table is 2 multiplier of the actual rate
+static t_u16 ax_mcs_rate_nss2[12][MCS_NUM_AX + 4] = {
+	{0x120, 0x90, 0x240, 0x120, 0x360, 0x481, 0x240, 0x61C, 0x360, 0x901,
+	 0xA22, 0xB42, 0xD82, 0xF03, 0x10E3, 0x12C3},	/*SG 160M */
+	{0x110, 0x88, 0x220, 0x110, 0x330, 0x440, 0x220, 0x661, 0x330, 0x881,
+	 0x992, 0xAA2, 0xCAC, 0xE2D, 0xFF3, 0x11B9},	/*MG 160M */
+	{0xF5, 0x7A, 0x1EA, 0xF5, 0x2DF, 0x3D4, 0x1EA, 0x5BE, 0x2DF, 0x7A8,
+	 0x1134, 0x992, 0xB7C, 0xCC2, 0xE5B, 0xFF3},	/*LG 160M */
+	{0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
+	 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962},	/*SG 80M */
+	{0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
+	 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC},	/*MG 80M */
+	{0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
+	 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9},	/*LG 80M */
+	{0x44, 0x22, 0x89, 0x44, 0xCE, 0x113, 0x89, 0x19D, 0xCE, 0x226, 0x26B,
+	 0x2B0, 0x339, 0x395, 0x408, 0x47B},	/*SG 40M */
+	{0x41, 0x20, 0x82, 0x41, 0xC3, 0x104, 0x82, 0x186, 0xC3, 0x208, 0x249,
+	 0x28A, 0x30C, 0x362, 0x3CE, 0x43B},	/*MG 40M */
+	{0x3A, 0x1D, 0x75, 0x3A, 0xAF, 0xEA, 0x75, 0x15F, 0xAF, 0x1D4, 0x20E,
+	 0x249, 0x2BE, 0x30C, 0x36D, 0x3CF},	/*LG 40M */
+	{0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
+	 0x158, 0x19D, 0x1CA, 0x204, 0x23D},	/*SG 20M */
+	{0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
+	 0x145, 0x186, 0x1B1, 0x1E7, 0x21D},	/*MG 20M */
+	{0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
+	 0x124, 0x15F, 0x186, 0x1B6, 0x1E7}	/*LG 20M */
+};
+
+#if 0
+// note: the value in the table is 2 multiplier of the actual rate
+t_u16 ax_tone_ru_rate_nss2[9][MCS_NUM_AX + 4] = {
+	{0xF, 0x8, 0x1E, 0xF, 0x2D, 0x3C, 0x1E, 0x5A, 0x2D, 0x78, 0x87, 0x96,
+	 0xB4, 0xC8, 0xE1, 0xFA},	/*SG 106-tone */
+	{0xE, 0x7, 0x1D, 0xE, 0x2B, 0x39, 0x1D, 0x55, 0x2B, 0x72, 0x80, 0x8E,
+	 0xAA, 0xBD, 0xD5, 0xED},	/*MG 106-tone */
+	{0xD, 0x7, 0x1A, 0xD, 0x27, 0x33, 0x1A, 0x4D, 0x27, 0x66, 0x73, 0x80,
+	 0x99, 0xAA, 0xC0, 0xD5},	/*LG 106-tone */
+	{0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2A, 0x16, 0x39, 0x40, 0x47,
+	 0x55, 0x5F, 0x6A, 0x76},	/*SG 52-tone */
+	{0x7, 0x4, 0xE, 0x7, 0x14, 0x1B, 0xE, 0x28, 0x14, 0x36, 0x3C, 0x43,
+	 0x50, 0x59, 0x64, 0x70},	/*MG 52-tone */
+	{0x6, 0x3, 0xC, 0x6, 0x12, 0x18, 0xC, 0x24, 0x12, 0x30, 0x36, 0x3C,
+	 0x48, 0x50, 0x5A, 0x64},	/*LG 52-tone */
+	{0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
+	 0x2F, 0x35, 0x3B},	/*SG 26-tone */
+	{0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
+	 0x2D, 0x32, 0x38},	/*MG 26-tone */
+	{0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
+	 0x28, 0x2D, 0x32}	/*LG 26-tone */
+};
+#endif
+
+/********************************************************
+ *			Local Functions
+ ********************************************************/
+/**
+ *  @brief Find a character in a string.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s            A pointer to string
+ *  @param c            Character to be located
+ *  @param n            The length of string
+ *
+ *  @return        A pointer to the first occurrence of c in string, or MNULL if
+ * c is not found.
+ */
+static void *
+wlan_memchr(pmlan_adapter pmadapter, void *s, int c, int n)
+{
+	const t_u8 *p = (t_u8 *)s;
+
+	ENTER();
+
+	while (n--) {
+		if ((t_u8)c == *p++) {
+			LEAVE();
+			return (void *)(p - 1);
+		}
+	}
+
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function finds the CFP in
+ *          cfp_table_BG/A based on region/code and band parameter.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param region     The region code
+ *  @param band       The band
+ *  @param cfp_no     A pointer to CFP number
+ *
+ *  @return           A pointer to CFP
+ */
+static chan_freq_power_t *
+wlan_get_region_cfp_table(pmlan_adapter pmadapter,
+			  t_u8 region, t_u8 band, int *cfp_no)
+{
+	t_u32 i;
+	t_u8 cfp_bg, cfp_a;
+
+	ENTER();
+
+	cfp_bg = cfp_a = region;
+	if (!region) {
+		/* Invalid region code, use CFP code */
+		cfp_bg = pmadapter->cfp_code_bg;
+		cfp_a = pmadapter->cfp_code_a;
+	}
+
+	if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+		/* Return the FW cfp table for requested region code, if
+		 * available. If region is not forced and the requested region
+		 * code is different, simply return the corresponding
+		 * pre-defined table.
+		 */
+		if (pmadapter->otp_region && pmadapter->cfp_otp_bg) {
+			if (pmadapter->otp_region->force_reg ||
+			    (cfp_bg ==
+			     (t_u8)pmadapter->otp_region->region_code)) {
+				*cfp_no = pmadapter->tx_power_table_bg_rows;
+				LEAVE();
+				return pmadapter->cfp_otp_bg;
+			}
+		}
+		for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+			PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i,
+			       cfp_table_BG[i].code);
+			/* Check if region/code matches for BG bands */
+			if (cfp_table_BG[i].code == cfp_bg) {
+				/* Select by band */
+				*cfp_no = cfp_table_BG[i].cfp_no;
+				LEAVE();
+				return cfp_table_BG[i].cfp;
+			}
+		}
+	}
+	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		/* Return the FW cfp table for requested region code */
+		if (pmadapter->otp_region && pmadapter->cfp_otp_a) {
+			if (pmadapter->otp_region->force_reg ||
+			    (cfp_a ==
+			     (t_u8)pmadapter->otp_region->region_code)) {
+				*cfp_no = pmadapter->tx_power_table_a_rows;
+				LEAVE();
+				return pmadapter->cfp_otp_a;
+			}
+		}
+		for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+			PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i,
+			       cfp_table_A[i].code);
+			/* Check if region/code matches for A bands */
+			if (cfp_table_A[i].code == cfp_a) {
+				/* Select by band */
+				*cfp_no = cfp_table_A[i].cfp_no;
+				LEAVE();
+				return cfp_table_A[i].cfp;
+			}
+		}
+	}
+
+	if (!region)
+		PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n",
+		       band, cfp_bg, cfp_a);
+	else
+		PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band,
+		       region);
+
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function copies dynamic CFP elements from one table to another.
+ *         Only copy elements where channel numbers match.
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param cfp         Destination table
+ *  @param num_cfp     Number of elements in dest table
+ *  @param cfp_src     Source table
+ *  @param num_cfp_src Number of elements in source table
+ */
+static t_void
+wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,
+		      chan_freq_power_t *cfp, t_u8 num_cfp,
+		      chan_freq_power_t *cfp_src, t_u8 num_cfp_src)
+{
+	int i, j;
+
+	ENTER();
+
+	if (cfp == cfp_src) {
+		LEAVE();
+		return;
+	}
+
+	/* first clear dest dynamic blacklisted entries */
+	/* do not clear the flags */
+	for (i = 0; i < num_cfp; i++) {
+		cfp[i].dynamic.blacklist = MFALSE;
+	}
+
+	/* copy dynamic blacklisted entries from source where channels match */
+	if (cfp_src) {
+		for (i = 0; i < num_cfp; i++)
+			for (j = 0; j < num_cfp_src; j++)
+				if (cfp[i].channel == cfp_src[j].channel) {
+					cfp[i].dynamic.blacklist =
+						cfp_src[j].dynamic.blacklist;
+					break;
+				}
+	}
+
+	LEAVE();
+}
+
+/********************************************************
+ *			Global Functions
+ ********************************************************/
+/**
+ *  @brief This function converts region string to integer code
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param country_code     Country string
+ *  @param cfp_bg           Pointer to buffer
+ *  @param cfp_a            Pointer to buffer
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,
+				   t_u8 *country_code, t_u8 *cfp_bg,
+				   t_u8 *cfp_a)
+{
+	t_u8 i;
+
+	ENTER();
+
+	if (pmadapter->otp_region) {
+		if (!memcmp(pmadapter, pmadapter->otp_region->country_code,
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			if (pmadapter->cfp_otp_bg)
+				*cfp_bg = pmadapter->otp_region->region_code;
+			if (pmadapter->cfp_otp_a)
+				*cfp_a = pmadapter->otp_region->region_code;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+	/* Look for code in mapping table */
+	for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
+		if (!memcmp(pmadapter, country_code_mapping[i].country_code,
+			    country_code, COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = country_code_mapping[i].cfp_code_bg;
+			*cfp_a = country_code_mapping[i].cfp_code_a;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	/* If still not found, look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
+			    COUNTRY_CODE_LEN - 1)) {
+			*cfp_bg = EU_CFP_CODE_BG;
+			*cfp_a = EU_CFP_CODE_A;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function finds if given country code is in EU table
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param country_code     Country string
+ *
+ *  @return                 MTRUE or MFALSE
+ */
+t_bool
+wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
+{
+	t_u8 i;
+
+	ENTER();
+
+	/* Look for code in EU country code table */
+	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
+		if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
+			    COUNTRY_CODE_LEN - 1)) {
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *   @brief This function adjust the antenna index
+ *
+ *   V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
+ *   8887: case1: 0 - 2.4G ant A,  1- 2.4G antB, 2-- 5G ant C
+ *   case2: 0 - 2.4G ant A,  1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
+ *   @param priv	A pointer to mlan_private structure
+ *   @param prx_pd	A pointer to the RxPD structure
+ *
+ *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+t_u8
+wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
+{
+	t_u8 antenna = prx_pd->antenna;
+#if defined(SD8887) || defined(SD8987)
+	t_u32 rx_channel = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+#endif
+	if (prx_pd->antenna == 0xff)
+		return 0;
+	if (priv->adapter->pcard_info->v16_fw_api) {
+		if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
+			antenna = 2;
+		else if (antenna & MBIT(1))
+			antenna = 1;
+		else if (antenna & MBIT(0))
+			antenna = 0;
+	}
+#if defined(SD8887) || defined(SD8987)
+#define ANTENNA_OFFSET 2
+	if (MFALSE
+#ifdef SD8887
+	    || IS_SD8887(priv->adapter->card_type)
+#endif
+#ifdef SD8987
+	    || IS_SD8987(priv->adapter->card_type)
+#endif
+		) {
+		if ((priv->adapter->antinfo & ANT_DIVERSITY_2G) &&
+		    (priv->adapter->antinfo & ANT_DIVERSITY_5G)) {
+#define MAX_2G_CHAN 14
+			if (rx_channel > MAX_2G_CHAN)
+				antenna += ANTENNA_OFFSET;
+		}
+	}
+#endif
+
+	return antenna;
+}
+
+/**
+ *  @brief This function adjust the rate index
+ *
+ *  @param priv    A pointer to mlan_private structure
+ *  @param rx_rate rx rate
+ *  @param rate_info rate info
+ *  @return        rate index
+ */
+t_u16
+wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
+{
+	t_u16 rate_index = 0;
+	t_u8 bw = 0;
+	t_u8 nss = 0;
+	t_bool sgi_enable = 0;
+	t_u8 gi = 0;
+#define MAX_MCS_NUM_AX 12
+
+#define MAX_MCS_NUM_SUPP 16
+#define MAX_MCS_NUM_AC 10
+#define RATE_INDEX_MCS0 12
+	bw = (rate_info & 0xC) >> 2;
+	sgi_enable = (rate_info & 0x10) >> 4;
+	if ((rate_info & 0x3) == 0) {
+		rate_index = (rx_rate > MLAN_RATE_INDEX_OFDM0) ? rx_rate - 1 :
+			rx_rate;
+	} else if ((rate_info & 0x03) == 1) {
+		rate_index = RATE_INDEX_MCS0 +
+			MAX_MCS_NUM_SUPP * 2 * sgi_enable +
+			MAX_MCS_NUM_SUPP * bw + rx_rate;
+	} else if ((rate_info & 0x3) == 2) {
+		if (IS_STREAM_2X2(priv->adapter->feature_control))
+			nss = rx_rate >> 4;	// 0:NSS1, 1:NSS2
+		rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
+			MAX_MCS_NUM_AC * 6 * sgi_enable +
+			MAX_MCS_NUM_AC * 2 * bw + MAX_MCS_NUM_AC * nss +
+			(rx_rate & 0x0f);
+	} else if ((rate_info & 0x3) == 3) {
+		gi = (rate_info & 0x10) >> 4 | (rate_info & 0x80) >> 6;
+		if (IS_STREAM_2X2(priv->adapter->feature_control))
+			nss = rx_rate >> 4;	// 0:NSS1, 1:NSS2
+		rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
+			MAX_MCS_NUM_AC * 12 + MAX_MCS_NUM_AX * 6 * gi +
+			MAX_MCS_NUM_AX * 2 * bw + MAX_MCS_NUM_AX * nss +
+			(rx_rate & 0x0f);
+	}
+	return rate_index;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief convert TX rate_info from v14 to v15+ FW rate_info
+ *
+ *  @param v14_rate_info      v14 rate info
+ *
+ *  @return             v15+ rate info
+ */
+t_u8
+wlan_convert_v14_tx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info)
+{
+	t_u8 rate_info = 0;
+
+	if (!pmpriv->adapter->pcard_info->v14_fw_api) {
+		PRINTM(MERROR, "%s: Not convert for this is not V14 FW\n",
+		       __func__);
+		return v14_rate_info;
+	}
+
+	rate_info = v14_rate_info & 0x01;
+	/* band */
+	rate_info |= (v14_rate_info & MBIT(1)) << 1;
+	/* short GI */
+	rate_info |= (v14_rate_info & MBIT(2)) << 2;
+	return rate_info;
+}
+
+/**
+ *  @brief convert RX rate_info from v14 to v15+ FW rate_info
+ *
+ *  @param v14_rate_info      v14 rate info
+ *
+ *  @return             v15+ rate info
+ */
+t_u8
+wlan_convert_v14_rx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info)
+{
+	t_u8 rate_info = 0;
+	t_u8 mode = 0;
+	t_u8 bw = 0;
+	t_u8 sgi = 0;
+
+	if (!pmpriv->adapter->pcard_info->v14_fw_api) {
+		PRINTM(MERROR, "%s: Not convert for this is not V14 FW\n",
+		       __func__);
+		return v14_rate_info;
+	}
+
+	mode = v14_rate_info & MBIT(0);
+	bw = v14_rate_info & MBIT(1);
+	sgi = (v14_rate_info & 0x04) >> 2;
+
+	rate_info = (mode & 0x01) | ((bw & 0x01) << 2) | ((sgi & 0x01) << 4);
+
+	return rate_info;
+}
+
+/**
+ *  @brief Use index to get the data rate
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param index            The index of data rate
+ *  @param tx_rate_info     Tx rate info
+ *  @param ext_rate_info    Extend tx rate info
+ *
+ *  @return                 Data rate or 0
+ */
+t_u32
+wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+			t_u8 tx_rate_info, t_u8 ext_rate_info)
+{
+#define MCS_NUM_SUPP 16
+	t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
+		{0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c,
+		 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c},	/*LG 40M */
+		{0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78,
+		 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258},	/*SG 40M */
+		{0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34,
+		 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104},	/*LG 20M */
+		{0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39,
+		 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}
+	};			/*SG 20M */
+
+#define MCS_NUM_AC 10
+	/* NSS 1. note: the value in the table is 2 multiplier of the actual
+	 * rate in other words, it is in the unit of 500 Kbs
+	 */
+	t_u16 ac_mcs_rate_nss1[8][MCS_NUM_AC] = {
+		{0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
+		 0x618},	/* LG 160M */
+		{0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
+		 0x6C6},	/* SG 160M */
+		{0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 0x249, 0x2BE,
+		 0x30C},	/* LG 80M */
+		{0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 0x28A, 0x30C,
+		 0x363},	/* SG 80M */
+		{0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x144,
+		 0x168},	/* LG 40M */
+		{0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 0x12C, 0x168,
+		 0x190},	/* SG 40M */
+		{0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C,
+		 0x00},		/* LG 20M */
+		{0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE,
+		 0x00},		/* SG 20M */
+	};
+	/* NSS 2. note: the value in the table is 2 multiplier of the actual
+	 * rate
+	 */
+	t_u16 ac_mcs_rate_nss2[8][MCS_NUM_AC] = {
+		{0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 0x924, 0xAF8,
+		 0xC30},	/*LG 160M */
+		{0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 0xA28, 0xC30,
+		 0xD8B},	/*SG 160M */
+
+		{0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
+		 0x618},	/*LG 80M */
+		{0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
+		 0x6C6},	/*SG 80M */
+		{0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 0x21C, 0x288,
+		 0x2D0},	/*LG 40M */
+		{0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 0x258, 0x2D0,
+		 0x320},	/*SG 40M */
+		{0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 0x138,
+		 0x00},		/*LG 20M */
+		{0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 0x15B,
+		 0x00},		/*SG 20M */
+	};
+
+	t_u32 rate = 0;
+	t_u8 mcs_index = 0;
+	t_u8 he_dcm = 0;
+//      t_u8 he_tone = 0;
+	t_u8 stbc = 0;
+
+	t_u8 bw = 0;
+	t_u8 gi = 0;
+
+	ENTER();
+
+	PRINTM(MINFO, "%s:index=%d, tx_rate_info=%d, ext_rate_info=%d\n",
+	       __func__, index, tx_rate_info, ext_rate_info);
+
+	if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
+		/* VHT rate */
+		mcs_index = index & 0xF;
+
+		if (mcs_index > 9)
+			mcs_index = 9;
+
+		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+		bw = (tx_rate_info & 0xC) >> 2;
+		/* LGI: gi =0, SGI: gi = 1 */
+		gi = (tx_rate_info & 0x10) >> 4;
+		if ((index >> 4) == 1) {
+			/* NSS = 2 */
+			rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
+		} else
+			/* NSS = 1 */
+			rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
+	} else
+	 if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE) {
+		/* VHT rate */
+		mcs_index = index & 0xF;
+		he_dcm = ext_rate_info & MBIT(0);
+
+		if (mcs_index > MCS_NUM_AX - 1)
+			mcs_index = MCS_NUM_AX - 1;
+
+		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
+		bw = (tx_rate_info & (MBIT(3) | MBIT(2))) >> 2;
+		/* BIT7:BIT4 0:0= 0.8us,0:1= 0.8us, 1:0=1.6us, 1:1=3.2us or
+		 * 0.8us
+		 */
+		gi = (tx_rate_info & MBIT(4)) >> 4 |
+			(tx_rate_info & MBIT(7)) >> 6;
+		/* STBC: BIT5 in tx rate info */
+		stbc = (tx_rate_info & MBIT(5)) >> 5;
+
+		if (gi > 3) {
+			PRINTM(MERROR, "Invalid gi value");
+			return 0;
+		}
+
+		if ((gi == 3) && stbc && he_dcm) {
+			gi = 0;
+			stbc = 0;
+			he_dcm = 0;
+		}
+		/* map to gi 0:0.8us,1:1.6us 2:3.2us */
+		if (gi > 0)
+			gi = gi - 1;
+
+//#ifdef ENABLE_802_11AX
+		// TODO: hardcode he_tone here, wait for FW value ready.
+//              he_tone = 4;
+
+		//he_tone = (ext_rate_info & 0xE) >> 1;
+//#endif
+
+		if ((index >> 4) == 1) {
+			switch (mcs_index) {
+			case 0:
+			case 1:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2 + he_dcm];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+					[mcs_index * 2 + he_dcm];
+				break;
+			case 2:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+					[mcs_index * 2];
+				break;
+			case 3:
+			case 4:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2 - 1 + he_dcm];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+					[mcs_index * 2 - 1 + he_dcm];
+				break;
+
+			default:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index + 4];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
+					[mcs_index + 4];
+				break;
+			}
+		} else {
+			switch (mcs_index) {
+			case 0:
+			case 1:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2 + he_dcm];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+					[mcs_index * 2 + he_dcm];
+				break;
+			case 2:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+					[mcs_index * 2];
+				break;
+			case 3:
+			case 4:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2 - 1 + he_dcm];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+					[mcs_index * 2 - 1 + he_dcm];
+				break;
+
+			default:
+// #if 0
+// if (he_tone < 3) {
+//      rate = ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index + 4];
+// } else {
+// #endif
+				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
+					[mcs_index + 4];
+				break;
+			}
+		}
+	} else if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
+		/* HT rate */
+		/* 20M: bw=0, 40M: bw=1 */
+		bw = (tx_rate_info & 0xC) >> 2;
+		/* LGI: gi =0, SGI: gi = 1 */
+		gi = (tx_rate_info & 0x10) >> 4;
+		if (index == MLAN_RATE_BITMAP_MCS0) {
+			if (gi == 1)
+				rate = 0x0D;	/* MCS 32 SGI rate */
+			else
+				rate = 0x0C;	/* MCS 32 LGI rate */
+		} else if (index < MCS_NUM_SUPP) {
+			if (bw <= 1)
+				rate = mcs_rate[2 * (1 - bw) + gi][index];
+			else
+				rate = WlanDataRates[0];
+		} else
+			rate = WlanDataRates[0];
+	} else {
+		/* 11n non HT rates */
+		if (index >= WLAN_SUPPORTED_RATES_EXT)
+			index = 0;
+		rate = WlanDataRates[index];
+	}
+	LEAVE();
+	return rate;
+}
+
+/**
+ *  @brief Use rate to get the index
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param rate         Data rate
+ *
+ *  @return                     Index or 0
+ */
+t_u8
+wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate)
+{
+	t_u16 *ptr;
+
+	ENTER();
+	if (rate) {
+		ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8)rate,
+				  sizeof(WlanDataRates));
+		if (ptr) {
+			LEAVE();
+			return (t_u8)(ptr - WlanDataRates);
+		}
+	}
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get active data rates
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param bss_mode         The specified BSS mode (Infra/IBSS)
+ *  @param config_bands     The specified band configuration
+ *  @param rates            The buf to return the active rates
+ *
+ *  @return                 The number of Rates
+ */
+t_u32
+wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+			   t_u16 config_bands, WLAN_802_11_RATES rates)
+{
+	t_u32 k;
+
+	ENTER();
+
+	if (pmpriv->media_connected != MTRUE) {
+		k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands,
+					     rates);
+	} else {
+		k = wlan_copy_rates(rates, 0,
+				    pmpriv->curr_bss_params.data_rates,
+				    pmpriv->curr_bss_params.num_of_rates);
+	}
+
+	LEAVE();
+	return k;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function search through all the regions cfp table to find the
+ * channel, if the channel is found then gets the MIN txpower of the channel
+ *            present in all the regions.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param channel      Channel number.
+ *
+ *  @return             The Tx power
+ */
+t_u8
+wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel)
+{
+	t_u8 i = 0;
+	t_u8 j = 0;
+	t_u8 tx_power = 0;
+	t_u32 cfp_no;
+	chan_freq_power_t *cfp = MNULL;
+	chan_freq_power_t *cfp_a = MNULL;
+	t_u32 cfp_no_a;
+
+	ENTER();
+
+	for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+		/* Get CFP */
+		cfp = cfp_table_BG[i].cfp;
+		cfp_no = cfp_table_BG[i].cfp_no;
+		/* Find matching channel and get Tx power */
+		for (j = 0; j < cfp_no; j++) {
+			if ((cfp + j)->channel == channel) {
+				if (tx_power != 0)
+					tx_power = MIN(tx_power,
+						       (cfp + j)->max_tx_power);
+				else
+					tx_power =
+						(t_u8)(cfp + j)->max_tx_power;
+				break;
+			}
+		}
+	}
+
+	for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+		/* Get CFP */
+		cfp_a = cfp_table_A[i].cfp;
+		cfp_no_a = cfp_table_A[i].cfp_no;
+		for (j = 0; j < cfp_no_a; j++) {
+			if ((cfp_a + j)->channel == channel) {
+				if (tx_power != 0)
+					tx_power =
+						MIN(tx_power,
+						    (cfp_a + j)->max_tx_power);
+				else
+					tx_power = (t_u8)((cfp_a +
+							   j)->max_tx_power);
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return tx_power;
+}
+
+/**
+ *  @brief Get the channel frequency power info for a specific channel
+ *
+ *  @param pmadapter            A pointer to mlan_adapter structure
+ *  @param band                 It can be BAND_A, BAND_G or BAND_B
+ *  @param channel              The channel to search for
+ *  @param region_channel       A pointer to region_chan_t structure
+ *
+ *  @return                     A pointer to chan_freq_power_t structure or
+ * MNULL if not found.
+ */
+
+chan_freq_power_t *
+wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, t_u8 band,
+				 t_u16 channel, region_chan_t *region_channel)
+{
+	region_chan_t *rc;
+	chan_freq_power_t *cfp = MNULL;
+	int i, j;
+
+	ENTER();
+
+	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
+		rc = &region_channel[j];
+
+		if (!rc->valid || !rc->pcfp)
+			continue;
+		switch (rc->band) {
+		case BAND_A:
+			switch (band) {
+			case BAND_AN:
+			case BAND_A | BAND_AN:
+			case BAND_A | BAND_AN | BAND_AAC:
+				/* Fall Through */
+			case BAND_A:	/* Matching BAND_A */
+				break;
+
+			default:
+				continue;
+			}
+			break;
+		case BAND_B:
+		case BAND_G:
+			switch (band) {
+			case BAND_GN:
+			case BAND_B | BAND_G | BAND_GN:
+			case BAND_G | BAND_GN:
+			case BAND_GN | BAND_GAC:
+			case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			case BAND_G | BAND_GN | BAND_GAC:
+			case BAND_B | BAND_G:
+				/* Fall Through */
+			case BAND_B:	/* Matching BAND_B/G */
+				/* Fall Through */
+			case BAND_G:
+				/* Fall Through */
+			case 0:
+				break;
+			default:
+				continue;
+			}
+			break;
+		default:
+			continue;
+		}
+		if (channel == FIRST_VALID_CHANNEL)
+			cfp = &rc->pcfp[0];
+		else {
+			for (i = 0; i < rc->num_cfp; i++) {
+				if (rc->pcfp[i].channel == channel) {
+					cfp = &rc->pcfp[i];
+					break;
+				}
+			}
+		}
+	}
+
+	if (!cfp && channel)
+		PRINTM(MCMND,
+		       "%s: can not find cfp by band %d & channel %d\n",
+		       __func__, band, channel);
+
+	LEAVE();
+	return cfp;
+}
+
+/**
+ *  @brief Find the channel frequency power info for a specific channel
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param band         It can be BAND_A, BAND_G or BAND_B
+ *  @param channel      The channel to search for
+ *
+ *  @return             A pointer to chan_freq_power_t structure or MNULL if not
+ * found.
+ */
+chan_freq_power_t *
+wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
+				  t_u8 band, t_u16 channel)
+{
+	chan_freq_power_t *cfp = MNULL;
+
+	ENTER();
+
+	/* Any station(s) with 11D enabled */
+	if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
+				 wlan_is_station) > 0)
+		cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel,
+						       pmadapter->
+						       universal_channel);
+	else
+		cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel,
+						       pmadapter->
+						       region_channel);
+
+	LEAVE();
+	return cfp;
+}
+
+/**
+ *  @brief Find the channel frequency power info for a specific frequency
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param band         It can be BAND_A, BAND_G or BAND_B
+ *  @param freq         The frequency to search for
+ *
+ *  @return         Pointer to chan_freq_power_t structure; MNULL if not found
+ */
+chan_freq_power_t *
+wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter, t_u8 band, t_u32 freq)
+{
+	chan_freq_power_t *cfp = MNULL;
+	region_chan_t *rc;
+	int i, j;
+
+	ENTER();
+
+	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
+		rc = &pmadapter->region_channel[j];
+
+		/* Any station(s) with 11D enabled */
+		if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
+					 wlan_is_station) > 0)
+			rc = &pmadapter->universal_channel[j];
+
+		if (!rc->valid || !rc->pcfp)
+			continue;
+		switch (rc->band) {
+		case BAND_A:
+			switch (band) {
+			case BAND_AN:
+			case BAND_A | BAND_AN:
+			case BAND_A | BAND_AN | BAND_AAC:
+				/* Fall Through */
+			case BAND_A:	/* Matching BAND_A */
+				break;
+			default:
+				continue;
+			}
+			break;
+		case BAND_B:
+		case BAND_G:
+			switch (band) {
+			case BAND_GN:
+			case BAND_B | BAND_G | BAND_GN:
+			case BAND_G | BAND_GN:
+			case BAND_GN | BAND_GAC:
+			case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+			case BAND_G | BAND_GN | BAND_GAC:
+			case BAND_B | BAND_G:
+				/* Fall Through */
+			case BAND_B:
+				/* Fall Through */
+			case BAND_G:
+				/* Fall Through */
+			case 0:
+				break;
+			default:
+				continue;
+			}
+			break;
+		default:
+			continue;
+		}
+		for (i = 0; i < rc->num_cfp; i++) {
+			if (rc->pcfp[i].freq == freq) {
+				cfp = &rc->pcfp[i];
+				break;
+			}
+		}
+	}
+
+	if (!cfp && freq)
+		PRINTM(MERROR,
+		       "%s: cannot find cfp by band %d & freq %d\n", __func__,
+		       band, freq);
+
+	LEAVE();
+	return cfp;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief Check if Rate Auto
+ *
+ *  @param pmpriv               A pointer to mlan_private structure
+ *
+ *  @return                     MTRUE or MFALSE
+ */
+t_u8
+wlan_is_rate_auto(mlan_private *pmpriv)
+{
+	t_u32 i;
+	int rate_num = 0;
+
+	ENTER();
+
+	for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
+		if (pmpriv->bitmap_rates[i])
+			rate_num++;
+
+	LEAVE();
+	if (rate_num > 1)
+		return MTRUE;
+	else
+		return MFALSE;
+}
+
+/**
+ *  @brief Covert Rate Bitmap to Rate index
+ *
+ *  @param pmadapter    Pointer to mlan_adapter structure
+ *  @param rate_bitmap  Pointer to rate bitmap
+ *  @param size         Size of the bitmap array
+ *
+ *  @return             Rate index
+ */
+int
+wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
+{
+	int i;
+
+	ENTER();
+
+	for (i = 0; i < size * 8; i++) {
+		if (rate_bitmap[i / 16] & (1 << (i % 16))) {
+			LEAVE();
+			return i;
+		}
+	}
+
+	LEAVE();
+	return -1;
+}
+
+/**
+ *  @brief Get supported data rates
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param bss_mode         The specified BSS mode (Infra/IBSS)
+ *  @param config_bands     The specified band configuration
+ *  @param rates            The buf to return the supported rates
+ *
+ *  @return                 The number of Rates
+ */
+t_u32
+wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
+			 t_u16 config_bands, WLAN_802_11_RATES rates)
+{
+	t_u32 k = 0;
+
+	ENTER();
+
+	if (bss_mode == MLAN_BSS_MODE_INFRA) {
+		/* Infra. mode */
+		switch (config_bands) {
+		case (t_u8)BAND_B:
+			PRINTM(MINFO, "Infra Band=%d SupportedRates_B\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_B,
+					    sizeof(SupportedRates_B));
+			break;
+		case (t_u8)BAND_G:
+		case BAND_G | BAND_GN:
+		case BAND_G | BAND_GN | BAND_GAC:
+		case BAND_G | BAND_GN | BAND_GAC | BAND_GAX:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_G,
+					    sizeof(SupportedRates_G));
+			break;
+		case BAND_B | BAND_G:
+		case BAND_A | BAND_B | BAND_G:
+		case BAND_A | BAND_B:
+		case BAND_A | BAND_B | BAND_G | BAND_GN:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_GAC:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_AAX:
+		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_GAC | BAND_AAX | BAND_GAX:
+		case BAND_B | BAND_G | BAND_GN:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC:
+		case BAND_B | BAND_G | BAND_GN | BAND_GAC | BAND_GAX:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_BG\n",
+			       config_bands);
+#ifdef WIFI_DIRECT_SUPPORT
+			if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				k = wlan_copy_rates(rates, k, SupportedRates_G,
+						    sizeof(SupportedRates_G));
+			else
+				k = wlan_copy_rates(rates, k, SupportedRates_BG,
+						    sizeof(SupportedRates_BG));
+#else
+			k = wlan_copy_rates(rates, k, SupportedRates_BG,
+					    sizeof(SupportedRates_BG));
+#endif
+			break;
+		case BAND_A:
+		case BAND_A | BAND_G:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_A,
+					    sizeof(SupportedRates_A));
+			break;
+		case BAND_AN:
+		case BAND_A | BAND_AN:
+		case BAND_A | BAND_G | BAND_AN | BAND_GN:
+		case BAND_A | BAND_AN | BAND_AAC:
+		case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
+		case BAND_A | BAND_AN | BAND_AAC | BAND_AAX:
+		case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_A,
+					    sizeof(SupportedRates_A));
+			break;
+		case BAND_GN:
+		case BAND_GN | BAND_GAC:
+		case BAND_GN | BAND_GAC | BAND_GAX:
+			PRINTM(MINFO, "Infra band=%d SupportedRates_N\n",
+			       config_bands);
+			k = wlan_copy_rates(rates, k, SupportedRates_N,
+					    sizeof(SupportedRates_N));
+			break;
+		}
+	} else {
+		/* Ad-hoc mode */
+		switch (config_bands) {
+		case (t_u8)BAND_B:
+			PRINTM(MINFO, "Band: Adhoc B\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_B,
+					    sizeof(AdhocRates_B));
+			break;
+		case (t_u8)BAND_G:
+			PRINTM(MINFO, "Band: Adhoc G only\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_G,
+					    sizeof(AdhocRates_G));
+			break;
+		case BAND_B | BAND_G:
+			PRINTM(MINFO, "Band: Adhoc BG\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_BG,
+					    sizeof(AdhocRates_BG));
+			break;
+		case BAND_A:
+		case BAND_A | BAND_AN | BAND_AAC:
+		case BAND_A | BAND_AN | BAND_AAC | BAND_AAX:
+
+			PRINTM(MINFO, "Band: Adhoc A\n");
+			k = wlan_copy_rates(rates, k, AdhocRates_A,
+					    sizeof(AdhocRates_A));
+			break;
+		}
+	}
+
+	LEAVE();
+	return k;
+}
+
+#define COUNTRY_ID_US 0
+#define COUNTRY_ID_JP 1
+#define COUNTRY_ID_CN 2
+#define COUNTRY_ID_EU 3
+typedef struct _oper_bw_chan {
+	/*non-global operating class */
+	t_u8 oper_class;
+	/*global operating class */
+	t_u8 global_oper_class;
+	/*bandwidth 0-20M 1-40M 2-80M 3-160M */
+	t_u8 bandwidth;
+	/*channel list */
+	t_u8 channel_list[13];
+} oper_bw_chan;
+
+/** oper class table for US*/
+static oper_bw_chan oper_bw_chan_us[] = {
+	/** non-Global oper class, global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 124, 0, {149, 153, 157, 161}},
+	{4,
+	 121,
+	 0,
+	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
+	{5, 125, 0, {149, 153, 157, 161, 165}},
+	{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
+	{22, 116, 1, {36, 44}},
+	{23, 119, 1, {52, 60}},
+	{24, 122, 1, {100, 108, 116, 124, 132, 140}},
+	{25, 126, 1, {149, 157}},
+	{26, 126, 1, {149, 157}},
+	{27, 117, 1, {40, 48}},
+	{28, 120, 1, {56, 64}},
+	{29, 123, 1, {104, 112, 120, 128, 136, 144}},
+	{30, 127, 1, {153, 161}},
+	{31, 127, 1, {153, 161}},
+	{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
+	{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for EU*/
+static oper_bw_chan oper_bw_chan_eu[] = {
+	/** non-global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{5, 116, 1, {36, 44}},
+	{6, 119, 1, {52, 60}},
+	{7, 122, 1, {100, 108, 116, 124, 132}},
+	{8, 117, 1, {40, 48}},
+	{9, 120, 1, {56, 64}},
+	{10, 123, 1, {104, 112, 120, 128, 136}},
+	{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{17, 125, 0, {149, 153, 157, 161, 165, 169}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for Japan*/
+static oper_bw_chan oper_bw_chan_jp[] = {
+	/** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
+	{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{31, 82, 0, {14}},
+	{32, 118, 0, {52, 56, 60, 64}},
+	{33, 118, 0, {52, 56, 60, 64}},
+	{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{36, 116, 1, {36, 44}},
+	{37, 119, 1, {52, 60}},
+	{38, 119, 1, {52, 60}},
+	{39, 122, 1, {100, 108, 116, 124, 132}},
+	{40, 122, 1, {100, 108, 116, 124, 132}},
+	{41, 117, 1, {40, 48}},
+	{42, 120, 1, {56, 64}},
+	{43, 120, 1, {56, 64}},
+	{44, 123, 1, {104, 112, 120, 128, 136}},
+	{45, 123, 1, {104, 112, 120, 128, 136}},
+	{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/** oper class table for China*/
+static oper_bw_chan oper_bw_chan_cn[] = {
+	/** non-Global oper class,global oper class, bandwidth, channel list*/
+	{1, 115, 0, {36, 40, 44, 48}},
+	{2, 118, 0, {52, 56, 60, 64}},
+	{3, 125, 0, {149, 153, 157, 161, 165}},
+	{4, 116, 1, {36, 44}},
+	{5, 119, 1, {52, 60}},
+	{6, 126, 1, {149, 157}},
+	{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
+	{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
+	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
+	{129, 129, 3, {50, 114}},
+	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
+};
+
+/**
+ *  @brief Get non-global operaing class table according to country
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param arraysize          A pointer to table size
+ *
+ *  @return                   A pointer to oper_bw_chan
+ */
+static oper_bw_chan *
+wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
+{
+	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
+	int country_id = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+
+	ENTER();
+
+	for (country_id = 0; country_id < 3; country_id++)
+		if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
+			    country_code[country_id], COUNTRY_CODE_LEN - 1))
+			break;
+	if (country_id >= 3)
+		country_id = COUNTRY_ID_US;	/*Set default to US */
+	if (wlan_is_etsi_country(pmpriv->adapter,
+				 pmpriv->adapter->country_code))
+		country_id = COUNTRY_ID_EU; /** Country in EU */
+
+	switch (country_id) {
+	case COUNTRY_ID_US:
+		poper_bw_chan = oper_bw_chan_us;
+		*arraysize = sizeof(oper_bw_chan_us);
+		break;
+	case COUNTRY_ID_JP:
+		poper_bw_chan = oper_bw_chan_jp;
+		*arraysize = sizeof(oper_bw_chan_jp);
+		break;
+	case COUNTRY_ID_CN:
+		poper_bw_chan = oper_bw_chan_cn;
+		*arraysize = sizeof(oper_bw_chan_cn);
+		break;
+	case COUNTRY_ID_EU:
+		poper_bw_chan = oper_bw_chan_eu;
+		*arraysize = sizeof(oper_bw_chan_eu);
+		break;
+	default:
+		PRINTM(MERROR, "Country not support!\n");
+		break;
+	}
+
+	LEAVE();
+	return poper_bw_chan;
+}
+
+/**
+ *  @brief Check validation of given channel and oper class
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param oper_class         operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+				t_u8 oper_class)
+{
+	int arraysize = 0, i = 0, channum = 0;
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+
+	ENTER();
+
+	for (i = 0; i < (int)sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (oper_class <= 0 || oper_class > 130) {
+		PRINTM(MERROR, "Invalid operating class!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (oper_class >= 128) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++) {
+		if (poper_bw_chan[i].oper_class == oper_class ||
+		    poper_bw_chan[i].global_oper_class == oper_class) {
+			for (channum = 0;
+			     channum <
+			     (int)sizeof(poper_bw_chan[i].channel_list);
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					LEAVE();
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
+	       oper_class, channel);
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Get current operating class from channel and bandwidth
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param channel            Channel number
+ *  @param bw                 Bandwidth
+ *  @param oper_class         A pointer to current operating class
+ *
+ *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel,
+			 t_u8 bw, t_u8 *oper_class)
+{
+	oper_bw_chan *poper_bw_chan = MNULL;
+	t_u8 center_freq_idx = 0;
+	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
+	int i = 0, arraysize = 0, channum = 0;
+
+	ENTER();
+
+	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
+
+	if (!poper_bw_chan) {
+		PRINTM(MCMND, "Operating class table do not find!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	for (i = 0; i < (int)sizeof(center_freqs); i++) {
+		if (channel == center_freqs[i]) {
+			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (bw == BW_80MHZ) {
+		center_freq_idx =
+			wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
+						 CHANNEL_BW_80MHZ);
+		channel = center_freq_idx;
+	}
+
+	for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++) {
+		if (poper_bw_chan[i].bandwidth == bw) {
+			for (channum = 0;
+			     channum <
+			     (int)(sizeof(poper_bw_chan[i].channel_list));
+			     channum++) {
+				if (poper_bw_chan[i].channel_list[channum] &&
+				    poper_bw_chan[i].channel_list[channum] ==
+				    channel) {
+					*oper_class =
+						poper_bw_chan[i].oper_class;
+					return MLAN_STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	PRINTM(MCMND, "Operating class not find!\n");
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief Add Supported operating classes IE
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *  @param curr_oper_class    Current operating class
+ *
+ *  @return                   Length
+ */
+int
+wlan_add_supported_oper_class_ie(mlan_private *pmpriv,
+				 t_u8 **pptlv_out, t_u8 curr_oper_class)
+{
+	t_u8 oper_class_us[] = { 1,
+		2,
+		3,
+		4,
+		5,
+		12,
+		22,
+		23,
+		24,
+		25,
+		26,
+		27,
+		28,
+		29,
+		30,
+		31,
+		32,
+		33,
+		128,
+		129,
+		130
+	};
+	t_u8 oper_class_eu[] = { 1,
+		2,
+		3,
+		4,
+		5,
+		6,
+		7,
+		8,
+		9,
+		10,
+		11,
+		12,
+		17,
+		128,
+		129,
+		130
+	};
+	t_u8 oper_class_jp[] = { 1,
+		30,
+		31,
+		32,
+		33,
+		34,
+		35,
+		36,
+		37,
+		38,
+		39,
+		40,
+		41,
+		42,
+		43,
+		44,
+		45,
+		56,
+		57,
+		58,
+		128,
+		129,
+		130
+	};
+	t_u8 oper_class_cn[] = { 1,
+		2,
+		3,
+		4,
+		5,
+		6,
+		7,
+		8,
+		9,
+		128,
+		129,
+		130
+	};
+	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
+	int country_id = 0, ret = 0;
+	MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
+
+	ENTER();
+
+	for (country_id = 0; country_id < 3; country_id++)
+		if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
+			    country_code[country_id], COUNTRY_CODE_LEN - 1))
+			break;
+	if (country_id >= 3)
+		country_id = COUNTRY_ID_US;	/*Set default to US */
+	if (wlan_is_etsi_country(pmpriv->adapter,
+				 pmpriv->adapter->country_code))
+		country_id = COUNTRY_ID_EU; /** Country in EU */
+	poper_class = (MrvlIETypes_SuppOperClass_t *) * pptlv_out;
+	memset(pmpriv->adapter, poper_class, 0,
+	       sizeof(MrvlIETypes_SuppOperClass_t));
+	poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
+	if (country_id == COUNTRY_ID_US) {
+		poper_class->header.len = sizeof(oper_class_us);
+		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+			   oper_class_us, sizeof(oper_class_us),
+			   poper_class->header.len);
+	} else if (country_id == COUNTRY_ID_JP) {
+		poper_class->header.len = sizeof(oper_class_jp);
+		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+			   oper_class_jp, sizeof(oper_class_jp),
+			   poper_class->header.len);
+	} else if (country_id == COUNTRY_ID_CN) {
+		poper_class->header.len = sizeof(oper_class_cn);
+		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+			   oper_class_cn, sizeof(oper_class_cn),
+			   poper_class->header.len);
+	} else if (country_id == COUNTRY_ID_EU) {
+		poper_class->header.len = sizeof(oper_class_eu);
+		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
+			   oper_class_eu, sizeof(oper_class_eu),
+			   poper_class->header.len);
+	}
+	poper_class->current_oper_class = curr_oper_class;
+	poper_class->header.len += sizeof(poper_class->current_oper_class);
+	DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class,
+		    sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
+	ret = sizeof(MrvlIEtypesHeader_t) + poper_class->header.len;
+	*pptlv_out += ret;
+	poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets region table.
+ *
+ *  @param pmpriv  A pointer to mlan_private structure
+ *  @param region  The region code
+ *  @param band    The band
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u8 band)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	int i = 0, j;
+	chan_freq_power_t *cfp;
+	int cfp_no;
+	region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];
+	t_u8 cfp_code_bg = region;
+	t_u8 cfp_code_a = region;
+
+	ENTER();
+
+	memcpy_ext(pmadapter, region_chan_old, pmadapter->region_channel,
+		   sizeof(pmadapter->region_channel), sizeof(region_chan_old));
+	memset(pmadapter, pmadapter->region_channel, 0,
+	       sizeof(pmadapter->region_channel));
+
+	if (band & (BAND_B | BAND_G | BAND_GN)) {
+		if (pmadapter->cfp_code_bg)
+			cfp_code_bg = pmadapter->cfp_code_bg;
+		PRINTM(MCMND, "%s: 2.4G 0x%x\n", __func__, cfp_code_bg);
+		cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
+						BAND_G | BAND_B | BAND_GN,
+						&cfp_no);
+		if (cfp) {
+			pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
+			pmadapter->region_channel[i].pcfp = cfp;
+		} else {
+			PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
+			       region);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmadapter->region_channel[i].valid = MTRUE;
+		pmadapter->region_channel[i].region = region;
+		if (band & BAND_GN)
+			pmadapter->region_channel[i].band = BAND_G;
+		else
+			pmadapter->region_channel[i].band =
+				(band & BAND_G) ? BAND_G : BAND_B;
+
+		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
+			if (region_chan_old[j].band & (BAND_B | BAND_G))
+				break;
+		}
+
+		if ((j < MAX_REGION_CHANNEL_NUM) &&
+		    (region_chan_old[j].valid == MTRUE)) {
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+					      region_chan_old[j].pcfp,
+					      region_chan_old[j].num_cfp);
+		} else if (cfp) {
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
+		}
+		i++;
+	}
+	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
+		if (pmadapter->cfp_code_bg)
+			cfp_code_a = pmadapter->cfp_code_a;
+		PRINTM(MCMND, "%s: 5G 0x%x\n", __func__, cfp_code_a);
+		cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
+						&cfp_no);
+		if (cfp) {
+			pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
+			pmadapter->region_channel[i].pcfp = cfp;
+		} else {
+			PRINTM(MERROR, "wrong region code %#x in Band A\n",
+			       region);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmadapter->region_channel[i].valid = MTRUE;
+		pmadapter->region_channel[i].region = region;
+		pmadapter->region_channel[i].band = BAND_A;
+
+		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
+			if (region_chan_old[j].band & BAND_A)
+				break;
+		}
+		if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid) {
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
+					      region_chan_old[j].pcfp,
+					      region_chan_old[j].num_cfp);
+		} else if (cfp) {
+			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get if radar detection is enabled or not on a certain channel
+ *
+ *  @param priv    Private driver information structure
+ *  @param chnl Channel to determine radar detection requirements
+ *
+ *  @return
+ *    - MTRUE if radar detection is required
+ *    - MFALSE otherwise
+ */
+t_bool
+wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
+{
+	int i, j;
+	t_bool required = MFALSE;
+	chan_freq_power_t *pcfp = MNULL;
+
+	ENTER();
+
+	/*get the cfp table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (priv->adapter->region_channel[i].band == BAND_A) {
+			pcfp = priv->adapter->region_channel[i].pcfp;
+			break;
+		}
+	}
+
+	if (!pcfp) {
+		/* This means operation in BAND-A is not support, we can
+		 * just return false here, it's harmless
+		 */
+		goto done;
+	}
+
+	/*get the radar detection requirements according to chan num */
+	for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+		if (pcfp[j].channel == chnl) {
+			required = pcfp[j].passive_scan_or_radar_detect;
+			break;
+		}
+	}
+
+done:
+	LEAVE();
+	return required;
+}
+
+/**
+ *  @brief Get if scan type is passive or not on a certain channel for b/g band
+ *
+ *  @param priv    Private driver information structure
+ *  @param chnl Channel to determine scan type
+ *
+ *  @return
+ *    - MTRUE if scan type is passive
+ *    - MFALSE otherwise
+ */
+
+t_bool
+wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
+{
+	int i, j;
+	t_bool passive = MFALSE;
+	chan_freq_power_t *pcfp = MNULL;
+
+	ENTER();
+
+	/*get the cfp table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) {
+			pcfp = priv->adapter->region_channel[i].pcfp;
+			break;
+		}
+	}
+
+	if (!pcfp) {
+		/*This means operation in BAND-B or BAND_G is not support, we
+		 * can just return false here
+		 */
+		goto done;
+	}
+
+	/*get the bg scan type according to chan num */
+	for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+		if (pcfp[j].channel == chnl) {
+			passive = pcfp[j].passive_scan_or_radar_detect;
+			break;
+		}
+	}
+
+done:
+	LEAVE();
+	return passive;
+}
+
+/**
+ *  @brief Get if a channel is NO_IR (passive) or not
+ *
+ *  @param priv     Private driver information structure
+ *  @param band     Band to check
+ *  @param chan     Channel to check
+ *
+ *  @return
+ *    - MTRUE if channel is passive
+ *    - MFALSE otherwise
+ */
+
+t_bool
+wlan_is_chan_passive(mlan_private *priv, t_u8 band, t_u8 chan)
+{
+	int i, j;
+	t_bool passive = MFALSE;
+	chan_freq_power_t *pcfp = MNULL;
+
+	ENTER();
+
+	/* get the cfp table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (priv->adapter->region_channel[i].band & band) {
+			pcfp = priv->adapter->region_channel[i].pcfp;
+			break;
+		}
+	}
+
+	if (pcfp) {
+		/* check table according to chan num */
+		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+			if (pcfp[j].channel == chan) {
+				if (pcfp[j].dynamic.flags & NXP_CHANNEL_PASSIVE)
+					passive = MTRUE;
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return passive;
+}
+
+/**
+ *  @brief Get if a channel is disabled or not
+ *
+ *  @param priv     Private driver information structure
+ *  @param band     Band to check
+ *  @param chan     Channel to check
+ *
+ *  @return
+ *    - MTRUE if channel is disabled
+ *    - MFALSE otherwise
+ */
+
+t_bool
+wlan_is_chan_disabled(mlan_private *priv, t_u8 band, t_u8 chan)
+{
+	int i, j;
+	t_bool disabled = MFALSE;
+	chan_freq_power_t *pcfp = MNULL;
+
+	ENTER();
+
+	/* get the cfp table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (priv->adapter->region_channel[i].band & band) {
+			pcfp = priv->adapter->region_channel[i].pcfp;
+			break;
+		}
+	}
+
+	if (pcfp) {
+		/* check table according to chan num */
+		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+			if (pcfp[j].channel == chan) {
+				if (pcfp[j].dynamic.flags &
+				    NXP_CHANNEL_DISABLED)
+					disabled = MTRUE;
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return disabled;
+}
+
+/**
+ *  @brief Get if a channel is blacklisted or not
+ *
+ *  @param priv     Private driver information structure
+ *  @param band     Band to check
+ *  @param chan     Channel to check
+ *
+ *  @return
+ *    - MTRUE if channel is blacklisted
+ *    - MFALSE otherwise
+ */
+
+t_bool
+wlan_is_chan_blacklisted(mlan_private *priv, t_u8 band, t_u8 chan)
+{
+	int i, j;
+	t_bool blacklist = MFALSE;
+	chan_freq_power_t *pcfp = MNULL;
+
+	ENTER();
+
+	/*get the cfp table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (priv->adapter->region_channel[i].band & band) {
+			pcfp = priv->adapter->region_channel[i].pcfp;
+			break;
+		}
+	}
+
+	if (pcfp) {
+		/*check table according to chan num */
+		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+			if (pcfp[j].channel == chan) {
+				blacklist = pcfp[j].dynamic.blacklist;
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return blacklist;
+}
+
+/**
+ *  @brief Set a channel as blacklisted or not
+ *
+ *  @param priv     Private driver information structure
+ *  @param band     Band to check
+ *  @param chan     Channel to check
+ *  @param bl       Blacklist if MTRUE
+ *
+ *  @return
+ *    - MTRUE if channel setting is updated
+ *    - MFALSE otherwise
+ */
+
+t_bool
+wlan_set_chan_blacklist(mlan_private *priv, t_u8 band, t_u8 chan, t_bool bl)
+{
+	int i, j;
+	t_bool set_bl = MFALSE;
+	chan_freq_power_t *pcfp = MNULL;
+
+	ENTER();
+
+	/*get the cfp table first */
+	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
+		if (priv->adapter->region_channel[i].band & band) {
+			pcfp = priv->adapter->region_channel[i].pcfp;
+			break;
+		}
+	}
+
+	if (pcfp) {
+		/*check table according to chan num */
+		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
+			if (pcfp[j].channel == chan) {
+				pcfp[j].dynamic.blacklist = bl;
+				set_bl = MTRUE;
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return set_bl;
+}
+
+/**
+ *  @brief Convert rateid in IEEE format to MRVL format
+ *
+ *  @param priv     Private driver information structure
+ *  @param IeeeMacRate  Rate in terms of IEEE format
+ *  @param pmbuf     A pointer to packet buffer
+ *
+ *  @return
+ *    Rate ID in terms of MRVL format
+ */
+t_u8
+wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
+				t_u8 *dst_mac)
+{
+	/* Set default rate ID to RATEID_DBPSK1Mbps */
+	t_u8 mrvlRATEID = 0;
+	const rate_map *rate_tbl = rate_map_table_1x1;
+	t_u32 cnt = sizeof(rate_map_table_1x1) / sizeof(rate_map);
+	t_u8 skip_nss2 = MTRUE;
+	t_u32 i = 0;
+	IEEEtypes_HTCap_t *htcap = MNULL;
+	t_u8 tx_mcs_supp = GET_TXMCSSUPP(priv->usr_dev_mcs_support);
+#ifdef UAP_SUPPORT
+	psta_node sta_ptr = MNULL;
+#endif
+
+	ENTER();
+
+	if (priv->adapter->hw_dev_mcs_support == HT_STREAM_MODE_2X2) {
+		rate_tbl = rate_map_table_2x2;
+		cnt = sizeof(rate_map_table_2x2) / sizeof(rate_map);
+	}
+#ifdef UAP_SUPPORT
+	if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
+		if (!dst_mac) {
+			LEAVE();
+			return mrvlRATEID;
+		}
+		sta_ptr =
+			(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+						   &priv->sta_list,
+						   priv->adapter->callbacks.
+						   moal_spin_lock,
+						   priv->adapter->callbacks.
+						   moal_spin_unlock);
+		if (!sta_ptr) {
+			LEAVE();
+			return mrvlRATEID;
+		}
+		while (sta_ptr != (sta_node *)&priv->sta_list) {
+			if (memcmp(priv->adapter, dst_mac, sta_ptr->mac_addr,
+				   MLAN_MAC_ADDR_LENGTH)) {
+				htcap = &(sta_ptr->HTcap);
+				break;
+			}
+			sta_ptr = sta_ptr->pnext;
+		}
+	}
+#endif
+#ifdef STA_SUPPORT
+	if (priv->bss_role == MLAN_BSS_ROLE_STA)
+		htcap = priv->curr_bss_params.bss_descriptor.pht_cap;
+#endif
+	if (htcap) {
+		/* If user configure tx to 2x2 and peer device rx is 2x2 */
+		if (tx_mcs_supp >= 2 && htcap->ht_cap.supported_mcs_set[1])
+			skip_nss2 = MFALSE;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (rate_tbl[i].nss && skip_nss2)
+			continue;
+		if (rate_tbl[i].rate == IeeeMacRate) {
+			mrvlRATEID = rate_tbl[i].id;
+			break;
+		}
+	}
+
+	return mrvlRATEID;
+}
+
+/**
+ *  @brief Convert rateid in MRVL format to IEEE format
+ *
+ *  @param IeeeMacRate  Rate in terms of MRVL format
+ *
+ *  @return
+ *    Rate ID in terms of IEEE format
+ */
+t_u8
+wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
+{
+	return rateUnit_500Kbps[rate];
+}
+
+/**
+ *  @brief	 sort cfp otp table
+ *
+ *  @param pmapdater	a pointer to mlan_adapter structure
+ *
+ *  @return
+ *    None
+ */
+static void
+wlan_sort_cfp_otp_table(mlan_adapter *pmadapter)
+{
+	t_u8 c, d;
+	chan_freq_power_t *ch1;
+	chan_freq_power_t *ch2;
+	chan_freq_power_t swap;
+
+	if (pmadapter->tx_power_table_a_rows <= 1)
+		return;
+	for (c = 0; c < pmadapter->tx_power_table_a_rows - 1; c++) {
+		for (d = 0; d < pmadapter->tx_power_table_a_rows - c - 1; d++) {
+			ch1 = (chan_freq_power_t *)(pmadapter->cfp_otp_a + d);
+			ch2 = (chan_freq_power_t *)(pmadapter->cfp_otp_a + d +
+						    1);
+			if (ch1->channel > ch2->channel) {
+				memcpy_ext(pmadapter, &swap, ch1,
+					   sizeof(chan_freq_power_t),
+					   sizeof(chan_freq_power_t));
+				memcpy_ext(pmadapter, ch1, ch2,
+					   sizeof(chan_freq_power_t),
+					   sizeof(chan_freq_power_t));
+				memcpy_ext(pmadapter, ch2, &swap,
+					   sizeof(chan_freq_power_t),
+					   sizeof(chan_freq_power_t));
+			}
+		}
+	}
+}
+
+/**
+ *  @brief	Update CFP tables and power tables from FW
+ *
+ *  @param priv		Private driver information structure
+ *  @param buf		Pointer to the buffer holding TLV data
+ *					from 0x242 command response.
+ *  @param buf_left	bufsize
+ *
+ *  @return
+ *    None
+ */
+void
+wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	MrvlIEtypesHeader_t *head;
+	t_u16 tlv;
+	t_u16 tlv_buf_len;
+	t_u16 tlv_buf_left;
+	t_u16 i;
+	int k = 0, rows, cols;
+	t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
+	t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
+	t_u8 *tlv_buf;
+	t_u8 *data;
+	t_u8 *tmp;
+	mlan_status ret;
+
+	ENTER();
+
+	if (!buf) {
+		PRINTM(MERROR, "CFP table update failed!\n");
+		goto out;
+	}
+	if (pmadapter->otp_region) {
+		memset(pmadapter, pmadapter->region_channel, 0,
+		       sizeof(pmadapter->region_channel));
+		wlan_free_fw_cfp_tables(pmadapter);
+	}
+	pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
+	pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
+	pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
+	pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
+	tlv_buf = (t_u8 *)buf;
+	tlv_buf_left = buf_left;
+
+	while (tlv_buf_left >= sizeof(*head)) {
+		head = (MrvlIEtypesHeader_t *)tlv_buf;
+		tlv = wlan_le16_to_cpu(head->type);
+		tlv_buf_len = wlan_le16_to_cpu(head->len);
+
+		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
+			break;
+		data = (t_u8 *)head + sizeof(*head);
+
+		switch (tlv) {
+		case TLV_TYPE_REGION_INFO:
+			/* Skip adding fw region info if it already exists or
+			 * if this TLV has no set data
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->otp_region)
+				break;
+
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(otp_region_info_t),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->otp_region);
+			if (ret != MLAN_STATUS_SUCCESS ||
+			    !pmadapter->otp_region) {
+				PRINTM(MERROR,
+				       "Memory allocation for the otp region info struct failed!\n");
+				break;
+			}
+			/* Save region info values from OTP in the otp_region
+			 * structure
+			 */
+			memcpy_ext(pmadapter, pmadapter->otp_region, data,
+				   sizeof(otp_region_info_t),
+				   sizeof(otp_region_info_t));
+			data += sizeof(otp_region_info_t);
+			/* Get pre-defined cfp tables corresponding to the
+			 * region code in OTP
+			 */
+			for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
+				if (cfp_table_BG[i].code ==
+				    pmadapter->otp_region->region_code) {
+					max_tx_pwr_bg = (cfp_table_BG[i].cfp)
+						->max_tx_power;
+					break;
+				}
+			}
+			for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+				if (cfp_table_A[i].code ==
+				    pmadapter->otp_region->region_code) {
+					max_tx_pwr_a = (cfp_table_A[i].cfp)
+						->max_tx_power;
+					break;
+				}
+			}
+			/* Update the region code and the country code in
+			 * pmadapter
+			 */
+			pmadapter->region_code =
+				pmadapter->otp_region->region_code;
+			pmadapter->country_code[0] =
+				pmadapter->otp_region->country_code[0];
+			pmadapter->country_code[1] =
+				pmadapter->otp_region->country_code[1];
+			pmadapter->country_code[2] = '\0';
+			pmadapter->domain_reg.country_code[0] =
+				pmadapter->otp_region->country_code[0];
+			pmadapter->domain_reg.country_code[1] =
+				pmadapter->otp_region->country_code[1];
+			pmadapter->domain_reg.country_code[2] = '\0';
+			PRINTM(MCMND, "OTP region: region_code=%d %c%c\n",
+			       pmadapter->otp_region->region_code,
+			       pmadapter->country_code[0],
+			       pmadapter->country_code[1]);
+			pmadapter->cfp_code_bg =
+				pmadapter->otp_region->region_code;
+			pmadapter->cfp_code_a =
+				pmadapter->otp_region->region_code;
+			break;
+		case TLV_TYPE_CHAN_ATTR_CFG:
+			/* Skip adding fw cfp tables if they already exist or
+			 * if this TLV has no set data
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
+				break;
+			}
+
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       pmadapter->
+					       tx_power_table_bg_rows *
+					       sizeof(chan_freq_power_t),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->cfp_otp_bg);
+			if (ret != MLAN_STATUS_SUCCESS ||
+			    !pmadapter->cfp_otp_bg) {
+				PRINTM(MERROR,
+				       "Memory allocation for storing otp bg table data failed!\n");
+				break;
+			}
+			/* Save channel usability flags from OTP data in the fw
+			 * cfp bg table and set frequency and max_tx_power
+			 * values
+			 */
+			for (i = 0; i < pmadapter->tx_power_table_bg_rows; i++) {
+				(pmadapter->cfp_otp_bg + i)->channel = *data;
+				if (*data == 14)
+					(pmadapter->cfp_otp_bg + i)->freq =
+						2484;
+				else
+					(pmadapter->cfp_otp_bg + i)->freq =
+						2412 + 5 * (*data - 1);
+				(pmadapter->cfp_otp_bg + i)->max_tx_power =
+					max_tx_pwr_bg;
+				data++;
+				(pmadapter->cfp_otp_bg + i)->dynamic.flags =
+					*data;
+				if (*data & NXP_CHANNEL_DFS)
+					(pmadapter->cfp_otp_bg + i)
+						->passive_scan_or_radar_detect =
+						MTRUE;
+				PRINTM(MCMD_D,
+				       "OTP Region (BG): chan=%d flags=0x%x\n",
+				       (pmadapter->cfp_otp_bg + i)->channel,
+				       (pmadapter->cfp_otp_bg +
+					i)->dynamic.flags);
+				data++;
+			}
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       pmadapter->
+					       tx_power_table_a_rows *
+					       sizeof(chan_freq_power_t),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->cfp_otp_a);
+			if (ret != MLAN_STATUS_SUCCESS || !pmadapter->cfp_otp_a) {
+				PRINTM(MERROR,
+				       "Memory allocation for storing otp a table data failed!\n");
+				break;
+			}
+			/* Save channel usability flags from OTP data in the fw
+			 * cfp a table and set frequency and max_tx_power values
+			 */
+			for (i = 0; i < pmadapter->tx_power_table_a_rows; i++) {
+				(pmadapter->cfp_otp_a + i)->channel = *data;
+				if (*data < 183)
+					/* 5GHz channels */
+					(pmadapter->cfp_otp_a + i)->freq =
+						5035 + 5 * (*data - 7);
+				else
+					/* 4GHz channels */
+					(pmadapter->cfp_otp_a + i)->freq =
+						4915 + 5 * (*data - 183);
+				(pmadapter->cfp_otp_a + i)->max_tx_power =
+					max_tx_pwr_a;
+				data++;
+				(pmadapter->cfp_otp_a + i)->dynamic.flags =
+					*data;
+				if (*data & NXP_CHANNEL_DFS)
+					(pmadapter->cfp_otp_a + i)
+						->passive_scan_or_radar_detect =
+						MTRUE;
+				PRINTM(MCMD_D,
+				       "OTP Region (A): chan=%d flags=0x%x\n",
+				       (pmadapter->cfp_otp_a + i)->channel,
+				       (pmadapter->cfp_otp_a +
+					i)->dynamic.flags);
+
+				data++;
+			}
+			break;
+		case TLV_TYPE_POWER_TABLE:
+			/* Skip adding fw power tables if this TLV has no data
+			 * or if they already exists but force reg rule is set
+			 * in the otp
+			 */
+			if (*data == 0)
+				break;
+			if (pmadapter->otp_region &&
+			    pmadapter->otp_region->force_reg &&
+			    pmadapter->tx_power_table_bg)
+				break;
+
+			/* Save the tlv data in power tables for band BG and A
+			 */
+			tmp = data;
+			i = 0;
+			while ((i <
+				pmadapter->tx_power_table_bg_rows *
+				pmadapter->tx_power_table_bg_cols) &&
+			       (i < tlv_buf_len) && (*tmp != 36)) {
+				i++;
+				tmp++;
+			}
+			if (!pmadapter->tx_power_table_bg) {
+				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+						       i, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       tx_power_table_bg);
+				if (ret != MLAN_STATUS_SUCCESS ||
+				    !pmadapter->tx_power_table_bg) {
+					PRINTM(MERROR,
+					       "Memory allocation for the BG-band power table failed!\n");
+					break;
+				}
+			}
+			memcpy_ext(pmadapter, pmadapter->tx_power_table_bg,
+				   data, i, i);
+			pmadapter->tx_power_table_bg_size = i;
+			data += i;
+			i = 0;
+			while ((i < pmadapter->tx_power_table_a_rows *
+				pmadapter->tx_power_table_a_cols) &&
+			       (i < (tlv_buf_len -
+				     pmadapter->tx_power_table_bg_size))) {
+				i++;
+			}
+			if (!pmadapter->tx_power_table_a) {
+				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+						       i, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       tx_power_table_a);
+				if (ret != MLAN_STATUS_SUCCESS ||
+				    !pmadapter->tx_power_table_a) {
+					PRINTM(MERROR,
+					       "Memory allocation for the A-band power table failed!\n");
+					break;
+				}
+			}
+			memcpy_ext(pmadapter, pmadapter->tx_power_table_a, data,
+				   i, i);
+			pmadapter->tx_power_table_a_size = i;
+			break;
+		case TLV_TYPE_POWER_TABLE_ATTR:
+			pmadapter->tx_power_table_bg_rows =
+				((power_table_attr_t *) data)->rows_2g;
+			pmadapter->tx_power_table_bg_cols =
+				((power_table_attr_t *) data)->cols_2g;
+			pmadapter->tx_power_table_a_rows =
+				((power_table_attr_t *) data)->rows_5g;
+			pmadapter->tx_power_table_a_cols =
+				((power_table_attr_t *) data)->cols_5g;
+			PRINTM(MCMD_D, "OTP region: bg_row=%d, a_row=%d\n",
+			       pmadapter->tx_power_table_bg_rows,
+			       pmadapter->tx_power_table_a_rows);
+			break;
+		default:
+			break;
+		}
+		tlv_buf += (sizeof(*head) + tlv_buf_len);
+		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
+	}
+	if (!pmadapter->cfp_otp_bg || !pmadapter->tx_power_table_bg)
+		goto out;
+	/* Set remaining flags for BG */
+	rows = pmadapter->tx_power_table_bg_rows;
+	cols = pmadapter->tx_power_table_bg_cols;
+
+	for (i = 0; i < rows; i++) {
+		k = (i * cols) + 1;
+		if ((pmadapter->cfp_otp_bg + i)->dynamic.flags &
+		    NXP_CHANNEL_DISABLED)
+			continue;
+
+		if (pmadapter->tx_power_table_bg[k + MOD_CCK] == 0)
+			(pmadapter->cfp_otp_bg + i)->dynamic.flags |=
+				NXP_CHANNEL_NO_CCK;
+
+		if (pmadapter->tx_power_table_bg[k + MOD_OFDM_PSK] == 0 &&
+		    pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM16] == 0 &&
+		    pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM64] == 0) {
+			(pmadapter->cfp_otp_bg + i)->dynamic.flags |=
+				NXP_CHANNEL_NO_OFDM;
+		}
+	}
+	if (pmadapter->cfp_otp_a)
+		wlan_sort_cfp_otp_table(pmadapter);
+out:
+	LEAVE();
+}
+
+/**
+ *  @brief	This function deallocates otp cfp and power tables memory.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ */
+void
+wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+	if (pmadapter->otp_region)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->otp_region);
+	if (pmadapter->cfp_otp_bg)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->cfp_otp_bg);
+	if (pmadapter->tx_power_table_bg)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->tx_power_table_bg);
+	pmadapter->otp_region = MNULL;
+	pmadapter->cfp_otp_bg = MNULL;
+	pmadapter->tx_power_table_bg = MNULL;
+	pmadapter->tx_power_table_bg_size = 0;
+	if (pmadapter->cfp_otp_a)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->cfp_otp_a);
+	if (pmadapter->tx_power_table_a)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->tx_power_table_a);
+	pmadapter->cfp_otp_a = MNULL;
+	pmadapter->tx_power_table_a = MNULL;
+	pmadapter->tx_power_table_a_size = 0;
+	LEAVE();
+}
+
+/**
+ *  @brief Get DFS chan list
+ *
+ *  @param pmadapter    Pointer to mlan_adapter
+ *  @param pioctl_req   Pointer to mlan_ioctl_req
+ *
+ *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_get_cfp_table(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_misc_cfg *ds_misc_cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	chan_freq_power_t *cfp = MNULL;
+	t_u32 cfp_no = 0;
+
+	ENTER();
+	if (pioctl_req) {
+		ds_misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+		if (pioctl_req->action == MLAN_ACT_GET) {
+			cfp = wlan_get_region_cfp_table(pmadapter,
+							pmadapter->region_code,
+							ds_misc_cfg->param.cfp.
+							band, &cfp_no);
+			if (cfp) {
+				ds_misc_cfg->param.cfp.num_chan = cfp_no;
+				memcpy_ext(pmadapter,
+					   ds_misc_cfg->param.cfp.cfp_tbl, cfp,
+					   cfp_no * sizeof(chan_freq_power_t),
+					   cfp_no * sizeof(chan_freq_power_t));
+			}
+			ret = MLAN_STATUS_SUCCESS;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief	Get power tables and cfp tables for set region code
+ *			into the IOCTL request buffer
+ *
+ *  @param pmadapter	Private mlan adapter structure
+ *  @param pioctl_req	Pointer to the IOCTL request structure
+ *
+ *  @return	success, otherwise fail
+ *
+ */
+mlan_status
+wlan_get_cfpinfo(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	chan_freq_power_t *cfp_bg = MNULL;
+	t_u32 cfp_no_bg = 0;
+	chan_freq_power_t *cfp_a = MNULL;
+	t_u32 cfp_no_a = 0;
+	t_u8 cfp_code_a = pmadapter->region_code;
+	t_u8 cfp_code_bg = pmadapter->region_code;
+	t_u32 len = 0, size = 0;
+	t_u8 *req_buf, *tmp;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!pioctl_req || !pioctl_req->pbuf) {
+		PRINTM(MERROR, "MLAN IOCTL information is not present!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	/* Calculate the total response size required to return region,
+	 * country codes, cfp tables and power tables
+	 */
+	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
+	/* Add size to store region, country and environment codes */
+	size += sizeof(t_u32);
+	if (pmadapter->cfp_code_bg)
+		cfp_code_bg = pmadapter->cfp_code_bg;
+
+	/* Get cfp table and its size corresponding to the region code */
+	cfp_bg = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
+					   BAND_G | BAND_B, &cfp_no_bg);
+	size += cfp_no_bg * sizeof(chan_freq_power_t);
+	if (pmadapter->cfp_code_a)
+		cfp_code_a = pmadapter->cfp_code_a;
+	cfp_a = wlan_get_region_cfp_table(pmadapter, cfp_code_a,
+					  BAND_A, &cfp_no_a);
+	size += cfp_no_a * sizeof(chan_freq_power_t);
+	if (pmadapter->otp_region)
+		size += sizeof(pmadapter->otp_region->environment);
+
+	/* Get power table size */
+	if (pmadapter->tx_power_table_bg) {
+		size += pmadapter->tx_power_table_bg_size;
+		/* Add size to store table size, rows and cols */
+		size += 3 * sizeof(t_u32);
+	}
+	if (pmadapter->tx_power_table_a) {
+		size += pmadapter->tx_power_table_a_size;
+		size += 3 * sizeof(t_u32);
+	}
+	/* Check information buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < size) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->buf_len_needed = size;
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto out;
+	}
+	/* Copy the total size of region code, country code and environment
+	 * in first four bytes of the IOCTL request buffer and then copy
+	 * codes respectively in following bytes
+	 */
+	req_buf = (t_u8 *)pioctl_req->pbuf;
+	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
+	if (pmadapter->otp_region)
+		size += sizeof(pmadapter->otp_region->environment);
+	tmp = (t_u8 *)&size;
+	memcpy_ext(pmadapter, req_buf, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+	memcpy_ext(pmadapter, req_buf + len, &pmadapter->region_code,
+		   sizeof(pmadapter->region_code),
+		   sizeof(pmadapter->region_code));
+	len += sizeof(pmadapter->region_code);
+	memcpy_ext(pmadapter, req_buf + len, &pmadapter->country_code,
+		   sizeof(pmadapter->country_code),
+		   sizeof(pmadapter->country_code));
+	len += sizeof(pmadapter->country_code);
+	if (pmadapter->otp_region) {
+		memcpy_ext(pmadapter, req_buf + len,
+			   &pmadapter->otp_region->environment,
+			   sizeof(pmadapter->otp_region->environment),
+			   sizeof(pmadapter->otp_region->environment));
+		len += sizeof(pmadapter->otp_region->environment);
+	}
+	/* copy the cfp table size followed by the entire table */
+	if (!cfp_bg)
+		goto out;
+	size = cfp_no_bg * sizeof(chan_freq_power_t);
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+	memcpy_ext(pmadapter, req_buf + len, cfp_bg, size, size);
+	len += size;
+	if (!cfp_a)
+		goto out;
+	size = cfp_no_a * sizeof(chan_freq_power_t);
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+	memcpy_ext(pmadapter, req_buf + len, cfp_a, size, size);
+	len += size;
+	/* Copy the size of the power table, number of rows, number of cols
+	 * and the entire power table
+	 */
+	if (!pmadapter->tx_power_table_bg)
+		goto out;
+	size = pmadapter->tx_power_table_bg_size;
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+
+	/* No. of rows */
+	size = pmadapter->tx_power_table_bg_rows;
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+
+	/* No. of cols */
+	size = pmadapter->tx_power_table_bg_size /
+		pmadapter->tx_power_table_bg_rows;
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+	memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
+		   pmadapter->tx_power_table_bg_size,
+		   pmadapter->tx_power_table_bg_size);
+	len += pmadapter->tx_power_table_bg_size;
+	if (!pmadapter->tx_power_table_a)
+		goto out;
+	size = pmadapter->tx_power_table_a_size;
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+
+	/* No. of rows */
+	size = pmadapter->tx_power_table_a_rows;
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+
+	/* No. of cols */
+	size = pmadapter->tx_power_table_a_size /
+		pmadapter->tx_power_table_a_rows;
+	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
+	len += sizeof(size);
+	memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
+		   pmadapter->tx_power_table_a_size,
+		   pmadapter->tx_power_table_a_size);
+	len += pmadapter->tx_power_table_a_size;
+out:
+	if (pioctl_req)
+		pioctl_req->data_read_written = len;
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_cmdevt.c b/wlan_sd8987/mlan/mlan_cmdevt.c
new file mode 100755
index 0000000..61fdf5c
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_cmdevt.c
@@ -0,0 +1,9134 @@
+/**
+ * @file mlan_cmdevt.c
+ *
+ *  @brief This file contains the handling of CMD/EVENT in MLAN
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    05/12/2009: initial version
+************************************************************/
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+#include "mlan_init.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/*******************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function inserts scan command node to scan_pending_q.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *  @return             N/A
+ */
+static t_void
+wlan_queue_scan_cmd(mlan_private *pmpriv, cmd_ctrl_node *pcmd_node)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL)
+		goto done;
+	pcmd_node->cmd_flag |= CMD_F_SCAN;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->scan_pending_q,
+			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function check if cmd allowed to send to firmware
+ *         during scan
+ *
+ *  @param cmd_id     cmd id
+ *
+ *  @return           MTRUE/MFALSE
+ */
+static t_u8
+wlan_is_cmd_allowed_during_scan(t_u16 cmd_id)
+{
+	t_u8 ret = MTRUE;
+	ENTER();
+	switch (cmd_id) {
+	case HostCmd_CMD_FUNC_INIT:
+	case HostCmd_CMD_CFG_DATA:
+	case HostCmd_CMD_REGION_POWER_CFG:
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+	case HostCmd_CMD_802_11_ASSOCIATE:
+	case HostCmd_CMD_802_11_DEAUTHENTICATE:
+	case HostCmd_CMD_802_11_DISASSOCIATE:
+	case HostCmd_CMD_802_11_AD_HOC_START:
+	case HostCmd_CMD_802_11_AD_HOC_JOIN:
+	case HostCmd_CMD_802_11_AD_HOC_STOP:
+	case HostCmd_CMD_11N_ADDBA_REQ:
+	case HostCmd_CMD_11N_ADDBA_RSP:
+	case HostCmd_CMD_11N_DELBA:
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+	case HostCmd_CMD_TDLS_CONFIG:
+	case HostCmd_CMD_TDLS_OPERATION:
+	case HostCmd_CMD_SOFT_RESET:
+#ifdef UAP_SUPPORT
+	case HOST_CMD_APCMD_SYS_RESET:
+	case HOST_CMD_APCMD_BSS_START:
+	case HOST_CMD_APCMD_BSS_STOP:
+	case HOST_CMD_APCMD_STA_DEAUTH:
+#endif
+	case HostCMD_APCMD_ACS_SCAN:
+		ret = MFALSE;
+		break;
+	default:
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function move the cmd from scan_pending_q to
+ *        cmd_pending_q
+ *
+ *  @param cmd_id     cmd id
+ *
+ *  @return           MTRUE/MFALSE
+ */
+t_void
+wlan_move_cmd_to_cmd_pending_q(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+
+	ENTER();
+
+	wlan_request_cmd_lock(pmadapter);
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->scan_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->scan_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, MTRUE);
+	}
+	wlan_release_cmd_lock(pmadapter);
+	LEAVE();
+}
+
+/**
+ *  @brief This function inserts command node to scan_pending_q or
+ *  cmd_pending_q
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *  @return             N/A
+ */
+
+static t_void
+wlan_queue_cmd(mlan_private *pmpriv, cmd_ctrl_node *pcmd_node, t_u16 cmd_no)
+{
+	ENTER();
+	if (pmpriv->adapter->scan_processing &&
+	    pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+		if (MFALSE == wlan_is_cmd_allowed_during_scan(cmd_no)) {
+			PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x scan_pending_q\n",
+			       cmd_no);
+			wlan_queue_scan_cmd(pmpriv, pcmd_node);
+			return;
+		}
+	}
+	wlan_insert_cmd_to_pending_q(pmpriv->adapter, pcmd_node, MTRUE);
+	LEAVE();
+}
+
+/**
+ *  @brief Internal function used to flush the scan pending queue
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+static void
+wlan_check_scan_queue(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	t_u16 num = 0;
+
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->scan_pending_q,
+						    MNULL, MNULL);
+	if (!pcmd_node) {
+		PRINTM(MERROR, "No pending scan command\n");
+		return;
+	}
+	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->scan_pending_q) {
+		num++;
+		pcmd_node = pcmd_node->pnext;
+	}
+	PRINTM(MERROR, "num_pending_scan=%d\n", num);
+}
+#endif
+
+/**
+ *  @brief This function will dump the pending commands id
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *
+ *  @return             N/A
+ */
+static void
+wlan_dump_pending_commands(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	HostCmd_DS_COMMAND *pcmd;
+
+	ENTER();
+	wlan_request_cmd_lock(pmadapter);
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->cmd_pending_q,
+						    MNULL, MNULL);
+	if (!pcmd_node) {
+		wlan_release_cmd_lock(pmadapter);
+		LEAVE();
+		return;
+	}
+	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+					      pcmd_node->cmdbuf->data_offset);
+		PRINTM(MERROR, "pending command id: 0x%x ioctl_buf=%p\n",
+		       wlan_le16_to_cpu(pcmd->command), pcmd_node->pioctl_buf);
+		pcmd_node = pcmd_node->pnext;
+	}
+#ifdef STA_SUPPORT
+	wlan_check_scan_queue(pmadapter);
+#endif
+	wlan_release_cmd_lock(pmadapter);
+	LEAVE();
+	return;
+}
+
+#define REASON_CODE_NO_CMD_NODE 1
+#define REASON_CODE_CMD_TIMEOUT 2
+#define REASON_CODE_CMD_TO_CARD_FAILURE 3
+#define REASON_CODE_EXT_SCAN_TIMEOUT 4
+/**
+ *  @brief This function dump debug info
+ *
+ *  @return     N/A
+ */
+static t_void
+wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u16 i;
+#ifdef SDIO
+	t_u8 j;
+	t_u8 mp_aggr_pkt_limit;
+#endif
+	t_u16 cmd_id, cmd_act;
+	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+
+	ENTER();
+
+	PRINTM(MERROR, "------------Dump info-----------\n", reason);
+	switch (reason) {
+	case REASON_CODE_NO_CMD_NODE:
+		pmadapter->dbg.num_no_cmd_node++;
+		PRINTM(MERROR, "No Free command node\n");
+		break;
+	case REASON_CODE_CMD_TIMEOUT:
+		PRINTM(MERROR, "Commmand Timeout\n");
+		break;
+	case REASON_CODE_CMD_TO_CARD_FAILURE:
+		PRINTM(MERROR, "Command to card failure\n");
+		break;
+	case REASON_CODE_EXT_SCAN_TIMEOUT:
+		PRINTM(MERROR, "EXT_SCAN_STATUS event Timeout\n");
+		break;
+	default:
+		break;
+	}
+	if ((reason == REASON_CODE_NO_CMD_NODE) &&
+	    (pmadapter->dbg.num_no_cmd_node > 1)) {
+		if (pmadapter->dbg.num_no_cmd_node >= 5) {
+			if (pmpriv)
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+		}
+		LEAVE();
+		return;
+	}
+	wlan_dump_pending_commands(pmadapter);
+	if (reason != REASON_CODE_CMD_TIMEOUT) {
+		if (!pmadapter->curr_cmd) {
+			PRINTM(MERROR, "CurCmd Empty\n");
+		} else {
+			pcmd_node = pmadapter->curr_cmd;
+			cmd_id = pmadapter->dbg.last_cmd_id
+				[pmadapter->dbg.last_cmd_index];
+			cmd_act = pmadapter->dbg.last_cmd_act
+				[pmadapter->dbg.last_cmd_index];
+			PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+			PRINTM(MERROR,
+			       "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
+			       sec, usec, cmd_id, cmd_act);
+#if defined(SDIO) || defined(PCIE)
+			if (!IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
+				t_u8 *pcmd_buf;
+				pcmd_buf = pcmd_node->cmdbuf->pbuf +
+					pcmd_node->cmdbuf->data_offset +
+					pmadapter->ops.intf_header_len;
+				for (i = 0; i < 16; i++)
+					PRINTM(MERROR, "%02x ", *pcmd_buf++);
+				PRINTM(MERROR, "\n");
+			}
+#endif
+			pmpriv = pcmd_node->priv;
+			if (pmpriv)
+				PRINTM(MERROR, "BSS type = %d BSS role= %d\n",
+				       pmpriv->bss_type, pmpriv->bss_role);
+		}
+	}
+	PRINTM(MERROR, "mlan_processing =%d\n", pmadapter->mlan_processing);
+	PRINTM(MERROR, "main_lock_flag =%d\n", pmadapter->main_lock_flag);
+	PRINTM(MERROR, "main_process_cnt =%d\n", pmadapter->main_process_cnt);
+	PRINTM(MERROR, "delay_task_flag =%d\n", pmadapter->delay_task_flag);
+	PRINTM(MERROR, "mlan_rx_processing =%d\n",
+	       pmadapter->mlan_rx_processing);
+	PRINTM(MERROR, "rx_pkts_queued=%d\n", pmadapter->rx_pkts_queued);
+	PRINTM(MERROR, "more_task_flag = %d\n", pmadapter->more_task_flag);
+	PRINTM(MERROR, "num_cmd_timeout = %d\n", pmadapter->num_cmd_timeout);
+	PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index);
+	PRINTM(MERROR, "last_cmd_id = ");
+	for (i = 0; i < DBG_CMD_NUM; i++)
+		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]);
+	PRINTM(MERROR, "\n");
+	PRINTM(MERROR, "last_cmd_act = ");
+	for (i = 0; i < DBG_CMD_NUM; i++)
+		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]);
+	PRINTM(MERROR, "\n");
+	PRINTM(MERROR, "last_cmd_resp_index = %d\n",
+	       pmadapter->dbg.last_cmd_resp_index);
+	PRINTM(MERROR, "last_cmd_resp_id = ");
+	for (i = 0; i < DBG_CMD_NUM; i++)
+		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]);
+	PRINTM(MERROR, "\n");
+	PRINTM(MERROR, "last_event_index = %d\n",
+	       pmadapter->dbg.last_event_index);
+	PRINTM(MERROR, "last_event = ");
+	for (i = 0; i < DBG_CMD_NUM; i++)
+		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]);
+	PRINTM(MERROR, "\n");
+
+	PRINTM(MERROR, "num_data_h2c_failure = %d\n",
+	       pmadapter->dbg.num_tx_host_to_card_failure);
+	PRINTM(MERROR, "num_cmd_h2c_failure = %d\n",
+	       pmadapter->dbg.num_cmd_host_to_card_failure);
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		PRINTM(MERROR, "num_data_c2h_failure = %d\n",
+		       pmadapter->dbg.num_rx_card_to_host_failure);
+		PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n",
+		       pmadapter->dbg.num_cmdevt_card_to_host_failure);
+		PRINTM(MERROR, "num_int_read_failure = %d\n",
+		       pmadapter->dbg.num_int_read_failure);
+		PRINTM(MERROR, "last_int_status = %d\n",
+		       pmadapter->dbg.last_int_status);
+	}
+#endif
+	PRINTM(MERROR, "num_alloc_buffer_failure = %d\n",
+	       pmadapter->dbg.num_alloc_buffer_failure);
+	PRINTM(MERROR, "num_pkt_dropped = %d\n",
+	       pmadapter->dbg.num_pkt_dropped);
+	PRINTM(MERROR, "num_no_cmd_node = %d\n",
+	       pmadapter->dbg.num_no_cmd_node);
+	PRINTM(MERROR, "num_event_deauth = %d\n",
+	       pmadapter->dbg.num_event_deauth);
+	PRINTM(MERROR, "num_event_disassoc = %d\n",
+	       pmadapter->dbg.num_event_disassoc);
+	PRINTM(MERROR, "num_event_link_lost = %d\n",
+	       pmadapter->dbg.num_event_link_lost);
+	PRINTM(MERROR, "num_cmd_deauth = %d\n", pmadapter->dbg.num_cmd_deauth);
+	PRINTM(MERROR, "num_cmd_assoc_success = %d\n",
+	       pmadapter->dbg.num_cmd_assoc_success);
+	PRINTM(MERROR, "num_cmd_assoc_failure = %d\n",
+	       pmadapter->dbg.num_cmd_assoc_failure);
+	PRINTM(MERROR, "num_cons_assoc_failure = %d\n",
+	       pmadapter->dbg.num_cons_assoc_failure);
+	PRINTM(MERROR, "cmd_resp_received=%d\n", pmadapter->cmd_resp_received);
+	PRINTM(MERROR, "event_received=%d\n", pmadapter->event_received);
+
+	PRINTM(MERROR, "max_tx_buf_size=%d\n", pmadapter->max_tx_buf_size);
+	PRINTM(MERROR, "tx_buf_size=%d\n", pmadapter->tx_buf_size);
+	PRINTM(MERROR, "curr_tx_buf_size=%d\n", pmadapter->curr_tx_buf_size);
+
+	PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent,
+	       pmadapter->cmd_sent);
+
+	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode,
+	       pmadapter->ps_state);
+	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d wakeup_timeout=%d\n",
+	       pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try,
+	       pmadapter->pm_wakeup_timeout);
+	PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n",
+	       pmadapter->is_hs_configured, pmadapter->hs_activated);
+	PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n",
+	       pmadapter->pps_uapsd_mode, pmadapter->sleep_period.period);
+	PRINTM(MERROR, "tx_lock_flag = %d\n", pmadapter->tx_lock_flag);
+	PRINTM(MERROR, "scan_processing = %d\n", pmadapter->scan_processing);
+	PRINTM(MERROR, "bypass_pkt_count=%d\n", pmadapter->bypass_pkt_count);
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
+		PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+		       pmadapter->pcard_sd->mp_rd_bitmap,
+		       pmadapter->pcard_sd->curr_rd_port);
+		PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+		       pmadapter->pcard_sd->mp_wr_bitmap,
+		       pmadapter->pcard_sd->curr_wr_port);
+		PRINTM(MMSG, "mp_data_port_mask = 0x%x\n",
+		       pmadapter->pcard_sd->mp_data_port_mask);
+
+		PRINTM(MERROR,
+		       "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n",
+		       pmadapter->pcard_sd->last_recv_rd_bitmap,
+		       pmadapter->pcard_sd->mp_invalid_update);
+		PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
+		       pmadapter->pcard_sd->last_recv_wr_bitmap,
+		       pmadapter->pcard_sd->last_mp_index);
+		for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
+			PRINTM(MERROR,
+			       "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n",
+			       pmadapter->pcard_sd->last_mp_wr_bitmap[i],
+			       pmadapter->pcard_sd->last_mp_wr_ports[i],
+			       pmadapter->pcard_sd->last_mp_wr_len[i],
+			       pmadapter->pcard_sd->last_curr_wr_port[i]);
+			for (j = 0; j < mp_aggr_pkt_limit; j++) {
+				PRINTM(MERROR, "0x%02x ",
+				       pmadapter->pcard_sd->last_mp_wr_info
+				       [i * mp_aggr_pkt_limit + j]);
+			}
+			PRINTM(MERROR, "\n");
+		}
+	}
+#endif
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type)) {
+		PRINTM(MERROR, "txbd_rdptr=0x%x txbd_wrptr=0x%x\n",
+		       pmadapter->pcard_pcie->txbd_rdptr,
+		       pmadapter->pcard_pcie->txbd_wrptr);
+		PRINTM(MERROR, "rxbd_rdptr=0x%x rxbd_wrptr=0x%x\n",
+		       pmadapter->pcard_pcie->rxbd_rdptr,
+		       pmadapter->pcard_pcie->rxbd_wrptr);
+		PRINTM(MERROR, "evtbd_rdptr=0x%x evt_wrptr=0x%x\n",
+		       pmadapter->pcard_pcie->evtbd_rdptr,
+		       pmadapter->pcard_pcie->evtbd_wrptr);
+		PRINTM(MERROR, "last_wr_index:%d\n",
+		       pmadapter->pcard_pcie->txbd_wrptr &
+		       (pmadapter->pcard_pcie->txrx_bd_size - 1));
+		PRINTM(MERROR, " txrx_bd_size = %d\n",
+		       pmadapter->pcard_pcie->txrx_bd_size);
+		PRINTM(MERROR, "Tx pkt size:\n");
+		for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
+			PRINTM(MERROR, "%04d ",
+			       pmadapter->pcard_pcie->last_tx_pkt_size[i]);
+			if (((i + 1) % 16) == 0)
+				PRINTM(MERROR, "\n");
+		}
+	}
+#endif
+	for (i = 0; i < pmadapter->priv_num; ++i) {
+		if (pmadapter->priv[i])
+			wlan_dump_ralist(pmadapter->priv[i]);
+	}
+	if (reason != REASON_CODE_CMD_TIMEOUT) {
+		if ((pmadapter->dbg.num_no_cmd_node >= 5)
+		    || (pmadapter->pm_wakeup_card_req &&
+			pmadapter->pm_wakeup_fw_try)
+		    || (reason == REASON_CODE_EXT_SCAN_TIMEOUT)
+			) {
+			if (pmpriv)
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_DBG_DUMP,
+						MNULL);
+			else {
+				pmpriv = wlan_get_priv(pmadapter,
+						       MLAN_BSS_ROLE_ANY);
+				if (pmpriv)
+					wlan_recv_event(pmpriv,
+							MLAN_EVENT_ID_DRV_DBG_DUMP,
+							MNULL);
+			}
+		}
+	}
+	PRINTM(MERROR, "-------- Dump info End---------\n", reason);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function convert a given character to hex
+ *
+ *  @param chr        Character to be converted
+ *
+ *  @return           The converted hex if chr is a valid hex, else 0
+ */
+static t_u32
+wlan_hexval(t_u8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		return chr - '0';
+	if (chr >= 'A' && chr <= 'F')
+		return chr - 'A' + 10;
+	if (chr >= 'a' && chr <= 'f')
+		return chr - 'a' + 10;
+
+	return 0;
+}
+
+/**
+ *  @brief This function convert a given string to hex
+ *
+ *  @param a            A pointer to string to be converted
+ *
+ *  @return             The converted hex value if param a is a valid hex, else
+ * 0
+ */
+static int
+wlan_atox(t_u8 *a)
+{
+	int i = 0;
+
+	ENTER();
+
+	while (wlan_isxdigit(*a))
+		i = i * 16 + wlan_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief This function parse cal data from ASCII to hex
+ *
+ *  @param src          A pointer to source data
+ *  @param len          Source data length
+ *  @param dst          A pointer to a buf to store the parsed data
+ *
+ *  @return             The parsed hex data length
+ */
+static t_u32
+wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
+{
+	t_u8 *ptr;
+	t_u8 *dptr;
+
+	ENTER();
+	ptr = src;
+	dptr = dst;
+
+	while (ptr - src < len) {
+		if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
+			ptr++;
+			continue;
+		}
+
+		if (wlan_isxdigit(*ptr)) {
+			*dptr++ = wlan_atox(ptr);
+			ptr += 2;
+		} else {
+			ptr++;
+		}
+	}
+	LEAVE();
+	return dptr - dst;
+}
+
+/**
+ *  @brief This function finds first occurrence of a char in a string
+ *
+ *  @param s            A pointer to the string to be searched
+ *  @param c            The character to search for
+ *
+ *  @return             Location of the first occurrence of the char
+ *                      if found, else NULL
+ */
+static t_u8 *
+wlan_strchr(t_u8 *s, int c)
+{
+	t_u8 *pos = s;
+	while (*pos != '\0') {
+		if (*pos == (t_u8)c)
+			return pos;
+		pos++;
+	}
+	return MNULL;
+}
+
+#define CFG_TYPE_HOSTCMD 0
+#define CFG_TYPE_DPDFILE 1
+
+/**
+ *    @brief WOAL parse ASCII format raw data to hex format
+ *
+ *    @param pmpriv       MOAL handle
+ *    @param cfg_type     Conf file type
+ *    @param data         Source data
+ *    @param size         data length
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+wlan_process_hostcmd_cfg(pmlan_private pmpriv,
+			 t_u16 cfg_type, t_u8 *data, t_size size)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *pos = data;
+	t_u8 *intf_s, *intf_e;
+	t_u8 *buf = MNULL;
+	t_u8 *ptr = MNULL;
+	t_u32 cmd_len = 0;
+	t_u8 start_raw = MFALSE;
+	mlan_ds_misc_cmd *hostcmd;
+	HostCmd_DS_GEN *pcmd = MNULL;
+	HostCmd_DS_802_11_CFG_DATA *pcfg_cmd = MNULL;
+	mlan_adapter *pmadapter = MNULL;
+	mlan_callbacks *pcb = MNULL;
+	t_u8 hostcmd_flag = MFALSE;
+
+	ENTER();
+	if (!pmpriv) {
+		PRINTM(MERROR, "pmpriv is NULL\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter = pmpriv->adapter;
+	pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+			       (t_u8 **)&hostcmd);
+	if (ret || !hostcmd) {
+		PRINTM(MERROR, "Could not allocate buffer space!\n");
+		LEAVE();
+		return ret;
+	}
+	buf = hostcmd->cmd;
+	ptr = buf;
+	while ((pos - data) < size) {
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos == '#') {	/* Line comment */
+			while (*pos != '\n')
+				pos++;
+			pos++;
+		}
+		if ((*pos == '\r' && *(pos + 1) == '\n') || *pos == '\n' ||
+		    *pos == '\0') {
+			pos++;
+			continue;	/* Needn't process this line */
+		}
+
+		if (*pos == '}') {
+			if (cfg_type == CFG_TYPE_DPDFILE && pcmd) {
+				/* Fill command head for DPD RAW data conf */
+				hostcmd->len = ptr - buf;
+				pcmd->command =
+					wlan_cpu_to_le16(HostCmd_CMD_CFG_DATA);
+				pcmd->size = wlan_cpu_to_le16(hostcmd->len);
+				pcfg_cmd = (HostCmd_DS_802_11_CFG_DATA
+					    *)((t_u8 *)pcmd + S_DS_GEN);
+				pcfg_cmd->action =
+					wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+				pcfg_cmd->type = wlan_cpu_to_le16(OID_TYPE_DPD);
+				pcfg_cmd->data_len =
+					wlan_cpu_to_le16(hostcmd->len -
+							 S_DS_GEN -
+							 sizeof
+							 (HostCmd_DS_802_11_CFG_DATA));
+				pcmd = MNULL;
+				pcfg_cmd = MNULL;
+			} else {
+				/* For hostcmd data conf */
+				cmd_len = *((t_u16 *)(buf + sizeof(t_u16)));
+				hostcmd->len = cmd_len;
+			}
+			ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, MNULL,
+					       (t_void *)hostcmd);
+			memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+			ptr = buf;
+			start_raw = MFALSE;
+			pos++;
+			continue;
+		}
+
+		if (start_raw == MFALSE) {
+			intf_s = wlan_strchr(pos, '=');
+			if (intf_s) {
+				if (*(intf_s + 1) == '=')
+					hostcmd_flag = MTRUE;
+				intf_e = wlan_strchr(intf_s, '{');
+			} else
+				intf_e = MNULL;
+
+			if (intf_s && intf_e) {
+				start_raw = MTRUE;
+				pos = intf_e + 1;
+				/* Reserve command head for DPD RAW data conf */
+				if (cfg_type == CFG_TYPE_DPDFILE &&
+				    !hostcmd_flag) {
+					pcmd = (HostCmd_DS_GEN *)ptr;
+					ptr += S_DS_GEN +
+						sizeof
+						(HostCmd_DS_802_11_CFG_DATA);
+				}
+				continue;
+			}
+		}
+
+		if (start_raw) {
+			/* Raw data block exists */
+			while (*pos != '\n') {
+				if ((*pos <= 'f' && *pos >= 'a') ||
+				    (*pos <= 'F' && *pos >= 'A') ||
+				    (*pos <= '9' && *pos >= '0')) {
+					*ptr++ = wlan_atox(pos);
+					pos += 2;
+				} else
+					pos++;
+			}
+		}
+	}
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes the command node.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *  @param cmd_no       cmd id
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param pdata_buf    A pointer to information buffer
+ *
+ *  @return             N/A
+ */
+static void
+wlan_init_cmd_node(pmlan_private pmpriv,
+		   cmd_ctrl_node *pcmd_node, t_u32 cmd_no,
+		   t_void *pioctl_buf, t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (pcmd_node == MNULL) {
+		LEAVE();
+		return;
+	}
+	pcmd_node->priv = pmpriv;
+	pcmd_node->cmd_no = cmd_no;
+	pcmd_node->pioctl_buf = pioctl_buf;
+	pcmd_node->pdata_buf = pdata_buf;
+
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		pcmd_node->cmdbuf =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+					       MOAL_MALLOC_BUFFER);
+		if (!pcmd_node->cmdbuf) {
+			PRINTM(MERROR, "Failed to allocate cmd_buffer\n");
+			LEAVE();
+			return;
+		}
+	}
+#endif /* USB */
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type))
+		pcmd_node->cmdbuf = pcmd_node->pmbuf;
+#endif
+
+	/* Make sure head_ptr for cmd buf is Align */
+	pcmd_node->cmdbuf->data_offset = 0;
+	memset(pmadapter, pcmd_node->cmdbuf->pbuf, 0,
+	       MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	/* Prepare mlan_buffer for command sending */
+	pcmd_node->cmdbuf->buf_type = MLAN_BUF_TYPE_CMD;
+#ifdef USB
+	if (IS_USB(pmadapter->card_type))
+		pcmd_node->cmdbuf->data_offset += MLAN_TYPE_LEN;
+#endif
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type))
+		pcmd_node->cmdbuf->data_offset +=
+			pmadapter->ops.intf_header_len;
+#endif
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function gets a free command node if available in
+ *              command free queue.
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *
+ *  @return cmd_ctrl_node   A pointer to cmd_ctrl_node structure or MNULL
+ */
+static cmd_ctrl_node *
+wlan_get_cmd_node(mlan_adapter *pmadapter)
+{
+	cmd_ctrl_node *pcmd_node;
+
+	ENTER();
+
+	if (pmadapter == MNULL) {
+		LEAVE();
+		return MNULL;
+	}
+	wlan_request_cmd_lock(pmadapter);
+	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
+			   MNULL, MNULL)) {
+		pcmd_node =
+			(cmd_ctrl_node *)util_dequeue_list(pmadapter->
+							   pmoal_handle,
+							   &pmadapter->
+							   cmd_free_q, MNULL,
+							   MNULL);
+	} else {
+		PRINTM(MERROR,
+		       "GET_CMD_NODE: cmd_ctrl_node is not available\n");
+		pcmd_node = MNULL;
+	}
+	wlan_release_cmd_lock(pmadapter);
+	LEAVE();
+	return pcmd_node;
+}
+
+/**
+ *  @brief This function cleans command node.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_clean_cmd_node(pmlan_adapter pmadapter, cmd_ctrl_node *pcmd_node)
+{
+	ENTER();
+
+	if (pcmd_node == MNULL) {
+		LEAVE();
+		return;
+	}
+	pcmd_node->cmd_no = 0;
+	pcmd_node->cmd_flag = 0;
+	pcmd_node->pioctl_buf = MNULL;
+	pcmd_node->pdata_buf = MNULL;
+
+#ifdef USB
+	if (IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
+		wlan_free_mlan_buffer(pmadapter, pcmd_node->cmdbuf);
+		pcmd_node->cmdbuf = MNULL;
+	}
+#endif
+
+	if (pcmd_node->respbuf) {
+		pmadapter->ops.cmdrsp_complete(pmadapter, pcmd_node->respbuf,
+					       MLAN_STATUS_SUCCESS);
+		pcmd_node->respbuf = MNULL;
+	}
+
+	LEAVE();
+	return;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function will return the pointer to the first entry in
+ *          pending cmd which is scan command
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *
+ *  @return             A pointer to first entry match pioctl_req
+ */
+static cmd_ctrl_node *
+wlan_get_pending_scan_cmd(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+
+	ENTER();
+
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->cmd_pending_q,
+						    MNULL, MNULL);
+	if (!pcmd_node) {
+		LEAVE();
+		return MNULL;
+	}
+	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+		if (pcmd_node->cmd_flag & CMD_F_SCAN) {
+			LEAVE();
+			return pcmd_node;
+		}
+		pcmd_node = pcmd_node->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+#endif
+
+/**
+ *  @brief This function will return the pointer to the first entry in
+ *          pending cmd which matches the given pioctl_req
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param pioctl_req   A pointer to mlan_ioctl_req buf
+ *
+ *  @return             A pointer to first entry match pioctl_req
+ */
+static cmd_ctrl_node *
+wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+
+	ENTER();
+
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->cmd_pending_q,
+						    MNULL, MNULL);
+	if (!pcmd_node) {
+		LEAVE();
+		return MNULL;
+	}
+	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+		if (pcmd_node->pioctl_buf &&
+		    (pcmd_node->pioctl_buf == pioctl_req)) {
+			LEAVE();
+			return pcmd_node;
+		}
+		pcmd_node = pcmd_node->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function will return the pointer to the first entry in
+ *          pending cmd which matches the given bss_index
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param bss_index    bss_index
+ *
+ *  @return             A pointer to first entry match pioctl_req
+ */
+static cmd_ctrl_node *
+wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	ENTER();
+
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->cmd_pending_q,
+						    MNULL, MNULL);
+	if (!pcmd_node) {
+		LEAVE();
+		return MNULL;
+	}
+	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			if (pioctl_buf->bss_index == bss_index) {
+				LEAVE();
+				return pcmd_node;
+			}
+		}
+		pcmd_node = pcmd_node->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function handles the command response of host_cmd
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_host_cmd(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc;
+	t_u16 size = wlan_le16_to_cpu(resp->size);
+
+	ENTER();
+
+	PRINTM(MINFO, "host command response size = %d\n", size);
+	size = MIN(size, MRVDRV_SIZE_OF_CMD_BUFFER);
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc->param.hostcmd.len = size;
+		memcpy_ext(pmpriv->adapter, misc->param.hostcmd.cmd,
+			   (void *)resp, size, MRVDRV_SIZE_OF_CMD_BUFFER);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends host command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @param cmd_no       A pointer to cmd_no
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_host_cmd(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *cmd, t_void *pdata_buf, t_u16 *cmd_no)
+{
+	mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
+
+	ENTER();
+
+	/* Copy the HOST command to command buffer */
+	memcpy_ext(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd, pcmd_ptr->len,
+		   MRVDRV_SIZE_OF_CMD_BUFFER);
+	*cmd_no = wlan_le16_to_cpu(cmd->command);
+	PRINTM(MCMND, "Prepare Host command: 0x%x size = %d\n", *cmd_no,
+	       pcmd_ptr->len);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function get the cmd timeout value
+ *
+ *  @param cmd_id     cmd id
+ *
+ *  @return           timeout value for this command
+ */
+static t_u16
+wlan_get_cmd_timeout(t_u16 cmd_id)
+{
+	t_u16 timeout;
+	ENTER();
+	switch (cmd_id) {
+	case HostCmd_CMD_802_11_SCAN:
+	case HostCmd_CMD_802_11_SCAN_EXT:
+		timeout = MRVDRV_TIMER_10S * 2;
+		break;
+	case HostCmd_CMD_FUNC_INIT:
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+	case HostCmd_CMD_802_11_ASSOCIATE:
+	case HostCmd_CMD_802_11_DEAUTHENTICATE:
+	case HostCmd_CMD_802_11_DISASSOCIATE:
+	case HostCmd_CMD_802_11_AD_HOC_START:
+	case HostCmd_CMD_802_11_AD_HOC_JOIN:
+	case HostCmd_CMD_802_11_AD_HOC_STOP:
+	case HostCmd_CMD_11N_ADDBA_REQ:
+	case HostCmd_CMD_11N_ADDBA_RSP:
+	case HostCmd_CMD_11N_DELBA:
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+	case HostCmd_CMD_TDLS_CONFIG:
+	case HostCmd_CMD_TDLS_OPERATION:
+	case HostCmd_CMD_SUPPLICANT_PMK:
+	case HostCmd_CMD_SUPPLICANT_PROFILE:
+	case HostCmd_CMD_SOFT_RESET:
+#ifdef UAP_SUPPORT
+	case HOST_CMD_APCMD_SYS_RESET:
+	case HOST_CMD_APCMD_BSS_START:
+	case HOST_CMD_APCMD_BSS_STOP:
+	case HOST_CMD_APCMD_STA_DEAUTH:
+#endif
+	case HostCMD_APCMD_ACS_SCAN:
+		timeout = MRVDRV_TIMER_5S;
+		break;
+	default:
+#ifdef IMX_SUPPORT
+		/*
+		 * During the roaming test and the 5AP connection test, cmd timeout are observed
+		 * for commands like 0x5e, 0x16, 0xd1. Observed that response has come just after
+		 * default timeout of 2 seconds for these commands. This random timeout is not
+		 * observed when the default timeout is increased to 5 seconds
+		 * (As an work around, Increase the default timeout to 5 seconds.
+		 * Need to further debug exact reason for delay in cmd responses)
+		 *
+		 */
+		timeout = MRVDRV_TIMER_1S * 5;
+#else
+		timeout = MRVDRV_TIMER_1S * 5;
+#endif
+		break;
+	}
+	LEAVE();
+	return timeout;
+}
+
+/**
+ *  @brief This function downloads a command to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_dnld_cmd_to_fw(mlan_private *pmpriv, cmd_ctrl_node *pcmd_node)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_COMMAND *pcmd;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	t_u16 cmd_code;
+	t_u16 cmd_size;
+	t_u32 age_ts_usec;
+#ifdef USB
+	t_u32 tmp;
+#endif
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u16 timeout = 0;
+
+	ENTER();
+
+	if (pcmd_node)
+		if (pcmd_node->pioctl_buf != MNULL)
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+	if (!pmadapter || !pcmd_node) {
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+				      pcmd_node->cmdbuf->data_offset);
+
+	/* Sanity test */
+	if (pcmd == MNULL || pcmd->size == 0) {
+		PRINTM(MERROR,
+		       "DNLD_CMD: pcmd is null or command size is zero, "
+		       "Not sending\n");
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Set command sequence number */
+	pmadapter->seq_num++;
+	pcmd->seq_num =
+		wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
+				 (pmadapter->seq_num, pcmd_node->priv->bss_num,
+				  pcmd_node->priv->bss_type));
+	cmd_code = wlan_le16_to_cpu(pcmd->command);
+	pcmd_node->cmd_no = cmd_code;
+	timeout = wlan_get_cmd_timeout(cmd_code);
+	cmd_size = wlan_le16_to_cpu(pcmd->size);
+
+	pcmd_node->cmdbuf->data_len = cmd_size;
+
+	wlan_request_cmd_lock(pmadapter);
+	pmadapter->curr_cmd = pcmd_node;
+	wlan_release_cmd_lock(pmadapter);
+
+	/* Save the last command id and action to debug log */
+	pmadapter->dbg.last_cmd_index =
+		(pmadapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
+	pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index] = cmd_code;
+	pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index] =
+		wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN));
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->dnld_cmd_in_secs,
+						  &age_ts_usec);
+
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		/* Add extra header for USB */
+		if (pcmd_node->cmdbuf->data_offset < MLAN_TYPE_LEN) {
+			PRINTM(MERROR,
+			       "DNLD_CMD: data_offset is too small=%d\n",
+			       pcmd_node->cmdbuf->data_offset);
+			if (pioctl_buf)
+				pioctl_buf->status_code =
+					MLAN_ERROR_CMD_DNLD_FAIL;
+
+			wlan_request_cmd_lock(pmadapter);
+			wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+			pmadapter->curr_cmd = MNULL;
+			wlan_release_cmd_lock(pmadapter);
+			if (pmadapter->dbg.last_cmd_index)
+				pmadapter->dbg.last_cmd_index--;
+			else
+				pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		tmp = wlan_cpu_to_le32(MLAN_USB_TYPE_CMD);
+		memcpy_ext(pmadapter, (t_u8 *)pcmd - MLAN_TYPE_LEN,
+			   (t_u8 *)&tmp, MLAN_TYPE_LEN, MLAN_TYPE_LEN);
+		pcmd_node->cmdbuf->data_offset -= MLAN_TYPE_LEN;
+		pcmd_node->cmdbuf->data_len += MLAN_TYPE_LEN;
+	}
+#endif
+
+	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
+	PRINTM_NETINTF(MCMND, pmpriv);
+	PRINTM(MCMND,
+	       "DNLD_CMD (%lu.%06lu): 0x%x, act 0x%x, len %d, seqno 0x%x timeout %d\n",
+	       sec, usec, cmd_code,
+	       wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN)), cmd_size,
+	       wlan_le16_to_cpu(pcmd->seq_num), timeout);
+	DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
+
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type)) {
+		pcmd_node->cmdbuf->data_offset -=
+			pmadapter->ops.intf_header_len;
+		pcmd_node->cmdbuf->data_len += pmadapter->ops.intf_header_len;
+	}
+#endif
+
+	/* Send the command to lower layer */
+	ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_CMD,
+					  pcmd_node->cmdbuf, MNULL);
+
+#ifdef USB
+	if (IS_USB(pmadapter->card_type) && (ret == MLAN_STATUS_PENDING))
+		pcmd_node->cmdbuf = MNULL;
+#endif
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR, "DNLD_CMD: Host to Card Failed\n");
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		}
+
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+		pmadapter->curr_cmd = MNULL;
+		wlan_release_cmd_lock(pmadapter);
+		if (pmadapter->dbg.last_cmd_index)
+			pmadapter->dbg.last_cmd_index--;
+		else
+			pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
+
+		pmadapter->dbg.num_cmd_host_to_card_failure++;
+		wlan_dump_info(pmadapter, REASON_CODE_CMD_TO_CARD_FAILURE);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Clear BSS_NO_BITS from HostCmd */
+	cmd_code &= HostCmd_CMD_ID_MASK;
+
+	/* For the command who has no command response, we should return here */
+	if (cmd_code == HostCmd_CMD_FW_DUMP_EVENT
+	    || cmd_code == HostCmd_CMD_SOFT_RESET) {
+		if (pcmd_node->pioctl_buf) {
+			PRINTM(MMSG,
+			       "CMD(0x%x) has no cmd resp: free curr_cmd and do ioctl_complete\n",
+			       cmd_code);
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			wlan_request_cmd_lock(pmadapter);
+			wlan_insert_cmd_to_free_q(pmadapter,
+						  pmadapter->curr_cmd);
+			pmadapter->curr_cmd = MNULL;
+			wlan_release_cmd_lock(pmadapter);
+		}
+		goto done;
+	}
+
+	/* Setup the timer after transmit command */
+	pcb->moal_start_timer(pmadapter->pmoal_handle,
+			      pmadapter->pmlan_cmd_timer, MFALSE, timeout);
+
+	pmadapter->cmd_timer_is_set = MTRUE;
+
+	ret = MLAN_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends sleep confirm command to firmware.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_dnld_sleep_confirm_cmd(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	static t_u32 i;
+#if defined(SDIO) || defined(PCIE)
+	t_u16 cmd_len = 0;
+#endif
+	opt_sleep_confirm_buffer *sleep_cfm_buf =
+		(opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
+					     pmadapter->psleep_cfm->
+					     data_offset);
+	mlan_buffer *pmbuf = MNULL;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type)) {
+		cmd_len = sizeof(OPT_Confirm_Sleep);
+		pmbuf = pmadapter->psleep_cfm;
+	}
+#endif
+	pmadapter->seq_num++;
+	sleep_cfm_buf->ps_cfm_sleep.seq_num =
+		wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
+				 (pmadapter->seq_num, pmpriv->bss_num,
+				  pmpriv->bss_type));
+	DBG_HEXDUMP(MCMD_D, "SLEEP_CFM", &sleep_cfm_buf->ps_cfm_sleep,
+		    sizeof(OPT_Confirm_Sleep));
+
+	/* Send sleep confirm command to firmware */
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+					       sizeof(opt_sleep_confirm_buffer),
+					       0, MOAL_MALLOC_BUFFER);
+
+		if (!pmbuf) {
+			PRINTM(MERROR,
+			       "Failed to allocate sleep confirm buffers\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmbuf->buf_type = MLAN_BUF_TYPE_CMD;
+		pmbuf->data_len = pmadapter->psleep_cfm->data_len;
+		memcpy_ext(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
+			   pmadapter->psleep_cfm->pbuf +
+			   pmadapter->psleep_cfm->data_offset,
+			   pmadapter->psleep_cfm->data_len, pmbuf->data_len);
+	}
+#endif /* USB */
+
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type))
+		pmadapter->psleep_cfm->data_len =
+			cmd_len + pmadapter->ops.intf_header_len;
+#endif
+
+	if (pmbuf)
+		ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_CMD, pmbuf,
+						  MNULL);
+
+#ifdef USB
+	if (IS_USB(pmadapter->card_type) && (ret != MLAN_STATUS_PENDING))
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR, "SLEEP_CFM: failed\n");
+		pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
+		goto done;
+	} else {
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+			pmadapter->ps_state = PS_STATE_SLEEP_CFM;
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+			if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl) {
+				/* Response is not needed for sleep confirm
+				 * command */
+				pmadapter->ps_state = PS_STATE_SLEEP;
+			} else {
+				pmadapter->ps_state = PS_STATE_SLEEP_CFM;
+			}
+
+			if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl &&
+			    (pmadapter->is_hs_configured &&
+			     !pmadapter->sleep_period.period)) {
+				pmadapter->pm_wakeup_card_req = MTRUE;
+				wlan_host_sleep_activated_event(wlan_get_priv
+								(pmadapter,
+								 MLAN_BSS_ROLE_STA),
+								MTRUE);
+			}
+		}
+#endif /* STA_SUPPORT */
+
+		PRINTM_NETINTF(MEVENT, pmpriv);
+#define NUM_SC_PER_LINE 16
+		if (++i % NUM_SC_PER_LINE == 0)
+			PRINTM(MEVENT, "+\n");
+		else
+			PRINTM(MEVENT, "+");
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Fetch bitmap rate index
+ *
+ *  @param rate_scope	A pointer to MrvlRateScope_t
+ *
+ *  @return		bitmap rate index
+ */
+static t_u16
+wlan_get_bitmap_index(MrvlRateScope_t *rate_scope)
+{
+	t_u16 index = 0;
+
+	if (rate_scope != MNULL) {
+		index += NELEMENTS(rate_scope->ht_mcs_rate_bitmap);
+		index += NELEMENTS(rate_scope->vht_mcs_rate_bitmap);
+	}
+
+	return index;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Event handler
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param event_id Event ID
+ *  @param pmevent  Event buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_recv_event(pmlan_private priv, mlan_event_id event_id, t_void *pmevent)
+{
+	pmlan_callbacks pcb = MNULL;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pcb = &priv->adapter->callbacks;
+
+	if (pmevent)
+		/* The caller has provided the event. */
+		pcb->moal_recv_event(priv->adapter->pmoal_handle,
+				     (pmlan_event)pmevent);
+	else {
+		mlan_event mevent;
+
+		memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
+		mevent.bss_index = priv->bss_index;
+		mevent.event_id = event_id;
+		mevent.event_len = 0;
+
+		pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates the command buffer and links
+ *          it to command free queue.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_cmd_buffer(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_array = MNULL;
+	t_u32 buf_size;
+	t_u32 i;
+
+	ENTER();
+
+	/* Allocate and initialize cmd_ctrl_node */
+	buf_size = sizeof(cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+			       MLAN_MEM_DEF | MLAN_MEM_DMA,
+			       (t_u8 **)&pcmd_array);
+	if (ret != MLAN_STATUS_SUCCESS || !pcmd_array) {
+		PRINTM(MERROR,
+		       "ALLOC_CMD_BUF: Failed to allocate pcmd_array\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	pmadapter->cmd_pool = pcmd_array;
+	memset(pmadapter, pmadapter->cmd_pool, 0, buf_size);
+
+#if defined(PCIE) || defined(SDIO)
+	if (!IS_USB(pmadapter->card_type)) {
+		/* Allocate and initialize command buffers */
+		for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+			pcmd_array[i].pmbuf =
+				wlan_alloc_mlan_buffer(pmadapter,
+						       MRVDRV_SIZE_OF_CMD_BUFFER,
+						       0, MOAL_MALLOC_BUFFER);
+			if (!pcmd_array[i].pmbuf) {
+				PRINTM(MERROR,
+				       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+	}
+#endif
+	wlan_request_cmd_lock(pmadapter);
+	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++)
+		wlan_insert_cmd_to_free_q(pmadapter, &pcmd_array[i]);
+	wlan_release_cmd_lock(pmadapter);
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the command buffer.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_free_cmd_buffer(mlan_adapter *pmadapter)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_array;
+	t_u32 i;
+
+	ENTER();
+
+	/* Need to check if cmd pool is allocated or not */
+	if (pmadapter->cmd_pool == MNULL) {
+		PRINTM(MINFO, "FREE_CMD_BUF: cmd_pool is Null\n");
+		goto done;
+	}
+
+	pcmd_array = pmadapter->cmd_pool;
+
+	/* Release shared memory buffers */
+	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+#ifdef USB
+		if (IS_USB(pmadapter->card_type) && pcmd_array[i].cmdbuf) {
+			PRINTM(MINFO, "Free all the USB command buffer.\n");
+			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].cmdbuf);
+			pcmd_array[i].cmdbuf = MNULL;
+		}
+#endif
+#if defined(SDIO) || defined(PCIE)
+		if (!IS_USB(pmadapter->card_type) && pcmd_array[i].pmbuf) {
+			PRINTM(MINFO, "Free all the command buffer.\n");
+			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].pmbuf);
+			pcmd_array[i].pmbuf = MNULL;
+		}
+#endif
+		if (pcmd_array[i].respbuf) {
+#ifdef USB
+			if (IS_USB(pmadapter->card_type))
+				pmadapter->callbacks.
+					moal_recv_complete(pmadapter->
+							   pmoal_handle,
+							   pcmd_array[i].
+							   respbuf,
+							   pmadapter->rx_cmd_ep,
+							   MLAN_STATUS_SUCCESS);
+#endif
+#if defined(SDIO) || defined(PCIE)
+			if (!IS_USB(pmadapter->card_type))
+				wlan_free_mlan_buffer(pmadapter,
+						      pcmd_array[i].respbuf);
+#endif
+			pcmd_array[i].respbuf = MNULL;
+		}
+	}
+	/* Release cmd_ctrl_node */
+	if (pmadapter->cmd_pool) {
+		PRINTM(MINFO, "Free command pool.\n");
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->cmd_pool);
+		pmadapter->cmd_pool = MNULL;
+	}
+
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles events generated by firmware
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_event(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+	t_u32 eventcause = pmadapter->event_cause;
+#ifdef DEBUG_LEVEL1
+	t_u32 in_ts_sec = 0, in_ts_usec = 0;
+#endif
+	ENTER();
+
+	/* Save the last event to debug log */
+	pmadapter->dbg.last_event_index =
+		(pmadapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
+	pmadapter->dbg.last_event[pmadapter->dbg.last_event_index] =
+		(t_u16)eventcause;
+
+	if ((eventcause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) {
+		if (wlan_11h_dfs_event_preprocessing(pmadapter) ==
+		    MLAN_STATUS_SUCCESS) {
+			memcpy_ext(pmadapter, (t_u8 *)&eventcause,
+				   pmbuf->pbuf + pmbuf->data_offset,
+				   sizeof(eventcause), sizeof(eventcause));
+		} else {
+			priv = wlan_get_priv_by_id(pmadapter,
+						   EVENT_GET_BSS_NUM
+						   (eventcause),
+						   EVENT_GET_BSS_TYPE
+						   (eventcause));
+			if (priv)
+				PRINTM_NETINTF(MEVENT, priv);
+			PRINTM(MERROR,
+			       "Error processing DFS Event: 0x%x\n",
+			       eventcause);
+			goto done;
+		}
+	}
+	/* Get BSS number and corresponding priv */
+	priv = wlan_get_priv_by_id(pmadapter, EVENT_GET_BSS_NUM(eventcause),
+				   EVENT_GET_BSS_TYPE(eventcause));
+	if (!priv)
+		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Clear BSS_NO_BITS from event */
+	eventcause &= EVENT_ID_MASK;
+	pmadapter->event_cause = eventcause;
+
+	if (pmbuf) {
+		pmbuf->bss_index = priv->bss_index;
+		memcpy_ext(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
+			   (t_u8 *)&eventcause, sizeof(eventcause),
+			   sizeof(eventcause));
+	}
+
+	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE
+	    && eventcause != EVENT_FW_DUMP_INFO) {
+		PRINTM_GET_SYS_TIME(MEVENT, &in_ts_sec, &in_ts_usec);
+		PRINTM_NETINTF(MEVENT, priv);
+		PRINTM(MEVENT, "%lu.%06lu : Event: 0x%x\n", in_ts_sec,
+		       in_ts_usec, eventcause);
+	}
+
+	ret = priv->ops.process_event(priv);
+done:
+	pmadapter->event_cause = 0;
+	pmadapter->pmlan_buffer_event = MNULL;
+	if (pmbuf)
+		pmadapter->ops.event_complete(pmadapter, pmbuf,
+					      MLAN_STATUS_SUCCESS);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function requests a lock on command queue.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_request_cmd_lock(mlan_adapter *pmadapter)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	/* Call MOAL spin lock callback function */
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_lock);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function releases a lock on command queue.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_release_cmd_lock(mlan_adapter *pmadapter)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	/* Call MOAL spin unlock callback function */
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pmadapter->pmlan_cmd_lock);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prepare the command before sending to firmware.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd_no       Command number
+ *  @param cmd_action   Command action: GET or SET
+ *  @param cmd_oid      Cmd oid: treated as sub command
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param pdata_buf    A pointer to information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_prepare_cmd(mlan_private *pmpriv, t_u16 cmd_no,
+		 t_u16 cmd_action, t_u32 cmd_oid,
+		 t_void *pioctl_buf, t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	HostCmd_DS_COMMAND *cmd_ptr = MNULL;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	ENTER();
+
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter = pmpriv->adapter;
+
+	/* Sanity test */
+	if (!pmadapter || pmadapter->surprise_removed) {
+		PRINTM(MERROR, "PREP_CMD: Card is Removed\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_FW_NOT_READY;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (pmadapter->hw_status == WlanHardwareStatusReset) {
+		if ((cmd_no != HostCmd_CMD_FUNC_INIT)
+#ifdef PCIE
+		    && (cmd_no != HostCmd_CMD_PCIE_HOST_BUF_DETAILS)
+#endif
+			) {
+			PRINTM(MERROR, "PREP_CMD: FW is in reset state\n");
+			if (pioctl_req)
+				pioctl_req->status_code =
+					MLAN_ERROR_FW_NOT_READY;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Get a new command node */
+	pcmd_node = wlan_get_cmd_node(pmadapter);
+
+	if (pcmd_node == MNULL) {
+		PRINTM(MERROR, "PREP_CMD: No free cmd node\n");
+		wlan_dump_info(pmadapter, REASON_CODE_NO_CMD_NODE);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/** reset num no cmd node */
+	pmadapter->dbg.num_no_cmd_node = 0;
+
+	/* Initialize the command node */
+	wlan_init_cmd_node(pmpriv, pcmd_node, cmd_no, pioctl_buf, pdata_buf);
+
+	if (pcmd_node->cmdbuf == MNULL) {
+		PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd_ptr = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+					 pcmd_node->cmdbuf->data_offset);
+	cmd_ptr->command = cmd_no;
+	cmd_ptr->result = 0;
+
+	/* Prepare command */
+	if (cmd_no)
+		ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
+					      cmd_oid, pioctl_buf, pdata_buf,
+					      cmd_ptr);
+	else {
+		ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf, &cmd_no);
+		pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
+	}
+
+	/* Return error, since the command preparation failed */
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
+		       cmd_no);
+		pcmd_node->pioctl_buf = MNULL;
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	/* Send command */
+#ifdef STA_SUPPORT
+	if (cmd_no == HostCmd_CMD_802_11_SCAN
+	    || cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
+		if (cmd_no == HostCmd_CMD_802_11_SCAN_EXT &&
+		    pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+		} else
+			wlan_queue_scan_cmd(pmpriv, pcmd_node);
+	} else {
+#endif
+		if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
+		    (cmd_action == HostCmd_ACT_GEN_SET) &&
+		    (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MFALSE);
+		else
+			wlan_queue_cmd(pmpriv, pcmd_node, cmd_no);
+#ifdef STA_SUPPORT
+	}
+#endif
+	wlan_release_cmd_lock(pmadapter);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function inserts command node to cmd_free_q
+ *              after cleaning it.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_insert_cmd_to_free_q(mlan_adapter *pmadapter, cmd_ctrl_node *pcmd_node)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ioctl_req *pioctl_req = MNULL;
+	ENTER();
+
+	if (pcmd_node == MNULL)
+		goto done;
+	if (pcmd_node->pioctl_buf) {
+		pioctl_req = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+		if (pioctl_req->status_code != MLAN_ERROR_NO_ERROR)
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_req,
+						 MLAN_STATUS_FAILURE);
+		else
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_req,
+						 MLAN_STATUS_SUCCESS);
+	}
+	/* Clean the node */
+	wlan_clean_cmd_node(pmadapter, pcmd_node);
+
+	/* Insert node into cmd_free_q */
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
+			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief This function queues the command to cmd list.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pcmd_node    A pointer to cmd_ctrl_node structure
+ *  @param add_tail      Specify if the cmd needs to be queued in the header or
+ * tail
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_insert_cmd_to_pending_q(mlan_adapter *pmadapter,
+			     cmd_ctrl_node *pcmd_node, t_u32 add_tail)
+{
+	HostCmd_DS_COMMAND *pcmd = MNULL;
+	t_u16 command;
+
+	ENTER();
+
+	if (pcmd_node == MNULL) {
+		PRINTM(MERROR, "QUEUE_CMD: pcmd_node is MNULL\n");
+		goto done;
+	}
+
+	pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+				      pcmd_node->cmdbuf->data_offset);
+
+	command = wlan_le16_to_cpu(pcmd->command);
+
+	/* Exit_PS command needs to be queued in the header always. */
+	if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
+		HostCmd_DS_802_11_PS_MODE_ENH *pm = &pcmd->params.psmode_enh;
+		if (wlan_le16_to_cpu(pm->action) == DIS_AUTO_PS) {
+			if (pmadapter->ps_state != PS_STATE_AWAKE)
+				add_tail = MFALSE;
+		}
+	}
+
+	if (add_tail) {
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->cmd_pending_q,
+				       (pmlan_linked_list)pcmd_node, MNULL,
+				       MNULL);
+	} else {
+		util_enqueue_list_head(pmadapter->pmoal_handle,
+				       &pmadapter->cmd_pending_q,
+				       (pmlan_linked_list)pcmd_node, MNULL,
+				       MNULL);
+	}
+
+	PRINTM_NETINTF(MCMND, pcmd_node->priv);
+	PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x is queued\n", command);
+
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function executes next command in command
+ *      pending queue. It will put firmware back to PS mode
+ *      if applicable.
+ *
+ *  @param pmadapter     A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_exec_next_cmd(mlan_adapter *pmadapter)
+{
+	mlan_private *priv = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_COMMAND *pcmd;
+
+	ENTER();
+
+	/* Sanity test */
+	if (pmadapter == MNULL) {
+		PRINTM(MERROR, "EXEC_NEXT_CMD: pmadapter is MNULL\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* Check if already in processing */
+	if (pmadapter->curr_cmd) {
+		PRINTM(MERROR,
+		       "EXEC_NEXT_CMD: there is command in processing!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	/* Check if any command is pending */
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->cmd_pending_q,
+						    MNULL, MNULL);
+
+	if (pcmd_node) {
+		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+					      pcmd_node->cmdbuf->data_offset);
+		priv = pcmd_node->priv;
+
+		if (pmadapter->ps_state != PS_STATE_AWAKE) {
+			PRINTM(MERROR,
+			       "Cannot send command in sleep state, this should not happen\n");
+			wlan_release_cmd_lock(pmadapter);
+			goto done;
+		}
+
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		wlan_release_cmd_lock(pmadapter);
+		ret = wlan_dnld_cmd_to_fw(priv, pcmd_node);
+		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+		/* Any command sent to the firmware when host is in sleep mode,
+		 * should de-configure host sleep */
+		/* We should skip the host sleep configuration command itself
+		 * though */
+		if (priv && (pcmd->command !=
+			     wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) {
+			if (pmadapter->hs_activated == MTRUE) {
+				pmadapter->is_hs_configured = MFALSE;
+				wlan_host_sleep_activated_event(priv, MFALSE);
+			}
+		}
+		goto done;
+	} else {
+		wlan_release_cmd_lock(pmadapter);
+	}
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_cmdresp(mlan_adapter *pmadapter)
+{
+	HostCmd_DS_COMMAND *resp = MNULL;
+	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	mlan_private *pmpriv_next = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 orig_cmdresp_no;
+	t_u16 cmdresp_no;
+	t_u16 cmdresp_result;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+	t_u32 i;
+
+	ENTER();
+
+	if (pmadapter->curr_cmd)
+		if (pmadapter->curr_cmd->pioctl_buf != MNULL) {
+			pioctl_buf = (mlan_ioctl_req *)
+				pmadapter->curr_cmd->pioctl_buf;
+		}
+
+	if (!pmadapter->curr_cmd || !pmadapter->curr_cmd->respbuf) {
+		resp = (HostCmd_DS_COMMAND *)pmadapter->upld_buf;
+		resp->command = wlan_le16_to_cpu(resp->command);
+		PRINTM(MERROR, "CMD_RESP: No curr_cmd, 0x%x\n", resp->command);
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	DBG_HEXDUMP(MCMD_D, "CMD_RESP",
+		    pmadapter->curr_cmd->respbuf->pbuf +
+		    pmadapter->curr_cmd->respbuf->data_offset,
+		    pmadapter->curr_cmd->respbuf->data_len);
+
+	resp = (HostCmd_DS_COMMAND *)(pmadapter->curr_cmd->respbuf->pbuf +
+				      pmadapter->curr_cmd->respbuf->
+				      data_offset);
+	orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
+	cmdresp_no = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
+	if (pmadapter->curr_cmd->cmd_no != cmdresp_no) {
+		PRINTM(MERROR, "cmdresp error: cmd=0x%x cmd_resp=0x%x\n",
+		       pmadapter->curr_cmd->cmd_no, cmdresp_no);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pmadapter->dnld_cmd_in_secs = 0;
+	/* Now we got response from FW, cancel the command timer */
+	if (pmadapter->cmd_timer_is_set) {
+		/* Cancel command timeout timer */
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_timer);
+		/* Cancel command timeout timer */
+		pmadapter->cmd_timer_is_set = MFALSE;
+	}
+	pmadapter->num_cmd_timeout = 0;
+	wlan_request_cmd_lock(pmadapter);
+	if (pmadapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
+		cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
+		pmadapter->curr_cmd = MNULL;
+		PRINTM(MCMND, "CMD_RESP: 0x%x been canceled!\n",
+		       wlan_le16_to_cpu(resp->command));
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	} else {
+		wlan_release_cmd_lock(pmadapter);
+	}
+	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
+		/* Copy original response back to response buffer */
+		if (pmpriv)
+			wlan_ret_host_cmd(pmpriv, resp, pioctl_buf);
+	}
+	resp->size = wlan_le16_to_cpu(resp->size);
+	resp->seq_num = wlan_le16_to_cpu(resp->seq_num);
+	resp->result = wlan_le16_to_cpu(resp->result);
+
+	/* Get BSS number and corresponding priv */
+	pmpriv = wlan_get_priv_by_id(pmadapter,
+				     HostCmd_GET_BSS_NO(resp->seq_num),
+				     HostCmd_GET_BSS_TYPE(resp->seq_num));
+	if (!pmpriv)
+		pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	/* Clear RET_BIT from HostCmd */
+	resp->command = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
+	if (!pmpriv) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cmdresp_no = resp->command;
+
+	cmdresp_result = resp->result;
+
+	/* Save the last command response to debug log */
+	pmadapter->dbg.last_cmd_resp_index =
+		(pmadapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
+	pmadapter->dbg.last_cmd_resp_id[pmadapter->dbg.last_cmd_resp_index] =
+		orig_cmdresp_no;
+
+	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
+	PRINTM_NETINTF(MCMND, pmadapter->curr_cmd->priv);
+	PRINTM(MCMND,
+	       "CMD_RESP (%lu.%06lu): 0x%x, result %d, len %d, seqno 0x%x\n",
+	       sec, usec, orig_cmdresp_no, cmdresp_result, resp->size,
+	       resp->seq_num);
+
+	if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
+		PRINTM(MERROR, "CMD_RESP: Invalid response to command!\n");
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+		pmadapter->curr_cmd = MNULL;
+		wlan_release_cmd_lock(pmadapter);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
+		pmadapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
+		if ((cmdresp_result == HostCmd_RESULT_OK)
+		    && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH)
+			)
+			ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
+	} else {
+		/* handle response */
+		ret = pmpriv->ops.process_cmdresp(pmpriv, cmdresp_no, resp,
+						  pioctl_buf);
+	}
+
+	/* Check init command response */
+	if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
+	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
+		if (ret == MLAN_STATUS_FAILURE) {
+#ifdef STA_SUPPORT
+			if (pmadapter->pwarm_reset_ioctl_req) {
+				/* warm reset failure */
+				pmadapter->pwarm_reset_ioctl_req->status_code =
+					MLAN_ERROR_CMD_RESP_FAIL;
+				pcb->moal_ioctl_complete(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 pwarm_reset_ioctl_req,
+							 MLAN_STATUS_FAILURE);
+				pmadapter->pwarm_reset_ioctl_req = MNULL;
+				goto done;
+			}
+#endif
+			PRINTM(MERROR,
+			       "cmd 0x%02x failed during initialization\n",
+			       cmdresp_no);
+			wlan_init_fw_complete(pmadapter);
+			goto done;
+		}
+#ifdef STA_SUPPORT
+#ifdef PCIE
+		/* init adma write pointer */
+		if (IS_PCIE(pmadapter->card_type) &&
+		    cmdresp_no == HostCmd_CMD_FUNC_SHUTDOWN &&
+		    pmadapter->pwarm_reset_ioctl_req) {
+#if defined(PCIE9098) || defined(PCIE9097)
+			if (pmadapter->pcard_pcie->reg->use_adma)
+#endif
+				wlan_pcie_init_fw(pmadapter);
+		}
+#endif
+#endif
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	if (pmadapter->curr_cmd) {
+		cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
+		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+		pmadapter->curr_cmd = MNULL;
+		if (pioctl_buf && (ret == MLAN_STATUS_SUCCESS))
+			pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
+		else if (pioctl_buf && (ret == MLAN_STATUS_FAILURE) &&
+			 !pioctl_buf->status_code)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+
+		/* Clean up and put current command back to cmd_free_q */
+		wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
+	}
+	wlan_release_cmd_lock(pmadapter);
+
+	if ((pmadapter->hw_status == WlanHardwareStatusInitializing) &&
+	    (pmadapter->last_init_cmd == cmdresp_no)) {
+		i = pmpriv->bss_index + 1;
+		while (i < pmadapter->priv_num &&
+		       (!(pmpriv_next = pmadapter->priv[i]) ||
+			pmpriv_next->bss_virtual))
+			i++;
+		if (!pmpriv_next || i >= pmadapter->priv_num) {
+#ifdef STA_SUPPORT
+			if (pmadapter->pwarm_reset_ioctl_req) {
+				/* warm reset complete */
+				PRINTM(MMSG, "wlan: warm reset complete\n");
+				pmadapter->hw_status = WlanHardwareStatusReady;
+				pcb->moal_ioctl_complete(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 pwarm_reset_ioctl_req,
+							 MLAN_STATUS_SUCCESS);
+				pmadapter->pwarm_reset_ioctl_req = MNULL;
+				goto done;
+			}
+#endif
+			pmadapter->hw_status = WlanHardwareStatusInitdone;
+		} else {
+			/* Issue init commands for the next interface */
+			ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
+		}
+	} else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
+		   (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
+		pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the timeout of command sending.
+ *          It will re-send the same command again.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return                   N/A
+ */
+t_void
+wlan_cmd_timeout_func(t_void *function_context)
+{
+	mlan_adapter *pmadapter = (mlan_adapter *)function_context;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+#if defined(SDIO) || defined(PCIE)
+	t_u8 i;
+#endif
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	pmadapter->cmd_timer_is_set = MFALSE;
+	if (!pmadapter->curr_cmd) {
+		if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+		    pmadapter->scan_processing) {
+			PRINTM(MMSG, "Ext scan enh timeout\n");
+			pmadapter->ext_scan_timeout = MTRUE;
+			wlan_dump_info(pmadapter, REASON_CODE_EXT_SCAN_TIMEOUT);
+			goto exit;
+		}
+		PRINTM(MWARN, "CurCmd Empty\n");
+		goto exit;
+	}
+	pmadapter->num_cmd_timeout++;
+	pcmd_node = pmadapter->curr_cmd;
+	if (pcmd_node->pioctl_buf != MNULL) {
+		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+		pioctl_buf->status_code = MLAN_ERROR_CMD_TIMEOUT;
+	}
+
+	pmadapter->dbg.timeout_cmd_id =
+		pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index];
+	pmadapter->dbg.timeout_cmd_act =
+		pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index];
+	PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
+	PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n", sec,
+	       usec, pmadapter->dbg.timeout_cmd_id,
+	       pmadapter->dbg.timeout_cmd_act);
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
+		t_u8 *pcmd_buf;
+		pcmd_buf = pcmd_node->cmdbuf->pbuf +
+			pcmd_node->cmdbuf->data_offset +
+			pmadapter->ops.intf_header_len;
+		for (i = 0; i < 16; i++)
+			PRINTM(MERROR, "%02x ", *pcmd_buf++);
+		PRINTM(MERROR, "\n");
+	}
+#endif
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type))
+		pmadapter->ops.debug_dump(pmadapter);
+#endif
+	pmpriv = pcmd_node->priv;
+	if (pmpriv)
+		PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type,
+		       pmpriv->bss_role);
+	wlan_dump_info(pmadapter, REASON_CODE_CMD_TIMEOUT);
+
+	if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
+	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec)
+		wlan_init_fw_complete(pmadapter);
+	else {
+		/* Signal MOAL to perform extra handling for debugging */
+		if (pmpriv) {
+			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP,
+					MNULL);
+		} else {
+			wlan_recv_event(wlan_get_priv(pmadapter,
+						      MLAN_BSS_ROLE_ANY),
+					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+		}
+	}
+
+exit:
+	LEAVE();
+	return;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Internal function used to flush the scan pending queue
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_flush_scan_queue(pmlan_adapter pmadapter)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	HostCmd_DS_COMMAND *pcmd = MNULL;
+	t_u16 cmd_no = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	wlan_request_cmd_lock(pmadapter);
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->scan_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->scan_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
+					      pcmd_node->cmdbuf->data_offset);
+		cmd_no = wlan_le16_to_cpu(pcmd->command);
+		PRINTM(MCMND, "flush scan queue: cmd 0x%02x\n", cmd_no);
+		if (pcmd_node->pioctl_buf &&
+		    cmd_no != HostCmd_CMD_802_11_SCAN
+		    && cmd_no != HostCmd_CMD_802_11_SCAN_EXT) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pcmd_node->pioctl_buf = MNULL;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+		}
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+
+	pmadapter->scan_processing = MFALSE;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel pending SCAN ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param pioctl_req   A pointer to pmlan_ioctl_req
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ */
+mlan_status
+wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+	pmlan_private priv = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	PRINTM(MIOCTL, "Cancel scan command\n");
+	wlan_request_cmd_lock(pmadapter);
+	/* IOCTL will be completed, avoid calling IOCTL complete again from
+	 * EVENT/CMDRESP */
+	if (pmadapter->pscan_ioctl_req) {
+		pioctl_buf = pmadapter->pscan_ioctl_req;
+		priv = pmadapter->priv[pioctl_buf->bss_index];
+		pmadapter->pscan_ioctl_req = MNULL;
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+	}
+
+	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
+		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) {
+			PRINTM(MIOCTL, "wlan_cancel_scan: current command\n");
+			pcmd_node = pmadapter->curr_cmd;
+			pcmd_node->pioctl_buf = MNULL;
+			pcmd_node->cmd_flag |= CMD_F_CANCELED;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+		}
+	}
+	while ((pcmd_node = wlan_get_pending_scan_cmd(pmadapter)) != MNULL) {
+		PRINTM(MIOCTL,
+		       "wlan_cancel_scan: find scan command in cmd_pending_q\n");
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+	if (pmadapter->scan_processing &&
+	    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+		if (priv) {
+			if (MLAN_STATUS_SUCCESS ==
+			    wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
+					     HostCmd_ACT_GEN_SET, 0, pioctl_req,
+					     MNULL)) {
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+				status = MLAN_STATUS_PENDING;
+			}
+		}
+	} else
+		/* Cancel all pending scan command */
+		wlan_flush_scan_queue(pmadapter);
+	LEAVE();
+	return status;
+}
+#endif
+
+/**
+ *  @brief Cancel all pending cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param flag         MTRUE/MFALSE
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter, t_u8 flag)
+{
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+	pmlan_private priv = MNULL;
+#endif
+	ENTER();
+	/* Cancel current cmd */
+	wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	/* IOCTL will be completed, avoid calling IOCTL complete again from
+	 * EVENT/CMDRESP */
+	if (pmadapter->pscan_ioctl_req) {
+		pioctl_buf = pmadapter->pscan_ioctl_req;
+		priv = pmadapter->priv[pioctl_buf->bss_index];
+		pmadapter->pscan_ioctl_req = MNULL;
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+	}
+#endif
+	if (pmadapter->curr_cmd) {
+		pcmd_node = pmadapter->curr_cmd;
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pcmd_node->pioctl_buf = MNULL;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+		}
+		if (flag) {
+			pmadapter->curr_cmd = MNULL;
+			wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+		}
+	}
+
+	/* Cancel all pending command */
+	while ((pcmd_node =
+		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						&pmadapter->cmd_pending_q,
+						MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		if (pcmd_node->pioctl_buf) {
+			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+			pcmd_node->pioctl_buf = MNULL;
+		}
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+	/* Cancel all pending scan command */
+	wlan_flush_scan_queue(pmadapter);
+	LEAVE();
+}
+
+/**
+ *  @brief Cancel specific bss's pending ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param bss_index    BSS index
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_ioctl_req *pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+	t_u8 flash_scan = MFALSE;
+#endif
+#ifdef STA_SUPPORT
+	pmlan_private priv = MNULL;
+#endif
+	ENTER();
+
+	PRINTM(MIOCTL, "MOAL Cancel BSS IOCTL: bss_index=%d\n", (int)bss_index);
+	wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	if (pmadapter->pscan_ioctl_req &&
+	    (pmadapter->pscan_ioctl_req->bss_index == bss_index)) {
+		/* IOCTL will be completed, avoid calling IOCTL complete again
+		 * from EVENT/CMDRESP */
+		flash_scan = MTRUE;
+		pioctl_buf = pmadapter->pscan_ioctl_req;
+		priv = pmadapter->priv[pioctl_buf->bss_index];
+		pmadapter->pscan_ioctl_req = MNULL;
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+	}
+#endif
+	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
+		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
+		if (pioctl_buf->bss_index == bss_index) {
+			pcmd_node = pmadapter->curr_cmd;
+			pcmd_node->pioctl_buf = MNULL;
+			pcmd_node->cmd_flag |= CMD_F_CANCELED;
+#ifdef STA_SUPPORT
+			if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
+				flash_scan = MTRUE;
+#endif
+			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf,
+						 MLAN_STATUS_FAILURE);
+		}
+	}
+	while ((pcmd_node =
+		wlan_get_bss_pending_ioctl_cmd(pmadapter,
+					       bss_index)) != MNULL) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
+		pcmd_node->pioctl_buf = MNULL;
+#ifdef STA_SUPPORT
+		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
+			flash_scan = MTRUE;
+#endif
+		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
+					 MLAN_STATUS_FAILURE);
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	if (flash_scan) {
+		if (pmadapter->scan_processing &&
+		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			if (priv) {
+				if (MLAN_STATUS_FAILURE ==
+				    wlan_prepare_cmd(priv,
+						     HostCmd_CMD_802_11_SCAN_EXT,
+						     HostCmd_ACT_GEN_SET, 0,
+						     MNULL, MNULL))
+					PRINTM(MERROR,
+					       "failed to prepare command");
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+			}
+		} else
+			/* Cancel all pending scan command */
+			wlan_flush_scan_queue(pmadapter);
+	}
+#endif
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Cancel pending ioctl cmd.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter
+ *  @param pioctl_req   A pointer to mlan_ioctl_req buf
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_cancel_pending_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	t_u8 find = MFALSE;
+#ifdef STA_SUPPORT
+	pmlan_private priv = MNULL;
+#endif
+
+	ENTER();
+
+	PRINTM(MIOCTL, "MOAL Cancel IOCTL: 0x%x sub_id=0x%x action=%d\n",
+	       pioctl_req->req_id, *((t_u32 *)pioctl_req->pbuf),
+	       (int)pioctl_req->action);
+
+	wlan_request_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	/* IOCTL will be completed, avoid calling IOCTL complete again from
+	 * EVENT/CMDRESP */
+	if (pmadapter->pscan_ioctl_req == pioctl_req) {
+		priv = pmadapter->priv[pioctl_req->bss_index];
+		pmadapter->pscan_ioctl_req = MNULL;
+		find = MTRUE;
+	}
+#endif
+	if ((pmadapter->curr_cmd) &&
+	    (pmadapter->curr_cmd->pioctl_buf == pioctl_req)) {
+		pcmd_node = pmadapter->curr_cmd;
+		pcmd_node->pioctl_buf = MNULL;
+		pcmd_node->cmd_flag |= CMD_F_CANCELED;
+		find = MTRUE;
+	}
+
+	while ((pcmd_node = wlan_get_pending_ioctl_cmd(pmadapter,
+						       pioctl_req)) != MNULL) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &pmadapter->cmd_pending_q,
+				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
+		pcmd_node->pioctl_buf = MNULL;
+		find = MTRUE;
+		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
+	}
+	wlan_release_cmd_lock(pmadapter);
+#ifdef STA_SUPPORT
+	if (pioctl_req->req_id == MLAN_IOCTL_SCAN) {
+		if (pmadapter->scan_processing &&
+		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			if (priv) {
+				if (MLAN_STATUS_FAILURE ==
+				    wlan_prepare_cmd(priv,
+						     HostCmd_CMD_802_11_SCAN_EXT,
+						     HostCmd_ACT_GEN_SET, 0,
+						     MNULL, MNULL))
+					PRINTM(MERROR,
+					       "Failed to prepare command");
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+			}
+		} else
+			/* Cancel all pending scan command */
+			wlan_flush_scan_queue(pmadapter);
+	}
+#endif
+	if (find) {
+		pioctl_req->status_code = MLAN_ERROR_CMD_CANCEL;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
+					 MLAN_STATUS_FAILURE);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function convert mlan_wifi_rate to wifi_rate.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pmlan_rate          A pointer to mlan_wifi_rate structure
+ *  @param prate   A pointer to wifi_rate
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_fill_hal_wifi_rate(pmlan_private pmpriv,
+			mlan_wifi_rate * pmlan_rate, wifi_rate * prate)
+{
+	t_u8 index = 0;
+	t_u8 rate_info = 0;
+
+	ENTER();
+
+	prate->preamble = pmlan_rate->preamble;
+	prate->nss = pmlan_rate->nss;
+	prate->bw = pmlan_rate->bw;
+	prate->rateMcsIdx = pmlan_rate->rateMcsIdx;
+	prate->reserved = 0;
+	prate->bitrate = wlan_le32_to_cpu(pmlan_rate->bitrate);
+
+	if (!prate->bitrate) {
+		index = prate->rateMcsIdx;
+		index |= prate->nss << 4;
+		if (prate->preamble == WIFI_PREAMBLE_HT)
+			rate_info = MLAN_RATE_FORMAT_HT;
+		else if (prate->preamble == WIFI_PREAMBLE_VHT)
+			rate_info = MLAN_RATE_FORMAT_VHT;
+		else
+			rate_info = MLAN_RATE_FORMAT_LG;
+		rate_info |= prate->bw << 2;
+		PRINTM(MCMND, "index=0x%x rate_info=0x%x\n", index, rate_info);
+		/** For rateMcsIdx, OFDM/CCK rate code would be as per ieee std
+		 * in the units of 0.5mbps. HT/VHT it would be mcs index */
+		/** For bitrate, in 100kbps */
+		if (rate_info == MLAN_RATE_FORMAT_LG)
+			prate->bitrate = prate->rateMcsIdx * 5;
+		else
+			prate->bitrate =
+				wlan_index_to_data_rate(pmpriv->adapter, index,
+							rate_info, 0) * 5;
+		PRINTM(MCMND, "bitrate(in 100kbps)=%d\n", prate->bitrate);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Handle the version_ext resp
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_ver_ext(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_VERSION_EXT *ver_ext = &resp->params.verext;
+	mlan_ds_get_info *info;
+	ENTER();
+	if (pioctl_buf) {
+		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		info->param.ver_ext.version_str_sel = ver_ext->version_str_sel;
+		memcpy_ext(pmpriv->adapter, info->param.ver_ext.version_str,
+			   ver_ext->version_str, sizeof(char) * 128,
+			   sizeof(char) * MLAN_MAX_VER_STR_LEN);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Handle the rx mgmt forward registration resp
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_rx_mgmt_ind(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	ENTER();
+
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc->param.mgmt_subtype_mask =
+			wlan_le32_to_cpu(resp->params.rx_mgmt_ind.
+					 mgmt_subtype_mask);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks conditions and prepares to
+ *              send sleep confirm command to firmware if OK.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_check_ps_cond(mlan_adapter *pmadapter)
+{
+	ENTER();
+
+	if (!pmadapter->cmd_sent && !pmadapter->curr_cmd &&
+	    !pmadapter->keep_wakeup && !wlan_is_tx_pending(pmadapter) &&
+	    !IS_CARD_RX_RCVD(pmadapter)) {
+		wlan_dnld_sleep_confirm_cmd(pmadapter);
+	} else {
+		PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s%s)\n",
+		       (pmadapter->cmd_sent) ? "D" : "",
+		       (pmadapter->curr_cmd) ? "C" : "",
+		       (wlan_is_tx_pending(pmadapter)) ? "T" : "",
+		       (IS_CARD_RX_RCVD(pmadapter)) ? "R" : "");
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function sends the HS_ACTIVATED event to the application
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param activated    MTRUE if activated, MFALSE if de-activated
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_host_sleep_activated_event(pmlan_private priv, t_u8 activated)
+{
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return;
+	}
+
+	if (activated) {
+		if (priv->adapter->is_hs_configured) {
+			priv->adapter->hs_activated = MTRUE;
+			wlan_update_rxreorder_tbl(priv->adapter, MTRUE);
+			PRINTM(MEVENT, "hs_activated\n");
+			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_ACTIVATED,
+					MNULL);
+		} else
+			PRINTM(MWARN, "hs_activated: HS not configured !!!\n");
+	} else {
+		PRINTM(MEVENT, "hs_deactived\n");
+		priv->adapter->hs_activated = MFALSE;
+		wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_DEACTIVATED, MNULL);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function sends the HS_WAKEUP event to the application
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_host_sleep_wakeup_event(pmlan_private priv)
+{
+	ENTER();
+
+	if (priv->adapter->is_hs_configured)
+		wlan_recv_event(priv, MLAN_EVENT_ID_FW_HS_WAKEUP, MNULL);
+	else
+		PRINTM(MWARN, "hs_wakeup: Host Sleep not configured !!!\n");
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function handles the command response of hs_cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &resp->params.opt_hs_cfg;
+
+	ENTER();
+
+	phs_cfg->params.hs_config.conditions =
+		wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
+	phs_cfg->action = wlan_le16_to_cpu(phs_cfg->action);
+	PRINTM(MCMND,
+	       "CMD_RESP: HS_CFG cmd reply result=%#x,"
+	       " action=0x%x conditions=0x%x gpio=0x%x gap=0x%x\n",
+	       resp->result, phs_cfg->action,
+	       phs_cfg->params.hs_config.conditions,
+	       phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap);
+	if ((phs_cfg->action == HS_ACTIVATE &&
+	     !pmadapter->pcard_info->supp_ps_handshake) ||
+	    pmadapter->pcard_info->supp_ps_handshake) {
+		/* clean up curr_cmd to allow suspend */
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
+		/* Clean up and put current command back to cmd_free_q */
+		wlan_request_cmd_lock(pmadapter);
+		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+		pmadapter->curr_cmd = MNULL;
+		wlan_release_cmd_lock(pmadapter);
+		if (!pmadapter->pcard_info->supp_ps_handshake) {
+			wlan_host_sleep_activated_event(pmpriv, MTRUE);
+			goto done;
+		}
+	}
+	if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
+		pmadapter->is_hs_configured = MTRUE;
+		if (pmadapter->pcard_info->supp_ps_handshake)
+			wlan_host_sleep_activated_event(pmpriv, MTRUE);
+	} else {
+		pmadapter->is_hs_configured = MFALSE;
+		if (pmadapter->hs_activated)
+			wlan_host_sleep_activated_event(pmpriv, MFALSE);
+	}
+
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Perform hs related activities on receiving the power up interrupt
+ *
+ *  @param pmadapter  A pointer to the adapter structure
+ *  @return           N/A
+ */
+t_void
+wlan_process_hs_config(pmlan_adapter pmadapter)
+{
+	ENTER();
+	PRINTM(MINFO, "Recevie interrupt/data in HS mode\n");
+	if (pmadapter->hs_cfg.gap == HOST_SLEEP_CFG_GAP_FF)
+		pmadapter->ops.wakeup_card(pmadapter, MTRUE);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Check sleep confirm command response and set the state to ASLEEP
+ *
+ *  @param pmadapter  A pointer to the adapter structure
+ *  @param pbuf       A pointer to the command response buffer
+ *  @param upld_len   Command response buffer length
+ *  @return           N/A
+ */
+void
+wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter, t_u8 *pbuf,
+				t_u32 upld_len)
+{
+	HostCmd_DS_COMMAND *cmd;
+	pmlan_private pmpriv;
+
+	ENTER();
+
+	if (!upld_len) {
+		PRINTM(MERROR, "Command size is 0\n");
+		LEAVE();
+		return;
+	}
+	cmd = (HostCmd_DS_COMMAND *)pbuf;
+	cmd->result = wlan_le16_to_cpu(cmd->result);
+	cmd->command = wlan_le16_to_cpu(cmd->command);
+	cmd->seq_num = wlan_le16_to_cpu(cmd->seq_num);
+
+	pmpriv = wlan_get_priv_by_id(pmadapter,
+				     HostCmd_GET_BSS_NO(cmd->seq_num),
+				     HostCmd_GET_BSS_TYPE(cmd->seq_num));
+	/* Update sequence number */
+	cmd->seq_num = HostCmd_GET_SEQ_NO(cmd->seq_num);
+	/* Clear RET_BIT from HostCmd */
+	cmd->command &= HostCmd_CMD_ID_MASK;
+	if (!pmpriv)
+		pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (cmd->command != HostCmd_CMD_802_11_PS_MODE_ENH) {
+		PRINTM(MERROR,
+		       "Received unexpected response for command %x, result = %x\n",
+		       cmd->command, cmd->result);
+		LEAVE();
+		return;
+	}
+	PRINTM_NETINTF(MEVENT, pmpriv);
+	PRINTM(MEVENT, "#\n");
+	if (cmd->result != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Sleep confirm command failed\n");
+		pmadapter->pm_wakeup_card_req = MFALSE;
+		pmadapter->ps_state = PS_STATE_AWAKE;
+		LEAVE();
+		return;
+	}
+	pmadapter->pm_wakeup_card_req = MTRUE;
+
+	if (pmadapter->is_hs_configured) {
+		wlan_host_sleep_activated_event(wlan_get_priv
+						(pmadapter, MLAN_BSS_ROLE_ANY),
+						MTRUE);
+	}
+	pmadapter->ps_state = PS_STATE_SLEEP;
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of power mode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param ps_bitmap    PS bitmap
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_enh_power_mode(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *cmd,
+			t_u16 cmd_action, t_u16 ps_bitmap, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_PS_MODE_ENH *psmode_enh = &cmd->params.psmode_enh;
+	t_u8 *tlv = MNULL;
+	t_u16 cmd_size = 0;
+
+	ENTER();
+
+	PRINTM(MCMND, "PS Command: action = 0x%x, bitmap = 0x%x\n", cmd_action,
+	       ps_bitmap);
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
+	if (cmd_action == DIS_AUTO_PS) {
+		psmode_enh->action = wlan_cpu_to_le16(DIS_AUTO_PS);
+		psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
+		cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
+	} else if (cmd_action == GET_PS) {
+		psmode_enh->action = wlan_cpu_to_le16(GET_PS);
+		psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
+		cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
+	} else if (cmd_action == EN_AUTO_PS) {
+		psmode_enh->action = wlan_cpu_to_le16(EN_AUTO_PS);
+		psmode_enh->params.auto_ps.ps_bitmap =
+			wlan_cpu_to_le16(ps_bitmap);
+		cmd_size = S_DS_GEN + AUTO_PS_FIX_SIZE;
+		tlv = (t_u8 *)cmd + cmd_size;
+		if (ps_bitmap & BITMAP_STA_PS) {
+			pmlan_adapter pmadapter = pmpriv->adapter;
+			MrvlIEtypes_ps_param_t *ps_tlv =
+				(MrvlIEtypes_ps_param_t *)tlv;
+			ps_param *ps_mode = &ps_tlv->param;
+			ps_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_PS_PARAM);
+			ps_tlv->header.len =
+				wlan_cpu_to_le16(sizeof(MrvlIEtypes_ps_param_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			cmd_size += sizeof(MrvlIEtypes_ps_param_t);
+			tlv += sizeof(MrvlIEtypes_ps_param_t);
+			ps_mode->null_pkt_interval =
+				wlan_cpu_to_le16(pmadapter->null_pkt_interval);
+			ps_mode->multiple_dtims =
+				wlan_cpu_to_le16(pmadapter->multiple_dtim);
+			ps_mode->bcn_miss_timeout =
+				wlan_cpu_to_le16(pmadapter->bcn_miss_time_out);
+			ps_mode->local_listen_interval =
+				wlan_cpu_to_le16(pmadapter->
+						 local_listen_interval);
+			ps_mode->delay_to_ps =
+				wlan_cpu_to_le16(pmadapter->delay_to_ps);
+			ps_mode->mode =
+				wlan_cpu_to_le16(pmadapter->enhanced_ps_mode);
+		}
+		if (ps_bitmap & BITMAP_BCN_TMO) {
+			MrvlIEtypes_bcn_timeout_t *bcn_tmo_tlv =
+				(MrvlIEtypes_bcn_timeout_t *) tlv;
+			mlan_ds_bcn_timeout *bcn_tmo =
+				(mlan_ds_bcn_timeout *) pdata_buf;
+			bcn_tmo_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_BCN_TIMEOUT);
+			bcn_tmo_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_bcn_timeout_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			bcn_tmo_tlv->bcn_miss_tmo_window =
+				wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_window);
+			bcn_tmo_tlv->bcn_miss_tmo_period =
+				wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_period);
+			bcn_tmo_tlv->bcn_rq_tmo_window =
+				wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_window);
+			bcn_tmo_tlv->bcn_rq_tmo_period =
+				wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_period);
+			cmd_size += sizeof(MrvlIEtypes_bcn_timeout_t);
+			tlv += sizeof(MrvlIEtypes_bcn_timeout_t);
+
+			psmode_enh->params.auto_ps.ps_bitmap = wlan_cpu_to_le16((ps_bitmap & (~BITMAP_BCN_TMO)) | BITMAP_STA_PS);
+		}
+		if (ps_bitmap & BITMAP_AUTO_DS) {
+			MrvlIEtypes_auto_ds_param_t *auto_ps_tlv =
+				(MrvlIEtypes_auto_ds_param_t *)tlv;
+			auto_ds_param *auto_ds = &auto_ps_tlv->param;
+			t_u16 idletime = 0;
+			auto_ps_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
+			auto_ps_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_auto_ds_param_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			cmd_size += sizeof(MrvlIEtypes_auto_ds_param_t);
+			tlv += sizeof(MrvlIEtypes_auto_ds_param_t);
+			if (pdata_buf)
+				idletime =
+					((mlan_ds_auto_ds *)pdata_buf)->
+					idletime;
+			auto_ds->deep_sleep_timeout =
+				wlan_cpu_to_le16(idletime);
+		}
+#if defined(UAP_SUPPORT)
+		if (pdata_buf &&
+		    (ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))) {
+			mlan_ds_ps_mgmt *ps_mgmt = (mlan_ds_ps_mgmt *)pdata_buf;
+			MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
+			MrvlIEtypes_inact_sleep_param_t *inact_tlv = MNULL;
+			if (ps_mgmt->flags & PS_FLAG_SLEEP_PARAM) {
+				sleep_tlv = (MrvlIEtypes_sleep_param_t *)tlv;
+				sleep_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_AP_SLEEP_PARAM);
+				sleep_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_sleep_param_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				sleep_tlv->ctrl_bitmap =
+					wlan_cpu_to_le32(ps_mgmt->sleep_param.
+							 ctrl_bitmap);
+				sleep_tlv->min_sleep =
+					wlan_cpu_to_le32(ps_mgmt->sleep_param.
+							 min_sleep);
+				sleep_tlv->max_sleep =
+					wlan_cpu_to_le32(ps_mgmt->sleep_param.
+							 max_sleep);
+				cmd_size += sizeof(MrvlIEtypes_sleep_param_t);
+				tlv += sizeof(MrvlIEtypes_sleep_param_t);
+			}
+			if (ps_mgmt->flags & PS_FLAG_INACT_SLEEP_PARAM) {
+				inact_tlv =
+					(MrvlIEtypes_inact_sleep_param_t *)tlv;
+				inact_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_AP_INACT_SLEEP_PARAM);
+				inact_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_inact_sleep_param_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				inact_tlv->inactivity_to =
+					wlan_cpu_to_le32(ps_mgmt->inact_param.
+							 inactivity_to);
+				inact_tlv->min_awake =
+					wlan_cpu_to_le32(ps_mgmt->inact_param.
+							 min_awake);
+				inact_tlv->max_awake =
+					wlan_cpu_to_le32(ps_mgmt->inact_param.
+							 max_awake);
+				cmd_size +=
+					sizeof(MrvlIEtypes_inact_sleep_param_t);
+				tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
+			}
+		}
+#endif
+		cmd->size = wlan_cpu_to_le16(cmd_size);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of ps_mode_enh
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_enh_power_mode(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	MrvlIEtypesHeader_t *mrvl_tlv = MNULL;
+	MrvlIEtypes_auto_ds_param_t *auto_ds_tlv = MNULL;
+	HostCmd_DS_802_11_PS_MODE_ENH *ps_mode = &resp->params.psmode_enh;
+
+	ENTER();
+
+	ps_mode->action = wlan_le16_to_cpu(ps_mode->action);
+	PRINTM(MINFO, "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
+	       resp->result, ps_mode->action);
+	if (ps_mode->action == EN_AUTO_PS) {
+		ps_mode->params.auto_ps.ps_bitmap =
+			wlan_le16_to_cpu(ps_mode->params.auto_ps.ps_bitmap);
+		if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_AUTO_DS) {
+			PRINTM(MCMND, "Enabled auto deep sleep\n");
+			pmpriv->adapter->is_deep_sleep = MTRUE;
+			mrvl_tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
+							   AUTO_PS_FIX_SIZE);
+			while (wlan_le16_to_cpu(mrvl_tlv->type) !=
+			       TLV_TYPE_AUTO_DS_PARAM) {
+				mrvl_tlv =
+					(MrvlIEtypesHeader_t
+					 *)((t_u8 *)mrvl_tlv +
+					    wlan_le16_to_cpu(mrvl_tlv->len) +
+					    sizeof(MrvlIEtypesHeader_t));
+			}
+			auto_ds_tlv = (MrvlIEtypes_auto_ds_param_t *)mrvl_tlv;
+			pmpriv->adapter->idle_time =
+				wlan_le16_to_cpu(auto_ds_tlv->param.
+						 deep_sleep_timeout);
+		}
+		if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_STA_PS) {
+			PRINTM(MCMND, "Enabled STA power save\n");
+			if (pmadapter->sleep_period.period) {
+				PRINTM(MCMND,
+				       "Setting uapsd/pps mode to TRUE\n");
+			}
+		}
+#if defined(UAP_SUPPORT)
+		if (ps_mode->params.auto_ps.ps_bitmap &
+		    (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
+			pmadapter->ps_mode = Wlan802_11PowerModePSP;
+			PRINTM(MCMND, "Enabled uAP power save\n");
+		}
+#endif
+	} else if (ps_mode->action == DIS_AUTO_PS) {
+		ps_mode->params.ps_bitmap =
+			wlan_cpu_to_le16(ps_mode->params.ps_bitmap);
+		if (ps_mode->params.ps_bitmap & BITMAP_AUTO_DS) {
+			pmpriv->adapter->is_deep_sleep = MFALSE;
+			PRINTM(MCMND, "Disabled auto deep sleep\n");
+		}
+		if (ps_mode->params.ps_bitmap & BITMAP_STA_PS) {
+			PRINTM(MCMND, "Disabled STA power save\n");
+			if (pmadapter->sleep_period.period) {
+				pmadapter->delay_null_pkt = MFALSE;
+				pmadapter->tx_lock_flag = MFALSE;
+				pmadapter->pps_uapsd_mode = MFALSE;
+			}
+		}
+#if defined(UAP_SUPPORT)
+		if (ps_mode->params.ps_bitmap &
+		    (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
+			pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+			PRINTM(MCMND, "Disabled uAP power save\n");
+		}
+#endif
+	} else if (ps_mode->action == GET_PS) {
+		ps_mode->params.ps_bitmap =
+			wlan_le16_to_cpu(ps_mode->params.ps_bitmap);
+		if (ps_mode->params.auto_ps.ps_bitmap &
+		    (BITMAP_STA_PS | BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))
+			pmadapter->ps_mode = Wlan802_11PowerModePSP;
+		else
+			pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+		PRINTM(MCMND, "ps_bitmap=0x%x\n", ps_mode->params.ps_bitmap);
+		if (pioctl_buf) {
+			mlan_ds_pm_cfg *pm_cfg =
+				(mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+			if (pm_cfg->sub_command == MLAN_OID_PM_CFG_IEEE_PS) {
+				if (ps_mode->params.auto_ps.ps_bitmap &
+				    BITMAP_STA_PS)
+					pm_cfg->param.ps_mode = 1;
+				else
+					pm_cfg->param.ps_mode = 0;
+			}
+#if defined(UAP_SUPPORT)
+			if (pm_cfg->sub_command == MLAN_OID_PM_CFG_PS_MODE) {
+				MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
+				MrvlIEtypes_inact_sleep_param_t *inact_tlv =
+					MNULL;
+				MrvlIEtypesHeader_t *tlv = MNULL;
+				t_u16 tlv_type = 0;
+				t_u16 tlv_len = 0;
+				t_u16 tlv_buf_left = 0;
+				pm_cfg->param.ps_mgmt.flags = PS_FLAG_PS_MODE;
+				if (ps_mode->params.ps_bitmap &
+				    BITMAP_UAP_INACT_PS)
+					pm_cfg->param.ps_mgmt.ps_mode =
+						PS_MODE_INACTIVITY;
+				else if (ps_mode->params.ps_bitmap &
+					 BITMAP_UAP_DTIM_PS)
+					pm_cfg->param.ps_mgmt.ps_mode =
+						PS_MODE_PERIODIC_DTIM;
+				else
+					pm_cfg->param.ps_mgmt.ps_mode =
+						PS_MODE_DISABLE;
+				tlv_buf_left = resp->size -
+					(S_DS_GEN + AUTO_PS_FIX_SIZE);
+				tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
+							      AUTO_PS_FIX_SIZE);
+				while (tlv_buf_left >=
+				       sizeof(MrvlIEtypesHeader_t)) {
+					tlv_type = wlan_le16_to_cpu(tlv->type);
+					tlv_len = wlan_le16_to_cpu(tlv->len);
+					switch (tlv_type) {
+					case TLV_TYPE_AP_SLEEP_PARAM:
+						sleep_tlv =
+							(MrvlIEtypes_sleep_param_t
+							 *)tlv;
+						pm_cfg->param.ps_mgmt.flags |=
+							PS_FLAG_SLEEP_PARAM;
+						pm_cfg->param.ps_mgmt.
+							sleep_param.
+							ctrl_bitmap =
+							wlan_le32_to_cpu
+							(sleep_tlv->
+							 ctrl_bitmap);
+						pm_cfg->param.ps_mgmt.
+							sleep_param.min_sleep =
+							wlan_le32_to_cpu
+							(sleep_tlv->min_sleep);
+						pm_cfg->param.ps_mgmt.
+							sleep_param.max_sleep =
+							wlan_le32_to_cpu
+							(sleep_tlv->max_sleep);
+						break;
+					case TLV_TYPE_AP_INACT_SLEEP_PARAM:
+						inact_tlv =
+							(MrvlIEtypes_inact_sleep_param_t
+							 *)tlv;
+						pm_cfg->param.ps_mgmt.flags |=
+							PS_FLAG_INACT_SLEEP_PARAM;
+						pm_cfg->param.ps_mgmt.
+							inact_param.
+							inactivity_to =
+							wlan_le32_to_cpu
+							(inact_tlv->
+							 inactivity_to);
+						pm_cfg->param.ps_mgmt.
+							inact_param.min_awake =
+							wlan_le32_to_cpu
+							(inact_tlv->min_awake);
+						pm_cfg->param.ps_mgmt.
+							inact_param.max_awake =
+							wlan_le32_to_cpu
+							(inact_tlv->max_awake);
+						break;
+					}
+					tlv_buf_left -=
+						tlv_len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv = (MrvlIEtypesHeader_t
+					       *)((t_u8 *)tlv +
+						  tlv_len +
+						  sizeof(MrvlIEtypesHeader_t));
+				}
+			}
+#endif
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of tx rate query
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_ds_rate *rate = MNULL;
+	ENTER();
+
+	pmpriv->tx_rate = resp->params.tx_rate.tx_rate;
+	pmpriv->tx_rate_info = resp->params.tx_rate.tx_rate_info;
+	if (pmpriv->adapter->pcard_info->v14_fw_api) {
+		pmpriv->tx_rate_info =
+			wlan_convert_v14_tx_rate_info(pmpriv,
+						      pmpriv->tx_rate_info);
+		PRINTM(MINFO,
+		       "%s: v14_fw_api=%d tx_rate=%d tx_rate_info=0x%x->0x%x\n",
+		       __func__, pmpriv->adapter->pcard_info->v14_fw_api,
+		       pmpriv->tx_rate, resp->params.tx_rate.tx_rate_info,
+		       pmpriv->tx_rate_info);
+	}
+	if ((pmpriv->tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE)
+		pmpriv->ext_tx_rate_info =
+			resp->params.tx_rate.ext_tx_rate_info;
+	else
+		pmpriv->ext_tx_rate_info = 0;
+
+	if (!pmpriv->is_data_rate_auto) {
+		pmpriv->data_rate =
+			wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate,
+						pmpriv->tx_rate_info,
+						pmpriv->ext_tx_rate_info);
+	}
+
+	if (pioctl_buf) {
+		rate = (mlan_ds_rate *)pioctl_buf->pbuf;
+		if (rate->sub_command == MLAN_OID_RATE_CFG) {
+			if (rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) {
+				if ((pmpriv->tx_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_VHT
+				    || ((pmpriv->tx_rate_info & 0x3) ==
+					MLAN_RATE_FORMAT_HE)
+					)
+
+					/* VHT rate */
+					rate->param.rate_cfg.rate =
+						(pmpriv->tx_rate) & 0xF;
+				else if ((pmpriv->tx_rate_info & 0x3) ==
+					 MLAN_RATE_FORMAT_HT)
+					/* HT rate */
+					rate->param.rate_cfg.rate =
+						pmpriv->tx_rate +
+						MLAN_RATE_INDEX_MCS0;
+				else
+					/* LG rate */
+					/* For HostCmd_CMD_802_11_TX_RATE_QUERY,
+					 * there is a hole (0x4) in rate table
+					 * between HR/DSSS and OFDM rates,
+					 * so minus 1 for OFDM rate index */
+					rate->param.rate_cfg.rate =
+						(pmpriv->tx_rate >
+						 MLAN_RATE_INDEX_OFDM0) ?
+						pmpriv->tx_rate - 1 :
+						pmpriv->tx_rate;
+			} else {
+				/* rate_type = MLAN_RATE_VALUE */
+				rate->param.rate_cfg.rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->tx_rate,
+								pmpriv->
+								tx_rate_info,
+								pmpriv->
+								ext_tx_rate_info);
+			}
+		} else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
+			/* Tx rate info */
+			if ((pmpriv->tx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT
+			    ||
+			    (pmpriv->tx_rate_info & 0x3) ==
+			    MLAN_RATE_FORMAT_HE) {
+				/* AX/VHT rate */
+				rate->param.data_rate.tx_rate_format =
+					pmpriv->tx_rate_info & 0x3;
+				rate->param.data_rate.tx_ht_bw =
+					(pmpriv->tx_rate_info & 0xC) >> 2;
+				if ((pmpriv->tx_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_HE)
+					rate->param.data_rate.tx_ht_gi =
+						(pmpriv->tx_rate_info & 0x10) >>
+						4 |
+						(pmpriv->tx_rate_info & 0x80) >>
+						6;
+				else
+					rate->param.data_rate.tx_ht_gi =
+						(pmpriv->tx_rate_info & 0x10) >>
+						4;
+				rate->param.data_rate.tx_nss =
+					((pmpriv->tx_rate) >> 4) & 0x03;
+				rate->param.data_rate.tx_mcs_index =
+					(pmpriv->tx_rate) & 0xF;
+				if ((pmpriv->tx_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_VHT
+				    || (pmpriv->tx_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_HE)
+					rate->param.data_rate.tx_data_rate =
+						wlan_index_to_data_rate
+						(pmadapter, pmpriv->tx_rate,
+						 pmpriv->tx_rate_info,
+						 pmpriv->ext_tx_rate_info);
+			} else if ((pmpriv->tx_rate_info & 0x3) ==
+				   MLAN_RATE_FORMAT_HT) {
+				/* HT rate */
+				rate->param.data_rate.tx_rate_format =
+					MLAN_RATE_FORMAT_HT;
+				rate->param.data_rate.tx_ht_bw =
+					(pmpriv->tx_rate_info & 0xC) >> 2;
+
+				rate->param.data_rate.tx_ht_gi =
+					(pmpriv->tx_rate_info & 0x10) >> 4;
+				rate->param.data_rate.tx_mcs_index =
+					pmpriv->tx_rate;
+				rate->param.data_rate.tx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->tx_rate,
+								pmpriv->
+								tx_rate_info,
+								pmpriv->
+								ext_tx_rate_info);
+			} else {
+				/* LG rate */
+				rate->param.data_rate.tx_rate_format =
+					MLAN_RATE_FORMAT_LG;
+				/* For HostCmd_CMD_802_11_TX_RATE_QUERY,
+				 * there is a hole in rate table
+				 * between HR/DSSS and OFDM rates,
+				 * so minus 1 for OFDM rate index */
+				rate->param.data_rate.tx_data_rate =
+					(pmpriv->tx_rate >
+					 MLAN_RATE_INDEX_OFDM0) ?
+					pmpriv->tx_rate - 1 : pmpriv->tx_rate;
+			}
+
+			/* Rx rate info */
+			if ((pmpriv->rxpd_rate_info & 0x3) ==
+			    MLAN_RATE_FORMAT_VHT
+			    || (pmpriv->rxpd_rate_info & 0x3) ==
+			    MLAN_RATE_FORMAT_HE) {
+				/* VHT rate */
+				rate->param.data_rate.rx_rate_format =
+					pmpriv->rxpd_rate_info & 0x3;
+				rate->param.data_rate.rx_ht_bw =
+					(pmpriv->rxpd_rate_info & 0xC) >> 2;
+				if ((pmpriv->rxpd_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_HE)
+					rate->param.data_rate.rx_ht_gi =
+						(pmpriv->rxpd_rate_info &
+						 0x10) >>
+						4 |
+						(pmpriv->rxpd_rate_info &
+						 0x80) >> 6;
+				else
+					rate->param.data_rate.rx_ht_gi =
+						(pmpriv->rxpd_rate_info &
+						 0x10) >> 4;
+				rate->param.data_rate.rx_nss =
+					((pmpriv->rxpd_rate) >> 4) & 0x3;
+				rate->param.data_rate.rx_mcs_index =
+					(pmpriv->rxpd_rate) & 0xF;
+				if ((pmpriv->rxpd_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_VHT
+				    || (pmpriv->rxpd_rate_info & 0x3) ==
+				    MLAN_RATE_FORMAT_HE)
+					rate->param.data_rate.rx_data_rate =
+						wlan_index_to_data_rate
+						(pmadapter, pmpriv->rxpd_rate,
+						 pmpriv->rxpd_rate_info,
+						 pmpriv->rxpd_rx_info);
+			} else if ((pmpriv->rxpd_rate_info & 0x3) ==
+				   MLAN_RATE_FORMAT_HT) {
+				/* HT rate */
+				rate->param.data_rate.rx_rate_format =
+					MLAN_RATE_FORMAT_HT;
+				rate->param.data_rate.rx_ht_bw =
+					(pmpriv->rxpd_rate_info & 0xC) >> 2;
+				rate->param.data_rate.rx_ht_gi =
+					(pmpriv->rxpd_rate_info & 0x10) >> 4;
+				rate->param.data_rate.rx_mcs_index =
+					pmpriv->rxpd_rate;
+				rate->param.data_rate.rx_data_rate =
+					wlan_index_to_data_rate(pmadapter,
+								pmpriv->
+								rxpd_rate,
+								pmpriv->
+								rxpd_rate_info,
+								0);
+			} else {
+				/* LG rate */
+				rate->param.data_rate.rx_rate_format =
+					MLAN_RATE_FORMAT_LG;
+				/* For rate index in RxPD,
+				 * there is a hole in rate table
+				 * between HR/DSSS and OFDM rates,
+				 * so minus 1 for OFDM rate index */
+				rate->param.data_rate.rx_data_rate =
+					(pmpriv->rxpd_rate >
+					 MLAN_RATE_INDEX_OFDM0) ?
+					pmpriv->rxpd_rate - 1 :
+					pmpriv->rxpd_rate;
+			}
+		}
+		pioctl_buf->data_read_written =
+			sizeof(mlan_data_rate) + MLAN_SUB_COMMAND_SIZE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function prepares command of robustcoex.
+ *
+ * @param pmpriv       A pointer to mlan_private structure
+ * @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action   The action: GET or SET
+ * @param pdata_buf    A pointer to data buffer
+ *
+ * @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_robustcoex(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_u16 *pdata_buf)
+{
+	HostCmd_DS_802_11_ROBUSTCOEX *rbstcx = &cmd->params.robustcoexparams;
+	mlan_ds_misc_robustcoex_params *robustcoex_params = MNULL;
+	MrvlIEtypes_RobustcoexSourceGPIO_t *tlv =
+		(MrvlIEtypes_RobustcoexSourceGPIO_t *) (rbstcx->tlv_buf);
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ROBUSTCOEX);
+	cmd->size = sizeof(HostCmd_DS_802_11_ROBUSTCOEX) + S_DS_GEN;
+	rbstcx->action = wlan_cpu_to_le16(cmd_action);
+	switch (cmd_action) {
+	case HostCmd_ACT_GEN_SET:
+		robustcoex_params =
+			(mlan_ds_misc_robustcoex_params *) pdata_buf;
+		if (robustcoex_params->method == ROBUSTCOEX_GPIO_CFG) {
+			cmd->size += sizeof(MrvlIEtypes_RobustcoexSourceGPIO_t);
+			tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_ROBUSTCOEX);
+			tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_RobustcoexSourceGPIO_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			tlv->enable = (t_u8)robustcoex_params->enable;
+			tlv->gpio_num = (t_u8)robustcoex_params->gpio_num;
+			tlv->gpio_polarity =
+				(t_u8)robustcoex_params->gpio_polarity;
+		}
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(PCIE)
+/**
+ * @brief This function enables SSU support.
+ *
+ * @param pmpriv       A pointer to mlan_private structure
+ * @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action   The action: GET or SET
+ * @param pdata_buf    A pointer to data buffer
+ *
+ * @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_ssu(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+	     t_u16 cmd_action, t_u16 *pdata_buf)
+{
+	HostCmd_DS_SSU_CFG *ssu_cfg_cmd = &cmd->params.ssu_params;
+	mlan_ds_ssu_params *ssu_params = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SSU);
+	cmd->size = sizeof(HostCmd_DS_SSU_CFG) + S_DS_GEN;
+	ssu_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+	switch (cmd_action) {
+	case HostCmd_ACT_GEN_SET:
+	case HostCmd_ACT_GEN_SET_DEFAULT:
+		ssu_params = (mlan_ds_ssu_params *) pdata_buf;
+		ssu_cfg_cmd->nskip = wlan_cpu_to_le32(ssu_params->nskip);
+		ssu_cfg_cmd->nsel = wlan_cpu_to_le32(ssu_params->nsel);
+		ssu_cfg_cmd->adcdownsample =
+			wlan_cpu_to_le32(ssu_params->adcdownsample);
+		ssu_cfg_cmd->mask_adc_pkt =
+			wlan_cpu_to_le32(ssu_params->mask_adc_pkt);
+		ssu_cfg_cmd->out_16bits =
+			wlan_cpu_to_le32(ssu_params->out_16bits);
+		ssu_cfg_cmd->spec_pwr_enable =
+			wlan_cpu_to_le32(ssu_params->spec_pwr_enable);
+		ssu_cfg_cmd->rate_deduction =
+			wlan_cpu_to_le32(ssu_params->rate_deduction);
+		ssu_cfg_cmd->n_pkt_avg =
+			wlan_cpu_to_le32(ssu_params->n_pkt_avg);
+		/* Initialize PCIE ring buffer */
+		ret = wlan_alloc_ssu_pcie_buf(pmadapter);
+		if (MLAN_STATUS_SUCCESS != ret) {
+			PRINTM(MERROR,
+			       "Failed to allocate PCIE host buffers for SSU\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		ssu_cfg_cmd->buffer_base_addr[0] =
+			wlan_cpu_to_le32((t_u32)pmadapter->ssu_buf->buf_pa);
+		ssu_cfg_cmd->buffer_base_addr[1] = wlan_cpu_to_le32((t_u32)
+								    ((t_u64)
+								     (pmadapter->
+								      ssu_buf->
+								      buf_pa >>
+								      32)));
+		ssu_cfg_cmd->buffer_pool_size =
+			wlan_cpu_to_le32(MLAN_SSU_BUF_SIZE);
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * @brief This function prepares command of dmcs config.
+ *
+ * @param pmpriv       A pointer to mlan_private structure
+ * @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action   The action: GET or SET
+ * @param pdata_buf    A pointer to data buffer
+ *
+ * @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_dmcs_config(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *cmd,
+		     t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_DMCS_CFG *dmcs = &cmd->params.dmcs;
+	mlan_ds_misc_mapping_policy *dmcs_params = MNULL;
+	t_u8 *mapping_policy = (t_u8 *)dmcs->tlv_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DMCS_CONFIG);
+	cmd->size = sizeof(HostCmd_DS_DMCS_CFG) + S_DS_GEN;
+	dmcs->action = wlan_cpu_to_le16(cmd_action);
+	dmcs_params = (mlan_ds_misc_mapping_policy *) pdata_buf;
+	dmcs->subcmd = wlan_cpu_to_le16(dmcs_params->subcmd);
+	switch (dmcs->subcmd) {
+	case 0:
+		cmd->size += sizeof(t_u8);
+		*mapping_policy = dmcs_params->mapping_policy;
+		break;
+	case 1:
+	default:
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of dmcs config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_dmcs_config(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_DMCS_CFG *dmcs = &resp->params.dmcs;
+	MrvlIEtypes_DmcsStatus_t *dmcs_status;
+	mlan_ds_misc_cfg *cfg = MNULL;
+	t_u16 tlv_buf_left = 0;
+	t_u16 tlv_type = 0, tlv_len = 0;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	int i = 0;
+
+	ENTER();
+	if (pioctl_buf) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)dmcs +
+					      sizeof(HostCmd_DS_DMCS_CFG));
+		tlv_buf_left =
+			resp->size - (sizeof(HostCmd_DS_DMCS_CFG) + S_DS_GEN);
+		while (tlv_buf_left > sizeof(MrvlIEtypesHeader_t)) {
+			tlv_type = wlan_le16_to_cpu(tlv->type);
+			tlv_len = wlan_le16_to_cpu(tlv->len);
+			if (tlv_buf_left <
+			    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+				PRINTM(MERROR,
+				       "Error while processing DMCS status tlv, bytes_left < TLV len\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+			switch (tlv_type) {
+			case TLV_TYPE_DMCS_STATUS:
+				dmcs_status = (MrvlIEtypes_DmcsStatus_t *) tlv;
+				cfg->param.dmcs_status.mapping_policy =
+					dmcs_status->mapping_policy;
+				memset(pmpriv->adapter,
+				       &cfg->param.dmcs_status.radio_status, 0,
+				       sizeof(dmcsStatus_t));
+				for (i = 0; i < MAX_NUM_MAC; i++) {
+					memcpy_ext(pmpriv->adapter,
+						   &cfg->param.dmcs_status.
+						   radio_status[i],
+						   &dmcs_status->
+						   radio_status[i],
+						   sizeof(dmcsStatus_t),
+						   sizeof(dmcsStatus_t));
+				}
+				break;
+			default:
+				break;
+			}
+			tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+			tlv = (MrvlIEtypesHeader_t
+			       *)((t_u8 *)tlv + tlv_len +
+				  sizeof(MrvlIEtypesHeader_t));
+		}
+		pioctl_buf->data_read_written =
+			sizeof(mlan_ds_misc_dmcs_status);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of tx_rate_cfg.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @param pioctl_buf	A pointer to ioctl buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_tx_rate_cfg(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *cmd,
+		     t_u16 cmd_action, t_void *pdata_buf,
+		     mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_TX_RATE_CFG *rate_cfg =
+		(HostCmd_DS_TX_RATE_CFG *)&(cmd->params.tx_rate_cfg);
+	MrvlRateScope_t *rate_scope;
+	MrvlRateDropPattern_t *rate_drop;
+	MrvlIETypes_rate_setting_t *rate_setting_tlv;
+	mlan_ds_rate *ds_rate = MNULL;
+	t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
+
+	t_u32 i;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
+
+	rate_cfg->action = wlan_cpu_to_le16(cmd_action);
+	rate_cfg->cfg_index = 0;
+
+	rate_scope = (MrvlRateScope_t *)rate_cfg->tlv_buf;
+	rate_scope->type = wlan_cpu_to_le16(TLV_TYPE_RATE_SCOPE);
+	rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) -
+					      sizeof(MrvlIEtypesHeader_t));
+	if (pbitmap_rates != MNULL) {
+		rate_scope->hr_dsss_rate_bitmap =
+			wlan_cpu_to_le16(pbitmap_rates[0]);
+		rate_scope->ofdm_rate_bitmap =
+			wlan_cpu_to_le16(pbitmap_rates[1]);
+		for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
+			rate_scope->ht_mcs_rate_bitmap[i] =
+				wlan_cpu_to_le16(pbitmap_rates[2 + i]);
+		for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
+			rate_scope->vht_mcs_rate_bitmap[i] =
+				wlan_cpu_to_le16(pbitmap_rates
+						 [2 +
+						  NELEMENTS(rate_scope->
+							    ht_mcs_rate_bitmap)
+						  + i]);
+		if (IS_FW_SUPPORT_11AX(pmpriv->adapter)) {
+			for (i = 0;
+			     i < NELEMENTS(rate_scope->he_mcs_rate_bitmap); i++)
+				rate_scope->he_mcs_rate_bitmap
+					[i] = wlan_cpu_to_le16(pbitmap_rates
+							       [2 +
+								wlan_get_bitmap_index
+								(rate_scope)
+								+ i]);
+		} else {
+			rate_scope->length =
+				wlan_cpu_to_le16(sizeof(MrvlRateScope_t) -
+						 sizeof(rate_scope->
+							he_mcs_rate_bitmap) -
+						 sizeof(MrvlIEtypesHeader_t));
+		}
+	} else {
+		rate_scope->hr_dsss_rate_bitmap =
+			wlan_cpu_to_le16(pmpriv->bitmap_rates[0]);
+		rate_scope->ofdm_rate_bitmap =
+			wlan_cpu_to_le16(pmpriv->bitmap_rates[1]);
+		for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
+			rate_scope->ht_mcs_rate_bitmap[i] =
+				wlan_cpu_to_le16(pmpriv->bitmap_rates[2 + i]);
+		for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
+			rate_scope->vht_mcs_rate_bitmap[i] =
+				wlan_cpu_to_le16(pmpriv->
+						 bitmap_rates[2 +
+							      NELEMENTS
+							      (rate_scope->
+							       ht_mcs_rate_bitmap)
+							      + i]);
+		if (IS_FW_SUPPORT_11AX(pmpriv->adapter)) {
+			for (i = 0;
+			     i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap);
+			     i++)
+				rate_scope->he_mcs_rate_bitmap
+					[i] =
+					wlan_cpu_to_le16(pmpriv->
+							 bitmap_rates[2 +
+								      wlan_get_bitmap_index
+								      (rate_scope)
+								      + i]);
+		} else {
+			rate_scope->length =
+				wlan_cpu_to_le16(sizeof(MrvlRateScope_t) -
+						 sizeof(rate_scope->
+							he_mcs_rate_bitmap) -
+						 sizeof(MrvlIEtypesHeader_t));
+		}
+	}
+
+	rate_drop =
+		(MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
+					  wlan_le16_to_cpu(rate_scope->length) +
+					  sizeof(MrvlIEtypesHeader_t));
+	rate_drop->type = wlan_cpu_to_le16(TLV_TYPE_RATE_DROP_PATTERN);
+	rate_drop->length = wlan_cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
+	rate_drop->rate_drop_mode = 0;
+
+	cmd->size =
+		wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) +
+				 rate_scope->length +
+				 sizeof(MrvlIEtypesHeader_t) +
+				 sizeof(MrvlRateDropPattern_t));
+	if (pioctl_buf && pmpriv->adapter->pcard_info->v17_fw_api) {
+		ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
+		rate_setting_tlv = (MrvlIETypes_rate_setting_t
+				    *) ((t_u8 *)rate_drop +
+					sizeof(MrvlRateDropPattern_t));
+		rate_setting_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_TX_RATE_CFG);
+		rate_setting_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (rate_setting_tlv->rate_setting));
+		rate_setting_tlv->rate_setting =
+			wlan_cpu_to_le16(ds_rate->param.rate_cfg.rate_setting);
+		PRINTM(MCMND, "he rate setting = %d\n",
+		       rate_setting_tlv->rate_setting);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_TX_RATE_CFG) +
+					 rate_scope->length +
+					 sizeof(MrvlIEtypesHeader_t) +
+					 sizeof(MrvlRateDropPattern_t) +
+					 sizeof(MrvlIETypes_rate_setting_t));
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of tx_rate_cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_tx_rate_cfg(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_ds_rate *ds_rate = MNULL;
+	HostCmd_DS_TX_RATE_CFG *prate_cfg = MNULL;
+	MrvlRateScope_t *prate_scope;
+	MrvlIEtypesHeader_t *head = MNULL;
+	t_u16 tlv, tlv_buf_len = 0;
+	t_u8 *tlv_buf;
+	t_u32 i;
+	t_s32 index;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	MrvlIETypes_rate_setting_t *rate_setting_tlv = MNULL;
+	t_u16 rate_setting = 0xffff;
+
+	ENTER();
+
+	if (resp == MNULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	prate_cfg = (HostCmd_DS_TX_RATE_CFG *)&(resp->params.tx_rate_cfg);
+
+	tlv_buf = (t_u8 *)prate_cfg->tlv_buf;
+	if (tlv_buf) {
+		tlv_buf_len = resp->size -
+			(sizeof(HostCmd_DS_TX_RATE_CFG) + S_DS_GEN);
+		tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len);
+	}
+
+	while (tlv_buf && tlv_buf_len > 0) {
+		tlv = (*tlv_buf);
+		tlv = tlv | (*(tlv_buf + 1) << 8);
+
+		switch (tlv) {
+		case TLV_TYPE_RATE_SCOPE:
+			prate_scope = (MrvlRateScope_t *)tlv_buf;
+			pmpriv->bitmap_rates[0] =
+				wlan_le16_to_cpu(prate_scope->
+						 hr_dsss_rate_bitmap);
+			pmpriv->bitmap_rates[1] =
+				wlan_le16_to_cpu(prate_scope->ofdm_rate_bitmap);
+			for (i = 0;
+			     i < NELEMENTS(prate_scope->ht_mcs_rate_bitmap);
+			     i++)
+				pmpriv->bitmap_rates[2 + i] =
+					wlan_le16_to_cpu(prate_scope->
+							 ht_mcs_rate_bitmap[i]);
+			for (i = 0;
+			     i < NELEMENTS(prate_scope->vht_mcs_rate_bitmap);
+			     i++)
+				pmpriv->bitmap_rates[2 +
+						     sizeof(prate_scope->
+							    ht_mcs_rate_bitmap)
+						     / sizeof(t_u16) + i] =
+					wlan_le16_to_cpu(prate_scope->
+							 vht_mcs_rate_bitmap
+							 [i]);
+			if (IS_FW_SUPPORT_11AX(pmadapter)) {
+				for (i = 0;
+				     i <
+				     NELEMENTS(prate_scope->he_mcs_rate_bitmap);
+				     i++)
+					pmpriv->bitmap_rates
+						[2 +
+						 sizeof(prate_scope->
+							ht_mcs_rate_bitmap) /
+						 sizeof(t_u16) +
+						 sizeof(prate_scope->
+							vht_mcs_rate_bitmap)
+						 / sizeof(t_u16) + i] =
+						wlan_le16_to_cpu(prate_scope->
+								 he_mcs_rate_bitmap
+								 [i]);
+			}
+			break;
+		case TLV_TYPE_TX_RATE_CFG:
+			rate_setting_tlv =
+				(MrvlIETypes_rate_setting_t *) tlv_buf;
+			rate_setting = rate_setting_tlv->rate_setting;
+			break;
+			/* Add RATE_DROP tlv here */
+		}
+
+		head = (MrvlIEtypesHeader_t *)tlv_buf;
+		head->len = wlan_le16_to_cpu(head->len);
+		tlv_buf += head->len + sizeof(MrvlIEtypesHeader_t);
+		tlv_buf_len -= (head->len + sizeof(MrvlIEtypesHeader_t));
+	}
+
+	pmpriv->is_data_rate_auto = wlan_is_rate_auto(pmpriv);
+
+	if (pmpriv->is_data_rate_auto) {
+		pmpriv->data_rate = 0;
+	} else {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	}
+
+	if (pioctl_buf) {
+		ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
+		if (ds_rate == MNULL) {
+			PRINTM(MERROR, "Request buffer not found!\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (pmpriv->is_data_rate_auto) {
+			ds_rate->param.rate_cfg.is_rate_auto = MTRUE;
+			ds_rate->param.rate_cfg.rate_format =
+				MLAN_RATE_FORMAT_AUTO;
+		} else {
+			ds_rate->param.rate_cfg.is_rate_auto = MFALSE;
+			/* check the LG rate */
+			index = wlan_get_rate_index(pmadapter,
+						    &pmpriv->bitmap_rates[0],
+						    4);
+			if (index != -1) {
+				if ((index >= MLAN_RATE_BITMAP_OFDM0) &&
+				    (index <= MLAN_RATE_BITMAP_OFDM7))
+					index -= (MLAN_RATE_BITMAP_OFDM0 -
+						  MLAN_RATE_INDEX_OFDM0);
+				ds_rate->param.rate_cfg.rate_format =
+					MLAN_RATE_FORMAT_LG;
+				ds_rate->param.rate_cfg.rate = index;
+			}
+			/* check the HT rate */
+			index = wlan_get_rate_index(pmadapter,
+						    &pmpriv->bitmap_rates[2],
+						    16);
+			if (index != -1) {
+				ds_rate->param.rate_cfg.rate_format =
+					MLAN_RATE_FORMAT_HT;
+				ds_rate->param.rate_cfg.rate = index;
+			}
+			/* check the VHT rate */
+			index = wlan_get_rate_index(pmadapter,
+						    &pmpriv->bitmap_rates[10],
+						    16);
+			if (index != -1) {
+				ds_rate->param.rate_cfg.rate_format =
+					MLAN_RATE_FORMAT_VHT;
+				ds_rate->param.rate_cfg.rate = index % 16;
+				ds_rate->param.rate_cfg.nss = index / 16;
+				ds_rate->param.rate_cfg.nss += MLAN_RATE_NSS1;
+			}
+			/* check the HE rate */
+			if (IS_FW_SUPPORT_11AX(pmadapter)) {
+				index = wlan_get_rate_index(pmadapter,
+							    &pmpriv->
+							    bitmap_rates[18],
+							    16);
+				if (index != -1) {
+					ds_rate->param.rate_cfg.rate_format =
+						MLAN_RATE_FORMAT_HE;
+					ds_rate->param.rate_cfg.rate =
+						index % 16;
+					ds_rate->param.rate_cfg.nss =
+						index / 16;
+					ds_rate->param.rate_cfg.nss +=
+						MLAN_RATE_NSS1;
+				}
+			}
+			ds_rate->param.rate_cfg.rate_setting = rate_setting;
+			PRINTM(MINFO, "Rate index is %d\n",
+			       ds_rate->param.rate_cfg.rate);
+		}
+		for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
+			ds_rate->param.rate_cfg.bitmap_rates[i] =
+				pmpriv->bitmap_rates[i];
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues adapter specific commands
+ *          to initialize firmware
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_adapter_get_hw_spec(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+#if defined(SDIO)
+	/*
+	 * This should be issued in the very first to config
+	 *   SDIO_GPIO interrupt mode.
+	 */
+	if (IS_SD(pmadapter->card_type) &&
+	    (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#endif
+
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type) &&
+	    (MLAN_STATUS_SUCCESS != wlan_set_pcie_buf_config(priv))) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#endif
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT, HostCmd_ACT_GEN_SET,
+			       0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/** DPD data dnld cmd prepare */
+	if ((pmadapter->pdpd_data) && (pmadapter->dpd_data_len > 0)) {
+		ret = wlan_process_hostcmd_cfg(priv, CFG_TYPE_DPDFILE,
+					       pmadapter->pdpd_data,
+					       pmadapter->dpd_data_len);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmadapter->pdpd_data = MNULL;
+		pmadapter->dpd_data_len = 0;
+	}
+	if ((pmadapter->ptxpwr_data) && (pmadapter->txpwr_data_len > 0)) {
+		ret = wlan_process_hostcmd_cfg(priv, CFG_TYPE_HOSTCMD,
+					       pmadapter->ptxpwr_data,
+					       pmadapter->txpwr_data_len);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmadapter->ptxpwr_data = MNULL;
+		pmadapter->txpwr_data_len = 0;
+	}
+	if (!pmadapter->pdpd_data &&
+	    (pmadapter->dpd_data_len == UNKNOW_DPD_LENGTH)) {
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
+				       HostCmd_ACT_GEN_GET, OID_TYPE_DPD, MNULL,
+				       MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/** Cal data dnld cmd prepare */
+	if ((pmadapter->pcal_data) && (pmadapter->cal_data_len > 0)) {
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
+				       HostCmd_ACT_GEN_SET, OID_TYPE_CAL, MNULL,
+				       MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmadapter->pcal_data = MNULL;
+		pmadapter->cal_data_len = 0;
+	}
+	/* Get FW region and cfp tables */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/*
+	 * Get HW spec
+	 */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues adapter specific commands
+ *          to initialize firmware
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_adapter_init_cmd(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = MNULL;
+#ifdef STA_SUPPORT
+	pmlan_private pmpriv_sta = MNULL;
+#endif
+	ENTER();
+
+	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+#ifdef STA_SUPPORT
+	pmpriv_sta = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
+#endif
+
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+	}
+#endif
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
+			       HostCmd_ACT_GEN_SET, 0, MNULL,
+			       &pmadapter->max_tx_buf_size);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#if defined(STA_SUPPORT)
+	if (pmpriv_sta && (pmpriv_sta->state_11d.user_enable_11d == ENABLE_11D)) {
+		/* Send command to FW to enable 11d */
+		ret = wlan_prepare_cmd(pmpriv_sta, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, Dot11D_i, MNULL,
+				       &pmpriv_sta->state_11d.user_enable_11d);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#endif
+
+#ifdef STA_SUPPORT
+	if (pmpriv_sta && (pmadapter->ps_mode == Wlan802_11PowerModePSP)) {
+		ret = wlan_prepare_cmd(pmpriv_sta,
+				       HostCmd_CMD_802_11_PS_MODE_ENH,
+				       EN_AUTO_PS, BITMAP_STA_PS, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#endif
+
+	if (pmadapter->init_auto_ds) {
+		mlan_ds_auto_ds auto_ds;
+		/* Enable auto deep sleep */
+		auto_ds.idletime = pmadapter->idle_time;
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+				       EN_AUTO_PS, BITMAP_AUTO_DS, MNULL,
+				       &auto_ds);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#define DEF_AUTO_NULL_PKT_PERIOD 30
+	if (pmpriv_sta) {
+		t_u32 value = DEF_AUTO_NULL_PKT_PERIOD;
+		ret = wlan_prepare_cmd(pmpriv_sta, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, NullPktPeriod_i,
+				       MNULL, &value);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (pmadapter->init_para.indrstcfg != 0xffffffff) {
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+		ind_rst_cfg.ir_mode = pmadapter->init_para.indrstcfg & 0xff;
+		ind_rst_cfg.gpio_pin =
+			(pmadapter->init_para.indrstcfg & 0xff00) >> 8;
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_INDEPENDENT_RESET_CFG,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       (t_void *)&ind_rst_cfg);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (pmadapter->inact_tmo) {
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       &pmadapter->inact_tmo);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+mlan_status
+wlan_cmd_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *cmd,
+			     t_u16 cmd_action, t_void *pdata_buf)
+{
+	mlan_ds_misc_rx_packet_coalesce *rx_pkt_cfg =
+		(mlan_ds_misc_rx_packet_coalesce *)pdata_buf;
+	HostCmd_DS_RX_PKT_COAL_CFG *prx_coal_cfg =
+		(HostCmd_DS_RX_PKT_COAL_CFG *)&cmd->params.rx_pkt_coal_cfg;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_PKT_COALESCE_CFG);
+	prx_coal_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		prx_coal_cfg->packet_threshold =
+			wlan_cpu_to_le32(rx_pkt_cfg->packet_threshold);
+		prx_coal_cfg->delay = wlan_cpu_to_le16(rx_pkt_cfg->delay);
+		PRINTM(MCMND,
+		       "Set RX coal config: packet threshold=%d delay=%d\n",
+		       rx_pkt_cfg->packet_threshold, rx_pkt_cfg->delay);
+		cmd->size =
+			wlan_cpu_to_le16(S_DS_GEN +
+					 sizeof(HostCmd_DS_RX_PKT_COAL_CFG));
+	} else {
+		cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of RX_PACKET_COAL_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+			     const HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_RX_PKT_COAL_CFG *presp_cfg =
+		&resp->params.rx_pkt_coal_cfg;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.rx_coalesce.packet_threshold =
+			wlan_le32_to_cpu(presp_cfg->packet_threshold);
+		pcfg->param.rx_coalesce.delay =
+			wlan_le16_to_cpu(presp_cfg->delay);
+		PRINTM(MCMND,
+		       "Get rx pkt coalesce info: packet threshold=%d delay=%d\n",
+		       pcfg->param.rx_coalesce.packet_threshold,
+		       pcfg->param.rx_coalesce.delay);
+		pioctl_buf->buf_len = sizeof(mlan_ds_misc_rx_packet_coalesce);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#endif
+
+/**
+ *  @brief This function download the vdll block.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param block            A pointer to VDLL block
+ *  @param block_len      The VDLL block length
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_download_vdll_block(mlan_adapter *pmadapter, t_u8 *block, t_u16 block_len)
+{
+	mlan_status status = MLAN_STATUS_FAILURE;
+	mlan_status ret = MLAN_STATUS_PENDING;
+#if defined(SDIO) || defined(PCIE)
+	pvdll_dnld_ctrl ctrl = &pmadapter->vdll_ctrl;
+#endif
+	mlan_buffer *pmbuf = MNULL;
+	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	HostCmd_DS_GEN *cmd_hdr = MNULL;
+	t_u16 msg_len = block_len + sizeof(HostCmd_DS_GEN);
+#ifdef USB
+	t_u32 tmp;
+#endif
+	ENTER();
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type)) {
+		pmbuf = ctrl->cmd_buf;
+		if (pmbuf)
+			pmbuf->data_offset += pmadapter->ops.intf_header_len;
+	}
+#endif
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+					       MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+					       MOAL_MALLOC_BUFFER);
+		if (pmbuf) {
+			tmp = wlan_cpu_to_le32(MLAN_USB_TYPE_VDLL);
+			memcpy_ext(pmadapter,
+				   (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset),
+				   (t_u8 *)&tmp, MLAN_TYPE_LEN, MLAN_TYPE_LEN);
+			pmbuf->data_offset += MLAN_TYPE_LEN;
+		}
+	}
+#endif
+	if (!pmbuf) {
+		PRINTM(MERROR, "dnld vdll: Fail to alloc vdll buf");
+		goto done;
+	}
+	cmd_hdr = (HostCmd_DS_GEN *)(pmbuf->pbuf + pmbuf->data_offset);
+	cmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_VDLL);
+	cmd_hdr->seq_num = wlan_cpu_to_le16(0xFF00);
+	cmd_hdr->size = wlan_cpu_to_le16(msg_len);
+
+	pmadapter->callbacks.moal_memcpy_ext(pmadapter->pmoal_handle,
+					     pmbuf->pbuf + pmbuf->data_offset +
+					     sizeof(HostCmd_DS_GEN),
+					     block, block_len, block_len);
+
+	pmbuf->data_len = msg_len;
+
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type)) {
+		pmbuf->data_offset -= pmadapter->ops.intf_header_len;
+		pmbuf->data_len += pmadapter->ops.intf_header_len;
+	}
+#endif
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		pmbuf->data_offset -= MLAN_TYPE_LEN;
+		pmbuf->data_len += MLAN_TYPE_LEN;
+	}
+#endif
+	PRINTM_NETINTF(MCMND, pmpriv);
+	PRINTM(MCMND, "DNLD_VDLL : block_len=%d\n", block_len);
+
+	ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_VDLL, pmbuf, MNULL);
+
+	if (ret == MLAN_STATUS_FAILURE)
+		PRINTM(MERROR, "DNLD_VDLL: Host to Card Failed\n");
+	else
+		status = MLAN_STATUS_SUCCESS;
+
+done:
+	if ((ret == MLAN_STATUS_FAILURE) || (ret == MLAN_STATUS_SUCCESS)) {
+#ifdef USB
+		if (IS_USB(pmadapter->card_type))
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+#endif
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief The function Get the VDLL image from moal
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param offset          offset
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ *
+ */
+static mlan_status
+wlan_get_vdll_image(pmlan_adapter pmadapter, t_u32 vdll_len)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (ctrl->vdll_mem) {
+		PRINTM(MCMND, "VDLL mem is not empty: %p len=%d\n",
+		       ctrl->vdll_mem, ctrl->vdll_len);
+		goto done;
+	}
+	if (pcb->moal_vmalloc && pcb->moal_vfree)
+		status = pcb->moal_vmalloc(pmadapter->pmoal_handle, vdll_len,
+					   (t_u8 **)&ctrl->vdll_mem);
+	else
+		status = pcb->moal_malloc(pmadapter->pmoal_handle, vdll_len,
+					  MLAN_MEM_DEF,
+					  (t_u8 **)&ctrl->vdll_mem);
+
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "VDLL: Fail to alloc vdll memory");
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_get_vdll_data(pmadapter->pmoal_handle, vdll_len,
+				    ctrl->vdll_mem)) {
+		PRINTM(MERROR, "VDLL: firmware image not available\n");
+		status = MLAN_STATUS_FAILURE;
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)ctrl->vdll_mem);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)ctrl->vdll_mem);
+		ctrl->vdll_mem = MNULL;
+		ctrl->vdll_len = 0;
+		goto done;
+	}
+	/*allocate a memory to store all VDLL images */
+	ctrl->vdll_len = vdll_len;
+	PRINTM(MMSG, "VDLL image: len=%d\n", ctrl->vdll_len);
+done:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function handle the multi_chan info event
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pevent       A pointer to event buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_process_vdll_event(pmlan_private pmpriv, pmlan_buffer pevent)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	vdll_ind *ind = MNULL;
+	t_u32 offset = 0;
+	t_u16 block_len = 0;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
+
+	ENTER();
+	ind = (vdll_ind *) (pevent->pbuf + pevent->data_offset +
+			    sizeof(mlan_event_id));
+	switch (wlan_le16_to_cpu(ind->type)) {
+	case VDLL_IND_TYPE_REQ:
+		offset = wlan_le32_to_cpu(ind->offset);
+		block_len = wlan_le16_to_cpu(ind->block_len);
+		PRINTM(MEVENT, "VDLL_IND: type=%d offset = 0x%x, len = %d\n",
+		       wlan_le16_to_cpu(ind->type), offset, block_len);
+		if (offset <= ctrl->vdll_len) {
+			block_len = MIN(block_len, ctrl->vdll_len - offset);
+			if (!pmadapter->cmd_sent) {
+				status = wlan_download_vdll_block(pmadapter,
+								  ctrl->
+								  vdll_mem +
+								  offset,
+								  block_len);
+				if (status)
+					PRINTM(MERROR,
+					       "Fail to download VDLL block\n");
+			} else {
+				PRINTM(MCMND,
+				       "cmd_sent=1, delay download VDLL block\n");
+				ctrl->pending_block_len = block_len;
+				ctrl->pending_block = ctrl->vdll_mem + offset;
+			}
+		} else {
+			PRINTM(MERROR,
+			       "Invalid VDLL req: offset=0x%x, len=%d, vdll_len=%d\n",
+			       offset, block_len, ctrl->vdll_len);
+		}
+		break;
+
+	case VDLL_IND_TYPE_OFFSET:
+		offset = wlan_le32_to_cpu(ind->offset);
+		PRINTM(MEVENT, "VDLL_IND (OFFSET): offset=0x%x\n", offset);
+		wlan_get_vdll_image(pmadapter, offset);
+		break;
+	case VDLL_IND_TYPE_ERR_SIG:
+		PRINTM(MERROR, "VDLL_IND (SIG ERR).\n");
+		break;
+	case VDLL_IND_TYPE_ERR_ID:
+		PRINTM(MERROR, "VDLL_IND (ID ERR).\n");
+		break;
+	default:
+		PRINTM(MERROR, "unknow vdll ind type=%d\n", ind->type);
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function prepares command of get_hw_spec.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd)
+{
+	HostCmd_DS_GET_HW_SPEC *hw_spec = &pcmd->params.hw_spec;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
+	pcmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
+	memcpy_ext(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef SDIO
+/**
+ *  @brief This function prepares command of sdio rx aggr command.
+ *
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Command action: GET or SET
+ *  @param pdata_buf    A pointer to new setting buf
+
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_sdio_rx_aggr_cfg(HostCmd_DS_COMMAND *pcmd,
+			  t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &pcmd->params.sdio_rx_aggr;
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
+	pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SDIO_SP_RX_AGGR_CFG) +
+				      S_DS_GEN);
+	cfg->action = cmd_action;
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		cfg->enable = *(t_u8 *)pdata_buf;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sdio rx aggr command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_sdio_rx_aggr_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &resp->params.sdio_rx_aggr;
+
+	pmadapter->pcard_sd->sdio_rx_aggr_enable = cfg->enable;
+	pmadapter->pcard_sd->sdio_rx_block_size =
+		wlan_le16_to_cpu(cfg->sdio_block_size);
+	PRINTM(MMSG, "SDIO rx aggr: %d block_size=%d\n", cfg->enable,
+	       pmadapter->pcard_sd->sdio_rx_block_size);
+	if (!pmadapter->pcard_sd->sdio_rx_block_size)
+		pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+	if (pmadapter->pcard_sd->sdio_rx_aggr_enable) {
+		pmadapter->pcard_sd->max_sp_rx_size = SDIO_CMD53_MAX_SIZE;
+		wlan_re_alloc_sdio_rx_mpa_buffer(pmadapter);
+	}
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function prepares command of set_cfg_data.
+ *
+ *  @param pmpriv       A pointer to mlan_private strcture
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Command action: GET or SET
+ *  @param pdata_buf    A pointer to cal_data buf
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_cfg_data(pmlan_private pmpriv,
+		  HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action,
+		  t_u32 cmd_oid, t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_802_11_CFG_DATA *pcfg_data = &(pcmd->params.cfg_data);
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u32 len = 0;
+	t_u32 data_offset;
+	t_u8 *temp_pcmd = (t_u8 *)pcmd;
+
+	ENTER();
+
+	data_offset = S_DS_GEN + sizeof(HostCmd_DS_802_11_CFG_DATA);
+
+	if ((cmd_oid == OID_TYPE_CAL) && (pmadapter->pcal_data) &&
+	    (pmadapter->cal_data_len > 0)) {
+		len = wlan_parse_cal_cfg((t_u8 *)pmadapter->pcal_data,
+					 pmadapter->cal_data_len,
+					 (t_u8 *)(temp_pcmd + data_offset));
+	}
+
+	pcfg_data->action = cmd_action;
+	pcfg_data->type = cmd_oid;
+	pcfg_data->data_len = len;
+
+	pcmd->command = HostCmd_CMD_CFG_DATA;
+	pcmd->size = pcfg_data->data_len + data_offset;
+
+	pcmd->command = wlan_cpu_to_le16(pcmd->command);
+	pcmd->size = wlan_cpu_to_le16(pcmd->size);
+
+	pcfg_data->action = wlan_cpu_to_le16(pcfg_data->action);
+	pcfg_data->type = wlan_cpu_to_le16(pcfg_data->type);
+	pcfg_data->data_len = wlan_cpu_to_le16(pcfg_data->data_len);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of set_cfg_data
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to A pointer to mlan_ioctl_req
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_cfg_data(IN pmlan_private pmpriv,
+		  IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 event_buf[100];
+	mlan_cmdresp_event *pevent = (mlan_cmdresp_event *) event_buf;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_CFG_DATA *pcfg_data = &resp->params.cfg_data;
+	t_u16 action;
+	t_u16 type;
+
+	ENTER();
+
+	if (resp->result != HostCmd_RESULT_OK) {
+		PRINTM(MERROR, "CFG data cmd resp failed\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	if (!pmadapter->pdpd_data &&
+	    (pmadapter->dpd_data_len == UNKNOW_DPD_LENGTH)
+	    && pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
+		action = wlan_le16_to_cpu(pcfg_data->action);
+		type = wlan_le16_to_cpu(pcfg_data->type);
+		if (action == HostCmd_ACT_GEN_GET && (type == OID_TYPE_DPD)) {
+			pcfg_data->action =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_STORE_HOST_CMD_RESP;
+			pevent->resp = (t_u8 *)resp;
+			pevent->event_len = wlan_le16_to_cpu(resp->size);
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_STORE_HOST_CMD_RESP,
+					(mlan_event *)pevent);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of mac_control.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A pointer to command information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_mac_control(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *pcmd,
+		     t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_MAC_CONTROL *pmac = &pcmd->params.mac_ctrl;
+	t_u32 action = *((t_u32 *)pdata_buf);
+
+	ENTER();
+
+	if (cmd_action != HostCmd_ACT_GEN_SET) {
+		PRINTM(MERROR, "wlan_cmd_mac_control(): support SET only.\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
+	pcmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
+	pmac->action = wlan_cpu_to_le32(action);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of mac_control
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_mac_control(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of get_hw_spec
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_get_hw_spec(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
+{
+	HostCmd_DS_GET_HW_SPEC *hw_spec = &resp->params.hw_spec;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 i;
+	t_u16 left_len;
+	t_u16 tlv_type = 0;
+	t_u16 tlv_len = 0;
+	MrvlIEtypes_fw_ver_info_t *api_rev = MNULL;
+	t_u16 api_id = 0;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	MrvlIEtypes_Max_Conn_t *tlv_max_conn = MNULL;
+	MrvlIEtypes_Extension_t *ext_tlv = MNULL;
+	MrvlIEtypes_fw_cap_info_t *fw_cap_tlv = MNULL;
+
+	ENTER();
+
+	pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
+	pmadapter->fw_cap_info &= pmadapter->init_para.dev_cap_mask;
+
+	PRINTM(MMSG, "fw_cap_info=0x%x, dev_cap_mask=0x%x\n",
+	       wlan_le32_to_cpu(hw_spec->fw_cap_info),
+	       pmadapter->init_para.dev_cap_mask);
+#ifdef STA_SUPPORT
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter))
+		pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter);
+	else
+		pmadapter->fw_bands = BAND_B;
+
+	if ((pmadapter->fw_bands & BAND_A) && (pmadapter->fw_bands & BAND_GN))
+		pmadapter->fw_bands |= BAND_AN;
+	if (!(pmadapter->fw_bands & BAND_G) && (pmadapter->fw_bands & BAND_GN))
+		pmadapter->fw_bands &= ~BAND_GN;
+
+	pmadapter->config_bands = pmadapter->fw_bands;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
+	}
+
+	if (pmadapter->fw_bands & BAND_A) {
+		if (pmadapter->fw_bands & BAND_AN) {
+			pmadapter->config_bands |= BAND_AN;
+			for (i = 0; i < pmadapter->priv_num; i++) {
+				if (pmadapter->priv[i])
+					pmadapter->priv[i]->config_bands |=
+						BAND_AN;
+			}
+		}
+		if (pmadapter->fw_bands & BAND_AAC) {
+			pmadapter->config_bands |= BAND_AAC;
+			for (i = 0; i < pmadapter->priv_num; i++) {
+				if (pmadapter->priv[i])
+					pmadapter->priv[i]->config_bands |=
+						BAND_AAC;
+			}
+		}
+		if (pmadapter->fw_bands & BAND_GAC) {
+			pmadapter->config_bands |= BAND_GAC;
+			for (i = 0; i < pmadapter->priv_num; i++) {
+				if (pmadapter->priv[i])
+					pmadapter->priv[i]->config_bands |=
+						BAND_GAC;
+			}
+		}
+		pmadapter->adhoc_start_band = BAND_A;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
+	} else if (pmadapter->fw_bands & BAND_G) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+	} else if (pmadapter->fw_bands & BAND_B) {
+		pmadapter->adhoc_start_band = BAND_B;
+		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
+	}
+#endif /* STA_SUPPORT */
+
+	pmadapter->fw_release_number =
+		wlan_le32_to_cpu(hw_spec->fw_release_number);
+	pmadapter->number_of_antenna =
+		wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0x00ff;
+	pmadapter->antinfo =
+		(wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0xff00) >> 8;
+	PRINTM(MCMND, "num_ant=%d, antinfo=0x%x\n",
+	       pmadapter->number_of_antenna, pmadapter->antinfo);
+
+	PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n",
+	       pmadapter->fw_release_number);
+	PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- " MACSTR "\n",
+	       MAC2STR(hw_spec->permanent_addr));
+	PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X  version=0x%X\n",
+	       wlan_le16_to_cpu(hw_spec->hw_if_version),
+	       wlan_le16_to_cpu(hw_spec->version));
+
+	if (pmpriv->curr_addr[0] == 0xff)
+		memmove(pmadapter, pmpriv->curr_addr, hw_spec->permanent_addr,
+			MLAN_MAC_ADDR_LENGTH);
+	memmove(pmadapter, pmadapter->permanent_addr, hw_spec->permanent_addr,
+		MLAN_MAC_ADDR_LENGTH);
+	pmadapter->hw_dot_11n_dev_cap =
+		wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap);
+	pmadapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11n_cap(pmadapter->priv[i]);
+	}
+
+	wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap);
+	wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_mcs_support);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	pmadapter->user_htstream = pmadapter->hw_dev_mcs_support;
+	/** separate stream config for 2.4G and 5G, will be changed according to
+	 * antenna cfg*/
+	if (pmadapter->fw_bands & BAND_A)
+		pmadapter->user_htstream |= (pmadapter->user_htstream << 8);
+	PRINTM(MCMND, "user_htstream=0x%x\n", pmadapter->user_htstream);
+#endif
+
+	if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) {
+		PRINTM(MCMND, "Enable Beamforming\n");
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->tx_bf_cap =
+					pmadapter->pcard_info->
+					default_11n_tx_bf_cap;
+		}
+	}
+	pmadapter->hw_dot_11ac_dev_cap =
+		wlan_le32_to_cpu(hw_spec->Dot11acDevCap);
+	pmadapter->hw_dot_11ac_mcs_support =
+		wlan_le32_to_cpu(hw_spec->Dot11acMcsSupport);
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11ac_cap(pmadapter->priv[i]);
+	}
+	wlan_show_dot11acdevcap(pmadapter, pmadapter->hw_dot_11ac_dev_cap);
+	wlan_show_dot11acmcssupport(pmadapter,
+				    pmadapter->hw_dot_11ac_mcs_support);
+
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		pmadapter->pcard_sd->mp_end_port =
+			wlan_le16_to_cpu(hw_spec->mp_end_port);
+
+		for (i = 1; i <= (unsigned)(pmadapter->pcard_sd->max_ports -
+					    pmadapter->pcard_sd->mp_end_port);
+		     i++)
+			pmadapter->pcard_sd->mp_data_port_mask &=
+				~(1 << (pmadapter->pcard_sd->max_ports - i));
+	}
+#endif
+
+	pmadapter->max_mgmt_ie_index =
+		wlan_le16_to_cpu(hw_spec->mgmt_buf_count);
+	PRINTM(MCMND, "GET_HW_SPEC: mgmt IE count=%d\n",
+	       pmadapter->max_mgmt_ie_index);
+	if (!pmadapter->max_mgmt_ie_index ||
+	    pmadapter->max_mgmt_ie_index > MAX_MGMT_IE_INDEX)
+		pmadapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
+
+	pmadapter->region_code = wlan_le16_to_cpu(hw_spec->region_code);
+	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+		/* Use the region code to search for the index */
+		if (pmadapter->region_code == region_code_index[i])
+			break;
+	}
+	/* If it's unidentified region code, use the default */
+	if (i >= MRVDRV_MAX_REGION_CODE) {
+		pmadapter->region_code = MRVDRV_DEFAULT_REGION_CODE;
+		PRINTM(MWARN,
+		       "unidentified region code, use the default (0x%02x)\n",
+		       MRVDRV_DEFAULT_REGION_CODE);
+	}
+	/* Synchronize CFP code with region code */
+	pmadapter->cfp_code_bg = pmadapter->region_code;
+	pmadapter->cfp_code_a = pmadapter->region_code;
+
+	if (pmadapter->fw_cap_info & ENHANCE_EXT_SCAN_ENABLE)
+		pmadapter->ext_scan_enh = MTRUE;
+
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		if ((pmadapter->fw_cap_info & SDIO_SP_RX_AGGR_ENABLE) &&
+		    pmadapter->pcard_sd->sdio_rx_aggr_enable) {
+			t_u8 sdio_sp_rx_aggr = MTRUE;
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       &sdio_sp_rx_aggr);
+			if (ret) {
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		} else {
+			pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+			PRINTM(MCMND, "FW: SDIO rx aggr disabled 0x%x\n",
+			       pmadapter->fw_cap_info);
+		}
+	}
+#endif
+
+	if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+				 pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#endif /* STA_SUPPORT */
+	if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
+		t_u8 ecsa_enable = MTRUE;
+		pmadapter->ecsa_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
+		       pmadapter->ecsa_enable);
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
+				       &ecsa_enable);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
+		pmadapter->getlog_enable = MTRUE;
+		PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
+		       pmadapter->getlog_enable);
+	}
+
+	left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
+	tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
+				      sizeof(HostCmd_DS_GET_HW_SPEC));
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_FW_VER_INFO:
+			api_rev = (MrvlIEtypes_fw_ver_info_t *) tlv;
+			api_id = wlan_le16_to_cpu(api_rev->api_id);
+			switch (api_id) {
+			case FW_API_VER_ID:
+				pmadapter->fw_ver = api_rev->major_ver;
+				pmadapter->fw_min_ver = api_rev->minor_ver;
+				PRINTM(MCMND, "fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case UAP_FW_API_VER_ID:
+				pmadapter->uap_fw_ver = api_rev->major_ver;
+				PRINTM(MCMND, "uap fw ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case CHANRPT_API_VER_ID:
+				pmadapter->chanrpt_param_bandcfg =
+					api_rev->minor_ver;
+				PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
+				       api_rev->major_ver, api_rev->minor_ver);
+				break;
+			case FW_HOTFIX_VER_ID:
+				pmadapter->fw_hotfix_ver = api_rev->major_ver;
+				PRINTM(MCMND, "fw hotfix ver=%d\n",
+				       api_rev->major_ver);
+				break;
+			default:
+				break;
+			}
+			break;
+		case TLV_TYPE_MAX_CONN:
+			tlv_max_conn = (MrvlIEtypes_Max_Conn_t *) tlv;
+			PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
+			       tlv_max_conn->max_p2p_conn,
+			       tlv_max_conn->max_sta_conn);
+			if (tlv_max_conn->max_p2p_conn &&
+			    tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					MIN(tlv_max_conn->max_sta_conn,
+					    tlv_max_conn->max_p2p_conn);
+			else if (tlv_max_conn->max_sta_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_sta_conn;
+			else if (tlv_max_conn->max_p2p_conn)
+				pmadapter->max_sta_conn =
+					tlv_max_conn->max_p2p_conn;
+			else
+				pmadapter->max_sta_conn = 0;
+			break;
+		case TLV_TYPE_EXTENSION_ID:
+			ext_tlv = (MrvlIEtypes_Extension_t *) tlv;
+			if (ext_tlv->ext_id == HE_CAPABILITY) {
+				ext_tlv->type = tlv_type;
+				ext_tlv->len = tlv_len;
+				wlan_update_11ax_cap(pmadapter,
+						     (MrvlIEtypes_Extension_t *)
+						     ext_tlv);
+			}
+
+			break;
+		case TLV_TYPE_FW_CAP_INFO:
+			fw_cap_tlv = (MrvlIEtypes_fw_cap_info_t *) tlv;
+			pmadapter->fw_cap_info =
+				wlan_le32_to_cpu(fw_cap_tlv->fw_cap_info);
+			pmadapter->fw_cap_ext =
+				wlan_le32_to_cpu(fw_cap_tlv->fw_cap_ext);
+			PRINTM(MCMND, "fw_cap_info=0x%x fw_cap_ext=0x%x\n",
+			       pmadapter->fw_cap_info, pmadapter->fw_cap_ext);
+			break;
+		default:
+			break;
+		}
+		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of radio_control.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_radio_control(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *cmd,
+			      t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_RADIO_CONTROL *pradio_control = &cmd->params.radio;
+	t_u32 radio_ctl;
+	ENTER();
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL)) +
+				     S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL);
+	pradio_control->action = wlan_cpu_to_le16(cmd_action);
+	memcpy_ext(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32),
+		   sizeof(radio_ctl));
+	pradio_control->control = wlan_cpu_to_le16((t_u16)radio_ctl);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of radio_control
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_802_11_radio_control(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_RADIO_CONTROL *pradio_ctrl =
+		(HostCmd_DS_802_11_RADIO_CONTROL *)&resp->params.radio;
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+	pmadapter->radio_on = wlan_le16_to_cpu(pradio_ctrl->control);
+	if (pioctl_buf) {
+		radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+		radio_cfg->param.radio_on_off = (t_u32)pmadapter->radio_on;
+		pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of remain_on_channel.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_remain_on_channel(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *cmd,
+			   t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
+		&cmd->params.remain_on_chan;
+	mlan_ds_remain_chan *cfg = (mlan_ds_remain_chan *)pdata_buf;
+	ENTER();
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_REMAIN_ON_CHANNEL)) +
+				     S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_REMAIN_ON_CHANNEL);
+	remain_channel->action = cmd_action;
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		if (cfg->remove) {
+			remain_channel->action = HostCmd_ACT_GEN_REMOVE;
+		} else {
+			remain_channel->bandcfg = cfg->bandcfg;
+			remain_channel->channel = cfg->channel;
+			remain_channel->remain_period =
+				wlan_cpu_to_le32(cfg->remain_period);
+		}
+	}
+	remain_channel->action = wlan_cpu_to_le16(remain_channel->action);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of remain_on_channel
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_remain_on_channel(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
+		&resp->params.remain_on_chan;
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+		radio_cfg->param.remain_chan.status = remain_channel->status;
+		radio_cfg->param.remain_chan.bandcfg = remain_channel->bandcfg;
+		radio_cfg->param.remain_chan.channel = remain_channel->channel;
+		radio_cfg->param.remain_chan.remain_period =
+			wlan_le32_to_cpu(remain_channel->remain_period);
+		pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ *  @brief This function prepares command of wifi direct mode.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wifi_direct_mode(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd,
+			  t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &cmd->params.wifi_direct_mode;
+	t_u16 mode = *((t_u16 *)pdata_buf);
+	ENTER();
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_WIFI_DIRECT_MODE)) +
+				     S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_WIFI_DIRECT_MODE_CONFIG);
+	wfd_mode->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		wfd_mode->mode = wlan_cpu_to_le16(mode);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of wifi direct mode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wifi_direct_mode(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &resp->params.wifi_direct_mode;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		bss->param.wfd_mode = wlan_le16_to_cpu(wfd_mode->mode);
+		pioctl_buf->data_read_written = sizeof(mlan_ds_bss);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of p2p_params_config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_p2p_params_config(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *cmd,
+			   t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
+		&cmd->params.p2p_params_config;
+	mlan_ds_wifi_direct_config *cfg =
+		(mlan_ds_wifi_direct_config *)pdata_buf;
+	MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
+	MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
+	t_u8 *tlv = MNULL;
+	ENTER();
+
+	cmd->size = sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) + S_DS_GEN;
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_P2P_PARAMS_CONFIG);
+	p2p_config->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		tlv = (t_u8 *)p2p_config->tlv_buf;
+		if (cfg->flags & WIFI_DIRECT_NOA) {
+			pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
+			pnoa_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
+			pnoa_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_NoA_setting_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			pnoa_tlv->enable = cfg->noa_enable;
+			pnoa_tlv->index = wlan_cpu_to_le16(cfg->index);
+			pnoa_tlv->noa_count = cfg->noa_count;
+			pnoa_tlv->noa_duration =
+				wlan_cpu_to_le32(cfg->noa_duration);
+			pnoa_tlv->noa_interval =
+				wlan_cpu_to_le32(cfg->noa_interval);
+			cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
+			tlv += sizeof(MrvlIEtypes_NoA_setting_t);
+			PRINTM(MCMND,
+			       "Set NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
+			       cfg->noa_enable, cfg->index, cfg->noa_count,
+			       (int)cfg->noa_duration, (int)cfg->noa_interval);
+		}
+		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
+			popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
+			popp_ps_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
+			popp_ps_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_OPP_PS_setting_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+
+			popp_ps_tlv->enable = cfg->ct_window;
+			popp_ps_tlv->enable |= cfg->opp_ps_enable << 7;
+			cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
+			PRINTM(MCMND, "Set OPP_PS: enable=%d ct_win=%d\n",
+			       cfg->opp_ps_enable, cfg->ct_window);
+		}
+	} else if (cmd_action == HostCmd_ACT_GEN_GET) {
+		tlv = (t_u8 *)p2p_config->tlv_buf;
+		if (cfg->flags & WIFI_DIRECT_NOA) {
+			pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
+			pnoa_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
+			pnoa_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_NoA_setting_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
+			tlv += sizeof(MrvlIEtypes_NoA_setting_t);
+		}
+
+		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
+			popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
+			popp_ps_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
+			popp_ps_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_OPP_PS_setting_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
+		}
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of p2p_params_config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_p2p_params_config(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
+		&resp->params.p2p_params_config;
+	mlan_ds_misc_cfg *cfg = MNULL;
+	MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
+	MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	t_u16 tlv_buf_left = 0;
+	t_u16 tlv_type = 0;
+	t_u16 tlv_len = 0;
+
+	ENTER();
+	if (wlan_le16_to_cpu(p2p_config->action) == HostCmd_ACT_GEN_GET) {
+		if (pioctl_buf) {
+			cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			tlv = (MrvlIEtypesHeader_t *)(p2p_config->tlv_buf);
+			tlv_buf_left =
+				resp->size -
+				(sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) +
+				 S_DS_GEN);
+			while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+				tlv_type = wlan_le16_to_cpu(tlv->type);
+				tlv_len = wlan_le16_to_cpu(tlv->len);
+				if (tlv_buf_left <
+				    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+					PRINTM(MERROR,
+					       "Error processing p2p param config TLVs, bytes left < TLV length\n");
+					break;
+				}
+				switch (tlv_type) {
+				case TLV_TYPE_WIFI_DIRECT_NOA:
+					pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)
+						tlv;
+					cfg->param.p2p_config.flags |=
+						WIFI_DIRECT_NOA;
+					cfg->param.p2p_config.noa_enable =
+						pnoa_tlv->enable;
+					cfg->param.p2p_config.index =
+						wlan_le16_to_cpu(pnoa_tlv->
+								 index);
+					cfg->param.p2p_config.noa_count =
+						pnoa_tlv->noa_count;
+					cfg->param.p2p_config.noa_duration =
+						wlan_le32_to_cpu(pnoa_tlv->
+								 noa_duration);
+					cfg->param.p2p_config.noa_interval =
+						wlan_le32_to_cpu(pnoa_tlv->
+								 noa_interval);
+					PRINTM(MCMND,
+					       "Get NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
+					       cfg->param.p2p_config.noa_enable,
+					       cfg->param.p2p_config.index,
+					       cfg->param.p2p_config.noa_count,
+					       (int)cfg->param.p2p_config.
+					       noa_duration,
+					       (int)cfg->param.p2p_config.
+					       noa_interval);
+					break;
+				case TLV_TYPE_WIFI_DIRECT_OPP_PS:
+					popp_ps_tlv =
+						(MrvlIEtypes_OPP_PS_setting_t *)
+						tlv;
+					cfg->param.p2p_config.flags |=
+						WIFI_DIRECT_OPP_PS;
+					cfg->param.p2p_config.opp_ps_enable =
+						(popp_ps_tlv->enable & 0x80) >>
+						7;
+					cfg->param.p2p_config.ct_window =
+						popp_ps_tlv->enable & 0x7f;
+					PRINTM(MCMND,
+					       "Get OPP_PS: enable=%d ct_win=%d\n",
+					       cfg->param.p2p_config.
+					       opp_ps_enable,
+					       cfg->param.p2p_config.ct_window);
+					break;
+				default:
+					break;
+				}
+				tlv_buf_left -=
+					tlv_len + sizeof(MrvlIEtypesHeader_t);
+				tlv = (MrvlIEtypesHeader_t
+				       *)((t_u8 *)tlv + tlv_len +
+					  sizeof(MrvlIEtypesHeader_t));
+			}
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_wifi_direct_config);
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function prepares command of GPIO TSF LATCH.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req buf
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_gpio_tsf_latch(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *cmd,
+			t_u16 cmd_action,
+			mlan_ioctl_req *pioctl_buf, t_void *pdata_buf)
+{
+	HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config =
+		&cmd->params.gpio_tsf_latch;
+	mlan_ds_gpio_tsf_latch *cfg = (mlan_ds_gpio_tsf_latch *) pdata_buf;
+	mlan_ds_misc_cfg *misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	mlan_ds_tsf_info *tsf_info = (mlan_ds_tsf_info *) pdata_buf;
+	MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL;
+	MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL;
+	t_u8 *tlv = MNULL;
+	ENTER();
+
+	cmd->size = sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) + S_DS_GEN;
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG);
+	gpio_tsf_config->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		tlv = (t_u8 *)gpio_tsf_config->tlv_buf;
+		if (misc_cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) {
+			gpio_tsf_latch_config =
+				(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *) tlv;
+			gpio_tsf_latch_config->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_GPIO_TSF_LATCH_CONFIG);
+			gpio_tsf_latch_config->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG)
+						 - sizeof(MrvlIEtypesHeader_t));
+			gpio_tsf_latch_config->clock_sync_mode =
+				cfg->clock_sync_mode;
+			gpio_tsf_latch_config->clock_sync_Role =
+				cfg->clock_sync_Role;
+			gpio_tsf_latch_config->clock_sync_gpio_pin_number =
+				cfg->clock_sync_gpio_pin_number;
+			gpio_tsf_latch_config->clock_sync_gpio_level_toggle =
+				cfg->clock_sync_gpio_level_toggle;
+			gpio_tsf_latch_config->clock_sync_gpio_pulse_width =
+				wlan_cpu_to_le16(cfg->
+						 clock_sync_gpio_pulse_width);
+			cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
+			tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
+			PRINTM(MCMND,
+			       "Set GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d GPIO pulse width=%d\n",
+			       cfg->clock_sync_mode, cfg->clock_sync_Role,
+			       cfg->clock_sync_gpio_pin_number,
+			       cfg->clock_sync_gpio_level_toggle,
+			       (int)cfg->clock_sync_gpio_pulse_width);
+		}
+	} else if (cmd_action == HostCmd_ACT_GEN_GET) {
+		tlv = (t_u8 *)gpio_tsf_config->tlv_buf;
+		if (misc_cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) {
+			gpio_tsf_latch_config =
+				(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *) tlv;
+			gpio_tsf_latch_config->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_GPIO_TSF_LATCH_CONFIG);
+			gpio_tsf_latch_config->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG)
+						 - sizeof(MrvlIEtypesHeader_t));
+			cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
+			tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
+		}
+
+		if (misc_cfg->sub_command == MLAN_OID_MISC_GET_TSF_INFO) {
+			gpio_tsf_latch_report =
+				(MrvlIEtypes_GPIO_TSF_LATCH_REPORT *) tlv;
+			gpio_tsf_latch_report->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_GPIO_TSF_LATCH_REPORT);
+			gpio_tsf_latch_report->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_GPIO_TSF_LATCH_REPORT)
+						 - sizeof(MrvlIEtypesHeader_t));
+			gpio_tsf_latch_report->tsf_format =
+				wlan_cpu_to_le16(tsf_info->tsf_format);
+			PRINTM(MCMND, "Get TSF info: format=%d\n",
+			       tsf_info->tsf_format);
+			cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT);
+		}
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of GPIO TSF Latch
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_gpio_tsf_latch(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config =
+		&resp->params.gpio_tsf_latch;
+	mlan_ds_misc_cfg *cfg = MNULL;
+	MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL;
+	MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	t_u16 tlv_buf_left = 0;
+	t_u16 tlv_type = 0;
+	t_u16 tlv_len = 0;
+
+	ENTER();
+	if (wlan_le16_to_cpu(gpio_tsf_config->action) == HostCmd_ACT_GEN_GET) {
+		if (pioctl_buf) {
+			cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			tlv = (MrvlIEtypesHeader_t *)(gpio_tsf_config->tlv_buf);
+			tlv_buf_left =
+				resp->size -
+				(sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG)
+				 + S_DS_GEN);
+			while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+				tlv_type = wlan_le16_to_cpu(tlv->type);
+				tlv_len = wlan_le16_to_cpu(tlv->len);
+				if (tlv_buf_left <
+				    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+					PRINTM(MERROR,
+					       "Error processing gpio tsf latch config TLVs, bytes left < TLV length\n");
+					break;
+				}
+				switch (tlv_type) {
+				case TLV_TYPE_GPIO_TSF_LATCH_CONFIG:
+					if (cfg->sub_command ==
+					    MLAN_OID_MISC_GPIO_TSF_LATCH) {
+						gpio_tsf_latch_config =
+							(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG
+							 *) tlv;
+						cfg->param.
+							gpio_tsf_latch_config.
+							clock_sync_mode =
+							gpio_tsf_latch_config->
+							clock_sync_mode;
+						cfg->param.
+							gpio_tsf_latch_config.
+							clock_sync_Role =
+							gpio_tsf_latch_config->
+							clock_sync_Role;
+						cfg->param.
+							gpio_tsf_latch_config.
+							clock_sync_gpio_pin_number
+							=
+							gpio_tsf_latch_config->
+							clock_sync_gpio_pin_number;
+						cfg->param.
+							gpio_tsf_latch_config.
+							clock_sync_gpio_level_toggle
+							=
+							gpio_tsf_latch_config->
+							clock_sync_gpio_level_toggle;
+						cfg->param.
+							gpio_tsf_latch_config.
+							clock_sync_gpio_pulse_width
+							=
+							wlan_le16_to_cpu
+							(gpio_tsf_latch_config->
+							 clock_sync_gpio_pulse_width);
+						PRINTM(MCMND,
+						       "Get GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d GPIO pulse width=%d\n",
+						       cfg->param.
+						       gpio_tsf_latch_config.
+						       clock_sync_mode,
+						       cfg->param.
+						       gpio_tsf_latch_config.
+						       clock_sync_Role,
+						       cfg->param.
+						       gpio_tsf_latch_config.
+						       clock_sync_gpio_pin_number,
+						       cfg->param.
+						       gpio_tsf_latch_config.
+						       clock_sync_gpio_level_toggle,
+						       (int)cfg->param.
+						       gpio_tsf_latch_config.
+						       clock_sync_gpio_pulse_width);
+					}
+					break;
+				case TLV_TYPE_GPIO_TSF_LATCH_REPORT:
+					if (cfg->sub_command ==
+					    MLAN_OID_MISC_GET_TSF_INFO) {
+						gpio_tsf_latch_report =
+							(MrvlIEtypes_GPIO_TSF_LATCH_REPORT
+							 *) tlv;
+						cfg->param.tsf_info.tsf_format =
+							wlan_le16_to_cpu
+							(gpio_tsf_latch_report->
+							 tsf_format);
+						cfg->param.tsf_info.tsf_info =
+							wlan_le16_to_cpu
+							(gpio_tsf_latch_report->
+							 tsf_info);
+						cfg->param.tsf_info.tsf =
+							wlan_le64_to_cpu
+							(gpio_tsf_latch_report->
+							 tsf);
+						cfg->param.tsf_info.tsf_offset =
+							wlan_le16_to_cpu
+							(gpio_tsf_latch_report->
+							 tsf_offset);
+						PRINTM(MCMND,
+						       "Get GPIO TSF latch report : format=%d\n info=%d tsf=%llu offset=%d",
+						       cfg->param.tsf_info.
+						       tsf_format,
+						       cfg->param.tsf_info.
+						       tsf_info,
+						       cfg->param.tsf_info.tsf,
+						       cfg->param.tsf_info.
+						       tsf_offset);
+					}
+					break;
+				default:
+					break;
+				}
+				tlv_buf_left -=
+					tlv_len + sizeof(MrvlIEtypesHeader_t);
+				tlv = (MrvlIEtypesHeader_t
+				       *)((t_u8 *)tlv + tlv_len +
+					  sizeof(MrvlIEtypesHeader_t));
+			}
+			if (cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH)
+				pioctl_buf->data_read_written =
+					sizeof(mlan_ds_gpio_tsf_latch);
+			else if (cfg->sub_command == MLAN_OID_MISC_GET_TSF_INFO)
+				pioctl_buf->data_read_written =
+					sizeof(mlan_ds_tsf_info);
+
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of mimo switch configuration.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	HostCmd_DS_MIMO_SWITCH *mimo_switch_cmd = &cmd->params.mimo_switch;
+	mlan_ds_mimo_switch *pmimo_switch = (mlan_ds_mimo_switch *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MIMO_SWITCH);
+	cmd->size =
+		wlan_cpu_to_le16((sizeof(HostCmd_DS_MIMO_SWITCH)) + S_DS_GEN);
+	mimo_switch_cmd->txpath_antmode = pmimo_switch->txpath_antmode;
+	mimo_switch_cmd->rxpath_antmode = pmimo_switch->rxpath_antmode;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of hs wakeup reason.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON);
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_HS_WAKEUP_REASON)) +
+				     S_DS_GEN);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *          hs wakeup reason
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_HS_WAKEUP_REASON *hs_wakeup_reason =
+		(HostCmd_DS_HS_WAKEUP_REASON *)&resp->params.hs_wakeup_reason;
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+	pm_cfg->param.wakeup_reason.hs_wakeup_reason =
+		wlan_le16_to_cpu(hs_wakeup_reason->wakeup_reason);
+	pioctl_buf->data_read_written = sizeof(mlan_ds_pm_cfg);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of tx_rx_pkt_stats
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @param pdata_buf    A pointer to information buffer
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_tx_rx_pkt_stats(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd,
+			 pmlan_ioctl_req pioctl_buf, t_void *pdata_buf)
+{
+	HostCmd_DS_TX_RX_HISTOGRAM *ptx_rx_histogram =
+		&cmd->params.tx_rx_histogram;
+	mlan_ds_misc_tx_rx_histogram *ptx_rx_pkt_stats =
+		(mlan_ds_misc_tx_rx_histogram *) pdata_buf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!ptx_rx_pkt_stats) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_TX_RX_PKT_STATS);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_RX_HISTOGRAM) + S_DS_GEN);
+
+	ptx_rx_histogram->enable = ptx_rx_pkt_stats->enable;
+	ptx_rx_histogram->action = wlan_cpu_to_le16(ptx_rx_pkt_stats->action);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of tx_rx_pkt_stats
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_tx_rx_pkt_stats(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_TX_RX_HISTOGRAM *ptx_rx_histogram =
+		&resp->params.tx_rx_histogram;
+	mlan_ds_misc_cfg *info;
+	t_u16 cmdsize = wlan_le16_to_cpu(resp->size), length;
+	t_u32 *pos, count = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		ptx_rx_histogram->action =
+			wlan_le16_to_cpu(ptx_rx_histogram->action);
+		info = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		length = cmdsize - S_DS_GEN -
+			sizeof(HostCmd_DS_TX_RX_HISTOGRAM);
+		if (length > 0) {
+			info->param.tx_rx_histogram.size = length;
+			memcpy_ext(pmpriv->adapter,
+				   info->param.tx_rx_histogram.value,
+				   (t_u8 *)ptx_rx_histogram +
+				   sizeof(HostCmd_DS_TX_RX_HISTOGRAM),
+				   length, info->param.tx_rx_histogram.size);
+			pos = (t_u32 *)info->param.tx_rx_histogram.value;
+			while (length - 4 * count) {
+				*pos = wlan_le32_to_cpu(*pos);
+				pos += 4;
+				count++;
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief This function prepares command of cwmode control.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_cw_mode_ctrl(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *cmd,
+		      t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CW_MODE_CTRL *cwmode_ctrl = &cmd->params.cwmode;
+	mlan_ds_cw_mode_ctrl *cw_mode = (mlan_ds_cw_mode_ctrl *) pdata_buf;
+	ENTER();
+	cmd->size =
+		wlan_cpu_to_le16((sizeof(HostCmd_DS_CW_MODE_CTRL)) + S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CW_MODE_CTRL);
+	cwmode_ctrl->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cwmode_ctrl->mode = cw_mode->mode;
+		cwmode_ctrl->channel = cw_mode->channel;
+		cwmode_ctrl->chanInfo = cw_mode->chanInfo;
+		cwmode_ctrl->txPower = wlan_cpu_to_le16(cw_mode->txPower);
+		cwmode_ctrl->rateInfo = wlan_cpu_to_le32(cw_mode->rateInfo);
+		cwmode_ctrl->pktLength = wlan_cpu_to_le16(cw_mode->pktLength);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief This function handles the command response of cwmode_ctrl
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_cw_mode_ctrl(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CW_MODE_CTRL *cwmode_resp = &resp->params.cwmode;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc->param.cwmode.mode = cwmode_resp->mode;
+		misc->param.cwmode.channel = cwmode_resp->channel;
+		misc->param.cwmode.chanInfo = cwmode_resp->chanInfo;
+		misc->param.cwmode.txPower =
+			wlan_le16_to_cpu(cwmode_resp->txPower);
+		misc->param.cwmode.rateInfo =
+			wlan_le32_to_cpu(cwmode_resp->rateInfo);
+		;
+		misc->param.cwmode.pktLength =
+			wlan_le16_to_cpu(cwmode_resp->pktLength);
+		;
+		pioctl_buf->data_read_written = sizeof(mlan_ds_misc_cfg);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of rf_antenna.
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_rf_antenna(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *cmd,
+			   t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_RF_ANTENNA *pantenna = &cmd->params.antenna;
+	mlan_ds_ant_cfg *ant_cfg = (mlan_ds_ant_cfg *)pdata_buf;
+	typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 {
+		/** Action */
+		t_u16 action;
+		/**  Antenna or 0xffff (diversity) */
+		t_u16 antenna_mode;
+		/** Evaluate time */
+		t_u16 evaluate_time;
+		/** Current antenna */
+		t_u16 current_antenna;
+	} HostCmd_DS_802_11_RF_ANTENNA_1X1;
+	HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 =
+		(HostCmd_DS_802_11_RF_ANTENNA_1X1 *)&cmd->params.antenna;
+	mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = (mlan_ds_ant_cfg_1x1 *) pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
+	if (!IS_STREAM_2X2(pmpriv->adapter->feature_control))
+		cmd->size =
+			wlan_cpu_to_le16(sizeof
+					 (HostCmd_DS_802_11_RF_ANTENNA_1X1) +
+					 S_DS_GEN);
+	else
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) +
+					 S_DS_GEN);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+			pantenna->action_tx =
+				wlan_cpu_to_le16(HostCmd_ACT_SET_TX);
+			pantenna->tx_antenna_mode =
+				wlan_cpu_to_le16((t_u16)ant_cfg->tx_antenna);
+			pantenna->action_rx =
+				wlan_cpu_to_le16(HostCmd_ACT_SET_RX);
+			pantenna->rx_antenna_mode =
+				wlan_cpu_to_le16((t_u16)ant_cfg->rx_antenna);
+		} else {
+			pantenna_1x1->action =
+				wlan_cpu_to_le16(HostCmd_ACT_SET_BOTH);
+			pantenna_1x1->antenna_mode =
+				wlan_cpu_to_le16((t_u16)ant_cfg_1x1->antenna);
+			pantenna_1x1->evaluate_time = wlan_cpu_to_le16((t_u16)
+								       ant_cfg_1x1->
+								       evaluate_time);
+		}
+	} else {
+		if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+			pantenna->action_tx =
+				wlan_cpu_to_le16(HostCmd_ACT_GET_TX);
+			pantenna->action_rx =
+				wlan_cpu_to_le16(HostCmd_ACT_GET_RX);
+		} else {
+			pantenna_1x1->action =
+				wlan_cpu_to_le16(HostCmd_ACT_GET_BOTH);
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of rf_antenna
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_RF_ANTENNA *pantenna = &resp->params.antenna;
+	t_u16 tx_ant_mode = wlan_le16_to_cpu(pantenna->tx_antenna_mode);
+	t_u16 rx_ant_mode = wlan_le16_to_cpu(pantenna->rx_antenna_mode);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	mlan_adapter *pmadapter = pmpriv->adapter;
+#endif
+	typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 {
+		/** Action */
+		t_u16 action;
+		/**  Antenna or 0xffff (diversity) */
+		t_u16 antenna_mode;
+		/** Evaluate time */
+		t_u16 evaluate_time;
+		/** Current antenna */
+		t_u16 current_antenna;
+	} HostCmd_DS_802_11_RF_ANTENNA_1X1;
+	HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 =
+		(HostCmd_DS_802_11_RF_ANTENNA_1X1 *)&resp->params.antenna;
+	t_u16 ant_mode = wlan_le16_to_cpu(pantenna_1x1->antenna_mode);
+	t_u16 evaluate_time = wlan_le16_to_cpu(pantenna_1x1->evaluate_time);
+	t_u16 current_antenna = wlan_le16_to_cpu(pantenna_1x1->current_antenna);
+	mlan_ds_radio_cfg *radio = MNULL;
+
+	ENTER();
+
+	if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+		PRINTM(MCMND,
+		       "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
+		       " Rx action = 0x%x, Rx Mode = 0x%04x\n",
+		       wlan_le16_to_cpu(pantenna->action_tx), tx_ant_mode,
+		       wlan_le16_to_cpu(pantenna->action_rx), rx_ant_mode);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if (IS_CARD9098(pmadapter->card_type) ||
+		    IS_CARD9097(pmadapter->card_type)) {
+			tx_ant_mode &= 0x0303;
+			rx_ant_mode &= 0x0303;
+			/** 2G antcfg TX */
+			if (tx_ant_mode & 0x00FF) {
+				pmadapter->user_htstream &= ~0xF0;
+				pmadapter->user_htstream |=
+					(bitcount(tx_ant_mode & 0x00FF) << 4);
+			}
+			/* 5G antcfg tx */
+			if (tx_ant_mode & 0xFF00) {
+				pmadapter->user_htstream &= ~0xF000;
+				pmadapter->user_htstream |=
+					(bitcount(tx_ant_mode & 0xFF00) << 12);
+			}
+			/* 2G antcfg RX */
+			if (rx_ant_mode & 0x00FF) {
+				pmadapter->user_htstream &= ~0xF;
+				pmadapter->user_htstream |=
+					bitcount(rx_ant_mode & 0x00FF);
+			}
+			/* 5G antcfg RX */
+			if (rx_ant_mode & 0xFF00) {
+				pmadapter->user_htstream &= ~0xF00;
+				pmadapter->user_htstream |=
+					(bitcount(rx_ant_mode & 0xFF00) << 8);
+			}
+			PRINTM(MCMND,
+			       "user_htstream=0x%x, tx_antenna=0x%x rx_antenna=0x%x\n",
+			       pmadapter->user_htstream, tx_ant_mode,
+			       rx_ant_mode);
+		}
+#endif
+	} else
+		PRINTM(MINFO,
+		       "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x, Evaluate time = %d, Current antenna = %d\n",
+		       wlan_le16_to_cpu(pantenna_1x1->action), ant_mode,
+		       evaluate_time, current_antenna);
+
+	if (pioctl_buf) {
+		radio = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
+		if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
+			radio->param.ant_cfg.tx_antenna = tx_ant_mode;
+			radio->param.ant_cfg.rx_antenna = rx_ant_mode;
+		} else {
+			radio->param.ant_cfg_1x1.antenna = ant_mode;
+			radio->param.ant_cfg_1x1.evaluate_time = evaluate_time;
+			radio->param.ant_cfg_1x1.current_antenna =
+				current_antenna;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of reg_access.
+ *
+ *  @param priv         A pointer to mlan_priv register.
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_reg_access(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+		    t_void *pdata_buf)
+{
+	mlan_ds_reg_rw *reg_rw;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	MrvlIEtypes_Reg_type_t *tlv;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+#endif
+
+	ENTER();
+
+	reg_rw = (mlan_ds_reg_rw *)pdata_buf;
+	switch (cmd->command) {
+	case HostCmd_CMD_MAC_REG_ACCESS:{
+			HostCmd_DS_MAC_REG_ACCESS *mac_reg;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_MAC_REG_ACCESS) +
+						 S_DS_GEN);
+			mac_reg =
+				(HostCmd_DS_MAC_REG_ACCESS *)&cmd->params.
+				mac_reg;
+			mac_reg->action = wlan_cpu_to_le16(cmd_action);
+			mac_reg->offset =
+				wlan_cpu_to_le16((t_u16)reg_rw->offset);
+			mac_reg->value = wlan_cpu_to_le32(reg_rw->value);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+			if ((reg_rw->type == MLAN_REG_MAC2) &&
+			    (IS_CARD9098(pmadapter->card_type) ||
+			     IS_CARD9097(pmadapter->card_type))) {
+				tlv = (MrvlIEtypes_Reg_type_t
+				       *) ((t_u8 *)cmd +
+					   sizeof(HostCmd_DS_MAC_REG_ACCESS) +
+					   S_DS_GEN);
+				tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_REG_ACCESS_CTRL);
+				tlv->header.len =
+					wlan_cpu_to_le16(sizeof(t_u8));
+				tlv->type = MLAN_REG_MAC2;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_MAC_REG_ACCESS)
+							 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_Reg_type_t));
+			}
+#endif
+			break;
+		}
+	case HostCmd_CMD_BBP_REG_ACCESS:{
+			HostCmd_DS_BBP_REG_ACCESS *bbp_reg;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_BBP_REG_ACCESS) +
+						 S_DS_GEN);
+			bbp_reg =
+				(HostCmd_DS_BBP_REG_ACCESS *)&cmd->params.
+				bbp_reg;
+			bbp_reg->action = wlan_cpu_to_le16(cmd_action);
+			bbp_reg->offset =
+				wlan_cpu_to_le16((t_u16)reg_rw->offset);
+			bbp_reg->value = (t_u8)reg_rw->value;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+			if ((reg_rw->type == MLAN_REG_BBP2) &&
+			    (IS_CARD9098(pmadapter->card_type) ||
+			     IS_CARD9097(pmadapter->card_type))) {
+				tlv = (MrvlIEtypes_Reg_type_t
+				       *) ((t_u8 *)cmd +
+					   sizeof(HostCmd_DS_BBP_REG_ACCESS) +
+					   S_DS_GEN);
+				tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_REG_ACCESS_CTRL);
+				tlv->header.len =
+					wlan_cpu_to_le16(sizeof(t_u8));
+				tlv->type = MLAN_REG_BBP2;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_BBP_REG_ACCESS)
+							 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_Reg_type_t));
+			}
+#endif
+			break;
+		}
+	case HostCmd_CMD_RF_REG_ACCESS:{
+			HostCmd_DS_RF_REG_ACCESS *rf_reg;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_RF_REG_ACCESS) +
+						 S_DS_GEN);
+			rf_reg = (HostCmd_DS_RF_REG_ACCESS *)&cmd->params.
+				rf_reg;
+			rf_reg->action = wlan_cpu_to_le16(cmd_action);
+			rf_reg->offset =
+				wlan_cpu_to_le16((t_u16)reg_rw->offset);
+			rf_reg->value = (t_u8)reg_rw->value;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+			if ((reg_rw->type == MLAN_REG_RF2) &&
+			    (IS_CARD9098(pmadapter->card_type) ||
+			     IS_CARD9097(pmadapter->card_type))) {
+				tlv = (MrvlIEtypes_Reg_type_t
+				       *) ((t_u8 *)cmd +
+					   sizeof(HostCmd_DS_RF_REG_ACCESS) +
+					   S_DS_GEN);
+				tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_REG_ACCESS_CTRL);
+				tlv->header.len =
+					wlan_cpu_to_le16(sizeof(t_u8));
+				tlv->type = MLAN_REG_RF2;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_RF_REG_ACCESS)
+							 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_Reg_type_t));
+			}
+#endif
+			break;
+		}
+	case HostCmd_CMD_CAU_REG_ACCESS:{
+			HostCmd_DS_RF_REG_ACCESS *cau_reg;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_RF_REG_ACCESS) +
+						 S_DS_GEN);
+			cau_reg =
+				(HostCmd_DS_RF_REG_ACCESS *)&cmd->params.rf_reg;
+			cau_reg->action = wlan_cpu_to_le16(cmd_action);
+			cau_reg->offset =
+				wlan_cpu_to_le16((t_u16)reg_rw->offset);
+			cau_reg->value = (t_u8)reg_rw->value;
+			break;
+		}
+	case HostCmd_CMD_TARGET_ACCESS:{
+			HostCmd_DS_TARGET_ACCESS *target;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_TARGET_ACCESS) +
+						 S_DS_GEN);
+			target = (HostCmd_DS_TARGET_ACCESS *)&cmd->params.
+				target;
+			target->action = wlan_cpu_to_le16(cmd_action);
+			target->csu_target =
+				wlan_cpu_to_le16(MLAN_CSU_TARGET_PSU);
+			target->address =
+				wlan_cpu_to_le16((t_u16)reg_rw->offset);
+			target->data = (t_u8)reg_rw->value;
+			break;
+		}
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:{
+			mlan_ds_read_eeprom *rd_eeprom =
+				(mlan_ds_read_eeprom *)pdata_buf;
+			HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
+				(HostCmd_DS_802_11_EEPROM_ACCESS *)&cmd->params.
+				eeprom;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_802_11_EEPROM_ACCESS)
+						 + S_DS_GEN);
+			cmd_eeprom->action = wlan_cpu_to_le16(cmd_action);
+			cmd_eeprom->offset =
+				wlan_cpu_to_le16(rd_eeprom->offset);
+			cmd_eeprom->byte_count =
+				wlan_cpu_to_le16(rd_eeprom->byte_count);
+			cmd_eeprom->value = 0;
+			break;
+		}
+	case HostCmd_CMD_BCA_REG_ACCESS:{
+			HostCmd_DS_BCA_REG_ACCESS *bca_reg;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_BCA_REG_ACCESS) +
+						 S_DS_GEN);
+			bca_reg =
+				(HostCmd_DS_BCA_REG_ACCESS *) & cmd->params.
+				bca_reg;
+			bca_reg->action = wlan_cpu_to_le16(cmd_action);
+			bca_reg->offset =
+				wlan_cpu_to_le16((t_u16)reg_rw->offset);
+			bca_reg->value = wlan_cpu_to_le32(reg_rw->value);
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+			if ((reg_rw->type == MLAN_REG_BCA2) &&
+			    (IS_CARD9098(pmadapter->card_type) ||
+			     IS_CARD9097(pmadapter->card_type))) {
+				tlv = (MrvlIEtypes_Reg_type_t
+				       *) ((t_u8 *)cmd +
+					   sizeof(HostCmd_DS_BCA_REG_ACCESS) +
+					   S_DS_GEN);
+				tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_REG_ACCESS_CTRL);
+				tlv->header.len =
+					wlan_cpu_to_le16(sizeof(t_u8));
+				tlv->type = MLAN_REG_BCA2;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_BCA_REG_ACCESS)
+							 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_Reg_type_t));
+			}
+#endif
+			break;
+		}
+	default:
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of reg_access
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param type         The type of reg access (MAC, BBP or RF)
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_reg_access(mlan_adapter *pmadapter, t_u16 type,
+		    HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_ds_reg_rw *reg_rw = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+		reg_rw = &reg_mem->param.reg_rw;
+		switch (type) {
+		case HostCmd_CMD_MAC_REG_ACCESS:{
+				HostCmd_DS_MAC_REG_ACCESS *reg;
+				reg = (HostCmd_DS_MAC_REG_ACCESS *)&resp->
+					params.mac_reg;
+				reg_rw->offset =
+					(t_u32)wlan_le16_to_cpu(reg->offset);
+				reg_rw->value = wlan_le32_to_cpu(reg->value);
+				break;
+			}
+		case HostCmd_CMD_BBP_REG_ACCESS:{
+				HostCmd_DS_BBP_REG_ACCESS *reg;
+				reg = (HostCmd_DS_BBP_REG_ACCESS *)&resp->
+					params.bbp_reg;
+				reg_rw->offset =
+					(t_u32)wlan_le16_to_cpu(reg->offset);
+				reg_rw->value = (t_u32)reg->value;
+				break;
+			}
+
+		case HostCmd_CMD_RF_REG_ACCESS:{
+				HostCmd_DS_RF_REG_ACCESS *reg;
+				reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.
+					rf_reg;
+				reg_rw->offset =
+					(t_u32)wlan_le16_to_cpu(reg->offset);
+				reg_rw->value = (t_u32)reg->value;
+				break;
+			}
+		case HostCmd_CMD_CAU_REG_ACCESS:{
+				HostCmd_DS_RF_REG_ACCESS *reg;
+				reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.
+					rf_reg;
+				reg_rw->offset =
+					(t_u32)wlan_le16_to_cpu(reg->offset);
+				reg_rw->value = (t_u32)reg->value;
+				break;
+			}
+		case HostCmd_CMD_TARGET_ACCESS:{
+				HostCmd_DS_TARGET_ACCESS *reg;
+				reg = (HostCmd_DS_TARGET_ACCESS *)&resp->params.
+					target;
+				reg_rw->offset =
+					(t_u32)wlan_le16_to_cpu(reg->address);
+				reg_rw->value = (t_u32)reg->data;
+				break;
+			}
+		case HostCmd_CMD_802_11_EEPROM_ACCESS:{
+				mlan_ds_read_eeprom *eeprom =
+					&reg_mem->param.rd_eeprom;
+				HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
+					(HostCmd_DS_802_11_EEPROM_ACCESS *)
+					&resp->params.eeprom;
+				cmd_eeprom->byte_count =
+					wlan_le16_to_cpu(cmd_eeprom->
+							 byte_count);
+				PRINTM(MINFO, "EEPROM read len=%x\n",
+				       cmd_eeprom->byte_count);
+				if (eeprom->byte_count < cmd_eeprom->byte_count) {
+					eeprom->byte_count = 0;
+					PRINTM(MINFO,
+					       "EEPROM read return length is too big\n");
+					pioctl_buf->status_code =
+						MLAN_ERROR_CMD_RESP_FAIL;
+					LEAVE();
+					return MLAN_STATUS_FAILURE;
+				}
+				eeprom->offset =
+					wlan_le16_to_cpu(cmd_eeprom->offset);
+				eeprom->byte_count = cmd_eeprom->byte_count;
+				if (eeprom->byte_count > 0) {
+					memcpy_ext(pmadapter, &eeprom->value,
+						   &cmd_eeprom->value,
+						   eeprom->byte_count,
+						   MAX_EEPROM_DATA);
+					HEXDUMP("EEPROM",
+						(char *)&eeprom->value,
+						MIN(MAX_EEPROM_DATA,
+						    eeprom->byte_count));
+				}
+				break;
+			}
+		case HostCmd_CMD_BCA_REG_ACCESS:{
+				HostCmd_DS_BCA_REG_ACCESS *reg;
+				reg = (HostCmd_DS_BCA_REG_ACCESS *) & resp->
+					params.bca_reg;
+				reg_rw->offset =
+					(t_u32)wlan_le16_to_cpu(reg->offset);
+				reg_rw->value = wlan_le32_to_cpu(reg->value);
+				break;
+			}
+		default:
+			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of mem_access.
+ *
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_mem_access(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+		    t_void *pdata_buf)
+{
+	mlan_ds_mem_rw *mem_rw = (mlan_ds_mem_rw *)pdata_buf;
+	HostCmd_DS_MEM_ACCESS *mem_access =
+		(HostCmd_DS_MEM_ACCESS *)&cmd->params.mem;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MEM_ACCESS) + S_DS_GEN);
+
+	mem_access->action = wlan_cpu_to_le16(cmd_action);
+	mem_access->addr = wlan_cpu_to_le32(mem_rw->addr);
+	mem_access->value = wlan_cpu_to_le32(mem_rw->value);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of mem_access
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_mem_access(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_ds_mem_rw *mem_rw = MNULL;
+	HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
+		mem_rw = &reg_mem->param.mem_rw;
+
+		mem_rw->addr = wlan_le32_to_cpu(mem->addr);
+		mem_rw->value = wlan_le32_to_cpu(mem->value);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *
+ *  @brief This function handles coex events generated by firmware
+ *
+ *  @param priv A pointer to mlan_private structure
+ *  @param pevent   A pointer to event buf
+ *
+ *  @return     N/A
+ */
+void
+wlan_bt_coex_wlan_param_update_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
+	MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
+	t_s32 len = pevent->data_len - sizeof(t_u32);
+	t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
+	t_u16 tlv_type, tlv_len;
+
+	ENTER();
+
+	while (len >= (t_s32)sizeof(MrvlIEtypesHeader_t)) {
+		tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		if ((tlv_len + (t_s32)sizeof(MrvlIEtypesHeader_t)) > len)
+			break;
+		switch (tlv_type) {
+		case TLV_BTCOEX_WL_AGGR_WINSIZE:
+			pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *) tlv;
+			pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
+			pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
+			pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
+			wlan_coex_ampdu_rxwinsize(pmadapter);
+			wlan_update_ampdu_txwinsize(pmadapter);
+			break;
+		case TLV_BTCOEX_WL_SCANTIME:
+			pScantlv = (MrvlIEtypes_BtCoexScanTime_t *) tlv;
+			pmadapter->coex_scan = pScantlv->coex_scan;
+			pmadapter->coex_min_scan_time =
+				wlan_le16_to_cpu(pScantlv->min_scan_time);
+			pmadapter->coex_max_scan_time =
+				wlan_le16_to_cpu(pScantlv->max_scan_time);
+			break;
+		default:
+			break;
+		}
+		len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
+	}
+	PRINTM(MEVENT,
+	       "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+	       pmadapter->coex_scan, pmadapter->coex_min_scan_time,
+	       pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
+	       pmadapter->coex_rx_win_size);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares command of supplicant pmk
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_supplicant_pmk(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *cmd,
+			       t_u16 cmd_action, t_void *pdata_buf)
+{
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *ppassphrase_tlv = MNULL;
+	MrvlIEtypes_SAE_Password_t *psae_password_tlv = MNULL;
+	MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
+	MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
+	HostCmd_DS_802_11_SUPPLICANT_PMK *pesupplicant_psk =
+		&cmd->params.esupplicant_psk;
+	t_u8 *ptlv_buffer = (t_u8 *)pesupplicant_psk->tlv_buffer;
+	mlan_ds_sec_cfg *sec = (mlan_ds_sec_cfg *)pdata_buf;
+	mlan_ds_passphrase *psk = MNULL;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u8 ssid_flag = 0, bssid_flag = 0, pmk_flag = 0, passphrase_flag = 0;
+	t_u8 sae_password_flag = 0;
+
+	ENTER();
+	psk = (mlan_ds_passphrase *)&sec->param.passphrase;
+
+	/*
+	 * Parse the rest of the buf here
+	 *  1) <ssid="valid ssid"> - This will get the passphrase, AKMP
+	 *     for specified ssid, if none specified then it will get all.
+	 *     Eg: iwpriv <mlanX> passphrase 0:ssid=nxp
+	 *  2) <psk="psk">:<passphrase="passphare">:<bssid="00:50:43:ef:23:f3">
+	 *     <ssid="valid ssid"> - passphrase and psk cannot be provided to
+	 *     the same SSID, Takes one SSID at a time, If ssid= is present
+	 *     the it should contain a passphrase or psk. If no arguments are
+	 *     provided then AKMP=802.1x, and passphrase should be provided
+	 *     after association.
+	 *     End of each parameter should be followed by a ':'(except for the
+	 *     last parameter) as the delimiter. If ':' has to be used in
+	 *     an SSID then a '/' should be preceded to ':' as a escape.
+	 *     Eg:iwpriv <mlanX> passphrase
+	 *               "1:ssid=mrvl AP:psk=abcdefgh:bssid=00:50:43:ef:23:f3"
+	 *     iwpriv <mlanX> passphrase
+	 *            "1:ssid=nxp/: AP:psk=abcdefgd:bssid=00:50:43:ef:23:f3"
+	 *     iwpriv <mlanX> passphrase "1:ssid=mrvlAP:psk=abcdefgd"
+	 *  3) <ssid="valid ssid"> - This will clear the passphrase
+	 *     for specified ssid, if none specified then it will clear all.
+	 *     Eg: iwpriv <mlanX> passphrase 2:ssid=nxp
+	 */
+
+	/* -1 is for t_u8 TlvBuffer[1] as this should not be included */
+	cmd->size = sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
+	if (psk && memcmp(pmpriv->adapter, (t_u8 *)&psk->bssid, zero_mac,
+			  sizeof(zero_mac))) {
+		pbssid_tlv = (MrvlIEtypes_Bssid_t *)ptlv_buffer;
+		pbssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
+		pbssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
+		memcpy_ext(pmpriv->adapter, pbssid_tlv->bssid,
+			   (t_u8 *)&psk->bssid, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		ptlv_buffer +=
+			(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		cmd->size +=
+			(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		pbssid_tlv->header.len =
+			wlan_cpu_to_le16(pbssid_tlv->header.len);
+		bssid_flag = 1;
+	}
+	if (psk && (psk->psk_type == MLAN_PSK_PMK)) {
+		ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
+		ppmk_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PMK);
+		ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
+		memcpy_ext(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
+			   MLAN_MAX_KEY_LENGTH, MLAN_MAX_KEY_LENGTH);
+		ptlv_buffer +=
+			(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		cmd->size +=
+			(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
+		ppmk_tlv->header.len = wlan_cpu_to_le16(ppmk_tlv->header.len);
+		pmk_flag = 1;
+	}
+	if (psk->ssid.ssid_len) {
+		pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)ptlv_buffer;
+		pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+		pssid_tlv->header.len = (t_u16)MIN(MLAN_MAX_SSID_LENGTH,
+						   psk->ssid.ssid_len);
+		memcpy_ext(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
+			   (t_u8 *)psk->ssid.ssid, psk->ssid.ssid_len,
+			   MLAN_MAX_SSID_LENGTH);
+		ptlv_buffer += (pssid_tlv->header.len +
+				sizeof(MrvlIEtypesHeader_t));
+		cmd->size += (pssid_tlv->header.len +
+			      sizeof(MrvlIEtypesHeader_t));
+		pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
+		ssid_flag = 1;
+	}
+	if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
+		ppassphrase_tlv = (MrvlIEtypes_Passphrase_t *)ptlv_buffer;
+		ppassphrase_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_PASSPHRASE);
+		ppassphrase_tlv->header.len =
+			(t_u16)MIN(MLAN_MAX_PASSPHRASE_LENGTH,
+				   psk->psk.passphrase.passphrase_len);
+		memcpy_ext(pmpriv->adapter, ppassphrase_tlv->passphrase,
+			   psk->psk.passphrase.passphrase,
+			   psk->psk.passphrase.passphrase_len,
+			   MLAN_MAX_PASSPHRASE_LENGTH);
+		ptlv_buffer += (ppassphrase_tlv->header.len +
+				sizeof(MrvlIEtypesHeader_t));
+		cmd->size += (ppassphrase_tlv->header.len +
+			      sizeof(MrvlIEtypesHeader_t));
+		ppassphrase_tlv->header.len =
+			wlan_cpu_to_le16(ppassphrase_tlv->header.len);
+		passphrase_flag = 1;
+	}
+	if (psk->psk_type == MLAN_PSK_SAE_PASSWORD) {
+		psae_password_tlv = (MrvlIEtypes_SAE_Password_t *) ptlv_buffer;
+		psae_password_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_SAE_PASSWORD);
+		psae_password_tlv->header.len =
+			(t_u16)MIN(MLAN_MAX_SAE_PASSWORD_LENGTH,
+				   psk->psk.sae_password.sae_password_len);
+		memcpy_ext(pmpriv->adapter, psae_password_tlv->sae_password,
+			   psk->psk.sae_password.sae_password,
+			   psk->psk.sae_password.sae_password_len,
+			   MLAN_MAX_SAE_PASSWORD_LENGTH);
+		ptlv_buffer +=
+			(psae_password_tlv->header.len +
+			 sizeof(MrvlIEtypesHeader_t));
+		cmd->size +=
+			(psae_password_tlv->header.len +
+			 sizeof(MrvlIEtypesHeader_t));
+		psae_password_tlv->header.len =
+			wlan_cpu_to_le16(psae_password_tlv->header.len);
+		sae_password_flag = 1;
+	}
+	if ((cmd_action == HostCmd_ACT_GEN_SET) &&
+	    ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag)
+	     && (!pmk_flag && !sae_password_flag)
+	    )) {
+		PRINTM(MERROR,
+		       "Invalid case,ssid/bssid present without pmk, passphrase or sae password\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
+	pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
+	pesupplicant_psk->cache_result = 0;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Handle the supplicant pmk response
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11_supplicant_pmk(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *resp,
+			       mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
+		&resp->params.esupplicant_psk;
+	mlan_ds_sec_cfg *sec_buf = MNULL;
+	mlan_ds_sec_cfg *sec = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
+	MrvlIEtypes_Passphrase_t *passphrase_tlv = MNULL;
+	MrvlIEtypes_SAE_Password_t *psae_password_tlv = MNULL;
+	MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
+	MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
+	t_u8 *tlv_buf = (t_u8 *)supplicant_pmk_resp->tlv_buffer;
+	t_u16 action = wlan_le16_to_cpu(supplicant_pmk_resp->action);
+	int tlv_buf_len = 0;
+	t_u16 tlv;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	tlv_buf_len = resp->size -
+		(sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1);
+
+	if (pioctl_buf) {
+		if (((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
+		    MLAN_OID_BSS_FIND_BSS) {
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_ds_sec_cfg),
+					       MLAN_MEM_DEF, (t_u8 **)&sec_buf);
+			if (ret || !sec_buf) {
+				PRINTM(MERROR, "Could not allocate sec_buf!\n");
+				LEAVE();
+				return ret;
+			}
+			sec = sec_buf;
+		} else {
+			sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
+		}
+		if (action == HostCmd_ACT_GEN_GET) {
+			while (tlv_buf_len > 0) {
+				tlv = (*tlv_buf) | (*(tlv_buf + 1) << 8);
+				if ((tlv != TLV_TYPE_SSID) &&
+				    (tlv != TLV_TYPE_BSSID) &&
+				    (tlv != TLV_TYPE_PASSPHRASE) &&
+				    (tlv != TLV_TYPE_PMK)
+				    && (tlv != TLV_TYPE_SAE_PASSWORD)
+					)
+					break;
+				switch (tlv) {
+				case TLV_TYPE_SSID:
+					pssid_tlv =
+						(MrvlIEtypes_SsIdParamSet_t *)
+						tlv_buf;
+					pssid_tlv->header.len =
+						wlan_le16_to_cpu(pssid_tlv->
+								 header.len);
+					memcpy_ext(pmpriv->adapter,
+						   sec->param.passphrase.ssid.
+						   ssid, pssid_tlv->ssid,
+						   pssid_tlv->header.len,
+						   MLAN_MAX_SSID_LENGTH);
+					sec->param.passphrase.ssid.ssid_len =
+						MIN(MLAN_MAX_SSID_LENGTH,
+						    pssid_tlv->header.len);
+					tlv_buf +=
+						pssid_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(pssid_tlv->header.len +
+						 sizeof(MrvlIEtypesHeader_t));
+					break;
+				case TLV_TYPE_BSSID:
+					pbssid_tlv =
+						(MrvlIEtypes_Bssid_t *)tlv_buf;
+					pbssid_tlv->header.len =
+						wlan_le16_to_cpu(pbssid_tlv->
+								 header.len);
+					memcpy_ext(pmpriv->adapter,
+						   &sec->param.passphrase.bssid,
+						   pbssid_tlv->bssid,
+						   MLAN_MAC_ADDR_LENGTH,
+						   MLAN_MAC_ADDR_LENGTH);
+					tlv_buf +=
+						pbssid_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(pbssid_tlv->header.len +
+						 sizeof(MrvlIEtypesHeader_t));
+					break;
+				case TLV_TYPE_PASSPHRASE:
+					passphrase_tlv =
+						(MrvlIEtypes_Passphrase_t *)
+						tlv_buf;
+					passphrase_tlv->header.len =
+						wlan_le16_to_cpu
+						(passphrase_tlv->header.len);
+					sec->param.passphrase.psk_type =
+						MLAN_PSK_PASSPHRASE;
+					sec->param.passphrase.psk.passphrase.
+						passphrase_len =
+						passphrase_tlv->header.len;
+					memcpy_ext(pmpriv->adapter,
+						   sec->param.passphrase.psk.
+						   passphrase.passphrase,
+						   passphrase_tlv->passphrase,
+						   passphrase_tlv->header.len,
+						   MLAN_MAX_PASSPHRASE_LENGTH);
+					tlv_buf +=
+						passphrase_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(passphrase_tlv->header.len +
+						 sizeof(MrvlIEtypesHeader_t));
+					break;
+				case TLV_TYPE_SAE_PASSWORD:
+					psae_password_tlv =
+						(MrvlIEtypes_SAE_Password_t *)
+						tlv_buf;
+					psae_password_tlv->header.len =
+						wlan_le16_to_cpu
+						(psae_password_tlv->header.len);
+					sec->param.passphrase.psk_type =
+						MLAN_PSK_SAE_PASSWORD;
+					sec->param.passphrase.psk.sae_password.
+						sae_password_len =
+						psae_password_tlv->header.len;
+					memcpy_ext(pmpriv->adapter,
+						   sec->param.passphrase.psk.
+						   sae_password.sae_password,
+						   psae_password_tlv->
+						   sae_password,
+						   psae_password_tlv->header.
+						   len,
+						   MLAN_MAX_SAE_PASSWORD_LENGTH);
+					tlv_buf +=
+						psae_password_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(psae_password_tlv->header.len +
+						 sizeof(MrvlIEtypesHeader_t));
+					break;
+				case TLV_TYPE_PMK:
+					ppmk_tlv = (MrvlIEtypes_PMK_t *)tlv_buf;
+					ppmk_tlv->header.len =
+						wlan_le16_to_cpu(ppmk_tlv->
+								 header.len);
+					sec->param.passphrase.psk_type =
+						MLAN_PSK_PMK;
+					memcpy_ext(pmpriv->adapter,
+						   sec->param.passphrase.psk.
+						   pmk.pmk, ppmk_tlv->pmk,
+						   ppmk_tlv->header.len,
+						   MLAN_MAX_KEY_LENGTH);
+					tlv_buf +=
+						ppmk_tlv->header.len +
+						sizeof(MrvlIEtypesHeader_t);
+					tlv_buf_len -=
+						(ppmk_tlv->header.len +
+						 sizeof(MrvlIEtypesHeader_t));
+					break;
+				}
+			}
+#ifdef STA_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
+			    ((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
+			    MLAN_OID_BSS_FIND_BSS) {
+				wlan_set_ewpa_mode(pmpriv,
+						   &sec->param.passphrase);
+				ret = wlan_find_bss(pmpriv, pioctl_buf);
+			}
+#endif
+
+		} else if (action == HostCmd_ACT_GEN_SET) {
+			PRINTM(MINFO, "Esupp PMK set: enable ewpa query\n");
+			pmpriv->ewpa_query = MTRUE;
+		}
+		if (sec_buf)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)sec_buf);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of independent reset.
+ *
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND *cmd,
+		     t_u16 cmd_action, t_void *pdata_buf)
+{
+	mlan_ds_ind_rst_cfg *pdata_ind_rst = (mlan_ds_ind_rst_cfg *) pdata_buf;
+	HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
+		(HostCmd_DS_INDEPENDENT_RESET_CFG *) & cmd->params.ind_rst_cfg;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_INDEPENDENT_RESET_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_INDEPENDENT_RESET_CFG) +
+				     S_DS_GEN);
+
+	ind_rst_cfg->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		ind_rst_cfg->ir_mode = pdata_ind_rst->ir_mode;
+		ind_rst_cfg->gpio_pin = pdata_ind_rst->gpio_pin;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of independent reset
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_ind_rst_cfg(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	const HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
+		(HostCmd_DS_INDEPENDENT_RESET_CFG *) & resp->params.ind_rst_cfg;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+		if (wlan_le16_to_cpu(ind_rst_cfg->action) ==
+		    HostCmd_ACT_GEN_GET) {
+			misc->param.ind_rst_cfg.ir_mode = ind_rst_cfg->ir_mode;
+			misc->param.ind_rst_cfg.gpio_pin =
+				ind_rst_cfg->gpio_pin;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of ps inactivity timeout.
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_ps_inactivity_timeout(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *cmd,
+			       t_u16 cmd_action, t_void *pdata_buf)
+{
+	t_u16 timeout = *((t_u16 *)pdata_buf);
+	HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *ps_inact_tmo =
+		(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *)
+		& cmd->params.ps_inact_tmo;
+
+	ENTER();
+
+	cmd->command =
+		wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT)
+				 + S_DS_GEN);
+
+	ps_inact_tmo->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		ps_inact_tmo->inact_tmo = wlan_cpu_to_le16(timeout);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of HostCmd_CMD_GET_TSF
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+		 t_u16 cmd_action)
+{
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_TSF)) + S_DS_GEN);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of HostCmd_CMD_GET_TSF
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_get_tsf(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	HostCmd_DS_TSF *tsf_pointer = (HostCmd_DS_TSF *) & resp->params.tsf;
+
+	ENTER();
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.misc_tsf = wlan_le64_to_cpu(tsf_pointer->tsf);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of chan_region_cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_chan_region_cfg(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u16 action;
+	HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
+	t_u8 *tlv_buf = MNULL;
+	t_u16 tlv_buf_left;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	mlan_ds_misc_chnrgpwr_cfg *cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	reg = (HostCmd_DS_CHAN_REGION_CFG *) & resp->params.reg_cfg;
+	if (!reg) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	action = wlan_le16_to_cpu(reg->action);
+	if (action != HostCmd_ACT_GEN_GET) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	tlv_buf = (t_u8 *)reg + sizeof(*reg);
+	tlv_buf_left = wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
+
+	/* Add FW cfp tables and region info */
+	wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
+	if (pmadapter->otp_region) {
+		wlan_set_regiontable(pmpriv,
+				     (t_u8)pmadapter->region_code,
+				     pmadapter->fw_bands);
+	}
+	if (!pioctl_buf)
+		goto done;
+
+	if (!pioctl_buf->pbuf) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	if (misc_cfg->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG) {
+		cfg = (mlan_ds_misc_chnrgpwr_cfg *) & (misc_cfg->param.
+						       rgchnpwr_cfg);
+		cfg->length = wlan_le16_to_cpu(resp->size);
+		memcpy_ext(pmpriv->adapter, cfg->chnrgpwr_buf, (t_u8 *)resp,
+			   cfg->length, sizeof(cfg->chnrgpwr_buf));
+	} else {
+		memset(pmpriv->adapter, &misc_cfg->param.custom_reg_domain, 0,
+		       sizeof(mlan_ds_custom_reg_domain));
+		if (pmadapter->otp_region)
+			memcpy_ext(pmpriv->adapter,
+				   &misc_cfg->param.custom_reg_domain.region,
+				   pmadapter->otp_region,
+				   sizeof(otp_region_info_t),
+				   sizeof(otp_region_info_t));
+		if (pmadapter->cfp_otp_bg) {
+			misc_cfg->param.custom_reg_domain.num_bg_chan =
+				pmadapter->tx_power_table_bg_rows;
+			memcpy_ext(pmpriv->adapter,
+				   (t_u8 *)misc_cfg->param.custom_reg_domain.
+				   cfp_tbl, (t_u8 *)pmadapter->cfp_otp_bg,
+				   pmadapter->tx_power_table_bg_rows *
+				   sizeof(chan_freq_power_t),
+				   pmadapter->tx_power_table_bg_rows *
+				   sizeof(chan_freq_power_t));
+		}
+		if (pmadapter->cfp_otp_a) {
+			misc_cfg->param.custom_reg_domain.num_a_chan =
+				pmadapter->tx_power_table_a_rows;
+			memcpy_ext(pmpriv->adapter,
+				   (t_u8 *)misc_cfg->param.custom_reg_domain.
+				   cfp_tbl +
+				   pmadapter->tx_power_table_bg_rows *
+				   sizeof(chan_freq_power_t),
+				   (t_u8 *)pmadapter->cfp_otp_a,
+				   pmadapter->tx_power_table_a_rows *
+				   sizeof(chan_freq_power_t),
+				   pmadapter->tx_power_table_a_rows *
+				   sizeof(chan_freq_power_t));
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of packet aggragation
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_packet_aggr_ctrl(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd,
+			  t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_PACKET_AGGR_CTRL *aggr_ctrl = &cmd->params.aggr_ctrl;
+	mlan_ds_misc_aggr_ctrl *aggr = (mlan_ds_misc_aggr_ctrl *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PACKET_AGGR_CTRL);
+	aggr_ctrl->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_PACKET_AGGR_CTRL) +
+				     S_DS_GEN);
+	aggr_ctrl->aggr_enable = 0;
+
+	if (aggr->tx.enable)
+		aggr_ctrl->aggr_enable |= MBIT(0);
+	aggr_ctrl->aggr_enable = wlan_cpu_to_le16(aggr_ctrl->aggr_enable);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *  packet aggregation
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_packet_aggr_ctrl(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	HostCmd_DS_PACKET_AGGR_CTRL *aggr_ctrl = &resp->params.aggr_ctrl;
+	mlan_ds_misc_aggr_ctrl *aggr = MNULL;
+#if defined(USB)
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 i;
+	t_u8 change = 0;
+	usb_tx_aggr_params *pusb_tx_aggr = MNULL;
+#endif
+
+	ENTER();
+
+	aggr_ctrl->aggr_enable = wlan_le16_to_cpu(aggr_ctrl->aggr_enable);
+	aggr_ctrl->tx_aggr_max_size =
+		wlan_le16_to_cpu(aggr_ctrl->tx_aggr_max_size);
+	aggr_ctrl->tx_aggr_max_num =
+		wlan_le16_to_cpu(aggr_ctrl->tx_aggr_max_num);
+	aggr_ctrl->tx_aggr_align = wlan_le16_to_cpu(aggr_ctrl->tx_aggr_align);
+	PRINTM(MCMND, "enable=0x%x, tx_size=%d, tx_num=%d, tx_align=%d\n",
+	       aggr_ctrl->aggr_enable, aggr_ctrl->tx_aggr_max_size,
+	       aggr_ctrl->tx_aggr_max_num, aggr_ctrl->tx_aggr_align);
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type)) {
+		if (aggr_ctrl->aggr_enable & MBIT(0)) {
+			if (!pmadapter->pcard_usb->usb_tx_aggr[0]
+			    .aggr_ctrl.enable) {
+				pmadapter->pcard_usb->usb_tx_aggr[0]
+					.aggr_ctrl.enable = MTRUE;
+				change = MTRUE;
+			}
+
+		} else {
+			if (pmadapter->pcard_usb->usb_tx_aggr[0]
+			    .aggr_ctrl.enable) {
+				pmadapter->pcard_usb->usb_tx_aggr[0]
+					.aggr_ctrl.enable = MFALSE;
+				change = MTRUE;
+			}
+		}
+		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_mode =
+			MLAN_USB_AGGR_MODE_LEN_V2;
+		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_align =
+			aggr_ctrl->tx_aggr_align;
+		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_max =
+			aggr_ctrl->tx_aggr_max_size;
+		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_tmo =
+			MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
+		if (change) {
+			wlan_reset_usb_tx_aggr(pmadapter);
+			for (i = 0; i < pmadapter->priv_num; ++i) {
+				if (pmadapter->priv[i]) {
+					pusb_tx_aggr =
+						wlan_get_usb_tx_aggr_params
+						(pmadapter, pmadapter->priv[i]
+						 ->port);
+					if (pusb_tx_aggr &&
+					    pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+					    MLAN_USB_AGGR_MODE_LEN_V2)
+						pmadapter->priv[i]->
+							intf_hr_len =
+							MLAN_USB_TX_AGGR_HEADER;
+					else
+						pmadapter->priv[i]->
+							intf_hr_len =
+							USB_INTF_HEADER_LEN;
+				}
+			}
+		}
+	}
+#endif
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		aggr = (mlan_ds_misc_aggr_ctrl *) & (misc->param.aggr_params);
+		if (aggr_ctrl->aggr_enable & MBIT(0))
+			aggr->tx.enable = MTRUE;
+		else
+			aggr->tx.enable = MFALSE;
+		aggr->tx.aggr_align = aggr_ctrl->tx_aggr_align;
+		aggr->tx.aggr_max_size = aggr_ctrl->tx_aggr_max_size;
+		aggr->tx.aggr_max_num = aggr_ctrl->tx_aggr_max_num;
+#if defined(USB)
+		if (IS_USB(pmadapter->card_type))
+			aggr->tx.aggr_tmo = pmadapter->pcard_usb->usb_tx_aggr[0]
+				.aggr_ctrl.aggr_tmo;
+#endif
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends fw dump event command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A void pointer to information buffer
+ *  @return             N/A
+ */
+mlan_status
+wlan_cmd_fw_dump_event(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd,
+		       t_u16 cmd_action, t_void *pdata_buf)
+{
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FW_DUMP_EVENT);
+	cmd->size = S_DS_GEN;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of get link layer statistics.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_cmd_802_11_link_statistic(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *cmd,
+			       t_u16 cmd_action, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_get_info *info = (mlan_ds_get_info *)(pioctl_buf->pbuf);
+	HostCmd_DS_802_11_LINK_STATISTIC *ll_stat =
+		&cmd->params.get_link_statistic;
+	wifi_link_layer_params *ll_params = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_LINK_STATS);
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+				     sizeof(HostCmd_DS_802_11_LINK_STATISTIC));
+	ll_stat->action = wlan_cpu_to_le16(cmd_action);
+
+	switch (cmd_action) {
+	case HostCmd_ACT_GEN_SET:
+		ll_params =
+			(wifi_link_layer_params *) info->param.link_statistic;
+		ll_stat->mpdu_size_threshold =
+			wlan_cpu_to_le32(ll_params->mpdu_size_threshold);
+		ll_stat->aggressive_statistics_gathering =
+			wlan_cpu_to_le32(ll_params->
+					 aggressive_statistics_gathering);
+		break;
+	case HostCmd_ACT_GEN_GET:
+		/** ll_stat->stat_type = wlan_cpu_to_le16(stat_type); */
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function fill link layer statistic from firmware
+ *
+ *  @param priv       					A pointer to mlan_private
+ * structure
+ *  @param link_statistic_ioctl_buf,    A pointer to fill ioctl buffer
+ *  @param resp         				A pointer to
+ * HostCmd_DS_COMMAND
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static void
+wlan_fill_link_statistic(mlan_private *priv,
+			 char *link_statistic_ioctl_buf,
+			 HostCmd_DS_COMMAND *resp)
+{
+	char *link_statistic = link_statistic_ioctl_buf;
+	wifi_radio_stat *radio_stat = MNULL;
+	wifi_iface_stat *iface_stat = MNULL;
+	mlan_wifi_iface_stat *fw_ifaceStat = MNULL;
+	mlan_wifi_radio_stat *fw_radioStat = MNULL;
+	t_u32 num_radio = 0;
+	int i = 0, chan_idx = 0, peerIdx = 0, rate_idx = 0;
+	t_u16 left_len = 0, tlv_type = 0, tlv_len = 0;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	HostCmd_DS_802_11_LINK_STATISTIC *plink_stat =
+		(HostCmd_DS_802_11_LINK_STATISTIC *) & resp->params.
+		get_link_statistic;
+
+	/* TLV parse */
+	left_len = resp->size - sizeof(HostCmd_DS_802_11_LINK_STATISTIC) -
+		S_DS_GEN;
+	tlv = (MrvlIEtypesHeader_t *)(plink_stat->value);
+	DBG_HEXDUMP(MDAT_D, "tlv:", (void *)tlv, 1024);
+	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		switch (tlv_type) {
+		case TLV_TYPE_LL_STAT_IFACE:
+			fw_ifaceStat = (mlan_wifi_iface_stat
+					*) ((t_u8 *)tlv +
+					    sizeof(MrvlIEtypesHeader_t));
+			break;
+		case TLV_TYPE_LL_STAT_RADIO:
+			fw_radioStat = (mlan_wifi_radio_stat
+					*) ((t_u8 *)tlv +
+					    sizeof(MrvlIEtypesHeader_t));
+			num_radio = MAX_RADIO;
+			break;
+		default:
+			break;
+		}
+		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+	if (!fw_ifaceStat || !fw_radioStat) {
+		PRINTM(MERROR, "!fw_ifaceStat || !fw_radioStat\n");
+		return;
+	}
+
+	*((t_u32 *)link_statistic) = num_radio;
+	link_statistic += sizeof(num_radio);
+
+	/* Fill radio stats array */
+	for (i = 0; i < num_radio; i++) {
+		radio_stat = (wifi_radio_stat *) link_statistic;
+		link_statistic += sizeof(wifi_radio_stat);
+
+		radio_stat->radio = wlan_le32_to_cpu(fw_radioStat[i].radio);
+
+		radio_stat->on_time = wlan_le32_to_cpu(fw_radioStat[i].on_time);
+		radio_stat->tx_time = wlan_le32_to_cpu(fw_radioStat[i].tx_time);
+		radio_stat->reserved0 =
+			wlan_le32_to_cpu(fw_radioStat[i].reserved0);
+		radio_stat->rx_time = wlan_le32_to_cpu(fw_radioStat[i].rx_time);
+		radio_stat->on_time_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_scan);
+		radio_stat->on_time_nbd =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_nbd);
+		radio_stat->on_time_gscan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_gscan);
+		radio_stat->on_time_roam_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_roam_scan);
+		radio_stat->on_time_pno_scan =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_pno_scan);
+		radio_stat->on_time_hs20 =
+			wlan_le32_to_cpu(fw_radioStat[i].on_time_hs20);
+
+		radio_stat->num_channels =
+			wlan_le32_to_cpu(fw_radioStat[i].num_channels);
+		for (chan_idx = 0; chan_idx < radio_stat->num_channels;
+		     chan_idx++) {
+			if (radio_stat->num_channels > MAX_NUM_CHAN) {
+				radio_stat->num_channels =
+					wlan_le32_to_cpu(MAX_NUM_CHAN);
+				PRINTM(MERROR,
+				       "%s : radio_stat->num_channels=%d\n",
+				       __func__, radio_stat->num_channels);
+				break;
+			}
+			radio_stat->channels[chan_idx].channel.width =
+				wlan_le32_to_cpu(fw_radioStat[i]
+						 .channels[chan_idx]
+						 .channel.width);
+			radio_stat->channels[chan_idx].channel.center_freq =
+				wlan_le32_to_cpu(fw_radioStat[i]
+						 .channels[chan_idx]
+						 .channel.center_freq);
+			radio_stat->channels[chan_idx].channel.center_freq0 =
+				wlan_le32_to_cpu(fw_radioStat[i]
+						 .channels[chan_idx]
+						 .channel.center_freq0);
+			radio_stat->channels[chan_idx].channel.center_freq1 =
+				wlan_le32_to_cpu(fw_radioStat[i]
+						 .channels[chan_idx]
+						 .channel.center_freq1);
+
+			radio_stat->channels[chan_idx]
+				.on_time =
+				wlan_le32_to_cpu(fw_radioStat[i].
+						 channels[chan_idx].on_time);
+			radio_stat->channels[chan_idx].cca_busy_time =
+				wlan_le32_to_cpu(fw_radioStat[i]
+						 .channels[chan_idx]
+						 .cca_busy_time);
+		}
+	}
+
+	/* Fill iface stats */
+	iface_stat = (wifi_iface_stat *) link_statistic;
+
+	/* get wifi_interface_link_layer_info in driver, not in firmware */
+	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+		iface_stat->info.mode = MLAN_INTERFACE_STA;
+		if (priv->media_connected)
+			iface_stat->info.state = MLAN_ASSOCIATING;
+		else
+			iface_stat->info.state = MLAN_DISCONNECTED;
+		iface_stat->info.roaming = MLAN_ROAMING_IDLE;
+		iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
+		memcpy_ext(priv->adapter, iface_stat->info.ssid,
+			   priv->curr_bss_params.bss_descriptor.ssid.ssid,
+			   MLAN_MAX_SSID_LENGTH, MLAN_MAX_SSID_LENGTH);
+		memcpy_ext(priv->adapter, iface_stat->info.bssid,
+			   priv->curr_bss_params.bss_descriptor.mac_address,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	} else {
+		iface_stat->info.mode = MLAN_INTERFACE_SOFTAP;
+		iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
+	}
+	memcpy_ext(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	memcpy_ext(priv->adapter, iface_stat->info.ap_country_str,
+		   priv->adapter->country_code, COUNTRY_CODE_LEN,
+		   COUNTRY_CODE_LEN);
+	memcpy_ext(priv->adapter, iface_stat->info.country_str,
+		   priv->adapter->country_code, COUNTRY_CODE_LEN,
+		   COUNTRY_CODE_LEN);
+
+	iface_stat->beacon_rx = wlan_le32_to_cpu(fw_ifaceStat->beacon_rx);
+	iface_stat->average_tsf_offset =
+		wlan_le64_to_cpu(fw_ifaceStat->average_tsf_offset);
+	iface_stat->leaky_ap_detected =
+		wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_detected);
+	iface_stat->leaky_ap_avg_num_frames_leaked =
+		wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_avg_num_frames_leaked);
+	iface_stat->leaky_ap_guard_time =
+		wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_guard_time);
+
+	/* Value of iface_stat should be Reaccumulate by each peer */
+	iface_stat->mgmt_rx = wlan_le32_to_cpu(fw_ifaceStat->mgmt_rx);
+	iface_stat->mgmt_action_rx =
+		wlan_le32_to_cpu(fw_ifaceStat->mgmt_action_rx);
+	iface_stat->mgmt_action_tx =
+		wlan_le32_to_cpu(fw_ifaceStat->mgmt_action_tx);
+
+	iface_stat->rssi_mgmt = wlan_le32_to_cpu(fw_ifaceStat->rssi_mgmt);
+	iface_stat->rssi_data = wlan_le32_to_cpu(fw_ifaceStat->rssi_data);
+	iface_stat->rssi_ack = wlan_le32_to_cpu(fw_ifaceStat->rssi_ack);
+
+	for (i = WMM_AC_BK; i <= WMM_AC_VO; i++) {
+		iface_stat->ac[i].ac = i;
+		iface_stat->ac[i].tx_mpdu =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_mpdu);
+		iface_stat->ac[i].rx_mpdu =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_mpdu);
+		iface_stat->ac[i].tx_mcast =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_mcast);
+		iface_stat->ac[i].rx_mcast =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_mcast);
+		iface_stat->ac[i].rx_ampdu =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_ampdu);
+		iface_stat->ac[i].tx_ampdu =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_ampdu);
+		iface_stat->ac[i].mpdu_lost =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].mpdu_lost);
+		iface_stat->ac[i].retries =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries);
+		iface_stat->ac[i].retries_short =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries_short);
+		iface_stat->ac[i].retries_long =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries_long);
+		iface_stat->ac[i].contention_time_min =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].
+					 contention_time_min);
+		iface_stat->ac[i].contention_time_max =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].
+					 contention_time_max);
+		iface_stat->ac[i].contention_time_avg =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].
+					 contention_time_avg);
+		iface_stat->ac[i].contention_num_samples =
+			wlan_le32_to_cpu(fw_ifaceStat->ac[i].
+					 contention_num_samples);
+	}
+
+	/* LL_STAT V3: STA-solution: support maxium 1 peers for AP */
+	iface_stat->num_peers = wlan_le32_to_cpu(fw_ifaceStat->num_peers);
+	for (peerIdx = 0; peerIdx < iface_stat->num_peers; peerIdx++) {
+		iface_stat->peer_info[peerIdx].type =
+			fw_ifaceStat->peer_info[peerIdx].type;
+		memcpy_ext(priv->adapter,
+			   iface_stat->peer_info[peerIdx].peer_mac_address,
+			   fw_ifaceStat->peer_info[peerIdx].peer_mac_address,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		iface_stat->peer_info[peerIdx].capabilities =
+			wlan_le32_to_cpu(fw_ifaceStat->peer_info[peerIdx].
+					 capabilities);
+		iface_stat->peer_info[peerIdx].num_rate =
+			wlan_le32_to_cpu(fw_ifaceStat->peer_info[peerIdx].
+					 num_rate);
+
+		PRINTM(MINFO,
+		       "bitrate  tx_mpdu  rx_mpdu  mpdu_lost retries retries_short retries_long\n");
+		for (rate_idx = 0;
+		     rate_idx < iface_stat->peer_info[peerIdx].num_rate;
+		     rate_idx++) {
+			wlan_fill_hal_wifi_rate(priv,
+						&fw_ifaceStat->
+						peer_info[peerIdx]
+						.rate_stats[rate_idx]
+						.rate,
+						&iface_stat->peer_info[peerIdx]
+						.rate_stats[rate_idx]
+						.rate);
+
+			iface_stat->peer_info[peerIdx]
+				.rate_stats[rate_idx]
+				.tx_mpdu =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx]
+						 .rate_stats[rate_idx]
+						 .tx_mpdu);
+			iface_stat->peer_info[peerIdx]
+				.rate_stats[rate_idx]
+				.rx_mpdu =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx]
+						 .rate_stats[rate_idx]
+						 .rx_mpdu);
+			iface_stat->peer_info[peerIdx]
+				.rate_stats[rate_idx]
+				.mpdu_lost =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx]
+						 .rate_stats[rate_idx]
+						 .mpdu_lost);
+			iface_stat->peer_info[peerIdx]
+				.rate_stats[rate_idx]
+				.retries =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx]
+						 .rate_stats[rate_idx]
+						 .retries);
+			iface_stat->peer_info[peerIdx]
+				.rate_stats[rate_idx]
+				.retries_short =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx]
+						 .rate_stats[rate_idx]
+						 .retries_short);
+			iface_stat->peer_info[peerIdx]
+				.rate_stats[rate_idx]
+				.retries_long =
+				wlan_le32_to_cpu(fw_ifaceStat->
+						 peer_info[peerIdx]
+						 .rate_stats[rate_idx]
+						 .retries_long);
+			PRINTM(MDAT_D,
+			       "0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x\n",
+			       iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .rate.bitrate, iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .tx_mpdu, iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .rx_mpdu, iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .mpdu_lost, iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .retries, iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .retries_short, iface_stat->peer_info[peerIdx]
+			       .rate_stats[rate_idx]
+			       .retries_long);
+		}
+	}
+}
+
+/**
+ *  @brief This function handles the command response of get_link_statistic
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_get_link_statistic(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_get_info *info;
+	t_u8 *link_statistic = MNULL;
+	t_u16 action = wlan_le16_to_cpu(resp->params.get_link_statistic.action);
+
+	ENTER();
+
+	if (pioctl_buf) {
+		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		link_statistic = info->param.link_statistic;
+
+		switch (action) {
+		case HostCmd_ACT_GEN_GET:
+			wlan_fill_link_statistic(pmpriv, link_statistic, resp);
+			break;
+		case HostCmd_ACT_GEN_SET:
+		case HostCmd_ACT_GEN_REMOVE:
+			/* nothing to do */
+			break;
+		default:
+			break;
+		}
+		/* Indicate ioctl complete */
+		pioctl_buf->data_read_written =
+			BUF_MAXLEN + MLAN_SUB_COMMAND_SIZE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends boot sleep configure command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A void pointer to information buffer
+ *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_boot_sleep(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+		    t_void *pdata_buf)
+{
+	HostCmd_DS_BOOT_SLEEP *boot_sleep = MNULL;
+	t_u16 enable = *(t_u16 *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_BOOT_SLEEP);
+	boot_sleep = &cmd->params.boot_sleep;
+	boot_sleep->action = wlan_cpu_to_le16(cmd_action);
+	boot_sleep->enable = wlan_cpu_to_le16(enable);
+
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_BOOT_SLEEP);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of boot sleep cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_boot_sleep(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_BOOT_SLEEP *boot_sleep = &resp->params.boot_sleep;
+	mlan_ds_misc_cfg *cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	ENTER();
+
+	cfg->param.boot_sleep = wlan_le16_to_cpu(boot_sleep->enable);
+	PRINTM(MCMND, "boot sleep cfg status %u", cfg->param.boot_sleep);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+
+/**
+ *  @brief This function handles send crypto command
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A void pointer to information buffer
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+		t_u16 cmd_action, t_u16 *pdata_buf)
+{
+	HostCmd_DS_CRYPTO *cry_cmd = &cmd->params.crypto_cmd;
+	mlan_ds_sup_cfg *cfg = (mlan_ds_sup_cfg *) pdata_buf;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	subcmd_prf_hmac_sha1_t *prf_hmac_sha1 = MNULL;
+	subcmd_hmac_sha1_t *hmac_sha1 = MNULL;
+	subcmd_hmac_sha256_t *hmac_sha256 = MNULL;
+	subcmd_sha256_t *sha256 = MNULL;
+	subcmd_rijndael_t *rijndael = MNULL;
+	subcmd_rc4_t *rc4 = MNULL;
+	subcmd_md5_t *md5 = MNULL;
+	subcmd_mrvl_f_t *mrvl_f = MNULL;
+	subcmd_sha256_kdf_t *sha256_kdf = MNULL;
+	t_u8 *ptlv = MNULL;
+	t_u8 tlv_bitmap = 0;
+	t_u32 i = 0;
+#endif
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CRYPTO);
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_CRYPTO);
+	cry_cmd->action = wlan_cpu_to_le16(cmd_action);
+	cry_cmd->subCmdCode = cfg->sub_command;
+	switch (cfg->sub_command) {
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	case HostCmd_CMD_CRYPTO_SUBCMD_PRF_HMAC_SHA1:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_PREFIX |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		prf_hmac_sha1 = (subcmd_prf_hmac_sha1_t *) cry_cmd->subCmd;
+		prf_hmac_sha1->output_len = cfg->output_len;
+		/* set tlv start */
+		ptlv = prf_hmac_sha1->tlv;
+		cmd->size += sizeof(subcmd_prf_hmac_sha1_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA1:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		hmac_sha1 = (subcmd_hmac_sha1_t *) cry_cmd->subCmd;
+		hmac_sha1->output_len = cfg->output_len;
+		hmac_sha1->data_blks_nr = cfg->data_blks_nr;
+		/* set tlv start */
+		ptlv = hmac_sha1->tlv;
+		cmd->size += sizeof(subcmd_hmac_sha1_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA256:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		hmac_sha256 = (subcmd_hmac_sha256_t *) cry_cmd->subCmd;
+		hmac_sha256->output_len = cfg->output_len;
+		hmac_sha256->data_blks_nr = cfg->data_blks_nr;
+		/* set tlv start */
+		ptlv = hmac_sha256->tlv;
+		cmd->size += sizeof(subcmd_hmac_sha256_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_SHA256:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		sha256 = (subcmd_sha256_t *) cry_cmd->subCmd;
+		sha256->output_len = cfg->output_len;
+		sha256->data_blks_nr = cfg->data_blks_nr;
+		/* set tlv start */
+		ptlv = sha256->tlv;
+		cmd->size += sizeof(subcmd_sha256_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_RIJNDAEL:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		rijndael = (subcmd_rijndael_t *) cry_cmd->subCmd;
+		rijndael->sub_action_code = cfg->sub_action_code;
+		rijndael->output_len = cfg->output_len;
+		/* set tlv start */
+		ptlv = rijndael->tlv;
+		cmd->size += sizeof(subcmd_rijndael_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_RC4:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_IV |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		rc4 = (subcmd_rc4_t *) cry_cmd->subCmd;
+		rc4->skip_bytes = cfg->skip_bytes;
+		rc4->output_len = cfg->output_len;
+		/* set tlv start */
+		ptlv = rc4->tlv;
+		cmd->size += sizeof(subcmd_rc4_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_MD5:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		md5 = (subcmd_md5_t *) cry_cmd->subCmd;
+		md5->output_len = cfg->output_len;
+		/* set tlv start */
+		ptlv = md5->tlv;
+		cmd->size += sizeof(subcmd_md5_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_MRVL_F:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		mrvl_f = (subcmd_mrvl_f_t *) cry_cmd->subCmd;
+		mrvl_f->iterations = cfg->iteration;
+		mrvl_f->count = cfg->count;
+		mrvl_f->output_len = cfg->output_len;
+		/* set tlv start */
+		ptlv = mrvl_f->tlv;
+		cmd->size += sizeof(subcmd_mrvl_f_t);
+		break;
+	case HostCmd_CMD_CRYPTO_SUBCMD_SHA256_KDF:
+		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
+			BIT_TLV_TYPE_CRYPTO_KEY_PREFIX |
+			BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
+		/* set subcmd start */
+		sha256_kdf = (subcmd_sha256_kdf_t *) cry_cmd->subCmd;
+		sha256_kdf->output_len = cfg->output_len;
+		/* set tlv start */
+		ptlv = sha256_kdf->tlv;
+		cmd->size += sizeof(subcmd_sha256_kdf_t);
+		break;
+#endif
+	default:
+		break;
+	}
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	/* add tlv */
+	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY) {
+		((MrvlIEParamSet_t *)ptlv)->Type =
+			wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY);
+		((MrvlIEParamSet_t *)ptlv)->Length =
+			wlan_cpu_to_le16(cfg->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   (t_u8 *)ptlv + sizeof(MrvlIEParamSet_t), cfg->key,
+			   cfg->key_len, cfg->key_len);
+		cmd->size += cfg->key_len + sizeof(MrvlIEParamSet_t);
+		ptlv += cfg->key_len + sizeof(MrvlIEParamSet_t);
+	}
+
+	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_PREFIX) {
+		((MrvlIEParamSet_t *)ptlv)->Type =
+			wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_PREFIX);
+		((MrvlIEParamSet_t *)ptlv)->Length =
+			wlan_cpu_to_le16(cfg->key_prefix_len);
+		memcpy_ext(pmpriv->adapter, ptlv + sizeof(MrvlIEParamSet_t),
+			   cfg->key_prefix, cfg->key_prefix_len,
+			   cfg->key_prefix_len);
+		cmd->size += cfg->key_prefix_len + sizeof(MrvlIEParamSet_t);
+		ptlv += cfg->key_prefix_len + sizeof(MrvlIEParamSet_t);
+	}
+
+	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_IV) {
+		((MrvlIEParamSet_t *)ptlv)->Type =
+			wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_IV);
+		((MrvlIEParamSet_t *)ptlv)->Length =
+			wlan_cpu_to_le16(cfg->key_iv_len);
+		memcpy_ext(pmpriv->adapter, ptlv + sizeof(MrvlIEParamSet_t),
+			   cfg->key_iv, cfg->key_iv_len, cfg->key_iv_len);
+		cmd->size += cfg->key_iv_len + sizeof(MrvlIEParamSet_t);
+		ptlv += cfg->key_iv_len + sizeof(MrvlIEParamSet_t);
+	}
+
+	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK) {
+		t_u16 data_blk_len = 0;
+		t_u8 *pdata_blk = MNULL;
+		for (i = 0; i < cfg->data_blks_nr; i++) {
+			data_blk_len = *(cfg->key_data_blk_len + i);
+			pdata_blk = *(cfg->key_data_blk + i);
+			((MrvlIEParamSet_t *)ptlv)->Type =
+				wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_DATA_BLK);
+			((MrvlIEParamSet_t *)ptlv)->Length =
+				wlan_cpu_to_le16(data_blk_len);
+			memcpy_ext(pmpriv->adapter,
+				   ptlv + sizeof(MrvlIEParamSet_t), pdata_blk,
+				   data_blk_len, data_blk_len);
+			cmd->size += data_blk_len + sizeof(MrvlIEParamSet_t);
+			ptlv += data_blk_len + sizeof(MrvlIEParamSet_t);
+		}
+	}
+#endif
+	HEXDUMP("HostCmd_DS_COMMAND wlan_cmd_crypto", cmd, cmd->size);
+
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of crypto command
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_crypto(pmlan_private pmpriv,
+		HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CRYPTO *crypto_cmd = &resp->params.crypto_cmd;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+	mlan_ds_sup_cfg *cfg = (mlan_ds_sup_cfg *) pioctl_buf->pbuf;
+#endif
+
+	ENTER();
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	if (!cfg) {
+		PRINTM(MERROR, "wlan_ret_crypto cfg is null \n");
+		goto done;
+	}
+	if (resp->result == HostCmd_RESULT_OK) {
+		/* copy the result */
+		memcpy_ext(pmpriv->adapter, cfg->output,
+			   (t_u8 *)crypto_cmd + sizeof(HostCmd_DS_CRYPTO) +
+			   sizeof(cfg->output_len),
+			   cfg->output_len, cfg->output_len);
+	}
+
+	/* Prevent the ioctl from completing when the cmd is freed */
+	if (cfg->call_back) {
+		pmadapter->curr_cmd->pioctl_buf = MNULL;
+		/* trigger wait q */
+		pcb->moal_notify_hostcmd_complete(pmadapter->pmoal_handle,
+						  pmpriv->bss_index);
+	}
+#endif
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function prepares command of mac_address.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_mac_address(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action)
+{
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_MAC_ADDRESS) +
+				     S_DS_GEN);
+	cmd->result = 0;
+
+	cmd->params.mac_addr.action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		memcpy_ext(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
+			   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		/* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of mac_address
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_802_11_mac_address(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	memcpy_ext(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+	PRINTM(MINFO, "MAC address: " MACSTR "\n", MAC2STR(pmpriv->curr_addr));
+	if (pioctl_buf) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		memcpy_ext(pmpriv->adapter, &bss->param.mac_addr,
+			   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		pioctl_buf->data_read_written =
+			MLAN_MAC_ADDR_LENGTH + MLAN_SUB_COMMAND_SIZE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of Rx abort cfg
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_rxabortcfg(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+		    t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_RX_ABORT_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_RX_ABORT_CFG *) & cmd->params.rx_abort_cfg;
+	mlan_ds_misc_rx_abort_cfg *cfg =
+		(mlan_ds_misc_rx_abort_cfg *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RX_ABORT_CFG) +
+				     S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->enable = (t_u8)cfg->enable;
+		cfg_cmd->rssi_threshold = (t_s8)cfg->rssi_threshold;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of Rx Abort Cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_rxabortcfg(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_RX_ABORT_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_RX_ABORT_CFG *) & resp->params.rx_abort_cfg;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.rx_abort_cfg.enable = (t_u8)cfg_cmd->enable;
+		misc_cfg->param.rx_abort_cfg.rssi_threshold =
+			(t_s8)cfg_cmd->rssi_threshold;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of Rx abort cfg ext
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_rxabortcfg_ext(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *cmd,
+			t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_RX_ABORT_CFG_EXT *cfg_cmd =
+		(HostCmd_DS_CMD_RX_ABORT_CFG_EXT *) & cmd->params.
+		rx_abort_cfg_ext;
+	mlan_ds_misc_rx_abort_cfg_ext *cfg =
+		(mlan_ds_misc_rx_abort_cfg_ext *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG_EXT);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RX_ABORT_CFG_EXT) +
+				     S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->enable = (t_u8)cfg->enable;
+		cfg_cmd->rssi_margin = (t_s8)cfg->rssi_margin;
+		cfg_cmd->ceil_rssi_threshold = (t_s8)cfg->ceil_rssi_threshold;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of Rx Abort Cfg ext
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_rxabortcfg_ext(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_RX_ABORT_CFG_EXT *cfg_cmd =
+		(HostCmd_DS_CMD_RX_ABORT_CFG_EXT *) & resp->params.
+		rx_abort_cfg_ext;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.rx_abort_cfg_ext.enable = cfg_cmd->enable;
+		misc_cfg->param.rx_abort_cfg_ext.rssi_margin =
+			cfg_cmd->rssi_margin;
+		misc_cfg->param.rx_abort_cfg_ext.ceil_rssi_threshold =
+			cfg_cmd->ceil_rssi_threshold;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function sets the hal/phy cfg 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
+ */
+mlan_status
+wlan_cmd_hal_phy_cfg(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *cmd,
+		     t_u16 cmd_action, t_u16 *pdata_buf)
+{
+	HostCmd_DS_HAL_PHY_CFG *hal_phy_cfg_cmd =
+		&cmd->params.hal_phy_cfg_params;
+	mlan_ds_hal_phy_cfg_params *hal_phy_cfg_params = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HAL_PHY_CFG);
+	cmd->size = sizeof(HostCmd_DS_HAL_PHY_CFG) + S_DS_GEN;
+	hal_phy_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+	hal_phy_cfg_params = (mlan_ds_hal_phy_cfg_params *) pdata_buf;
+	hal_phy_cfg_cmd->dot11b_psd_mask_cfg =
+		hal_phy_cfg_params->dot11b_psd_mask_cfg;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of hal_phy_cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_hal_phy_cfg(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_HAL_PHY_CFG *cfg_cmd =
+		(HostCmd_DS_HAL_PHY_CFG *) & resp->params.hal_phy_cfg_params;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.hal_phy_cfg_params.dot11b_psd_mask_cfg =
+			cfg_cmd->dot11b_psd_mask_cfg;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of Dot11mc unassoc ftm cfg
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *cmd,
+				 t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *) & cmd->params.
+		dot11mc_unassoc_ftm_cfg;
+	mlan_ds_misc_dot11mc_unassoc_ftm_cfg *cfg =
+		(mlan_ds_misc_dot11mc_unassoc_ftm_cfg *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG)
+				 + S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->state = wlan_cpu_to_le16(cfg->state);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of Dot11mc unassoc ftm cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *) & resp->params.
+		dot11mc_unassoc_ftm_cfg;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.dot11mc_unassoc_ftm_cfg.state =
+			wlan_le16_to_cpu(cfg_cmd->state);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of Tx ampdu prot mode
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *cmd,
+			    t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd =
+		(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *) & cmd->params.
+		tx_ampdu_prot_mode;
+	mlan_ds_misc_tx_ampdu_prot_mode *cfg =
+		(mlan_ds_misc_tx_ampdu_prot_mode *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_AMPDU_PROT_MODE);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE) +
+				     S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of Tx ampdu prot mode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_tx_ampdu_prot_mode(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd =
+		(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *) & resp->params.
+		tx_ampdu_prot_mode;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.tx_ampdu_prot_mode.mode =
+			wlan_le16_to_cpu(cfg_cmd->mode);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of Rate Adapt cfg
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_rate_adapt_cfg(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *cmd,
+			t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_RATE_ADAPT_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_RATE_ADAPT_CFG *) & cmd->params.rate_adapt_cfg;
+	mlan_ds_misc_rate_adapt_cfg *cfg =
+		(mlan_ds_misc_rate_adapt_cfg *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RATE_ADAPT_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RATE_ADAPT_CFG) +
+				     S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->sr_rateadapt = (t_u8)cfg->sr_rateadapt;
+		cfg_cmd->ra_low_thresh = (t_u8)cfg->ra_low_thresh;
+		cfg_cmd->ra_high_thresh = (t_u8)cfg->ra_high_thresh;
+		cfg_cmd->ra_interval = wlan_cpu_to_le16(cfg->ra_interval);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of Rate Adapt Cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_rate_adapt_cfg(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_RATE_ADAPT_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_RATE_ADAPT_CFG *) & resp->params.rate_adapt_cfg;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.rate_adapt_cfg.sr_rateadapt =
+			(t_u8)cfg_cmd->sr_rateadapt;
+		misc_cfg->param.rate_adapt_cfg.ra_low_thresh =
+			(t_u8)cfg_cmd->ra_low_thresh;
+		misc_cfg->param.rate_adapt_cfg.ra_high_thresh =
+			(t_u8)cfg_cmd->ra_high_thresh;
+		misc_cfg->param.rate_adapt_cfg.ra_interval =
+			wlan_le16_to_cpu(cfg_cmd->ra_interval);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of CCK Desense cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd,
+			 t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_CCK_DESENSE_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_CCK_DESENSE_CFG *) & cmd->params.
+		cck_desense_cfg;
+	mlan_ds_misc_cck_desense_cfg *cfg =
+		(mlan_ds_misc_cck_desense_cfg *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CCK_DESENSE_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_CCK_DESENSE_CFG) +
+				     S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode);
+		cfg_cmd->margin = (t_s8)cfg->margin;
+		cfg_cmd->ceil_thresh = (t_s8)cfg->ceil_thresh;
+		cfg_cmd->num_on_intervals = (t_u8)cfg->num_on_intervals;
+		cfg_cmd->num_off_intervals = (t_u8)cfg->num_off_intervals;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of CCK Desense Cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_cck_desense_cfg(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_CCK_DESENSE_CFG *cfg_cmd =
+		(HostCmd_DS_CMD_CCK_DESENSE_CFG *) & resp->params.
+		cck_desense_cfg;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.cck_desense_cfg.mode =
+			wlan_le16_to_cpu(cfg_cmd->mode);
+		misc_cfg->param.cck_desense_cfg.margin = (t_s8)cfg_cmd->margin;
+		misc_cfg->param.cck_desense_cfg.ceil_thresh =
+			(t_s8)cfg_cmd->ceil_thresh;
+		misc_cfg->param.cck_desense_cfg.num_on_intervals =
+			(t_u8)cfg_cmd->num_on_intervals;
+		misc_cfg->param.cck_desense_cfg.num_off_intervals =
+			(t_u8)cfg_cmd->num_off_intervals;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends dynamic bandwidth command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param cmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @param pdata_buf    A void pointer to information buffer
+ *  @return             N/A
+ */
+mlan_status
+wlan_cmd_config_dyn_bw(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd,
+		       t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_DYN_BW *dyn_bw_cmd = &cmd->params.dyn_bw;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DYN_BW);
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DYN_BW);
+	dyn_bw_cmd->action = wlan_cpu_to_le16(cmd_action);
+	dyn_bw_cmd->dyn_bw = wlan_cpu_to_le16(*(t_u16 *)pdata_buf);
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of dyn_bw
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_dyn_bw(pmlan_private pmpriv,
+		HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *cfg = MNULL;
+	HostCmd_DS_DYN_BW *dyn_bw = &resp->params.dyn_bw;
+
+	ENTER();
+	if (pioctl_buf &&
+	    (wlan_le16_to_cpu(dyn_bw->action) == HostCmd_ACT_GEN_GET)) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		cfg->param.dyn_bw = wlan_le16_to_cpu(dyn_bw->dyn_bw);
+		PRINTM(MCMND, "Get dynamic bandwidth 0x%x\n",
+		       cfg->param.dyn_bw);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of CHAN_TRPC_CONFIG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_get_chan_trpc_config(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *cmd,
+			      t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CHANNEL_TRPC_CONFIG *trpc_cfg = &cmd->params.ch_trpc_config;
+	mlan_ds_misc_chan_trpc_cfg *cfg =
+		(mlan_ds_misc_chan_trpc_cfg *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CHANNEL_TRPC_CONFIG);
+	trpc_cfg->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CHANNEL_TRPC_CONFIG) +
+				     S_DS_GEN);
+	trpc_cfg->sub_band = wlan_cpu_to_le16(cfg->sub_band);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of LOW_POWER_MODE_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *cmd,
+				    t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_LOW_POWER_MODE_CFG *lpm_cfg = &cmd->params.lpm_cfg;
+	t_u16 lpm = *(t_u16 *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_LOW_POWER_MODE_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_LOW_POWER_MODE_CFG) +
+				     S_DS_GEN);
+	lpm_cfg->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		lpm_cfg->lpm = wlan_cpu_to_le16(lpm);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of low power mode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+
+ */
+mlan_status
+wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *resp,
+				    mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_power_cfg *cfg = MNULL;
+	HostCmd_DS_LOW_POWER_MODE_CFG *lpm_cfg = &resp->params.lpm_cfg;
+
+	ENTER();
+
+	if (pioctl_buf &&
+	    (wlan_le16_to_cpu(lpm_cfg->action) == HostCmd_ACT_GEN_GET)) {
+		cfg = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
+		cfg->param.lpm = wlan_le16_to_cpu(lpm_cfg->lpm);
+		PRINTM(MCMND, "Get low power mode %d\n", cfg->param.lpm);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *  packet aggregation
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_get_chan_trpc_config(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	HostCmd_DS_CHANNEL_TRPC_CONFIG *trpc_cfg = &resp->params.ch_trpc_config;
+	mlan_ds_misc_chan_trpc_cfg *cfg = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		cfg = (mlan_ds_misc_chan_trpc_cfg *) & (misc->param.trpc_cfg);
+		cfg->sub_band = wlan_le16_to_cpu(trpc_cfg->sub_band);
+		cfg->length = wlan_le16_to_cpu(resp->size);
+		memcpy_ext(pmadapter, cfg->trpc_buf, (t_u8 *)resp, cfg->length,
+			   sizeof(cfg->trpc_buf));
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of RANGE_EXT
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_range_ext(pmlan_private pmpriv,
+		   HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_RANGE_EXT *range_ext = &cmd->params.range_ext;
+	t_u8 mode = *(t_u8 *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RANGE_EXT);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RANGE_EXT) + S_DS_GEN);
+	range_ext->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		range_ext->mode = mode;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of RANGE_EXT
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_range_ext(pmlan_private pmpriv,
+		   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	HostCmd_DS_RANGE_EXT *range_ext = &resp->params.range_ext;
+
+	ENTER();
+
+	if (pioctl_buf &&
+	    (wlan_le16_to_cpu(range_ext->action) == HostCmd_ACT_GEN_GET)) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.range_ext_mode = range_ext->mode;
+		PRINTM(MCMND, "Get range ext mode %d\n",
+		       misc_cfg->param.range_ext_mode);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/wlan_sd8987/mlan/mlan_decl.h b/wlan_sd8987/mlan/mlan_decl.h
new file mode 100755
index 0000000..db7f060
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_decl.h
@@ -0,0 +1,2288 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION "292.p10"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8, *t_ps8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8, *t_pu8;
+/** Signed short (2-bytes) */
+typedef short t_s16, *t_ps16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16, *t_pu16;
+/** Signed long (4-bytes) */
+typedef int t_s32, *t_ps32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32, *t_pu32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64, *t_ps64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64, *t_pu64;
+/** Void pointer (4-bytes) */
+typedef void t_void, *t_pvoid;
+/** Size type */
+typedef t_u32 t_size;
+/** Boolean type */
+typedef t_u8 t_bool;
+
+#ifdef MLAN_64BIT
+/** Pointer type (64-bit) */
+typedef t_u64 t_ptr;
+/** Signed value (64-bit) */
+typedef t_s64 t_sval;
+#else
+/** Pointer type (32-bit) */
+typedef t_u32 t_ptr;
+/** Signed value (32-bit) */
+typedef t_s32 t_sval;
+#endif
+
+/** Constants below */
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define MLAN_PACK_START
+/** Structure packeing end */
+#define MLAN_PACK_END __attribute__((packed))
+#else /* !__GNUC__ */
+#ifdef PRAGMA_PACK
+/** Structure packing begins */
+#define MLAN_PACK_START
+/** Structure packeing end */
+#define MLAN_PACK_END
+#else /* !PRAGMA_PACK */
+/** Structure packing begins */
+#define MLAN_PACK_START __packed
+/** Structure packing end */
+#define MLAN_PACK_END
+#endif /* PRAGMA_PACK */
+#endif /* __GNUC__ */
+
+#ifndef INLINE
+#ifdef __GNUC__
+/** inline directive */
+#define INLINE inline
+#else
+/** inline directive */
+#define INLINE __inline
+#endif
+#endif
+
+/** MLAN TRUE */
+#define MTRUE (1)
+/** MLAN FALSE */
+#define MFALSE (0)
+
+#ifndef MACSTR
+/** MAC address security format */
+#define MACSTR "%02x:XX:XX:XX:%02x:%02x"
+#endif
+
+#ifndef MAC2STR
+/** MAC address security print arguments */
+#define MAC2STR(a) (a)[0], (a)[4], (a)[5]
+#endif
+
+#ifndef FULL_MACSTR
+#define FULL_MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+#ifndef FULL_MAC2STR
+#define FULL_MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Macros for Data Alignment : size */
+#define ALIGN_SZ(p, a) (((p) + ((a)-1)) & ~((a)-1))
+
+/** Macros for Data Alignment : address */
+#define ALIGN_ADDR(p, a)                                                       \
+	((((t_ptr)(p)) + (((t_ptr)(a)) - 1)) & ~(((t_ptr)(a)) - 1))
+
+/** Return the byte offset of a field in the given structure */
+#define MLAN_FIELD_OFFSET(type, field) ((t_u32)(t_ptr) & (((type *)0)->field))
+/** Return aligned offset */
+#define OFFSET_ALIGN_ADDR(p, a) (t_u32)(ALIGN_ADDR(p, a) - (t_ptr)p)
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM (16)
+#else
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM (2)
+#endif
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN 2
+
+/** US country code */
+#define COUNTRY_CODE_US 0x10
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT 32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE 32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT + MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED 16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT 2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED 16
+
+#ifdef STA_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE 64
+/** Default Win size attached during ADDBA response */
+#define MLAN_STA_AMPDU_DEF_RXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE 64
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_UAP_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif /* UAP_SUPPORT */
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** WFD use the same window size for tx/rx */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif
+
+/** Block ack timeout value */
+#define MLAN_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff
+/** Maximum Tx Win size configured for ADDBA request [10 bits] */
+#define MLAN_AMPDU_MAX_TXWINSIZE 0x3ff
+/** Maximum Rx Win size configured for ADDBA request [10 bits] */
+#define MLAN_AMPDU_MAX_RXWINSIZE 0x3ff
+
+/** Rate index for HR/DSSS 0 */
+#define MLAN_RATE_INDEX_HRDSSS0 0
+/** Rate index for HR/DSSS 3 */
+#define MLAN_RATE_INDEX_HRDSSS3 3
+/** Rate index for OFDM 0 */
+#define MLAN_RATE_INDEX_OFDM0 4
+/** Rate index for OFDM 7 */
+#define MLAN_RATE_INDEX_OFDM7 11
+/** Rate index for MCS 0 */
+#define MLAN_RATE_INDEX_MCS0 0
+/** Rate index for MCS 2 */
+#define MLAN_RATE_INDEX_MCS2 2
+/** Rate index for MCS 4 */
+#define MLAN_RATE_INDEX_MCS4 4
+/** Rate index for MCS 7 */
+#define MLAN_RATE_INDEX_MCS7 7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9 9
+/** Rate index for MCS11 */
+#define MLAN_RATE_INDEX_MCS11 11
+/** Rate index for MCS15 */
+#define MLAN_RATE_INDEX_MCS15 15
+/** Rate index for MCS 32 */
+#define MLAN_RATE_INDEX_MCS32 32
+/** Rate index for MCS 127 */
+#define MLAN_RATE_INDEX_MCS127 127
+#define MLAN_RATE_NSS1 1
+#define MLAN_RATE_NSS2 2
+
+/** Rate bitmap for OFDM 0 */
+#define MLAN_RATE_BITMAP_OFDM0 16
+/** Rate bitmap for OFDM 7 */
+#define MLAN_RATE_BITMAP_OFDM7 23
+/** Rate bitmap for MCS 0 */
+#define MLAN_RATE_BITMAP_MCS0 32
+/** Rate bitmap for MCS 127 */
+#define MLAN_RATE_BITMAP_MCS127 159
+#define MLAN_RATE_BITMAP_NSS1_MCS0 160
+#define MLAN_RATE_BITMAP_NSS1_MCS9 169
+#define MLAN_RATE_BITMAP_NSS2_MCS0 176
+#define MLAN_RATE_BITMAP_NSS2_MCS9 185
+
+/** MU beamformer */
+#define DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK (MBIT(19))
+
+/** Size of rx data buffer 3839+256 */
+#define MLAN_RX_DATA_BUF_SIZE 4096
+
+/** Size of command buffer */
+/** because cal_data_size 2.4 k */
+#define MRVDRV_SIZE_OF_CMD_BUFFER (3 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE MRVDRV_SIZE_OF_CMD_BUFFER
+/** Upload size */
+#define WLAN_UPLD_SIZE MRVDRV_SIZE_OF_CMD_BUFFER
+
+#if defined(PCIE)
+#define MLAN_SSU_MAX_PKT_SIZE (283 * 4)
+#define MLAN_SSU_HEADER_SIZE 256
+/**
+ * Size of DMA buffer to collect 10ms SSU data:
+ * 2500 spectral packets, plus header
+ */
+#define MLAN_SSU_BUF_SIZE_1MS (MLAN_SSU_MAX_PKT_SIZE * 250)
+#define MLAN_SSU_BUF_SIZE (MLAN_SSU_HEADER_SIZE + MLAN_SSU_BUF_SIZE_1MS * 10)
+#define MLAN_SSU_BUF_SIZE_HOST (MLAN_SSU_BUF_SIZE)
+#endif
+
+/** driver initial the fw reset */
+#define FW_RELOAD_SDIO_INBAND_RESET 1
+/** out band reset trigger reset, no interface re-emulation */
+#define FW_RELOAD_NO_EMULATION 2
+/** out band reset with interface re-emulation */
+#define FW_RELOAD_WITH_EMULATION 3
+#ifdef PCIE
+/** pcie card reset */
+#define FW_RELOAD_PCIE_RESET 4
+#endif
+#define FW_RELOAD_SDIO_HW_RESET   5
+
+#ifdef USB
+#define MLAN_USB_BLOCK_SIZE (512)
+#define MLAN_USB_AGGR_MODE_NUM (0)
+#define MLAN_USB_AGGR_MODE_LEN (1)
+#define MLAN_USB_AGGR_MODE_LEN_V2 (2)
+#define MLAN_USB_TX_AGGR_MAX_LEN (16000)
+#define MLAN_USB_TX_AGGR_MAX_NUM 10
+#define MLAN_USB_TX_AGGR_V2_ALIGN 4
+#define MLAN_USB_TX_AGGR_HEADER 4
+#define MLAN_USB_MAX_PKT_SIZE (MLAN_USB_BLOCK_SIZE * 4)
+
+#define MLAN_USB_RX_ALIGN_SIZE MLAN_USB_BLOCK_SIZE
+#define MLAN_USB_RX_MAX_AGGR_NUM (8)
+#define MLAN_USB_RX_DEAGGR_TIMEOUT_USEC (200)
+
+#define MLAN_USB_TX_AGGR_ALIGN (MLAN_USB_BLOCK_SIZE * 4)
+#define MLAN_USB_TX_MAX_AGGR_NUM (8)
+#define MLAN_USB_TX_MAX_AGGR_SIZE                                              \
+	(MLAN_USB_BLOCK_SIZE * 4 * MLAN_USB_TX_MAX_AGGR_NUM)
+#define MLAN_USB_TX_MIN_AGGR_TIMEOUT (1)
+#define MLAN_USB_TX_MAX_AGGR_TIMEOUT (4)
+#define MLAN_USB_TX_AGGR_TIMEOUT_MSEC MLAN_USB_TX_MIN_AGGR_TIMEOUT
+#define MLAN_USB_TX_AGGR_TIMEOUT_DYN (0xFFFF)
+#endif /*USB*/
+/** MLAN MAC Address Length */
+#define MLAN_MAC_ADDR_LENGTH (6)
+/** MLAN 802.11 MAC Address */
+	typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
+
+/** MLAN Maximum SSID Length */
+#define MLAN_MAX_SSID_LENGTH (32)
+
+/** RTS/FRAG related defines */
+/** Minimum RTS value */
+#define MLAN_RTS_MIN_VALUE (0)
+/** Maximum RTS value */
+#define MLAN_RTS_MAX_VALUE (2347)
+/** Minimum FRAG value */
+#define MLAN_FRAG_MIN_VALUE (256)
+/** Maximum FRAG value */
+#define MLAN_FRAG_MAX_VALUE (2346)
+
+/** Minimum tx retry count */
+#define MLAN_TX_RETRY_MIN (0)
+/** Maximum tx retry count */
+#define MLAN_TX_RETRY_MAX (14)
+
+/** max Wmm AC queues */
+#define MAX_AC_QUEUES 4
+
+#ifdef SDIO
+/** define SDIO block size for data Tx/Rx */
+/* We support up to 480-byte block size due to FW buffer limitation. */
+#define MLAN_SDIO_BLOCK_SIZE 256
+
+/** define SDIO block size for firmware download */
+#define MLAN_SDIO_BLOCK_SIZE_FW_DNLD MLAN_SDIO_BLOCK_SIZE
+
+/** define allocated buffer size */
+#define ALLOC_BUF_SIZE MLAN_RX_DATA_BUF_SIZE
+/** SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT (16)
+/** SDIO MP aggr pkt limit 8 */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_8 (8)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK 0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK 0x80000000
+#endif /* SDIO */
+
+/** SD Interface */
+#define INTF_SD MBIT(0)
+#define IS_SD(ct) (ct & (INTF_SD << 8))
+/** PCIE Interface */
+#define INTF_PCIE MBIT(1)
+#define IS_PCIE(ct) (ct & (INTF_PCIE << 8))
+/** USB Interface */
+#define INTF_USB MBIT(2)
+#define IS_USB(ct) (ct & (INTF_USB << 8))
+
+/** 8887 card type */
+#define CARD_TYPE_8887 0x01
+/** 8897 card type */
+#define CARD_TYPE_8897 0x02
+/** 8977 card type */
+#define CARD_TYPE_8977 0x03
+/** 8997 card type */
+#define CARD_TYPE_8997 0x04
+/** 8987 card type */
+#define CARD_TYPE_8987 0x05
+/** 9098 card type */
+#define CARD_TYPE_9098 0x06
+/** 9097 card type */
+#define CARD_TYPE_9097 0x07
+/** 8978 card type */
+#define CARD_TYPE_8978 0x08
+/** 9177 card type */
+#define CARD_TYPE_9177 0x09
+/** 8801 card type */
+#define CARD_TYPE_8801 0x0a
+
+/** 9098 A0 reverion num */
+#define CHIP_9098_REV_A0 1
+#define CHIP_9098_REV_A1 2
+/** 9097 CHIP REV */
+#define CHIP_9097_REV_B0 1
+
+#define INTF_MASK 0xff
+#define CARD_TYPE_MASK 0xff
+
+#ifdef SDIO
+/** SD8887 card type */
+#define CARD_TYPE_SD8887 (CARD_TYPE_8887 | (INTF_SD << 8))
+/** SD8897 card type */
+#define CARD_TYPE_SD8897 (CARD_TYPE_8897 | (INTF_SD << 8))
+/** SD8977 card type */
+#define CARD_TYPE_SD8977 (CARD_TYPE_8977 | (INTF_SD << 8))
+/** SD8978 card type */
+#define CARD_TYPE_SD8978 (CARD_TYPE_8978 | (INTF_SD << 8))
+/** SD8997 card type */
+#define CARD_TYPE_SD8997 (CARD_TYPE_8997 | (INTF_SD << 8))
+/** SD8987 card type */
+#define CARD_TYPE_SD8987 (CARD_TYPE_8987 | (INTF_SD << 8))
+/** SD9097 card type */
+#define CARD_TYPE_SD9097 (CARD_TYPE_9097 | (INTF_SD << 8))
+/** SD9098 card type */
+#define CARD_TYPE_SD9098 (CARD_TYPE_9098 | (INTF_SD << 8))
+/** SD9177 card type */
+#define CARD_TYPE_SD9177 (CARD_TYPE_9177 | (INTF_SD << 8))
+/** SD8801 card type */
+#define CARD_TYPE_SD8801 (CARD_TYPE_8801 | (INTF_SD << 8))
+
+#define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
+#define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
+#define IS_SD8977(ct) (CARD_TYPE_SD8977 == (ct))
+#define IS_SD8978(ct) (CARD_TYPE_SD8978 == (ct))
+#define IS_SD8997(ct) (CARD_TYPE_SD8997 == (ct))
+#define IS_SD8987(ct) (CARD_TYPE_SD8987 == (ct))
+#define IS_SD9097(ct) (CARD_TYPE_SD9097 == (ct))
+#define IS_SD9098(ct) (CARD_TYPE_SD9098 == (ct))
+#define IS_SD9177(ct) (CARD_TYPE_SD9177 == (ct))
+#define IS_SD8801(ct) (CARD_TYPE_SD8801 == (ct))
+
+/** SD8887 Card */
+#define CARD_SD8887 "SD8887"
+/** SD8897 Card */
+#define CARD_SD8897 "SD8897"
+/** SD8977 Card */
+#define CARD_SD8977 "SD8977"
+/** SD8978 Card */
+#define CARD_SD8978 "SD8978"
+/** SD8997 Card */
+#define CARD_SD8997 "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987 "SD8987"
+/** SD9097 Card */
+#define CARD_SD9097 "SD9097"
+/** SDIW620 Card */
+#define CARD_SDIW620 "SDIW620"
+/** SD9098 Card */
+#define CARD_SD9098 "SD9098"
+/** SD9177 Card */
+#define CARD_SD9177 "SD9177"
+/** SD8801 Card */
+#define CARD_SD8801 "SD8801"
+#endif
+
+#ifdef PCIE
+/** PCIE8897 card type */
+#define CARD_TYPE_PCIE8897 (CARD_TYPE_8897 | (INTF_PCIE << 8))
+/** PCIE8997 card type */
+#define CARD_TYPE_PCIE8997 (CARD_TYPE_8997 | (INTF_PCIE << 8))
+/** PCIE9097 card type */
+#define CARD_TYPE_PCIE9097 (CARD_TYPE_9097 | (INTF_PCIE << 8))
+/** PCIE9098 card type */
+#define CARD_TYPE_PCIE9098 (CARD_TYPE_9098 | (INTF_PCIE << 8))
+
+#define IS_PCIE8897(ct) (CARD_TYPE_PCIE8897 == (ct))
+#define IS_PCIE8997(ct) (CARD_TYPE_PCIE8997 == (ct))
+#define IS_PCIE9097(ct) (CARD_TYPE_PCIE9097 == (ct))
+#define IS_PCIE9098(ct) (CARD_TYPE_PCIE9098 == (ct))
+
+/** PCIE8897 Card */
+#define CARD_PCIE8897 "PCIE8897"
+/** PCIE8997 Card */
+#define CARD_PCIE8997 "PCIE8997"
+/** PCIE9097 Card */
+#define CARD_PCIE9097 "PCIE9097"
+/** PCIEIW620 Card */
+#define CARD_PCIEIW620 "PCIEIW620"
+/** PCIE9000S Card */
+#define CARD_PCIE9000S "PCIE9000S"
+/** PCIE9098 Card */
+#define CARD_PCIE9098 "PCIE9098"
+/** PCIEAW690 Card */
+#define CARD_PCIEAW690 "PCIEAW690"
+#endif
+
+#ifdef USB
+/** USB8801 card type */
+#define CARD_TYPE_USB8801   (CARD_TYPE_8801 | (INTF_USB << 8))
+/** USB8897 card type */
+#define CARD_TYPE_USB8897 (CARD_TYPE_8897 | (INTF_USB << 8))
+/** USB8997 card type */
+#define CARD_TYPE_USB8997 (CARD_TYPE_8997 | (INTF_USB << 8))
+/** USB8978 card type */
+#define CARD_TYPE_USB8978 (CARD_TYPE_8978 | (INTF_USB << 8))
+/** USB9098 card type */
+#define CARD_TYPE_USB9098 (CARD_TYPE_9098 | (INTF_USB << 8))
+/** USB9097 card type */
+#define CARD_TYPE_USB9097 (CARD_TYPE_9097 | (INTF_USB << 8))
+
+#define IS_USB8801(ct) (CARD_TYPE_USB8801 == (ct))
+#define IS_USB8897(ct) (CARD_TYPE_USB8897 == (ct))
+#define IS_USB8997(ct) (CARD_TYPE_USB8997 == (ct))
+#define IS_USB8978(ct) (CARD_TYPE_USB8978 == (ct))
+#define IS_USB9098(ct) (CARD_TYPE_USB9098 == (ct))
+#define IS_USB9097(ct) (CARD_TYPE_USB9097 == (ct))
+
+/** USB8801 Card */
+#define CARD_USB8801     "USB8801"
+/** USB8897 Card */
+#define CARD_USB8897 "USB8897"
+/** USB8997 Card */
+#define CARD_USB8997 "USB8997"
+/** USB8978 Card */
+#define CARD_USB8978 "USB8978"
+/** USB9098 Card */
+#define CARD_USB9098 "USB9098"
+/** USB9097 Card */
+#define CARD_USB9097 "USB9097"
+/** USBIW620 Card */
+#define CARD_USBIW620 "USBIW620"
+#endif
+
+#define IS_CARD8801(ct) (CARD_TYPE_8801 == ((ct) & 0xf))
+#define IS_CARD8887(ct) (CARD_TYPE_8887 == ((ct)&0xf))
+#define IS_CARD8897(ct) (CARD_TYPE_8897 == ((ct)&0xf))
+#define IS_CARD8977(ct) (CARD_TYPE_8977 == ((ct)&0xf))
+#define IS_CARD8997(ct) (CARD_TYPE_8997 == ((ct)&0xf))
+#define IS_CARD8987(ct) (CARD_TYPE_8987 == ((ct)&0xf))
+#define IS_CARD9098(ct) (CARD_TYPE_9098 == ((ct)&0xf))
+#define IS_CARD9097(ct) (CARD_TYPE_9097 == ((ct)&0xf))
+#define IS_CARD9177(ct) (CARD_TYPE_9177 == ((ct)&0xf))
+
+typedef struct _card_type_entry {
+	t_u16 card_type;
+	t_u16 func_id;
+	char *name;
+} card_type_entry;
+
+#if defined(SDIO) || defined(PCIE)
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY 2
+#endif /* SDIO || PCIE */
+
+#ifdef PCIE
+typedef enum {
+	PCIE_INT_MODE_LEGACY = 0,
+	PCIE_INT_MODE_MSI,
+	PCIE_INT_MODE_MSIX,
+	PCIE_INT_MODE_MAX,
+} PCIE_INT_MODE;
+#endif /* PCIE */
+
+/** IN parameter */
+#define IN
+/** OUT parameter */
+#define OUT
+
+/** BIT value */
+#define MBIT(x) (((t_u32)1) << (x))
+
+/** Buffer flag for requeued packet */
+#define MLAN_BUF_FLAG_REQUEUED_PKT MBIT(0)
+/** Buffer flag for transmit buf from moal */
+#define MLAN_BUF_FLAG_MOAL_TX_BUF MBIT(1)
+/** Buffer flag for malloc mlan_buffer */
+#define MLAN_BUF_FLAG_MALLOC_BUF MBIT(2)
+
+/** Buffer flag for bridge packet */
+#define MLAN_BUF_FLAG_BRIDGE_BUF MBIT(3)
+
+#ifdef USB
+/** Buffer flag for deaggregated rx packet */
+#define MLAN_BUF_FLAG_RX_DEAGGR MBIT(5)
+
+/** Buffer flag for sleep confirm resp packet */
+#define MLAN_BUF_FLAG_SLEEPCFM_RESP MBIT(6)
+
+/** Buffer flag for USB TX AGGR */
+#define MLAN_BUF_FLAG_USB_TX_AGGR MBIT(7)
+#endif
+
+/** Buffer flag for TDLS */
+#define MLAN_BUF_FLAG_TDLS MBIT(8)
+
+/** Buffer flag for TCP_ACK */
+#define MLAN_BUF_FLAG_TCP_ACK MBIT(9)
+
+/** Buffer flag for TX_STATUS */
+#define MLAN_BUF_FLAG_TX_STATUS MBIT(10)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT MBIT(12)
+/** Buffer flag for Diag pkt */
+#define MLAN_BUF_FLAG_DIAG_BUF MBIT(13)
+
+#define MLAN_BUF_FLAG_TX_CTRL MBIT(14)
+
+#ifdef DEBUG_LEVEL1
+/** Debug level bit definition */
+#define MMSG MBIT(0)
+#define MFATAL MBIT(1)
+#define MERROR MBIT(2)
+#define MDATA MBIT(3)
+#define MCMND MBIT(4)
+#define MEVENT MBIT(5)
+#define MINTR MBIT(6)
+#define MIOCTL MBIT(7)
+
+#define MREG_D MBIT(9)
+
+#define MMPA_D MBIT(15)
+#define MDAT_D MBIT(16)
+#define MCMD_D MBIT(17)
+#define MEVT_D MBIT(18)
+#define MFW_D MBIT(19)
+#define MIF_D MBIT(20)
+
+#define MENTRY MBIT(28)
+#define MWARN MBIT(29)
+#define MINFO MBIT(30)
+#define MHEX_DUMP MBIT(31)
+#endif /* DEBUG_LEVEL1 */
+
+/** Memory allocation type: DMA */
+#define MLAN_MEM_DMA MBIT(0)
+
+/** Default memory allocation flag */
+#define MLAN_MEM_DEF 0
+
+/** mlan_status */
+typedef enum _mlan_status {
+	MLAN_STATUS_FAILURE = 0xffffffff,
+	MLAN_STATUS_SUCCESS = 0,
+	MLAN_STATUS_PENDING,
+	MLAN_STATUS_RESOURCE,
+#ifdef USB
+	/* Status pending and no resource */
+	MLAN_STATUS_PRESOURCE,
+#endif
+	MLAN_STATUS_COMPLETE,
+	MLAN_STATUS_FILE_ERR,
+} mlan_status;
+
+/** mlan_error_code */
+typedef enum _mlan_error_code {
+	/** No error */
+	MLAN_ERROR_NO_ERROR = 0,
+	/** Firmware/device errors below (MSB=0) */
+	MLAN_ERROR_FW_NOT_READY = 0x00000001,
+	MLAN_ERROR_FW_BUSY = 0x00000002,
+	MLAN_ERROR_FW_CMDRESP = 0x00000003,
+	MLAN_ERROR_DATA_TX_FAIL = 0x00000004,
+	MLAN_ERROR_DATA_RX_FAIL = 0x00000005,
+	/** Driver errors below (MSB=1) */
+	MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001,
+	MLAN_ERROR_PKT_TIMEOUT = 0x80000002,
+	MLAN_ERROR_PKT_INVALID = 0x80000003,
+	MLAN_ERROR_CMD_INVALID = 0x80000004,
+	MLAN_ERROR_CMD_TIMEOUT = 0x80000005,
+	MLAN_ERROR_CMD_DNLD_FAIL = 0x80000006,
+	MLAN_ERROR_CMD_CANCEL = 0x80000007,
+	MLAN_ERROR_CMD_RESP_FAIL = 0x80000008,
+	MLAN_ERROR_CMD_ASSOC_FAIL = 0x80000009,
+	MLAN_ERROR_CMD_SCAN_FAIL = 0x8000000A,
+	MLAN_ERROR_IOCTL_INVALID = 0x8000000B,
+	MLAN_ERROR_IOCTL_FAIL = 0x8000000C,
+	MLAN_ERROR_EVENT_UNKNOWN = 0x8000000D,
+	MLAN_ERROR_INVALID_PARAMETER = 0x8000000E,
+	MLAN_ERROR_NO_MEM = 0x8000000F,
+	/** More to add */
+} mlan_error_code;
+
+/** mlan_buf_type */
+typedef enum _mlan_buf_type {
+	MLAN_BUF_TYPE_CMD = 1,
+	MLAN_BUF_TYPE_DATA,
+	MLAN_BUF_TYPE_EVENT,
+	MLAN_BUF_TYPE_RAW_DATA,
+#ifdef SDIO
+	MLAN_BUF_TYPE_SPA_DATA,
+#endif
+} mlan_buf_type;
+
+#ifdef USB
+/** mlan_usb_ep */
+typedef enum _mlan_usb_ep {
+	MLAN_USB_EP_CTRL = 0,
+	MLAN_USB_EP_CMD_EVENT = 1,
+	MLAN_USB_EP_DATA = 2,
+	MLAN_USB_EP_DATA_CH2 = 3,
+	MLAN_USB_EP_CMD_EVENT_IF2 = 4,
+	MLAN_USB_EP_DATA_IF2 = 5,
+	MLAN_USB_EP_DATA_CH2_IF2 = 6,
+} mlan_usb_ep;
+
+/** Timeout in milliseconds for usb_bulk_msg function */
+#define MLAN_USB_BULK_MSG_TIMEOUT 100
+#endif /* USB */
+
+/** MLAN BSS type */
+typedef enum _mlan_bss_type {
+	MLAN_BSS_TYPE_STA = 0,
+	MLAN_BSS_TYPE_UAP = 1,
+#ifdef WIFI_DIRECT_SUPPORT
+	MLAN_BSS_TYPE_WIFIDIRECT = 2,
+#endif
+	MLAN_BSS_TYPE_ANY = 0xff,
+} mlan_bss_type;
+
+/** MLAN BSS role */
+typedef enum _mlan_bss_role {
+	MLAN_BSS_ROLE_STA = 0,
+	MLAN_BSS_ROLE_UAP = 1,
+	MLAN_BSS_ROLE_ANY = 0xff,
+} mlan_bss_role;
+
+/** BSS role mask */
+#define BSS_ROLE_MASK (MBIT(0) | MBIT(1))
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_MASK)
+
+/** mlan_data_frame_type */
+typedef enum _mlan_data_frame_type {
+	MLAN_DATA_FRAME_TYPE_ETH_II = 0,
+	MLAN_DATA_FRAME_TYPE_802_11,
+} mlan_data_frame_type;
+
+/** mlan_event_id */
+typedef enum _mlan_event_id {
+	/* Event generated by firmware (MSB=0) */
+	MLAN_EVENT_ID_FW_UNKNOWN = 0x00000001,
+	MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED = 0x00000002,
+	MLAN_EVENT_ID_FW_ADHOC_LINK_LOST = 0x00000003,
+	MLAN_EVENT_ID_FW_DISCONNECTED = 0x00000004,
+	MLAN_EVENT_ID_FW_MIC_ERR_UNI = 0x00000005,
+	MLAN_EVENT_ID_FW_MIC_ERR_MUL = 0x00000006,
+	MLAN_EVENT_ID_FW_BCN_RSSI_LOW = 0x00000007,
+	MLAN_EVENT_ID_FW_BCN_RSSI_HIGH = 0x00000008,
+	MLAN_EVENT_ID_FW_BCN_SNR_LOW = 0x00000009,
+	MLAN_EVENT_ID_FW_BCN_SNR_HIGH = 0x0000000A,
+	MLAN_EVENT_ID_FW_MAX_FAIL = 0x0000000B,
+	MLAN_EVENT_ID_FW_DATA_RSSI_LOW = 0x0000000C,
+	MLAN_EVENT_ID_FW_DATA_RSSI_HIGH = 0x0000000D,
+	MLAN_EVENT_ID_FW_DATA_SNR_LOW = 0x0000000E,
+	MLAN_EVENT_ID_FW_DATA_SNR_HIGH = 0x0000000F,
+	MLAN_EVENT_ID_FW_LINK_QUALITY = 0x00000010,
+	MLAN_EVENT_ID_FW_PORT_RELEASE = 0x00000011,
+	MLAN_EVENT_ID_FW_PRE_BCN_LOST = 0x00000012,
+	MLAN_EVENT_ID_FW_DEBUG_INFO = 0x00000013,
+	MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE = 0x0000001A,
+	MLAN_EVENT_ID_FW_HS_WAKEUP = 0x0000001B,
+	MLAN_EVENT_ID_FW_BG_SCAN = 0x0000001D,
+	MLAN_EVENT_ID_FW_BG_SCAN_STOPPED = 0x0000001E,
+	MLAN_EVENT_ID_FW_WEP_ICV_ERR = 0x00000020,
+	MLAN_EVENT_ID_FW_STOP_TX = 0x00000021,
+	MLAN_EVENT_ID_FW_START_TX = 0x00000022,
+	MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN = 0x00000023,
+	MLAN_EVENT_ID_FW_RADAR_DETECTED = 0x00000024,
+	MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY = 0x00000025,
+	MLAN_EVENT_ID_FW_BW_CHANGED = 0x00000026,
+	MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED = 0x0000002B,
+
+#ifdef UAP_SUPPORT
+	MLAN_EVENT_ID_UAP_FW_BSS_START = 0x0000002C,
+	MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE = 0x0000002D,
+	MLAN_EVENT_ID_UAP_FW_BSS_IDLE = 0x0000002E,
+	MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES = 0x0000002F,
+	MLAN_EVENT_ID_UAP_FW_STA_CONNECT = 0x00000030,
+	MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT = 0x00000031,
+#endif
+
+	MLAN_EVENT_ID_FW_DUMP_INFO = 0x00000033,
+
+	MLAN_EVENT_ID_FW_TX_STATUS = 0x00000034,
+	MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE = 0x00000036,
+#if defined(PCIE)
+	MLAN_EVENT_ID_SSU_DUMP_FILE = 0x00000039,
+#endif /* SSU_SUPPORT */
+	/* Event generated by MLAN driver (MSB=1) */
+	MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001,
+	MLAN_EVENT_ID_DRV_DEFER_HANDLING = 0x80000002,
+	MLAN_EVENT_ID_DRV_HS_ACTIVATED = 0x80000003,
+	MLAN_EVENT_ID_DRV_HS_DEACTIVATED = 0x80000004,
+	MLAN_EVENT_ID_DRV_MGMT_FRAME = 0x80000005,
+	MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM = 0x80000006,
+	MLAN_EVENT_ID_DRV_PASSTHRU = 0x80000007,
+	MLAN_EVENT_ID_DRV_SCAN_REPORT = 0x80000009,
+	MLAN_EVENT_ID_DRV_MEAS_REPORT = 0x8000000A,
+	MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT = 0x8000000B,
+	MLAN_EVENT_ID_DRV_REPORT_STRING = 0x8000000F,
+	MLAN_EVENT_ID_DRV_DBG_DUMP = 0x80000012,
+	MLAN_EVENT_ID_DRV_BGSCAN_RESULT = 0x80000013,
+	MLAN_EVENT_ID_DRV_FLUSH_RX_WORK = 0x80000015,
+	MLAN_EVENT_ID_DRV_DEFER_RX_WORK = 0x80000016,
+	MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ = 0x80000017,
+	MLAN_EVENT_ID_DRV_FT_RESPONSE = 0x80000018,
+	MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK = 0x80000019,
+#ifdef UAP_SUPPORT
+	MLAN_EVENT_ID_DRV_UAP_CHAN_INFO = 0x80000020,
+#endif
+	MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER = 0x80000026,
+	MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER = 0x80000027,
+	MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER = 0x80000028,
+	MLAN_EVENT_ID_DRV_WIFI_STATUS = 0x80000029,
+	MLAN_EVENT_ID_STORE_HOST_CMD_RESP = 0x80000030,
+} mlan_event_id;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+	/** Firmware image buffer pointer */
+	t_u8 *pfw_buf;
+	/** Firmware image length */
+	t_u32 fw_len;
+	/** Firmware reload flag */
+	t_u8 fw_reload;
+} mlan_fw_image, *pmlan_fw_image;
+
+/** MrvlIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlIEtypesHeader {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+} MLAN_PACK_END MrvlIEtypesHeader_t;
+
+/** MrvlExtIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlExtIEtypesHeader {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+	/** ext id */
+	t_u8 ext_id;
+} MLAN_PACK_END MrvlExtIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlExtIEtypes_Data_t {
+	/** Header */
+	MrvlExtIEtypesHeader_t header;
+	/** Data */
+	t_u8 data[];
+} MLAN_PACK_END MrvlExtIEtypes_Data_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Data */
+	t_u8 data[];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+#define OID_TYPE_CAL 0x2
+#define OID_TYPE_DPD 0xa
+#define UNKNOW_DPD_LENGTH   0xffffffff
+
+/** Custom data structure */
+typedef struct _mlan_init_param {
+	/** DPD data buffer pointer */
+	t_u8 *pdpd_data_buf;
+	/** DPD data length */
+	t_u32 dpd_data_len;
+	/** region txpowerlimit cfg data buffer pointer */
+	t_u8 *ptxpwr_data_buf;
+	/** region txpowerlimit cfg data length */
+	t_u32 txpwr_data_len;
+	/** Cal data buffer pointer */
+	t_u8 *pcal_data_buf;
+	/** Cal data length */
+	t_u32 cal_data_len;
+	/** Other custom data */
+} mlan_init_param, *pmlan_init_param;
+
+/** channel type */
+enum mlan_channel_type {
+	CHAN_NO_HT,
+	CHAN_HT20,
+	CHAN_HT40MINUS,
+	CHAN_HT40PLUS,
+	CHAN_VHT80
+};
+
+/** channel band */
+enum { BAND_2GHZ = 0,
+	BAND_5GHZ = 1,
+	BAND_4GHZ = 2,
+};
+
+/** channel offset */
+enum { SEC_CHAN_NONE = 0,
+	SEC_CHAN_ABOVE = 1,
+	SEC_CHAN_5MHZ = 2,
+	SEC_CHAN_BELOW = 3
+};
+
+/** channel bandwidth */
+enum { CHAN_BW_20MHZ = 0,
+	CHAN_BW_10MHZ,
+	CHAN_BW_40MHZ,
+	CHAN_BW_80MHZ,
+};
+
+/** scan mode */
+enum { SCAN_MODE_MANUAL = 0,
+	SCAN_MODE_ACS,
+	SCAN_MODE_USER,
+};
+
+/** DFS state */
+typedef enum _dfs_state_t {
+	/** Channel can be used, CAC (Channel Availability Check) must be done
+	   before using it */
+	DFS_USABLE = 0,
+	/** Channel is not available, radar was detected */
+	DFS_UNAVAILABLE = 1,
+	/** Channel is Available, CAC is done and is free of radar */
+	DFS_AVAILABLE = 2,
+} dfs_state_t;
+
+/** max cac time 10 minutes */
+#define MAX_CAC_DWELL_TIME 600000
+/** default cac time 60 seconds */
+#define DEF_CAC_DWELL_TIME 60000
+/** start freq for 5G */
+#define START_FREQ_11A_BAND 5000
+
+typedef enum _dfs_w53_cfg_t {
+	/** DFS W53 Default Fw Value */
+	DFS_W53_DEFAULT_FW = 0,
+	/** DFS W53 New W53 Rules/Standard */
+	DFS_W53_NEW = 1,
+	/** DFS W53 Old W53 Rules/Standard */
+	DFS_W53_OLD = 2
+} dfs_w53_cfg_t;
+
+/** Band_Config_t */
+typedef MLAN_PACK_START struct _Band_Config_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Channel Selection Mode - (00)=manual, (01)=ACS,  (02)=user*/
+	t_u8 scanMode:2;
+	/** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */
+	t_u8 chan2Offset:2;
+	/** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */
+	t_u8 chanWidth:2;
+	/** Band Info - (00)=2.4GHz, (01)=5GHz */
+	t_u8 chanBand:2;
+#else
+	/** Band Info - (00)=2.4GHz, (01)=5GHz */
+	t_u8 chanBand:2;
+	/** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */
+	t_u8 chanWidth:2;
+	/** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */
+	t_u8 chan2Offset:2;
+	/** Channel Selection Mode - (00)=manual, (01)=ACS, (02)=Adoption mode*/
+	t_u8 scanMode:2;
+#endif
+} MLAN_PACK_END Band_Config_t;
+
+/** channel_band_t */
+typedef MLAN_PACK_START struct _chan_band_info {
+	/** Band Configuration */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** 11n flag */
+	t_u8 is_11n_enabled;
+	/** center channel */
+	t_u8 center_chan;
+	/** dfs channel flag */
+	t_u8 is_dfs_chan;
+} MLAN_PACK_END chan_band_info;
+
+/** Channel usability flags */
+#define NXP_CHANNEL_NO_OFDM MBIT(9)
+#define NXP_CHANNEL_NO_CCK MBIT(8)
+#define NXP_CHANNEL_DISABLED MBIT(7)
+/* BIT 5/6 resevered for FW */
+#define NXP_CHANNEL_NOHT160 MBIT(4)
+#define NXP_CHANNEL_NOHT80 MBIT(3)
+#define NXP_CHANNEL_NOHT40 MBIT(2)
+#define NXP_CHANNEL_DFS MBIT(1)
+#define NXP_CHANNEL_PASSIVE MBIT(0)
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+	/** extra flags to specify channel usability
+	 *  bit 9 : if set, channel is non-OFDM
+	 *  bit 8 : if set, channel is non-CCK
+	 *  bit 7 : if set, channel is disabled
+	 *  bit  5/6 resevered for FW
+	 *  bit 4 : if set, 160MHz on channel is disabled
+	 *  bit 3 : if set, 80MHz on channel is disabled
+	 *  bit 2 : if set, 40MHz on channel is disabled
+	 *  bit 1 : if set, channel is DFS channel
+	 *  bit 0 : if set, channel is passive
+	 */
+	t_u16 flags;
+	/** TRUE: Channel is blacklisted (do not use) */
+	t_bool blacklist;
+	/** DFS state of the channel
+	 * 0:DFS_USABLE  1:DFS_AVAILABLE  2:DFS_UNAVAILABLE */
+	dfs_state_t dfs_state;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+	/** Channel Number */
+	t_u16 channel;
+	/** Frequency of this Channel */
+	t_u32 freq;
+	/** Max allowed Tx power level */
+	t_u16 max_tx_power;
+	/** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+	 * FALSE:radar detect not required for BAND A or active scan for BAND
+	 * B/G*/
+	t_bool passive_scan_or_radar_detect;
+	/** Elements associated to cfp that change at run-time */
+	cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** mlan_event data structure */
+typedef struct _mlan_event {
+	/** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+	/** Event ID */
+	mlan_event_id event_id;
+	/** Event length */
+	t_u32 event_len;
+	/** Event buffer */
+	t_u8 event_buf[];
+} mlan_event, *pmlan_event;
+
+/** mlan_cmdresp_event data structure */
+typedef struct _mlan_cmdresp_event {
+    /** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+    /** Event ID */
+	mlan_event_id event_id;
+    /** Event length */
+	t_u32 event_len;
+    /** resp buffer pointer */
+	t_u8 *resp;
+} mlan_cmdresp_event, *pmlan_cmdresp_event;
+
+/** csi event data structure */
+
+/** mlan_ioctl_req data structure */
+typedef struct _mlan_ioctl_req {
+	/** Pointer to previous mlan_ioctl_req */
+	struct _mlan_ioctl_req *pprev;
+	/** Pointer to next mlan_ioctl_req */
+	struct _mlan_ioctl_req *pnext;
+	/** Status code from firmware/driver */
+	t_u32 status_code;
+	/** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+	/** Request id */
+	t_u32 req_id;
+	/** Action: set or get */
+	t_u32 action;
+	/** Pointer to buffer */
+	t_u8 *pbuf;
+	/** Length of buffer */
+	t_u32 buf_len;
+	/** Length of the data read/written in buffer */
+	t_u32 data_read_written;
+	/** Length of buffer needed */
+	t_u32 buf_len_needed;
+	/** Reserved for MOAL module */
+	t_ptr reserved_1;
+} mlan_ioctl_req, *pmlan_ioctl_req;
+
+/** txpower structure */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Host tx power ctrl:
+	     0x0: use fw setting for TX power
+	     0x1: value specified in bit[6] and bit[5:0] are valid */
+	t_u8 hostctl:1;
+	/** Sign of the power specified in bit[5:0] */
+	t_u8 sign:1;
+	/** Power to be used for transmission(in dBm) */
+	t_u8 abs_val:6;
+#else
+	/** Power to be used for transmission(in dBm) */
+	t_u8 abs_val:6;
+	/** Sign of the power specified in bit[5:0] */
+	t_u8 sign:1;
+	/** Host tx power ctrl:
+	     0x0: use fw setting for TX power
+	     0x1: value specified in bit[6] and bit[5:0] are valid */
+	t_u8 hostctl:1;
+#endif
+} MLAN_PACK_END tx_power_t;
+/* pkt_txctrl */
+typedef MLAN_PACK_START struct _pkt_txctrl {
+	/**Data rate in unit of 0.5Mbps */
+	t_u16 data_rate;
+	/*Channel number to transmit the frame */
+	t_u8 channel;
+	/** Bandwidth to transmit the frame*/
+	t_u8 bw;
+	/** Power to be used for transmission*/
+	union {
+		tx_power_t tp;
+		t_u8 val;
+	} tx_power;
+	/** Retry time of tx transmission*/
+	t_u8 retry_limit;
+} MLAN_PACK_END pkt_txctrl, *ppkt_txctrl;
+
+/** pkt_rxinfo */
+typedef MLAN_PACK_START struct _pkt_rxinfo {
+	/** Data rate of received paccket*/
+	t_u16 data_rate;
+	/** Channel on which packet was received*/
+	t_u8 channel;
+	/** Rx antenna*/
+	t_u8 antenna;
+	/** Rx Rssi*/
+	t_u8 rssi;
+} MLAN_PACK_END pkt_rxinfo, *ppkt_rxinfo;
+
+/** mlan_buffer data structure */
+typedef struct _mlan_buffer {
+	/** Pointer to previous mlan_buffer */
+	struct _mlan_buffer *pprev;
+	/** Pointer to next mlan_buffer */
+	struct _mlan_buffer *pnext;
+	/** Status code from firmware/driver */
+	t_u32 status_code;
+	/** Flags for this buffer */
+	t_u32 flags;
+	/** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+	/** Buffer descriptor, e.g. skb in Linux */
+	t_void *pdesc;
+	/** Pointer to buffer */
+	t_u8 *pbuf;
+#ifdef PCIE
+	/** Physical address of the pbuf pointer */
+	t_u64 buf_pa;
+	t_u32 total_pcie_buf_len;
+#endif
+	/** Offset to data */
+	t_u32 data_offset;
+	/** Data length */
+	t_u32 data_len;
+	/** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+	/** Fields below are valid for data packet only */
+	/** QoS priority */
+	t_u32 priority;
+	/** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+	/** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+	/** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+	/** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+	/** tx_seq_num */
+	t_u32 tx_seq_num;
+    /** Time stamp when packet is deque from rx_q(seconds) */
+	t_u32 extra_ts_sec;
+	/** Time stamp when packet is dequed from rx_q(micro seconds) */
+	t_u32 extra_ts_usec;
+	/** Fields below are valid for MLAN module only */
+	/** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+	/** Use count for this buffer */
+	t_u32 use_count;
+	union {
+		pkt_txctrl tx_info;
+		pkt_rxinfo rx_info;
+	} u;
+} mlan_buffer, *pmlan_buffer, **ppmlan_buffer;
+
+/** mlan_hw_info data structure */
+typedef struct _mlan_hw_info {
+	t_u32 fw_cap;
+	t_u32 fw_cap_ext;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+	/** BSS type */
+	t_u32 bss_type;
+	/** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+	/** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+	/** BSS Priority */
+	t_u32 bss_priority;
+	/** BSS number */
+	t_u32 bss_num;
+	/** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+	/** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+	/** TSID: Range: 0->7 */
+	t_u8 tid;
+	/** TSID specified is valid */
+	t_u8 valid;
+	/** AC TSID is active on */
+	t_u8 access_category;
+	/** UP specified for the TSID */
+	t_u8 user_priority;
+	/** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+	/** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+	/** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+	/** Type definition of mlan_ds_wmm_ts_status for
+	   MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE 256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+	/** IE Index */
+	t_u16 ie_index;
+	/** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+	/** IE Length */
+	t_u16 ie_length;
+	/** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW 4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX 26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+	/** size of buffer */
+	t_u16 buf_size;
+	/** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** No of tuples */
+	t_u16 count;
+	/** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+	/** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** Max TDLS config data length */
+#define MAX_TDLS_DATA_LEN 1024
+
+/** Action commands for TDLS enable/disable */
+#define WLAN_TDLS_CONFIG 0x00
+/** Action commands for TDLS configuration :Set */
+#define WLAN_TDLS_SET_INFO 0x01
+/** Action commands for TDLS configuration :Discovery Request */
+#define WLAN_TDLS_DISCOVERY_REQ 0x02
+/** Action commands for TDLS configuration :Setup Request */
+#define WLAN_TDLS_SETUP_REQ 0x03
+/** Action commands for TDLS configuration :Tear down Request */
+#define WLAN_TDLS_TEAR_DOWN_REQ 0x04
+/** Action ID for TDLS power mode */
+#define WLAN_TDLS_POWER_MODE 0x05
+/**Action ID for init TDLS Channel Switch*/
+#define WLAN_TDLS_INIT_CHAN_SWITCH 0x06
+/** Action ID for stop TDLS Channel Switch */
+#define WLAN_TDLS_STOP_CHAN_SWITCH 0x07
+/** Action ID for configure CS related parameters */
+#define WLAN_TDLS_CS_PARAMS 0x08
+/** Action ID for Disable CS */
+#define WLAN_TDLS_CS_DISABLE 0x09
+/** Action ID for TDLS link status */
+#define WLAN_TDLS_LINK_STATUS 0x0A
+/** Action ID for Host TDLS config uapsd and CS */
+#define WLAN_HOST_TDLS_CONFIG 0x0D
+/** Action ID for TDLS CS immediate return */
+#define WLAN_TDLS_DEBUG_CS_RET_IM 0xFFF7
+/** Action ID for TDLS Stop RX */
+#define WLAN_TDLS_DEBUG_STOP_RX 0xFFF8
+/** Action ID for TDLS Allow weak security for links establish */
+#define WLAN_TDLS_DEBUG_ALLOW_WEAK_SECURITY 0xFFF9
+/** Action ID for TDLS Ignore key lifetime expiry */
+#define WLAN_TDLS_DEBUG_IGNORE_KEY_EXPIRY 0xFFFA
+/** Action ID for TDLS Higher/Lower mac Test */
+#define WLAN_TDLS_DEBUG_HIGHER_LOWER_MAC 0xFFFB
+/** Action ID for TDLS Prohibited Test */
+#define WLAN_TDLS_DEBUG_SETUP_PROHIBITED 0xFFFC
+/** Action ID for TDLS Existing link Test */
+#define WLAN_TDLS_DEBUG_SETUP_SAME_LINK 0xFFFD
+/** Action ID for TDLS Fail Setup Confirm */
+#define WLAN_TDLS_DEBUG_FAIL_SETUP_CONFIRM 0xFFFE
+/** Action commands for TDLS debug: Wrong BSS Request */
+#define WLAN_TDLS_DEBUG_WRONG_BSS 0xFFFF
+
+/** tdls each link rate information */
+typedef MLAN_PACK_START struct _tdls_link_rate_info {
+	/** Tx Data Rate */
+	t_u8 tx_data_rate;
+	/** Tx Rate HT info*/
+	t_u8 tx_rate_htinfo;
+} MLAN_PACK_END tdls_link_rate_info;
+
+/** tdls each link status */
+typedef MLAN_PACK_START struct _tdls_each_link_status {
+	/** peer mac Address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Link Flags */
+	t_u8 link_flags;
+	/** Traffic Status */
+	t_u8 traffic_status;
+	/** Tx Failure Count */
+	t_u8 tx_fail_count;
+	/** Channel Number */
+	t_u32 active_channel;
+	/** Last Data RSSI in dBm */
+	t_s16 data_rssi_last;
+	/** Last Data NF in dBm */
+	t_s16 data_nf_last;
+	/** AVG DATA RSSI in dBm */
+	t_s16 data_rssi_avg;
+	/** AVG DATA NF in dBm */
+	t_s16 data_nf_avg;
+	union {
+		/** tdls rate info */
+		tdls_link_rate_info rate_info;
+		/** tdls link final rate*/
+		t_u16 final_data_rate;
+	} u;
+	/** Security Method */
+	t_u8 security_method;
+	/** Key Lifetime in milliseconds */
+	t_u32 key_lifetime;
+	/** Key Length */
+	t_u8 key_length;
+	/** actual key */
+	t_u8 key[1];
+} MLAN_PACK_END tdls_each_link_status;
+
+/** TDLS configuration data */
+typedef MLAN_PACK_START struct _tdls_all_config {
+	union {
+		/** TDLS state enable disable */
+		MLAN_PACK_START struct _tdls_config {
+			/** enable or disable */
+			t_u16 enable;
+		} MLAN_PACK_END tdls_config;
+		/** Host tdls config */
+		MLAN_PACK_START struct _host_tdls_cfg {
+			/** support uapsd */
+			t_u8 uapsd_support;
+			/** channel_switch */
+			t_u8 cs_support;
+			/** TLV  length */
+			t_u16 tlv_len;
+			/** tdls info */
+			t_u8 tlv_buffer[];
+		} MLAN_PACK_END host_tdls_cfg;
+		/** TDLS set info */
+		MLAN_PACK_START struct _tdls_set_data {
+			/** (tlv + capInfo) length */
+			t_u16 tlv_length;
+			/** Cap Info */
+			t_u16 cap_info;
+			/** TLV buffer */
+			t_u8 tlv_buffer[];
+		} MLAN_PACK_END tdls_set;
+
+		/** TDLS discovery and others having mac argument */
+		MLAN_PACK_START struct _tdls_discovery_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+		} MLAN_PACK_END tdls_discovery, tdls_stop_chan_switch,
+			tdls_link_status_req;
+
+		/** TDLS discovery Response */
+		MLAN_PACK_START struct _tdls_discovery_resp {
+			/** payload length */
+			t_u16 payload_len;
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** RSSI */
+			t_s8 rssi;
+			/** Cap Info */
+			t_u16 cap_info;
+			/** TLV buffer */
+			t_u8 tlv_buffer[];
+		} MLAN_PACK_END tdls_discovery_resp;
+
+		/** TDLS setup request */
+		MLAN_PACK_START struct _tdls_setup_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** timeout value in milliseconds */
+			t_u32 setup_timeout;
+			/** key lifetime in milliseconds */
+			t_u32 key_lifetime;
+		} MLAN_PACK_END tdls_setup;
+
+		/** TDLS tear down info */
+		MLAN_PACK_START struct _tdls_tear_down_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** reason code */
+			t_u16 reason_code;
+		} MLAN_PACK_END tdls_tear_down, tdls_cmd_resp;
+
+		/** TDLS power mode info */
+		MLAN_PACK_START struct _tdls_power_mode_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** Power Mode */
+			t_u16 power_mode;
+		} MLAN_PACK_END tdls_power_mode;
+
+		/** TDLS channel switch info */
+		MLAN_PACK_START struct _tdls_chan_switch {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** Channel Switch primary channel no */
+			t_u8 primary_channel;
+			/** Channel Switch secondary channel offset */
+			t_u8 secondary_channel_offset;
+			/** Channel Switch Band */
+			t_u8 band;
+			/** Channel Switch time in milliseconds */
+			t_u16 switch_time;
+			/** Channel Switch timeout in milliseconds */
+			t_u16 switch_timeout;
+			/** Channel Regulatory class*/
+			t_u8 regulatory_class;
+			/** peridicity flag*/
+			t_u8 periodicity;
+		} MLAN_PACK_END tdls_chan_switch;
+
+		/** TDLS channel switch paramters */
+		MLAN_PACK_START struct _tdls_cs_params {
+			/** unit time, multiples of 10ms */
+			t_u8 unit_time;
+			/** threshold for other link */
+			t_u8 threshold_otherlink;
+			/** threshold for direct link */
+			t_u8 threshold_directlink;
+		} MLAN_PACK_END tdls_cs_params;
+
+		/** tdls disable channel switch */
+		MLAN_PACK_START struct _tdls_disable_cs {
+			/** Data*/
+			t_u16 data;
+		} MLAN_PACK_END tdls_disable_cs;
+		/** TDLS debug data */
+		MLAN_PACK_START struct _tdls_debug_data {
+			/** debug data */
+			t_u16 debug_data;
+		} MLAN_PACK_END tdls_debug_data;
+
+		/** TDLS link status Response */
+		MLAN_PACK_START struct _tdls_link_status_resp {
+			/** payload length */
+			t_u16 payload_len;
+			/** number of links */
+			t_u8 active_links;
+			/** structure for link status */
+			tdls_each_link_status link_stats[1];
+		} MLAN_PACK_END tdls_link_status_resp;
+
+	} u;
+} MLAN_PACK_END tdls_all_config;
+
+/** TDLS configuration buffer */
+typedef MLAN_PACK_START struct _buf_tdls_config {
+	/** TDLS Action */
+	t_u16 tdls_action;
+	/** TDLS data */
+	t_u8 tdls_data[MAX_TDLS_DATA_LEN];
+} MLAN_PACK_END mlan_ds_misc_tdls_config;
+
+/** Event structure for tear down */
+typedef struct _tdls_tear_down_event {
+	/** Peer mac address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Reason code */
+	t_u16 reason_code;
+} tdls_tear_down_event;
+
+/** channel width */
+typedef enum wifi_channel_width {
+	WIFI_CHAN_WIDTH_20 = 0,
+	WIFI_CHAN_WIDTH_40 = 1,
+	WIFI_CHAN_WIDTH_80 = 2,
+	WIFI_CHAN_WIDTH_160 = 3,
+	WIFI_CHAN_WIDTH_80P80 = 4,
+	WIFI_CHAN_WIDTH_5 = 5,
+	WIFI_CHAN_WIDTH_10 = 6,
+	WIFI_CHAN_WIDTH_INVALID = -1
+} wifi_channel_width_t;
+
+/** channel information */
+typedef struct {
+	/** channel width (20, 40, 80, 80+80, 160) */
+	wifi_channel_width_t width;
+	/** primary 20 MHz channel */
+	int center_freq;
+	/** center frequency (MHz) first segment */
+	int center_freq0;
+	/** center frequency (MHz) second segment */
+	int center_freq1;
+} wifi_channel_info;
+
+/** wifi rate */
+typedef struct {
+	/** 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+	t_u32 preamble:3;
+	/** 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+	t_u32 nss:2;
+	/** 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+	t_u32 bw:3;
+	/** OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps
+	 */
+	/** HT/VHT it would be mcs index */
+	t_u32 rateMcsIdx:8;
+	/** reserved */
+	t_u32 reserved:16;
+	/** units of 100 Kbps */
+	t_u32 bitrate;
+} wifi_rate;
+
+/** wifi Preamble type */
+typedef enum {
+	WIFI_PREAMBLE_LEGACY = 0x1,
+	WIFI_PREAMBLE_HT = 0x2,
+	WIFI_PREAMBLE_VHT = 0x4
+} wifi_preamble;
+
+/** timeval */
+typedef struct {
+	/** Time (seconds) */
+	t_u32 time_sec;
+	/** Time (micro seconds) */
+	t_u32 time_usec;
+} wifi_timeval;
+
+#define MAX_NUM_RATE 32
+#define MAX_RADIO 2
+#define MAX_NUM_CHAN 1
+#define VHT_NUM_SUPPORT_MCS 10
+#define MCS_NUM_SUPP 16
+
+#define BUF_MAXLEN 4096
+/** connection state */
+typedef enum {
+	MLAN_DISCONNECTED = 0,
+	MLAN_AUTHENTICATING = 1,
+	MLAN_ASSOCIATING = 2,
+	MLAN_ASSOCIATED = 3,
+	/** if done by firmware/driver */
+	MLAN_EAPOL_STARTED = 4,
+	/** if done by firmware/driver */
+	MLAN_EAPOL_COMPLETED = 5,
+} mlan_connection_state;
+/** roam state */
+typedef enum {
+	MLAN_ROAMING_IDLE = 0,
+	MLAN_ROAMING_ACTIVE = 1,
+} mlan_roam_state;
+/** interface mode */
+typedef enum {
+	MLAN_INTERFACE_STA = 0,
+	MLAN_INTERFACE_SOFTAP = 1,
+	MLAN_INTERFACE_IBSS = 2,
+	MLAN_INTERFACE_P2P_CLIENT = 3,
+	MLAN_INTERFACE_P2P_GO = 4,
+	MLAN_INTERFACE_NAN = 5,
+	MLAN_INTERFACE_MESH = 6,
+} mlan_interface_mode;
+
+/** set for QOS association */
+#define MLAN_CAPABILITY_QOS 0x00000001
+/** set for protected association (802.11 beacon frame control protected bit
+ * set) */
+#define MLAN_CAPABILITY_PROTECTED 0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define MLAN_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define MLAN_CAPABILITY_HS20 0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define MLAN_CAPABILITY_SSID_UTF8 0x00000010
+/** set is 802.11 Country Element is present */
+#define MLAN_CAPABILITY_COUNTRY 0x00000020
+
+/** link layer status */
+typedef struct {
+	/** interface mode */
+	mlan_interface_mode mode;
+	/** interface mac address (self) */
+	t_u8 mac_addr[6];
+	/** connection state (valid for STA, CLI only) */
+	mlan_connection_state state;
+	/** roaming state */
+	mlan_roam_state roaming;
+	/** WIFI_CAPABILITY_XXX (self) */
+	t_u32 capabilities;
+	/** null terminated SSID */
+	t_u8 ssid[33];
+	/** bssid */
+	t_u8 bssid[6];
+	/** country string advertised by AP */
+	t_u8 ap_country_str[3];
+	/** country string for this association */
+	t_u8 country_str[3];
+} mlan_interface_link_layer_info, *mlan_interface_handle;
+
+/** channel statistics */
+typedef struct {
+	/** channel */
+	wifi_channel_info channel;
+	/** msecs the radio is awake (32 bits number accruing over time) */
+	t_u32 on_time;
+	/** msecs the CCA register is busy (32 bits number accruing over time)
+	 */
+	t_u32 cca_busy_time;
+} wifi_channel_stat;
+
+#define timeval_to_msec(timeval)                                               \
+	(t_u64)((t_u64)(timeval.time_sec) * 1000 +                             \
+		(t_u64)(timeval.time_usec) / 1000)
+#define timeval_to_usec(timeval)                                               \
+	(t_u64)((t_u64)(timeval.time_sec) * 1000 * 1000 +                      \
+		(t_u64)(timeval.time_usec))
+#define is_zero_timeval(timeval)                                               \
+	((timeval.time_sec == 0) && (timeval.time_usec == 0))
+
+/** radio statistics */
+typedef struct {
+	/** wifi radio (if multiple radio supported) */
+	int radio;
+	/** msecs the radio is awake (32 bits number accruing over time) */
+	t_u32 on_time;
+	/** msecs the radio is transmitting (32 bits number accruing over time)
+	 */
+	t_u32 tx_time;
+	/**  TBD: num_tx_levels: number of radio transmit power levels */
+	t_u32 reserved0;
+	/** TBD: tx_time_per_levels: pointer to an array of radio transmit per
+	 * power levels in msecs accured over time */
+	/* t_u32 *reserved1; */
+	/** msecs the radio is in active receive (32 bits number accruing over
+	 * time) */
+	t_u32 rx_time;
+	/** msecs the radio is awake due to all scan (32 bits number accruing
+	 * over time) */
+	t_u32 on_time_scan;
+	/** msecs the radio is awake due to NAN (32 bits number accruing over
+	 * time) */
+	t_u32 on_time_nbd;
+	/** msecs the radio is awake due to G?scan (32 bits number accruing over
+	 * time) */
+	t_u32 on_time_gscan;
+	/** msecs the radio is awake due to roam?scan (32 bits number accruing
+	 * over time) */
+	t_u32 on_time_roam_scan;
+	/** msecs the radio is awake due to PNO scan (32 bits number accruing
+	 * over time) */
+	t_u32 on_time_pno_scan;
+	/** msecs the radio is awake due to HS2.0 scans and GAS exchange (32
+	 * bits number accruing over time) */
+	t_u32 on_time_hs20;
+	/** number of channels */
+	t_u32 num_channels;
+	/** channel statistics */
+	wifi_channel_stat channels[MAX_NUM_CHAN];
+} wifi_radio_stat;
+
+/** per rate statistics */
+typedef struct {
+	/** rate information */
+	wifi_rate rate;
+	/** number of successfully transmitted data pkts (ACK rcvd) */
+	t_u32 tx_mpdu;
+	/** number of received data pkts */
+	t_u32 rx_mpdu;
+	/** number of data packet losses (no ACK) */
+	t_u32 mpdu_lost;
+	/** total number of data pkt retries */
+	t_u32 retries;
+	/** number of short data pkt retries */
+	t_u32 retries_short;
+	/** number of long data pkt retries */
+	t_u32 retries_long;
+} wifi_rate_stat;
+
+/** wifi peer type */
+typedef enum {
+	WIFI_PEER_STA,
+	WIFI_PEER_AP,
+	WIFI_PEER_P2P_GO,
+	WIFI_PEER_P2P_CLIENT,
+	WIFI_PEER_NAN,
+	WIFI_PEER_TDLS,
+	WIFI_PEER_INVALID,
+} wifi_peer_type;
+
+/** per peer statistics */
+typedef struct {
+	/** peer type (AP, TDLS, GO etc.) */
+	wifi_peer_type type;
+	/** mac address */
+	t_u8 peer_mac_address[6];
+	/** peer WIFI_CAPABILITY_XXX */
+	t_u32 capabilities;
+	/** number of rates */
+	t_u32 num_rate;
+	/** per rate statistics, number of entries  = num_rate */
+	wifi_rate_stat rate_stats[];
+} wifi_peer_info;
+
+/** per access category statistics */
+typedef struct {
+	/** access category (VI, VO, BE, BK) */
+	mlan_wmm_ac_e ac;
+	/** number of successfully transmitted unicast data pkts (ACK rcvd) */
+	t_u32 tx_mpdu;
+	/** number of received unicast mpdus */
+	t_u32 rx_mpdu;
+	/** number of succesfully transmitted multicast data packets */
+	/** STA case: implies ACK received from AP for the unicast packet in
+	 * which mcast pkt was sent */
+	t_u32 tx_mcast;
+	/** number of received multicast data packets */
+	t_u32 rx_mcast;
+	/** number of received unicast a-mpdus */
+	t_u32 rx_ampdu;
+	/** number of transmitted unicast a-mpdus */
+	t_u32 tx_ampdu;
+	/** number of data pkt losses (no ACK) */
+	t_u32 mpdu_lost;
+	/** total number of data pkt retries */
+	t_u32 retries;
+	/** number of short data pkt retries */
+	t_u32 retries_short;
+	/** number of long data pkt retries */
+	t_u32 retries_long;
+	/** data pkt min contention time (usecs) */
+	t_u32 contention_time_min;
+	/** data pkt max contention time (usecs) */
+	t_u32 contention_time_max;
+	/** data pkt avg contention time (usecs) */
+	t_u32 contention_time_avg;
+	/** num of data pkts used for contention statistics */
+	t_u32 contention_num_samples;
+} wifi_wmm_ac_stat;
+
+/** interface statistics */
+typedef struct {
+	/** wifi interface */
+	/* wifi_interface_handle iface; */
+	/** current state of the interface */
+	mlan_interface_link_layer_info info;
+	/** access point beacon received count from connected AP */
+	t_u32 beacon_rx;
+	/** Average beacon offset encountered (beacon_TSF - TBTT)
+	 *    the average_tsf_offset field is used so as to calculate the
+	 *    typical beacon contention time on the channel as well may be
+	 *    used to debug beacon synchronization and related power consumption
+	 * issue
+	 */
+	t_u64 average_tsf_offset;
+	/** indicate that this AP typically leaks packets beyond the driver
+	 * guard time */
+	t_u32 leaky_ap_detected;
+	/** average number of frame leaked by AP after frame with PM bit set was
+	 * ACK'ed by AP */
+	t_u32 leaky_ap_avg_num_frames_leaked;
+	/** Guard time currently in force (when implementing IEEE power
+	 * management based on frame control PM bit), How long driver waits
+	 * before shutting down the radio and after receiving an ACK for a data
+	 * frame with PM bit set)
+	 */
+	t_u32 leaky_ap_guard_time;
+	/** access point mgmt frames received count from connected AP (including
+	 * Beacon) */
+	t_u32 mgmt_rx;
+	/** action frames received count */
+	t_u32 mgmt_action_rx;
+	/** action frames transmit count */
+	t_u32 mgmt_action_tx;
+	/** access Point Beacon and Management frames RSSI (averaged) */
+	t_s32 rssi_mgmt;
+	/** access Point Data Frames RSSI (averaged) from connected AP */
+	t_s32 rssi_data;
+	/** access Point ACK RSSI (averaged) from connected AP */
+	t_s32 rssi_ack;
+	/** per ac data packet statistics */
+	wifi_wmm_ac_stat ac[MAX_AC_QUEUES];
+	/** number of peers */
+	t_u32 num_peers;
+	/** per peer statistics */
+	wifi_peer_info peer_info[];
+} wifi_iface_stat;
+
+/** link layer stat configuration params */
+typedef struct {
+	/** threshold to classify the pkts as short or long */
+	t_u32 mpdu_size_threshold;
+	/** wifi statistics bitmap */
+	t_u32 aggressive_statistics_gathering;
+} wifi_link_layer_params;
+
+/** wifi statistics bitmap  */
+#define WIFI_STATS_RADIO 0x00000001 /** all radio statistics */
+#define WIFI_STATS_RADIO_CCA                                                   \
+	0x00000002 /** cca_busy_time (within radio statistics) */
+#define WIFI_STATS_RADIO_CHANNELS                                              \
+	0x00000004 /** all channel statistics (within radio statistics) */
+#define WIFI_STATS_RADIO_SCAN                                                  \
+	0x00000008 /** all scan statistics (within radio statistics) */
+#define WIFI_STATS_IFACE 0x00000010 /** all interface statistics */
+#define WIFI_STATS_IFACE_TXRATE                                                \
+	0x00000020 /** all tx rate statistics (within interface statistics) */
+#define WIFI_STATS_IFACE_AC                                                    \
+	0x00000040 /** all ac statistics (within interface statistics) */
+#define WIFI_STATS_IFACE_CONTENTION                                            \
+	0x00000080 /** all contention (min, max, avg) statistics (within ac    \
+		      statisctics) */
+
+/** station stats */
+typedef struct _sta_stats {
+	t_u64 last_rx_in_msec;
+} sta_stats;
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+/** mlan_callbacks data structure */
+typedef struct _mlan_callbacks {
+	/** moal_get_fw_data */
+	mlan_status (*moal_get_fw_data) (t_void *pmoal,
+					 t_u32 offset, t_u32 len, t_u8 *pbuf);
+	mlan_status (*moal_get_vdll_data) (t_void *pmoal, t_u32 len,
+					   t_u8 *pbuf);
+	/** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (t_void *pmoal,
+						  mlan_status status,
+						  pmlan_hw_info phw,
+						  pmlan_bss_tbl ptbl);
+	/** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (t_void *pmoal,
+					      mlan_status status);
+	/** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (t_void *pmoal,
+						  mlan_status status);
+	/** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (t_void *pmoal,
+						  pmlan_buffer pmbuf,
+						  mlan_status status);
+	/** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (t_void *pmoal,
+					   pmlan_buffer pmbuf, t_u32 port,
+					   mlan_status status);
+	/** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (t_void *pmoal, pmlan_buffer pmbuf);
+    /** moal_recv_amsdu_packet */
+	mlan_status (*moal_recv_amsdu_packet) (t_void *pmoal,
+					       pmlan_buffer pmbuf);
+	/** moal_recv_event */
+	mlan_status (*moal_recv_event) (t_void *pmoal, pmlan_event pmevent);
+	/** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (t_void *pmoal,
+					    pmlan_ioctl_req pioctl_req,
+					    mlan_status status);
+
+	/** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (t_void *pmoal,
+					       t_u32 size, ppmlan_buffer pmbuf);
+	/** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (t_void *pmoal,
+					      pmlan_buffer pmbuf);
+
+#ifdef USB
+	/** moal_write_data_async */
+	mlan_status (*moal_write_data_async) (t_void *pmoal,
+					      pmlan_buffer pmbuf, t_u32 port);
+#endif				/* USB */
+#if defined(SDIO) || defined(PCIE)
+	/** moal_write_reg */
+	mlan_status (*moal_write_reg) (t_void *pmoal, t_u32 reg, t_u32 data);
+	/** moal_read_reg */
+	mlan_status (*moal_read_reg) (t_void *pmoal, t_u32 reg, t_u32 *data);
+#endif				/* SDIO || PCIE */
+	/** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (t_void *pmoal,
+					     pmlan_buffer pmbuf,
+					     t_u32 port, t_u32 timeout);
+	/** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (t_void *pmoal,
+					    pmlan_buffer pmbuf,
+					    t_u32 port, t_u32 timeout);
+	/** moal_malloc */
+	mlan_status (*moal_malloc) (t_void *pmoal, t_u32 size,
+				    t_u32 flag, t_u8 **ppbuf);
+	/** moal_mfree */
+	mlan_status (*moal_mfree) (t_void *pmoal, t_u8 *pbuf);
+	/** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (t_void *pmoal, t_u32 size, t_u8 **ppbuf);
+	/** moal_vfree */
+	mlan_status (*moal_vfree) (t_void *pmoal, t_u8 *pbuf);
+#ifdef PCIE
+	/** moal_malloc_consistent */
+	mlan_status (*moal_malloc_consistent) (t_void *pmoal,
+					       t_u32 size, t_u8 **ppbuf,
+					       t_u64 *pbuf_pa);
+	/** moal_mfree_consistent */
+	mlan_status (*moal_mfree_consistent) (t_void *pmoal,
+					      t_u32 size, t_u8 *pbuf,
+					      t_u64 buf_pa);
+	/** moal_map_memory */
+	mlan_status (*moal_map_memory) (t_void *pmoal, t_u8 *pbuf,
+					t_u64 *pbuf_pa, t_u32 size, t_u32 flag);
+	/** moal_unmap_memory */
+	mlan_status (*moal_unmap_memory) (t_void *pmoal, t_u8 *pbuf,
+					  t_u64 buf_pa, t_u32 size, t_u32 flag);
+#endif				/* PCIE */
+	/** moal_memset */
+	t_void *(*moal_memset) (t_void *pmoal, t_void *pmem,
+				t_u8 byte, t_u32 num);
+	/** moal_memcpy */
+	t_void *(*moal_memcpy) (t_void *pmoal, t_void *pdest,
+				const t_void *psrc, t_u32 num);
+	/** moal_memcpy_ext */
+	t_void *(*moal_memcpy_ext) (t_void *pmoal, t_void *pdest,
+				    const t_void *psrc, t_u32 num,
+				    t_u32 dest_size);
+	/** moal_memmove */
+	t_void *(*moal_memmove) (t_void *pmoal, t_void *pdest,
+				 const t_void *psrc, t_u32 num);
+	/** moal_memcmp */
+	t_s32 (*moal_memcmp) (t_void *pmoal, const t_void *pmem1,
+			      const t_void *pmem2, t_u32 num);
+	/** moal_udelay */
+	t_void (*moal_udelay) (t_void *pmoal, t_u32 udelay);
+	/** moal_usleep_range */
+	t_void (*moal_usleep_range) (t_void *pmoal,
+				     t_u32 min_delay, t_u32 max_delay);
+	/** moal_get_boot_ktime */
+	mlan_status (*moal_get_boot_ktime) (t_void *pmoal, t_u64 *pnsec);
+	/** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (t_void *pmoal,
+					     t_u32 *psec, t_u32 *pusec);
+	/** moal_init_timer*/
+	mlan_status (*moal_init_timer) (t_void *pmoal,
+					t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					t_void *pcontext);
+	/** moal_free_timer */
+	mlan_status (*moal_free_timer) (t_void *pmoal, t_void *ptimer);
+	/** moal_start_timer*/
+	mlan_status (*moal_start_timer) (t_void *pmoal,
+					 t_void *ptimer, t_u8 periodic,
+					 t_u32 msec);
+	/** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (t_void *pmoal, t_void *ptimer);
+	/** moal_init_lock */
+	mlan_status (*moal_init_lock) (t_void *pmoal, t_void **pplock);
+	/** moal_free_lock */
+	mlan_status (*moal_free_lock) (t_void *pmoal, t_void *plock);
+	/** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (t_void *pmoal, t_void *plock);
+	/** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (t_void *pmoal, t_void *plock);
+	/** moal_print */
+	t_void (*moal_print) (t_void *pmoal, t_u32 level,
+			      char *pformat, IN ...);
+	/** moal_print_netintf */
+	t_void (*moal_print_netintf) (t_void *pmoal,
+				      t_u32 bss_index, t_u32 level);
+	/** moal_assert */
+	t_void (*moal_assert) (t_void *pmoal, t_u32 cond);
+
+	/** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (t_void *pmoal,
+				      t_u32 bss_index, t_u16 rx_rate,
+				      t_s8 snr, t_s8 nflr, t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (t_void *pmoal,
+					   t_u32 bss_index,
+					   t_u8 *peer_addr, t_s8 snr,
+					   t_s8 nflr);
+	t_u64 (*moal_do_div) (t_u64 num, t_u32 base);
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	mlan_status (*moal_wait_hostcmd_complete) (t_void *pmoal,
+						   t_u32 bss_index);
+	mlan_status (*moal_notify_hostcmd_complete) (t_void *pmoal,
+						     t_u32 bss_index);
+#endif
+	void (*moal_tp_accounting) (t_void *pmoal,
+				    t_void *buf, t_u32 drop_point);
+	void (*moal_tp_accounting_rx_param) (t_void *pmoal,
+					     unsigned int type,
+					     unsigned int rsvd1);
+	void (*moal_amsdu_tp_accounting) (t_void *pmoal, t_s32 delay,
+					  t_s32 copy_delay);
+} mlan_callbacks, *pmlan_callbacks;
+
+/** Parameter unchanged, use MLAN default setting */
+#define ROBUSTCOEX_GPIO_UNCHANGED 0
+/** Parameter enabled, override MLAN default setting */
+#define ROBUSTCOEX_GPIO_CFG 1
+
+#if defined(SDIO)
+/** Interrupt Mode SDIO */
+#define INT_MODE_SDIO 0
+/** Interrupt Mode GPIO */
+#define INT_MODE_GPIO 1
+/** New mode: GPIO-1 as a duplicated signal of interrupt as appear of SDIO_DAT1
+ */
+#define GPIO_INT_NEW_MODE 255
+#endif
+
+/** Parameter unchanged, use MLAN default setting */
+#define MLAN_INIT_PARA_UNCHANGED 0
+/** Parameter enabled, override MLAN default setting */
+#define MLAN_INIT_PARA_ENABLED 1
+/** Parameter disabled, override MLAN default setting */
+#define MLAN_INIT_PARA_DISABLED 2
+
+/** Control bit for stream 2X2 */
+#define FEATURE_CTRL_STREAM_2X2 MBIT(0)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT MBIT(1)
+#ifdef USB
+/** Control bit for winner check & not wait for FW ready event */
+#define FEATURE_CTRL_USB_NEW_INIT MBIT(2)
+#endif
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT 0xffffffff
+/** Check if stream 2X2 enabled */
+#define IS_STREAM_2X2(x) ((x)&FEATURE_CTRL_STREAM_2X2)
+/** Check if DFS support enabled */
+#define IS_DFS_SUPPORT(x) ((x)&FEATURE_CTRL_DFS_SUPPORT)
+#ifdef USB
+/** Check if winner check & not wait for FW ready event */
+#define IS_USB_NEW_INIT(x) ((x)&FEATURE_CTRL_USB_NEW_INIT)
+#endif
+
+/*
+#define DRV_MODE_NAN                 MBIT(4)
+#define DRV_MODE_11P                 MBIT(5)
+#define DRV_MODE_MAC80211            MBIT(6)
+#define DRV_MODE_DFS                 MBIT(7)*/
+#define DRV_MODE_MASK (MBIT(4) | MBIT(5) | MBIT(6) | MBIT(7))
+
+/** mlan_device data structure */
+typedef struct _mlan_device {
+	/** MOAL Handle */
+	t_void *pmoal_handle;
+	/** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+	/** Callbacks */
+	mlan_callbacks callbacks;
+#ifdef MFG_CMD_SUPPORT
+	/** MFG mode */
+	t_u32 mfg_mode;
+#endif
+#ifdef PCIE
+	t_u16 ring_size;
+#endif
+#if defined(SDIO)
+	/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+	/** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#endif
+#ifdef DEBUG_LEVEL1
+	/** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+	/** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+	/** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+	/** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#ifdef SDIO
+	/** SDIO Single port rx aggr */
+	t_u8 sdio_rx_aggr_enable;
+	/* see blk_queue_max_segment_size */
+	t_u32 max_seg_size;
+	/* see blk_queue_max_segments */
+	t_u16 max_segs;
+#endif
+	/** Auto deep sleep */
+	t_u32 auto_ds;
+	/** IEEE PS mode */
+	t_u32 ps_mode;
+	/** Max Tx buffer size */
+	t_u32 max_tx_buf;
+#if defined(STA_SUPPORT)
+	/** 802.11d configuration */
+	t_u32 cfg_11d;
+#endif
+	/** Feature control bitmask */
+	t_u32 feature_control;
+	/** enable/disable rx work */
+	t_u8 rx_work;
+	/** dev cap mask */
+	t_u32 dev_cap_mask;
+	/** oob independent reset */
+	t_u32 indrstcfg;
+	/** dtim interval */
+	t_u16 multi_dtim;
+	/** IEEE ps inactivity timeout value */
+	t_u16 inact_tmo;
+	/** card type */
+	t_u16 card_type;
+	/** card rev */
+	t_u8 card_rev;
+	/** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+	/** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+	/** Dynamic MIMO-SISO switch for hscfg*/
+	t_u8 hs_mimo_switch;
+#ifdef USB
+	/** Tx CMD endpoint address */
+	t_u8 tx_cmd_ep;
+	/** Rx CMD/EVT endpoint address */
+	t_u8 rx_cmd_ep;
+
+	/** Rx data endpoint address */
+	t_u8 rx_data_ep;
+	/** Tx data endpoint address */
+	t_u8 tx_data_ep;
+#endif
+	/** passive to active scan */
+	t_u8 passive_to_active_scan;
+	/** uap max supported station per chip */
+	t_u8 uap_max_sta;
+	/** drv mode */
+	t_u32 drv_mode;
+	/** dfs w53 cfg */
+	t_u8 dfs53cfg;
+    /** extend enhance scan */
+	t_u8 ext_scan;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(pmlan_device pmdevice,
+				   t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(t_void *padapter);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(t_void *padapter, pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(t_void *padapter,
+					 pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(t_void *padapter);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(t_void *padapter);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(t_void *padapter);
+
+/** Rx process */
+mlan_status mlan_rx_process(t_void *padapter, t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(t_void *padapter, pmlan_buffer pmbuf);
+
+#ifdef USB
+/** mlan_write_data_async_complete */
+MLAN_API mlan_status mlan_write_data_async_complete(t_void *padapter,
+						    pmlan_buffer pmbuf,
+						    t_u32 port,
+						    mlan_status status);
+
+/** Packet Reception */
+MLAN_API mlan_status mlan_recv(t_void *padapter, pmlan_buffer pmbuf,
+			       t_u32 port);
+#endif /* USB */
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(t_void *padapter,
+					       pmlan_buffer pmbuf,
+					       mlan_status status);
+
+/** handle amsdu deaggregated packet */
+void mlan_process_deaggr_pkt(t_void *padapter, pmlan_buffer pmbuf, t_u8 *drop);
+
+#if defined(SDIO) || defined(PCIE)
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(t_u16 msg_id, t_void *padapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+#endif /* SDIO || PCIE */
+
+MLAN_API t_void mlan_pm_wakeup_card(t_void *padapter, t_u8 keep_wakeup);
+
+MLAN_API t_u8 mlan_is_main_process_running(t_void *adapter);
+#ifdef PCIE
+MLAN_API t_void mlan_set_int_mode(t_void *adapter, t_u32 int_mode,
+				  t_u8 func_num);
+#endif
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(t_void *padapter, pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(t_void *padapter, t_u8 bss_num, t_u8 tid);
+
+/** mlan mask host interrupt */
+MLAN_API mlan_status mlan_disable_host_int(t_void *padapter);
+/** mlan unmask host interrupt */
+MLAN_API mlan_status mlan_enable_host_int(t_void *padapter);
+
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8987/mlan/mlan_fw.h b/wlan_sd8987/mlan/mlan_fw.h
new file mode 100755
index 0000000..f3cc13e
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_fw.h
@@ -0,0 +1,7780 @@
+/** @file mlan_fw.h
+ *
+ *  @brief This file contains firmware specific defines.
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/27/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_FW_H_
+#define _MLAN_FW_H_
+
+/** Interface header length */
+#ifdef USB
+#define USB_INTF_HEADER_LEN 0
+#endif /* USB */
+#ifdef SDIO
+#define SDIO_INTF_HEADER_LEN 4
+#endif /* SDIO */
+#ifdef PCIE
+#define PCIE_INTF_HEADER_LEN 4
+#endif /* PCIE */
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+#define WPA_GCMP_KEY_LEN 32
+
+#define WPA_CCMP_256_KEY_LEN 32
+
+/** Ethernet header */
+typedef MLAN_PACK_START struct {
+	/** Ethernet header destination address */
+	t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Ethernet header source address */
+	t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Ethernet header length */
+	t_u16 h803_len;
+
+} MLAN_PACK_END Eth803Hdr_t;
+
+/** RFC 1042 header */
+typedef MLAN_PACK_START struct {
+	/** LLC DSAP */
+	t_u8 llc_dsap;
+	/** LLC SSAP */
+	t_u8 llc_ssap;
+	/** LLC CTRL */
+	t_u8 llc_ctrl;
+	/** SNAP OUI */
+	t_u8 snap_oui[3];
+	/** SNAP type */
+	t_u16 snap_type;
+
+} MLAN_PACK_END Rfc1042Hdr_t;
+
+/** Rx packet header */
+typedef MLAN_PACK_START struct {
+	/** Etherner header */
+	Eth803Hdr_t eth803_hdr;
+	/** RFC 1042 header */
+	Rfc1042Hdr_t rfc1042_hdr;
+
+} MLAN_PACK_END RxPacketHdr_t;
+
+/** Rates supported in band B */
+#define B_SUPPORTED_RATES 5
+/** Rates supported in band G */
+#define G_SUPPORTED_RATES 9
+/** Rates supported in band BG */
+#define BG_SUPPORTED_RATES 13
+
+/** Setup the number of rates passed in the driver/firmware API */
+#define A_SUPPORTED_RATES 9
+
+/** CapInfo Short Slot Time Disabled */
+/* #define SHORT_SLOT_TIME_DISABLED(CapInfo)
+ * ((IEEEtypes_CapInfo_t)(CapInfo).short_slot_time = 0) */
+#define SHORT_SLOT_TIME_DISABLED(CapInfo) (CapInfo &= ~MBIT(10))
+/** CapInfo Short Slot Time Enabled */
+#define SHORT_SLOT_TIME_ENABLED(CapInfo) (CapInfo |= MBIT(10))
+/** CapInfo Spectrum Mgmt Disabled */
+#define SPECTRUM_MGMT_DISABLED(CapInfo) (CapInfo &= ~MBIT(8))
+/** CapInfo Spectrum Mgmt Enabled */
+#define SPECTRUM_MGMT_ENABLED(CapInfo) (CapInfo |= MBIT(8))
+/** CapInfo Radio Measurement Disabled */
+#define RADIO_MEASUREMENT_DISABLED(CapInfo) (CapInfo &= ~MBIT(12))
+/** CapInfo Radio Measurement Enabled */
+#define RADIO_MEASUREMENT_ENABLED(CapInfo) (CapInfo |= MBIT(12))
+
+/** Setup the number of rates passed in the driver/firmware API */
+#define HOSTCMD_SUPPORTED_RATES 14
+
+/** Rates supported in band N */
+#define N_SUPPORTED_RATES 3
+#ifdef STA_SUPPORT
+/** All bands (B, G, N, AAC, GAC) */
+#define ALL_802_11_BANDS                                                       \
+	(BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AAC | BAND_GAC)
+#else
+/** All bands (B, G, A) */
+#define ALL_802_11_BANDS (BAND_B | BAND_G | BAND_A)
+#endif /* STA_SUPPORT */
+
+#ifdef STA_SUPPORT
+/** Firmware multiple bands support */
+#define FW_MULTI_BANDS_SUPPORT                                                 \
+	(MBIT(8) | MBIT(9) | MBIT(10) | MBIT(11) | MBIT(12) | MBIT(13))
+#else
+/** Firmware multiple bands support */
+#define FW_MULTI_BANDS_SUPPORT (MBIT(8) | MBIT(9) | MBIT(10))
+#endif /* STA_SUPPORT */
+/** Check if multiple bands support is enabled in firmware */
+#define IS_SUPPORT_MULTI_BANDS(_adapter)                                       \
+	(_adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT)
+/** Get default bands of the firmware */
+/* need to shift bit 12 and bit 13 in fw_cap_info from the firmware
+ * to bit 13 and 14 for 11ac so that bit 11 is for GN, bit 12 for AN,
+ * bit 13 for GAC, and bit 14 for AAC, in order to be compatible with
+ * the band capability defined in the driver after right shift of 8 bits */
+#define GET_FW_DEFAULT_BANDS(_adapter)                                         \
+	(((((_adapter->fw_cap_info & 0x3000) << 1) |                           \
+	   (_adapter->fw_cap_info & ~0xF000)) >>                               \
+	  8) &                                                                 \
+	 ALL_802_11_BANDS)
+
+extern t_u8 SupportedRates_B[B_SUPPORTED_RATES];
+extern t_u8 SupportedRates_G[G_SUPPORTED_RATES];
+extern t_u8 SupportedRates_BG[BG_SUPPORTED_RATES];
+extern t_u8 SupportedRates_A[A_SUPPORTED_RATES];
+extern t_u8 SupportedRates_N[N_SUPPORTED_RATES];
+extern t_u8 AdhocRates_G[G_SUPPORTED_RATES];
+extern t_u8 AdhocRates_B[B_SUPPORTED_RATES];
+extern t_u8 AdhocRates_BG[BG_SUPPORTED_RATES];
+extern t_u8 AdhocRates_A[A_SUPPORTED_RATES];
+
+/** Default auto deep sleep mode */
+#define DEFAULT_AUTO_DS_MODE MTRUE
+/** Default power save mode */
+#define DEFAULT_PS_MODE Wlan802_11PowerModePSP
+
+/** WEP Key index mask */
+#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff
+/** Length of WEP 40 bit key */
+#define WEP_40_BIT_LEN 5
+/** Length of WEP 104 bit key */
+#define WEP_104_BIT_LEN 13
+
+/** Key information enabled */
+#define KEY_INFO_ENABLED 0x01
+/** KEY_TYPE_ID */
+typedef enum _KEY_TYPE_ID {
+	/** Key type : WEP */
+	KEY_TYPE_ID_WEP = 0,
+	/** Key type : TKIP */
+	KEY_TYPE_ID_TKIP = 1,
+	/** Key type : AES */
+	KEY_TYPE_ID_AES = 2,
+	KEY_TYPE_ID_WAPI = 3,
+	KEY_TYPE_ID_AES_CMAC = 4,
+	/** Key type : GCMP */
+	KEY_TYPE_ID_GCMP = 5,
+	/** Key type : GCMP_256 */
+	KEY_TYPE_ID_GCMP_256 = 6,
+	/** Key type : CCMP_256 */
+	KEY_TYPE_ID_CCMP_256 = 7,
+	/** Key type : GMAC_128 */
+	KEY_TYPE_ID_BIP_GMAC_128 = 8,
+	/** Key type : GMAC_256 */
+	KEY_TYPE_ID_BIP_GMAC_256 = 9,
+} KEY_TYPE_ID;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY 0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY 0x02
+
+/** KEY_INFO_WEP*/
+typedef enum _KEY_INFO_WEP {
+	KEY_INFO_WEP_MCAST = 0x01,
+	KEY_INFO_WEP_UNICAST = 0x02,
+	KEY_INFO_WEP_ENABLED = 0x04
+} KEY_INFO_WEP;
+
+/** KEY_INFO_TKIP */
+typedef enum _KEY_INFO_TKIP {
+	KEY_INFO_TKIP_MCAST = 0x01,
+	KEY_INFO_TKIP_UNICAST = 0x02,
+	KEY_INFO_TKIP_ENABLED = 0x04
+} KEY_INFO_TKIP;
+
+/** KEY_INFO_AES*/
+typedef enum _KEY_INFO_AES {
+	KEY_INFO_AES_MCAST = 0x01,
+	KEY_INFO_AES_UNICAST = 0x02,
+	KEY_INFO_AES_ENABLED = 0x04,
+	KEY_INFO_AES_MCAST_IGTK = 0x400,
+} KEY_INFO_AES;
+
+/** WPA AES key length */
+#define WPA_AES_KEY_LEN 16
+/** WPA TKIP key length */
+#define WPA_TKIP_KEY_LEN 32
+/** WPA AES IGTK key length */
+#define CMAC_AES_KEY_LEN 16
+/** IGTK key length */
+#define WPA_IGTK_KEY_LEN 16
+#define WPA_IGTK_256_KEY_LEN 32
+
+/** WAPI key length */
+#define WAPI_KEY_LEN 50
+/** KEY_INFO_WAPI*/
+typedef enum _KEY_INFO_WAPI {
+	KEY_INFO_WAPI_MCAST = 0x01,
+	KEY_INFO_WAPI_UNICAST = 0x02,
+	KEY_INFO_WAPI_ENABLED = 0x04
+} KEY_INFO_WAPI;
+
+/** Maximum ethernet frame length sans FCS */
+#define MV_ETH_FRAME_LEN 1514
+
+#if defined(SDIO) || defined(PCIE)
+/** Length of SNAP header */
+#define MRVDRV_SNAP_HEADER_LEN 8
+
+/** The number of times to try when polling for status bits */
+#define MAX_POLL_TRIES 100
+
+/** The number of times to try when waiting for downloaded firmware to
+     become active when multiple interface is present */
+#define MAX_MULTI_INTERFACE_POLL_TRIES 150
+/** The number of times to try when waiting for downloaded firmware to
+     become active. (polling the scratch register). */
+#define MAX_FIRMWARE_POLL_TRIES 100
+
+/** FW fill in rx_len with extra 204 bytes */
+#define EXTRA_LEN 256
+
+/** Buffer size for ethernet Tx packets */
+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE                                       \
+	(MV_ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN)
+
+/** Buffer size for ethernet Rx packets */
+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE                                       \
+	(MV_ETH_FRAME_LEN + sizeof(RxPD) + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
+#endif /* SDIO || PCIE */
+
+#ifdef SDIO
+/* Macros in interface module */
+/** Firmware ready */
+#define SDIO_FIRMWARE_READY 0xfedc
+#endif /* SDIO */
+
+#ifdef PCIE
+/* Macros in interface module */
+/** Firmware ready */
+#define PCIE_FIRMWARE_READY 0xfedcba00
+#endif
+
+/** Enumeration definition*/
+/** WLAN_802_11_PRIVACY_FILTER */
+typedef enum _WLAN_802_11_PRIVACY_FILTER {
+	Wlan802_11PrivFilterAcceptAll,
+	Wlan802_11PrivFilter8021xWEP
+} WLAN_802_11_PRIVACY_FILTER;
+
+/** WLAN_802_11_WEP_STATUS */
+typedef enum _WLAN_802_11_WEP_STATUS {
+	Wlan802_11WEPEnabled,
+	Wlan802_11WEPDisabled,
+	Wlan802_11WEPKeyAbsent,
+	Wlan802_11WEPNotSupported
+} WLAN_802_11_WEP_STATUS;
+
+/** SNR calculation */
+#define CAL_SNR(RSSI, NF) ((t_s16)((t_s16)(RSSI) - (t_s16)(NF)))
+
+/** 2K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_2K 2048
+
+/** Terminating TLV Type */
+#define MRVL_TERMINATE_TLV_ID 0xffff
+
+/** TLV type : SSID */
+#define TLV_TYPE_SSID 0x0000
+/** TLV type : Rates */
+#define TLV_TYPE_RATES 0x0001
+/** TLV type : PHY FH */
+#define TLV_TYPE_PHY_FH 0x0002
+/** TLV type : PHY DS */
+#define TLV_TYPE_PHY_DS 0x0003
+/** TLV type : CF */
+#define TLV_TYPE_CF 0x0004
+/** TLV type : IBSS */
+#define TLV_TYPE_IBSS 0x0006
+
+/** TLV type : Domain */
+#define TLV_TYPE_DOMAIN 0x0007
+
+/** TLV type : Power constraint */
+#define TLV_TYPE_POWER_CONSTRAINT 0x0020
+
+/** TLV type : Power capability */
+#define TLV_TYPE_POWER_CAPABILITY 0x0021
+
+#define TLV_TYPE_HT_CAPABILITY 0x002d
+
+#define TLV_TYPE_EXTENSION_ID 0x00ff
+
+/**TLV type : Host MLME Flag*/
+#define TLV_TYPE_HOST_MLME (PROPRIETARY_TLV_BASE_ID + 307)
+
+/** TLV type : AP wacp mode */
+#define TLV_TYPE_UAP_WACP_MODE (PROPRIETARY_TLV_BASE_ID + 0x147)	/* 0x0247 */
+
+/** TLV type : Vendor Specific IE */
+#define TLV_TYPE_VENDOR_SPECIFIC_IE 0x00dd
+
+/** TLV type : Key material */
+#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0x00)	/* 0x0100 */
+/** TLV type : Channel list */
+#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 0x01)	/* 0x0101 */
+/** TLV type : Number of probes */
+#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 0x02)	/* 0x0102 */
+/** TLV type : Beacon RSSI low */
+#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 0x04)	/* 0x0104 */
+/** TLV type : Beacon SNR low */
+#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 0x05)	/* 0x0105 */
+/** TLV type : Fail count */
+#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 0x06)	/* 0x0106 */
+/** TLV type : BCN miss */
+#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 0x07)	/* 0x0107 */
+/** TLV type : LED behavior */
+#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 0x09)	/* 0x0109 */
+/** TLV type : Passthrough */
+#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 0x0a)	/* 0x010a */
+/** TLV type : Power TBL 2.4 Ghz */
+#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 0x0c)	/* 0x010c   \
+									 */
+/** TLV type : Power TBL 5 GHz */
+#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 0x0d)	/* 0x010d */
+/** TLV type : WMM queue status */
+#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 0x10)	/* 0x0110 */
+/** TLV type : Wildcard SSID */
+#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 0x12)	/* 0x0112 */
+/** TLV type : TSF timestamp */
+#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 0x13)	/* 0x0113 */
+/** TLV type : ARP filter */
+#define TLV_TYPE_ARP_FILTER (PROPRIETARY_TLV_BASE_ID + 0x15)	/* 0x0115 */
+/** TLV type : Beacon RSSI high */
+#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 0x16)	/* 0x0116 */
+/** TLV type : Beacon SNR high */
+#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 0x17)	/* 0x0117 */
+/** TLV type : Start BG scan later */
+#define TLV_TYPE_STARTBGSCANLATER (PROPRIETARY_TLV_BASE_ID + 0x1e)	/* 0x011e   \
+									 */
+/** TLV type: BG scan repeat count */
+#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 0xb0)	/* 0x01b0 */
+/** TLV type : Authentication type */
+#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 0x1f)	/* 0x011f */
+/** TLV type : BSSID */
+#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 0x23)	/* 0x0123 */
+
+/** TLV type : Link Quality */
+#define TLV_TYPE_LINK_QUALITY (PROPRIETARY_TLV_BASE_ID + 0x24)	/* 0x0124 */
+
+/** TLV type : Data RSSI low */
+#define TLV_TYPE_RSSI_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x26)	/* 0x0126 */
+/** TLV type : Data SNR low */
+#define TLV_TYPE_SNR_LOW_DATA (PROPRIETARY_TLV_BASE_ID + 0x27)	/* 0x0127 */
+/** TLV type : Data RSSI high */
+#define TLV_TYPE_RSSI_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x28)	/* 0x0128 */
+/** TLV type : Data SNR high */
+#define TLV_TYPE_SNR_HIGH_DATA (PROPRIETARY_TLV_BASE_ID + 0x29)	/* 0x0129 */
+
+/** TLV type : Channel band list */
+#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 0x2a)	/* 0x012a */
+
+/** TLV type : Security Cfg */
+#define TLV_TYPE_SECURITY_CFG (PROPRIETARY_TLV_BASE_ID + 0x3a)	/* 0x013a */
+
+/** TLV type : Passphrase */
+#define TLV_TYPE_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 0x3c)	/* 0x013c */
+/** TLV type : SAE Password */
+#define TLV_TYPE_SAE_PASSWORD (PROPRIETARY_TLV_BASE_ID + 0x141)	/* 0x0241 */
+/** TLV type : SAE PWE Derivation Mode */
+#define TLV_TYPE_WPA3_SAE_PWE_DERIVATION_MODE (PROPRIETARY_TLV_BASE_ID + 339)	/* 0x0100 + 0x153 */
+/** TLV type : Encryption Protocol TLV */
+#define TLV_TYPE_ENCRYPTION_PROTO (PROPRIETARY_TLV_BASE_ID + 0x40)	/* 0x0140   \
+									 */
+/** TLV type : Cipher TLV */
+#define TLV_TYPE_CIPHER (PROPRIETARY_TLV_BASE_ID + 0x42)	/* 0x0142 */
+/** TLV type : PMK */
+#define TLV_TYPE_PMK (PROPRIETARY_TLV_BASE_ID + 0x44)	/* 0x0144 */
+
+/** TLV type : BCN miss */
+#define TLV_TYPE_PRE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 0x49)	/* 0x0149 */
+
+/** TLV type: WAPI IE */
+#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 0x5e)	/* 0x015e */
+
+/** TLV type: MGMT IE */
+#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 0x69)	/* 0x0169 */
+/** TLV type: MAX_MGMT_IE */
+#define TLV_TYPE_MAX_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 0xaa)	/* 0x01aa */
+
+/** TLV type: key param v2 */
+#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 0x9C)	/* 0x019C */
+
+/** TLV type: ps params in hs */
+#define TLV_TYPE_PS_PARAMS_IN_HS (PROPRIETARY_TLV_BASE_ID + 0xB5)	/* 0x01b5 */
+/** TLV type: hs wake hold off */
+#define TLV_TYPE_HS_WAKE_HOLDOFF (PROPRIETARY_TLV_BASE_ID + 0xB6)	/* 0x01b6 */
+/** TLV type: wake up source */
+#define TLV_TYPE_HS_WAKEUP_SOURCE_GPIO                                         \
+	(PROPRIETARY_TLV_BASE_ID + 0x105)	/* 0x0205 */
+/** TLV type: management filter  */
+#define TLV_TYPE_MGMT_FRAME_WAKEUP                                             \
+	(PROPRIETARY_TLV_BASE_ID + 0x116)	/* 0x0216 */
+/** TLV type: extend wakeup source */
+#define TLV_TYPE_WAKEUP_EXTEND (PROPRIETARY_TLV_BASE_ID + 0x118)	/* 0x0218 */
+/** TLV type: HS antenna mode */
+#define TLV_TYPE_HS_ANTMODE (PROPRIETARY_TLV_BASE_ID + 0x119)	/* 0x0219 */
+
+/** TLV type: robustcoex mode */
+#define TLV_TYPE_ROBUSTCOEX (PROPRIETARY_TLV_BASE_ID + 0x11B)	/* 0x021B */
+
+#define TLV_TYPE_DMCS_STATUS (PROPRIETARY_TLV_BASE_ID + 0x13A)	/* 0x023A */
+
+/** TLV type : TDLS IDLE TIMEOUT */
+#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 0xC2)	/* 0x01C2  \
+									 */
+
+/** TLV type : HT Capabilities */
+#define TLV_TYPE_HT_CAP (PROPRIETARY_TLV_BASE_ID + 0x4a)	/* 0x014a */
+/** TLV type : HT Information */
+#define TLV_TYPE_HT_INFO (PROPRIETARY_TLV_BASE_ID + 0x4b)	/* 0x014b */
+/** TLV type : Secondary Channel Offset */
+#define TLV_SECONDARY_CHANNEL_OFFSET                                           \
+	(PROPRIETARY_TLV_BASE_ID + 0x4c)	/* 0x014c */
+/** TLV type : 20/40 BSS Coexistence */
+#define TLV_TYPE_2040BSS_COEXISTENCE                                           \
+	(PROPRIETARY_TLV_BASE_ID + 0x4d)	/* 0x014d */
+/** TLV type : Overlapping BSS Scan Parameters */
+#define TLV_TYPE_OVERLAP_BSS_SCAN_PARAM                                        \
+	(PROPRIETARY_TLV_BASE_ID + 0x4e)	/* 0x014e */
+/** TLV type : Extended capabilities */
+#define TLV_TYPE_EXTCAP (PROPRIETARY_TLV_BASE_ID + 0x4f)	/* 0x014f */
+/** TLV type : Set of MCS values that STA desires to use within the BSS */
+#define TLV_TYPE_HT_OPERATIONAL_MCS_SET                                        \
+	(PROPRIETARY_TLV_BASE_ID + 0x50)	/* 0x0150 */
+/** TLV ID : Management Frame */
+#define TLV_TYPE_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 0x68)	/* 0x0168 */
+/** TLV type : RXBA_SYNC */
+#define TLV_TYPE_RXBA_SYNC (PROPRIETARY_TLV_BASE_ID + 0x99)	/* 0x0199 */
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** TLV type : AP PSK */
+#define TLV_TYPE_UAP_PSK (PROPRIETARY_TLV_BASE_ID + 0xa8)	/* 0x01a8 */
+/** TLV type : p2p NOA */
+#define TLV_TYPE_WIFI_DIRECT_NOA (PROPRIETARY_TLV_BASE_ID + 0x83)
+/** TLV type : p2p opp ps */
+#define TLV_TYPE_WIFI_DIRECT_OPP_PS (PROPRIETARY_TLV_BASE_ID + 0x84)
+#endif /* WIFI_DIRECT_SUPPORT */
+/** TLV type : GPIO TSF LATCH CONFIG */
+#define TLV_TYPE_GPIO_TSF_LATCH_CONFIG (PROPRIETARY_TLV_BASE_ID + 0x153)
+/** TLV type : GPIO TSF LATCH REPORT*/
+#define TLV_TYPE_GPIO_TSF_LATCH_REPORT (PROPRIETARY_TLV_BASE_ID + 0x154)
+
+/** TLV : 20/40 coex config */
+#define TLV_TYPE_2040_BSS_COEX_CONTROL                                         \
+	(PROPRIETARY_TLV_BASE_ID + 0x98)	/* 0x0198 */
+
+/** TLV type :  aggr win size */
+#define TLV_BTCOEX_WL_AGGR_WINSIZE (PROPRIETARY_TLV_BASE_ID + 0xca)
+/** TLV type :  scan time */
+#define TLV_BTCOEX_WL_SCANTIME (PROPRIETARY_TLV_BASE_ID + 0Xcb)
+/** TLV type : Ewpa_eapol_pkt */
+#define TLV_TYPE_EAPOL_PKT (PROPRIETARY_TLV_BASE_ID + 0xcf)
+
+#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 0x9a)
+
+/** TLV type :  EES Configuration */
+#define TLV_TYPE_EES_CFG (PROPRIETARY_TLV_BASE_ID + 0xda)
+/** TLV type :  EES Network Configuration */
+#define TLV_TYPE_EES_NET_CFG (PROPRIETARY_TLV_BASE_ID + 0xdb)
+
+#define TLV_TYPE_LL_STAT_IFACE (PROPRIETARY_TLV_BASE_ID + 300)
+#define TLV_TYPE_LL_STAT_RADIO (PROPRIETARY_TLV_BASE_ID + 301)
+
+/** TLV type: fw cap info */
+#define TLV_TYPE_FW_CAP_INFO (PROPRIETARY_TLV_BASE_ID + 318)
+
+/** ADDBA TID mask */
+#define ADDBA_TID_MASK (MBIT(2) | MBIT(3) | MBIT(4) | MBIT(5))
+/** DELBA TID mask */
+#define DELBA_TID_MASK (MBIT(12) | MBIT(13) | MBIT(14) | MBIT(15))
+/** ADDBA Starting Sequence Number Mask */
+#define SSN_MASK 0xfff0
+
+/** Block Ack result status */
+/** Block Ack Result : Success */
+#define BA_RESULT_SUCCESS 0x0
+/** Block Ack Result : Execution failure */
+#define BA_RESULT_FAILURE 0x1
+/** Block Ack Result : Timeout */
+#define BA_RESULT_TIMEOUT 0x2
+/** Block Ack Result : Data invalid */
+#define BA_RESULT_DATA_INVALID 0x3
+
+/** Get the baStatus (NOT_SETUP, COMPLETE, IN_PROGRESS)
+ *  in Tx BA stream table */
+#define IS_BASTREAM_SETUP(ptr) (ptr->ba_status)
+
+/** An AMPDU/AMSDU could be disallowed for certain TID. 0xff means
+ *  no aggregation is enabled for the assigned TID */
+#define BA_STREAM_NOT_ALLOWED 0xff
+
+#ifdef STA_SUPPORT
+#endif
+
+/** Test if 11n is enabled by checking the HTCap IE */
+#define IS_11N_ENABLED(priv)                                                   \
+	((priv->config_bands & BAND_GN || priv->config_bands & BAND_AN) &&     \
+	 priv->curr_bss_params.bss_descriptor.pht_cap &&                       \
+	 !priv->curr_bss_params.bss_descriptor.disable_11n)
+/** Find out if we are the initiator or not */
+#define INITIATOR_BIT(DelBAParamSet)                                           \
+	(((DelBAParamSet)&MBIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
+
+/** 4K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_4K 4096
+/** 8K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_8K 8192
+/** 12K buf size */
+#define MLAN_TX_DATA_BUF_SIZE_12K 12288
+/** Max Rx AMPDU Size */
+#define MAX_RX_AMPDU_SIZE_64K 0x03
+/** Non green field station */
+#define NON_GREENFIELD_STAS 0x04
+
+/** Max AMSDU size support */
+#define HWSPEC_MAX_AMSDU_SUPP MBIT(31)
+/** Greenfield support */
+#define HWSPEC_GREENFIELD_SUPP MBIT(29)
+/** SM Power Save enable */
+#define CAPINFO_SMPS_ENABLE MBIT(27)
+/** RX STBC support */
+#define HWSPEC_RXSTBC_SUPP MBIT(26)
+/** ShortGI @ 40Mhz support */
+#define HWSPEC_SHORTGI40_SUPP MBIT(24)
+/** ShortGI @ 20Mhz support */
+#define HWSPEC_SHORTGI20_SUPP MBIT(23)
+/** RX LDPC support */
+#define HWSPEC_LDPC_SUPP MBIT(22)
+/** Channel width 40Mhz support */
+#define HWSPEC_CHANBW40_SUPP MBIT(17)
+/** SM Power Save mode */
+#define CAPINFO_SMPS_MODE MBIT(9)
+/** 40Mhz intolarent enable */
+#define CAPINFO_40MHZ_INTOLARENT MBIT(8)
+
+/** Default 11n capability mask for 2.4GHz */
+#define DEFAULT_11N_CAP_MASK_BG                                                \
+	(HWSPEC_SHORTGI20_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+/** Default 11n capability mask for 5GHz */
+#define DEFAULT_11N_CAP_MASK_A                                                 \
+	(HWSPEC_CHANBW40_SUPP | HWSPEC_SHORTGI20_SUPP|HWSPEC_MAX_AMSDU_SUPP |                        \
+	 HWSPEC_SHORTGI40_SUPP | HWSPEC_RXSTBC_SUPP | HWSPEC_LDPC_SUPP)
+
+/** Default 11n TX BF capability 2X2 chip **/
+#define DEFAULT_11N_TX_BF_CAP_2X2 0x19E74618
+/** Default 11n TX BF capability 1X1 chip **/
+#define DEFAULT_11N_TX_BF_CAP_1X1 0x19E74608
+
+/** Bits to ignore in hw_dev_cap as these bits are set in get_hw_spec */
+#define IGN_HW_DEV_CAP (CAPINFO_40MHZ_INTOLARENT | (CAPINFO_SMPS_ENABLE | CAPINFO_SMPS_MODE))
+
+/** HW_SPEC FwCapInfo : If FW support RSN Replay Detection */
+#define ISSUPP_RSN_REPLAY_DETECTION(FwCapInfo) (FwCapInfo & MBIT(28))
+
+/** HW_SPEC FwCapInfo */
+#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & MBIT(11))
+
+/** HW_SPEC Dot11nDevCap : MAX AMSDU supported */
+#define ISSUPP_MAXAMSDU(Dot11nDevCap) (Dot11nDevCap & MBIT(31))
+/** HW_SPEC Dot11nDevCap : Beamforming support */
+#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & MBIT(30))
+/** HW_SPEC Dot11nDevCap : Green field support */
+#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & MBIT(29))
+/** HW_SPEC Dot11nDevCap : AMPDU support */
+#define ISSUPP_AMPDU(Dot11nDevCap) (Dot11nDevCap & MBIT(28))
+/** HW_SPEC Dot11nDevCap : MIMO PS support  */
+#define ISSUPP_MIMOPS(Dot11nDevCap) (Dot11nDevCap & MBIT(27))
+/** HW_SPEC Dot11nDevCap : Rx STBC support */
+#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(26))
+/** HW_SPEC Dot11nDevCap : Tx STBC support */
+#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & MBIT(25))
+/** HW_SPEC Dot11nDevCap : Short GI @ 40Mhz support */
+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
+/** HW_SPEC Dot11nDevCap : Reset Short GI @ 40Mhz support */
+#define RESETSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(24))
+/** HW_SPEC Dot11nDevCap : Short GI @ 20Mhz support */
+#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & MBIT(23))
+/** HW_SPEC Dot11nDevCap : Rx LDPC support */
+#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & MBIT(22))
+/** HW_SPEC Dot11nDevCap : Number of TX BA streams supported */
+#define ISSUPP_GETTXBASTREAM(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF)
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 40Mhz  support */
+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 20Mhz  support */
+#define ISSUPP_CHANWIDTH20(Dot11nDevCap) (Dot11nDevCap & MBIT(16))
+/** HW_SPEC Dot11nDevCap : Channel BW support @ 10Mhz  support */
+#define ISSUPP_CHANWIDTH10(Dot11nDevCap) (Dot11nDevCap & MBIT(15))
+/** Dot11nUsrCap : SMPS static/dynamic mode if BIT27 MIMO PS support eanbled */
+#define ISSUPP_SMPS_DYNAMIC_MODE(Dot11nDevCap) (Dot11nDevCap & MBIT(9))
+/** Dot11nUsrCap : 40Mhz intolarance enabled */
+#define ISENABLED_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap & MBIT(8))
+/** Dot11nUsrCap : Reset 40Mhz intolarance enabled */
+#define RESET_40MHZ_INTOLARENT(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(8))
+/** HW_SPEC Dot11nDevCap : Rx AntennaD support */
+#define ISSUPP_RXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(7))
+/** HW_SPEC Dot11nDevCap : Rx AntennaC support */
+#define ISSUPP_RXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(6))
+/** HW_SPEC Dot11nDevCap : Rx AntennaB support */
+#define ISSUPP_RXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(5))
+/** HW_SPEC Dot11nDevCap : Rx AntennaA support */
+#define ISSUPP_RXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(4))
+/** HW_SPEC Dot11nDevCap : Tx AntennaD support */
+#define ISSUPP_TXANTENNAD(Dot11nDevCap) (Dot11nDevCap & MBIT(3))
+/** HW_SPEC Dot11nDevCap : Tx AntennaC support */
+#define ISSUPP_TXANTENNAC(Dot11nDevCap) (Dot11nDevCap & MBIT(2))
+/** HW_SPEC Dot11nDevCap : Tx AntennaB support */
+#define ISSUPP_TXANTENNAB(Dot11nDevCap) (Dot11nDevCap & MBIT(1))
+/** HW_SPEC Dot11nDevCap : Tx AntennaA support */
+#define ISSUPP_TXANTENNAA(Dot11nDevCap) (Dot11nDevCap & MBIT(0))
+
+/** HW_SPEC Dot11nDevCap : Set support of channel bw @ 40Mhz */
+#define SETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap |= MBIT(17))
+/** HW_SPEC Dot11nDevCap : Reset support of channel bw @ 40Mhz */
+#define RESETSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap &= ~MBIT(17))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_TXMCSSUPP(DevMCSSupported) (DevMCSSupported >> 4)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
+
+/** GET HTCapInfo : Supported Channel BW */
+#define GETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo & MBIT(1))
+/** GET HTCapInfo : Support for Greenfield */
+#define GETHT_GREENFIELD(HTCapInfo) (HTCapInfo & MBIT(4))
+/** GET HTCapInfo : Support for Short GI @ 20Mhz */
+#define GETHT_SHORTGI20(HTCapInfo) (HTCapInfo & MBIT(5))
+/** GET HTCapInfo : Support for Short GI @ 40Mhz */
+#define GETHT_SHORTGI40(HTCapInfo) (HTCapInfo & MBIT(6))
+/** GET HTCapInfo : Support for Tx STBC */
+#define GETHT_TXSTBC(HTCapInfo) (HTCapInfo & MBIT(7))
+
+/** GET HTCapInfo : Support for Rx STBC */
+#define GETHT_RXSTBC(HTCapInfo) ((HTCapInfo >> 8) & 0x03)
+/** GET HTCapInfo : Support for Delayed ACK */
+#define GETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo & MBIT(10))
+/** GET HTCapInfo : Support for Max AMSDU */
+#define GETHT_MAXAMSDU(HTCapInfo) (HTCapInfo & MBIT(11))
+
+/** GET HTCapInfo : Support 40Mhz Intolarence */
+#define GETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo & MBIT(14))
+
+/** SET HTCapInfo : Set support for LDPC coding capability */
+#define SETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo |= MBIT(0))
+/** SET HTCapInfo : Set support for Channel BW */
+#define SETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo |= MBIT(1))
+/** SET HTCapInfo : Set support for Greenfield */
+#define SETHT_GREENFIELD(HTCapInfo) (HTCapInfo |= MBIT(4))
+/** SET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define SETHT_SHORTGI20(HTCapInfo) (HTCapInfo |= MBIT(5))
+/** SET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define SETHT_SHORTGI40(HTCapInfo) (HTCapInfo |= MBIT(6))
+/** SET HTCapInfo : Set support for Tx STBC */
+#define SETHT_TXSTBC(HTCapInfo) (HTCapInfo |= MBIT(7))
+/** SET HTCapInfo : Set support for Rx STBC */
+#define SETHT_RXSTBC(HTCapInfo, value) (HTCapInfo |= (value << 8))
+/** SET HTCapInfo : Set support for delayed block ack */
+#define SETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo |= MBIT(10))
+/** SET HTCapInfo : Set support for Max size AMSDU */
+#define SETHT_MAXAMSDU(HTCapInfo) (HTCapInfo |= MBIT(11))
+/** SET HTCapInfo : Set support for DSSS/CCK Rates @ 40Mhz */
+#define SETHT_DSSSCCK40(HTCapInfo) (HTCapInfo |= MBIT(12))
+/** SET HTCapInfo : Enable 40Mhz Intolarence */
+#define SETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo |= MBIT(14))
+
+/** SET HTCapInfo : Set SM power save disabled */
+#define SETHT_SMPS_DISABLE(HTCapInfo) ((HTCapInfo) |= (MBIT(2) | MBIT(3)))
+/** SET HTCapInfo : Set Dynamic SM power save */
+#define SETHT_SMPS_DYNAMIC(HTCapInfo) ((HTCapInfo) |= MBIT(2))
+
+/** RESET HTCapInfo : Set support for LDPC coding capability */
+#define RESETHT_LDPCCODINGCAP(HTCapInfo) (HTCapInfo &= ~MBIT(0))
+/** RESET HTCapInfo : Set support for Channel BW */
+#define RESETHT_SUPPCHANWIDTH(HTCapInfo) (HTCapInfo &= ~MBIT(1))
+/** RESET HTCapInfo : Set support for Greenfield */
+#define RESETHT_GREENFIELD(HTCapInfo) (HTCapInfo &= ~MBIT(4))
+/** RESET HTCapInfo : Set support for Short GI @ 20Mhz */
+#define RESETHT_SHORTGI20(HTCapInfo) (HTCapInfo &= ~MBIT(5))
+/** RESET HTCapInfo : Set support for Short GI @ 40Mhz */
+#define RESETHT_SHORTGI40(HTCapInfo) (HTCapInfo &= ~MBIT(6))
+/** RESET HTCapInfo : Set support for Tx STBC */
+#define RESETHT_TXSTBC(HTCapInfo) (HTCapInfo &= ~MBIT(7))
+/** RESET HTCapInfo : Set support for Rx STBC */
+#define RESETHT_RXSTBC(HTCapInfo) (HTCapInfo &= ~(0x03 << 8))
+/** RESET HTCapInfo : Set support for delayed block ack */
+#define RESETHT_DELAYEDBACK(HTCapInfo) (HTCapInfo &= ~MBIT(10))
+/** RESET HTCapInfo : Set support for Max size AMSDU */
+#define RESETHT_MAXAMSDU(HTCapInfo) (HTCapInfo &= ~MBIT(11))
+/** RESET HTCapInfo : Disable 40Mhz Intolarence */
+#define RESETHT_40MHZ_INTOLARANT(HTCapInfo) (HTCapInfo &= ~MBIT(14))
+/** RESET HTCapInfo: Enable SM power save */
+#define RESETHT_SM_POWERSAVE(HTCapInfo) ((HTCapInfo) &= ~(MBIT(2) | MBIT(3)))
+/** RESET HTExtCap : Clear RD Responder bit */
+#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~MBIT(11))
+/** SET MCS32 */
+#define SETHT_MCS32(x) (x[4] |= 1)
+/** Set mcs set defined bit */
+#define SETHT_MCS_SET_DEFINED(x) (x[12] |= 1)
+/** Set the highest Rx data rate */
+#define SETHT_RX_HIGHEST_DT_SUPP(x, y) ((*(t_u16 *)(x + 10)) = y)
+/** AMPDU factor size */
+#define AMPDU_FACTOR_64K 0x03
+/** Set AMPDU size in A-MPDU paramter field */
+#define SETAMPDU_SIZE(x, y)                                                    \
+	do {                                                                   \
+		x = x & ~0x03;                                                 \
+		x |= y & 0x03;                                                 \
+	} while (0) /** Set AMPDU spacing in A-MPDU paramter field */
+#define SETAMPDU_SPACING(x, y)                                                 \
+	do {                                                                   \
+		x = x & ~0x1c;                                                 \
+		x |= (y & 0x07) << 2;                                          \
+	} while (0)
+
+/** RadioType : Support for Band A */
+#define ISSUPP_BANDA(FwCapInfo) (FwCapInfo & MBIT(10))
+/** RadioType : Support for 40Mhz channel BW */
+#define ISALLOWED_CHANWIDTH40(Field2) (Field2 & MBIT(2))
+/** RadioType : Set support 40Mhz channel */
+#define SET_CHANWIDTH40(Field2) (Field2 |= MBIT(2))
+/** RadioType : Reset support 40Mhz channel */
+#define RESET_CHANWIDTH40(Field2) (Field2 &= ~(MBIT(0) | MBIT(1) | MBIT(2)))
+/** RadioType : Get secondary channel */
+#define GET_SECONDARYCHAN(Field2) (Field2 & (MBIT(0) | MBIT(1)))
+
+/** ExtCap : Support for FILS */
+#define ISSUPP_EXTCAP_FILS(ext_cap) (ext_cap.FILS)
+/** ExtCap : Set support FILS */
+#define SET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 1)
+/** ExtCap : Reset support FILS */
+#define RESET_EXTCAP_FILS(ext_cap) (ext_cap.FILS = 0)
+
+/** ExtCap : Support for TDLS */
+#define ISSUPP_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport)
+/** ExtCap : Set support TDLS */
+#define SET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 1)
+/** ExtCap : Reset support TDLS */
+#define RESET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 0)
+/** ExtCap : Support for TDLS UAPSD */
+#define ISSUPP_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport)
+/** ExtCap : Set support TDLS UAPSD */
+#define SET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 1)
+/** ExtCap : Reset support TDLS UAPSD */
+#define RESET_EXTCAP_TDLS_UAPSD(ext_cap) (ext_cap.TDLSPeerUAPSDSupport = 0)
+/** ExtCap : Support for TDLS CHANNEL SWITCH */
+#define ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching)
+/** ExtCap : Set support TDLS CHANNEL SWITCH */
+#define SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap) (ext_cap.TDLSChannelSwitching = 1)
+/** ExtCap : Reset support TDLS CHANNEL SWITCH */
+#define RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap)                                 \
+	(ext_cap.TDLSChannelSwitching = 0)
+/** ExtCap : Set support Multi BSSID */
+#define SET_EXTCAP_MULTI_BSSID(ext_cap) (ext_cap.MultipleBSSID = 1)
+/** ExtCap : Support for Interworking */
+#define ISSUPP_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking)
+/** ExtCap : Set support Interworking */
+#define SET_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking = 1)
+/** ExtCap : Reset support Interworking */
+#define RESET_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking = 0)
+/** ExtCap : Support for Operation Mode Notification */
+#define ISSUPP_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf)
+/** ExtCap : Set support Operation Mode Notification */
+#define SET_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf = 1)
+/** ExtCap : Reset support Operation Mode Notification */
+#define RESET_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf = 0)
+/** ExtCap : Support for QosMap */
+#define ISSUPP_EXTCAP_QOS_MAP(ext_cap) (ext_cap.Qos_Map)
+/** ExtCap : Set Support QosMap */
+#define SET_EXTCAP_QOS_MAP(ext_cap) (ext_cap.Qos_Map = 1)
+/** ExtCap : Reset support QosMap */
+#define RESET_EXTCAP_QOS_MAP(ext_cap) (ext_cap.Qos_Map = 0)
+/** ExtCap : Support for BSS_Transition */
+#define ISSUPP_EXTCAP_BSS_TRANSITION(ext_cap) (ext_cap.BSS_Transition)
+/** ExtCap : Set Support BSS_Transition */
+#define SET_EXTCAP_BSS_TRANSITION(ext_cap) (ext_cap.BSS_Transition = 1)
+/** ExtCap : Reset support BSS_Transition */
+#define RESET_EXTCAP_BSS_TRANSITION(ext_cap) (ext_cap.BSS_Transition = 0)
+
+/** ExtCap : Support for TDLS wider bandwidth */
+#define ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap) (ext_cap.TDLSWildBandwidth)
+/** ExtCap : Set support TDLS wider bandwidth */
+#define SET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap) (ext_cap.TDLSWildBandwidth = 1)
+/** ExtCap : Reset support TDLS wider bandwidth */
+#define RESET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap)                             \
+	(ext_cap.TDLSWildBandwidth = 0)
+
+/** ExtCap : Support for extend channel switch */
+#define ISSUPP_EXTCAP_EXT_CHANNEL_SWITCH(ext_cap) (ext_cap.ExtChanSwitching)
+/** ExtCap : Set support Ext Channel Switch */
+#define SET_EXTCAP_EXT_CHANNEL_SWITCH(ext_cap) (ext_cap.ExtChanSwitching = 1)
+/** ExtCap: Set Timing Measurement */
+#define SET_EXTCAP_EXT_TIMING_MEASUREMENT(ext_cap)                             \
+	(ext_cap.TimingMeasurement = 1)
+/** ExtCap : Reset support Ext Channel Switch */
+#define RESET_EXTCAP_EXT_CHANNEL_SWITCH(ext_cap) (ext_cap.ExtChanSwitching = 0)
+
+/** ExtCap : Support for TWT RESP */
+#define ISSUPP_EXTCAP_EXT_TWT_RESP(ext_cap) (ext_cap.TWTResp)
+/** ExtCap : Set support Ext TWT_REQ */
+#define SET_EXTCAP_TWT_REQ(ext_cap) (ext_cap.TWTReq = 1)
+/** ExtCap : ReSet support Ext TWT REQ */
+#define RESET_EXTCAP_TWT_REQ(ext_cap) (ext_cap.TWTReq = 0)
+
+/** LLC/SNAP header len   */
+#define LLC_SNAP_LEN 8
+
+/** bandwidth following HTCAP */
+#define BW_FOLLOW_HTCAP 0
+/** bandwidth following VHTCAP */
+#define BW_FOLLOW_VHTCAP 1
+
+/** HW_SPEC FwCapInfo */
+#define HWSPEC_11ACSGI80_SUPP MBIT(5)
+#define HWSPEC_11ACRXSTBC_SUPP MBIT(8)
+
+#define ISSUPP_11ACENABLED(FwCapInfo) (FwCapInfo & (MBIT(12) | MBIT(13)))
+
+#define ISSUPP_11AC2GENABLED(FwCapInfo) (FwCapInfo & MBIT(12))
+#define ISSUPP_11AC5GENABLED(FwCapInfo) (FwCapInfo & MBIT(13))
+
+/** HW_SPEC Dot11acDevCap : HTC-VHT supported */
+#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & MBIT(22))
+/** HW_SPEC Dot11acDevCap : VHT TXOP PS support */
+#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & MBIT(21))
+/** HW_SPEC Dot11acDevCap : MU RX beamformee support */
+#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(20))
+/** HW_SPEC Dot11acDevCap : MU TX beamformee support */
+#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(19))
+/** HW_SPEC Dot11acDevCap : SU Beamformee support */
+#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & MBIT(12))
+/** HW_SPEC Dot11acDevCap : SU Beamformer support */
+#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & MBIT(11))
+/** HW_SPEC Dot11acDevCap : Rx STBC support */
+#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(8))
+/** HW_SPEC Dot11acDevCap : Tx STBC support */
+#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & MBIT(7))
+/** HW_SPEC Dot11acDevCap : Short GI support for 160MHz BW */
+#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & MBIT(6))
+/** HW_SPEC Dot11acDevCap : Short GI support for 80MHz BW */
+#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & MBIT(5))
+/** HW_SPEC Dot11acDevCap : LDPC coding support */
+#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & MBIT(4))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160/80+80 MHz support */
+#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & MBIT(3))
+/** HW_SPEC Dot11acDevCap : Channel BW 20/40/80/160 MHz support */
+#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & MBIT(2))
+
+/** Set VHT Cap Info: Max MPDU length */
+#define SET_VHTCAP_MAXMPDULEN(VHTCapInfo, value) (VHTCapInfo |= (value & 0x03))
+/** Reset VHT Cap Info: Max MPDU length */
+#define RESET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo &= ~(MBIT(0) | MBIT(1)))
+
+/** SET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define SET_VHTCAP_CHWDSET(VHTCapInfo, value)                                  \
+	(VHTCapInfo |= ((value & 0x3) << 2))
+/** SET VHT CapInfo:  Rx STBC (3 bits) */
+#define SET_VHTCAP_RXSTBC(VHTCapInfo, value)                                   \
+	(VHTCapInfo |= ((value & 0x7) << 8))
+/** SET VHT CapInfo:  Commpressed Steering Num of BFer Ant Supported (3 bits) */
+#define SET_VHTCAP_SNBFERANT(VHTCapInfo, value)                                \
+	(VHTCapInfo |= ((value & 0x7) << 13))
+/** SET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define SET_VHTCAP_NUMSNDDM(VHTCapInfo, value)                                 \
+	(VHTCapInfo |= ((value & 0x7) << 16))
+/** SET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define SET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo, value)                           \
+	(VHTCapInfo |= ((value & 0x7) << 23))
+/** SET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define SET_VHTCAP_LINKADPCAP(VHTCapInfo, value)                               \
+	(VHTCapInfo |= ((value & 0x3) << 26))
+
+/** HW_SPEC Dot11acDevCap : ReSet VHT Link Adapation Capable */
+#define RESET_11ACVHTLINKCAPA(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x03))
+/** HW_SPEC Dot11acDevCap : ReSet Maximum AMPDU Length Exponent */
+#define RESET_11ACAMPDULENEXP(Dot11acDevCap, value) (Dot11acDevCap &= ~(0x07))
+/** HW_SPEC Dot11acDevCap : ReSet support of HTC-VHT */
+#define RESET_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(22))
+/** HW_SPEC Dot11acDevCap : ReSet support of VHT TXOP PS */
+#define RESET_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(21))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU RX beamformee */
+#define RESET_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(20))
+/** HW_SPEC Dot11acDevCap : ReSet support of MU TX beamformee */
+#define RESET_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(19))
+/** HW_SPEC Dot11acDevCap : ReSet Number of Sounding Dimensions */
+#define RESET_11ACSOUNDINGNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 16))
+/** HW_SPEC Dot11acDevCap : ReSet Compressed Steering Number
+ * of Beamformer Antenna */
+#define RESET_11ACBFANTNUM(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 13))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformee */
+#define RESET_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(12))
+/** HW_SPEC Dot11acDevCap : ReSet support of SU Beamformer */
+#define RESET_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(11))
+/** HW_SPEC Dot11acDevCap : ReSet support of Rx STBC */
+#define RESET_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~((0x07) << 8))
+/** HW_SPEC Dot11acDevCap : ReSet support of Tx STBC */
+#define RESET_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(7))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 160MHz BW */
+#define RESET_11ACSGI160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(6))
+/** HW_SPEC Dot11acDevCap : ReSet support of Short GI support for 80MHz BW */
+#define RESET_11ACSGI80(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(5))
+/** HW_SPEC Dot11acDevCap : ReSet support of LDPC coding */
+#define RESET_11ACLDPC(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(4))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+ * Channel BW 20/40/80/160/80+80 MHz */
+#define RESET_11ACBW8080(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(3))
+/** HW_SPEC Dot11acDevCap : ReSet support of
+ * Channel BW 20/40/80/160 MHz */
+#define RESET_11ACBW160(Dot11acDevCap) (Dot11acDevCap &= ~MBIT(2))
+/** HW_SPEC Dot11acDevCap : ReSet Max MPDU length */
+#define RESET_11ACMAXMPDULEN(Dot11acDevCap) (Dot11acDevCap &= ~(0x03))
+
+/** Default 11ac capability mask for 2.4GHz */
+#define DEFAULT_11AC_CAP_MASK_BG                                               \
+	(HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** Default 11ac capability mask for 5GHz */
+#define DEFAULT_11AC_CAP_MASK_A (HWSPEC_11ACSGI80_SUPP | HWSPEC_11ACRXSTBC_SUPP)
+/** GET VHT CapInfo : MAX MPDU Length */
+#define GET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo & 0x3)
+/** GET VHT CapInfo:  Supported Channel Width SET (2 bits)*/
+#define GET_VHTCAP_CHWDSET(VHTCapInfo) ((VHTCapInfo >> 2) & 0x3)
+/** GET VHT CapInfo:  Rx STBC (3 bits) */
+#define GET_VHTCAP_RXSTBC(VHTCapInfo) ((VHTCapInfo >> 8) & 0x7)
+/** GET VHT CapInfo:  Compressed Steering Num of BFer Ant Supported (3 bits) */
+#define GET_VHTCAP_SNBFERANT(VHTCapInfo) ((VHTCapInfo >> 13) & 0x7)
+/** GET VHT CapInfo:  Num of Sounding Dimensions (3 bits) */
+#define GET_VHTCAP_NUMSNDDM(VHTCapInfo) ((VHTCapInfo >> 16) & 0x7)
+/** GET VHT CapInfo:  Max AMPDU Length Exponent (3 bits) */
+#define GET_VHTCAP_MAXAMPDULENEXP(VHTCapInfo) ((VHTCapInfo >> 23) & 0x7)
+/** GET VHT CapInfo:  VHT Link Adaptation Capable (2 bits) */
+#define GET_VHTCAP_LINKADPCAP(VHTCapInfo) ((VHTCapInfo >> 26) & 0x3)
+/**SET OPERATING MODE:Channel Width:80M*/
+#define SET_OPER_MODE_80M(oper_mode)                                           \
+	(oper_mode = (oper_mode & ~MBIT(0)) | MBIT(1))
+/**SET OPERATING MODE:Channel Width:40M*/
+#define SET_OPER_MODE_40M(oper_mode)                                           \
+	(oper_mode = (oper_mode & ~MBIT(1)) | MBIT(0))
+/**SET OPERATING MODE:Channel Width:20M*/
+#define SET_OPER_MODE_20M(oper_mode) (oper_mode &= ~(0x03))
+#define IS_OPER_MODE_20M(oper_mode) (((oper_mode) & (MBIT(0) | MBIT(1))) == 0)
+/**SET OPERATING MODE:Rx NSS:2*/
+#define SET_OPER_MODE_2NSS(oper_mode)                                          \
+	(oper_mode = (oper_mode & ~(MBIT(5) | MBIT(6))) | MBIT(4))
+/**SET OPERATING MODE:Rx NSS:1*/
+#define SET_OPER_MODE_1NSS(oper_mode)                                          \
+	(oper_mode &= ~(MBIT(4) | MBIT(5) | MBIT(6)))
+
+#define NO_NSS_SUPPORT 0x3
+#define GET_VHTMCS(MCSMapSet) (MCSMapSet & 0xFFFF)
+#define GET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3)
+#define RET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3)
+#define SET_VHTNSSMCS(MCSMapSet, nss, value)                                   \
+	(MCSMapSet |= (value & 0x3) << (2 * (nss - 1)))
+
+/** DevMCSSupported : Tx MCS supported */
+#define GET_DEVTXMCSMAP(DevMCSMap) (DevMCSMap >> 16)
+#define GET_DEVNSSTXMCS(DevMCSMap, nss)                                        \
+	((DevMCSMap >> (2 * (nss - 1) + 16)) & 0x3)
+#define SET_DEVNSSTXMCS(DevMCSMap, nss, value)                                 \
+	(DevMCSMap |= (value & 0x3) << (2 * (nss - 1) + 16))
+#define RESET_DEVTXMCSMAP(DevMCSMap) (DevMCSMap &= 0xFFFF)
+/** DevMCSSupported : Rx MCS supported */
+#define GET_DEVRXMCSMAP(DevMCSMap) (DevMCSMap & 0xFFFF)
+#define GET_DEVNSSRXMCS(DevMCSMap, nss) ((DevMCSMap >> (2 * (nss - 1))) & 0x3)
+#define SET_DEVNSSRXMCS(DevMCSMap, nss, value)                                 \
+	(DevMCSMap |= (value & 0x3) << (2 * (nss - 1)))
+#define RESET_DEVRXMCSMAP(DevMCSMap) (DevMCSMap &= 0xFFFF0000)
+
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_DROP_PATTERN (PROPRIETARY_TLV_BASE_ID + 0x51)	/* 0x0151  \
+									 */
+/** TLV type : Rate drop pattern */
+#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 0x52)	/* 0x0152  \
+									 */
+/** TLV type : Rate scope */
+#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 0x53)	/* 0x0153 */
+
+/** TLV type : Power group */
+#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 0x54)	/* 0x0154 */
+
+/** Modulation class for DSSS Rates */
+#define MOD_CLASS_HR_DSSS 0x03
+/** Modulation class for OFDM Rates */
+#define MOD_CLASS_OFDM 0x07
+/** Modulation class for HT Rates */
+#define MOD_CLASS_HT 0x08
+/** Modulation class for VHT Rates */
+#define MOD_CLASS_VHT 0x09
+/** HT bandwidth 20 MHz */
+#define HT_BW_20 0
+/** HT bandwidth 40 MHz */
+#define HT_BW_40 1
+/** HT bandwidth 80 MHz */
+#define HT_BW_80 2
+
+/** TLV type : TX RATE CFG, rename from TLV_TYPE_GI_LTF_SIZE to include CMD and
+ * HE ER SU settings to this tlv */
+#define TLV_TYPE_TX_RATE_CFG (PROPRIETARY_TLV_BASE_ID + 319)	/* 0x023f */
+
+/** TLV type : Scan Response */
+#define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 0x56)	/* 0x0156 */
+/** TLV type : Scan Response Stats */
+#define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 0x57)	/* 0x0157 */
+
+/** TLV type : 11h Basic Rpt */
+#define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 0x5b)	/* 0x015b  \
+									 */
+
+/** TLV type : DFS W53 Configuration */
+#define TLV_TYPE_DFS_W53_CFG (PROPRIETARY_TLV_BASE_ID + 0x145)	// + 325
+#ifdef OPCHAN
+/** TLV type : OpChannel control */
+#define TLV_TYPE_OPCHAN_CONTROL_DESC                                           \
+	(PROPRIETARY_TLV_BASE_ID + 0x79)	/* 0x0179 */
+/** TLV type : OpChannel channel group control */
+#define TLV_TYPE_OPCHAN_CHANGRP_CTRL                                           \
+	(PROPRIETARY_TLV_BASE_ID + 0x7a)	/* 0x017a */
+#endif
+
+/** TLV type : Action frame */
+#define TLV_TYPE_IEEE_ACTION_FRAME (PROPRIETARY_TLV_BASE_ID + 0x8c)	/* 0x018c  \
+									 */
+
+/** TLV type : SCAN channel gap */
+#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 0xc5)	/* 0x01c5   \
+									 */
+/** TLV type : Channel statistics */
+#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 0xc6)	/* 0x01c6 */
+/** TLV type : BSS_MODE */
+#define TLV_TYPE_BSS_MODE (PROPRIETARY_TLV_BASE_ID + 0xce)	/* 0x01ce */
+
+/** Firmware Host Command ID Constants */
+/** Host Command ID : Get hardware specifications */
+#define HostCmd_CMD_GET_HW_SPEC 0x0003
+/** Host Command ID : 802.11 scan */
+#define HostCmd_CMD_802_11_SCAN 0x0006
+/** Host Command ID : 802.11 get log */
+#define HostCmd_CMD_802_11_GET_LOG 0x000b
+
+/** Host Command id: GET_TX_RX_PKT_STATS */
+#define HOST_CMD_TX_RX_PKT_STATS 0x008d
+
+/** Host Command ID : 802.11 get/set link layer statistic */
+#define HostCmd_CMD_802_11_LINK_STATS 0x0256
+
+/** Host Command ID : MAC multicast address */
+#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010
+/** Host Command ID : 802.11 EEPROM access */
+#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059
+/** Host Command ID : 802.11 associate */
+#define HostCmd_CMD_802_11_ASSOCIATE 0x0012
+
+/** Host Command ID : 802.11 SNMP MIB */
+#define HostCmd_CMD_802_11_SNMP_MIB 0x0016
+/** Host Command ID : MAC register access */
+#define HostCmd_CMD_MAC_REG_ACCESS 0x0019
+/** Host Command ID : BBP register access */
+#define HostCmd_CMD_BBP_REG_ACCESS 0x001a
+/** Host Command ID : RF register access */
+#define HostCmd_CMD_RF_REG_ACCESS 0x001b
+
+/** Host Command ID : 802.11 radio control */
+#define HostCmd_CMD_802_11_RADIO_CONTROL 0x001c
+/** Host Command ID : 802.11 RF channel */
+#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
+/** Host Command ID : 802.11 RF Tx power */
+#define HostCmd_CMD_802_11_RF_TX_POWER 0x001e
+
+/** Host Command ID : 802.11 RF antenna */
+#define HostCmd_CMD_802_11_RF_ANTENNA 0x0020
+
+/** Host Command ID : 802.11 deauthenticate */
+#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
+/** Host Command ID: 802.11 disassoicate */
+#define HostCmd_CMD_802_11_DISASSOCIATE 0x0026
+/** Host Command ID : MAC control */
+#define HostCmd_CMD_MAC_CONTROL 0x0028
+/** Host Command ID : 802.11 Ad-Hoc start */
+#define HostCmd_CMD_802_11_AD_HOC_START 0x002b
+/** Host Command ID : 802.11 Ad-Hoc join */
+#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c
+
+/** Host Command ID: CW Mode */
+#define HostCmd_CMD_CW_MODE_CTRL 0x0239
+/** Host Command ID : 802.11 key material */
+#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e
+
+/** Host Command ID : 802.11 Ad-Hoc stop */
+#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040
+
+/** Host Command ID : 802.22 MAC address */
+#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D
+
+/** Host Command ID : WMM Traffic Stream Status */
+#define HostCmd_CMD_WMM_TS_STATUS 0x005d
+
+/** Host Command ID : 802.11 D domain information */
+#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b
+
+/*This command gets/sets the Transmit Rate-based Power Control (TRPC) channel
+ * configuration.*/
+#define HostCmd_CHANNEL_TRPC_CONFIG 0x00fb
+
+/** Host Command ID : 802.11 TPC information */
+#define HostCmd_CMD_802_11_TPC_INFO 0x005f
+/** Host Command ID : 802.11 TPC adapt req */
+#define HostCmd_CMD_802_11_TPC_ADAPT_REQ 0x0060
+/** Host Command ID : 802.11 channel SW ann */
+#define HostCmd_CMD_802_11_CHAN_SW_ANN 0x0061
+
+/** Host Command ID : Measurement request */
+#define HostCmd_CMD_MEASUREMENT_REQUEST 0x0062
+/** Host Command ID : Measurement report */
+#define HostCmd_CMD_MEASUREMENT_REPORT 0x0063
+
+/** Host Command ID : 802.11 sleep parameters */
+#define HostCmd_CMD_802_11_SLEEP_PARAMS 0x0066
+
+/** Host Command ID : 802.11 ps inactivity timeout */
+#define HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT 0x0067
+
+/** Host Command ID : 802.11 sleep period */
+#define HostCmd_CMD_802_11_SLEEP_PERIOD 0x0068
+
+/** Host Command ID: 802.11 BG scan config */
+#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b
+/** Host Command ID : 802.11 BG scan query */
+#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c
+
+/** Host Command ID : WMM ADDTS req */
+#define HostCmd_CMD_WMM_ADDTS_REQ 0x006E
+/** Host Command ID : WMM DELTS req */
+#define HostCmd_CMD_WMM_DELTS_REQ 0x006F
+/** Host Command ID : WMM queue configuration */
+#define HostCmd_CMD_WMM_QUEUE_CONFIG 0x0070
+/** Host Command ID : 802.11 get status */
+#define HostCmd_CMD_WMM_GET_STATUS 0x0071
+
+/** Host Command ID : 802.11 subscribe event */
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075
+
+/** Host Command ID : 802.11 Tx rate query */
+#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f
+/** Host Command ID :Get timestamp value */
+#define HostCmd_CMD_GET_TSF 0x0080
+
+/** Host Command ID : WMM queue stats */
+#define HostCmd_CMD_WMM_QUEUE_STATS 0x0081
+
+/** Host Command ID : KEEP ALIVE command */
+#define HostCmd_CMD_AUTO_TX 0x0082
+
+/** Host Command ID : 802.11 IBSS coalescing status */
+#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083
+
+/** Host Command ID : Memory access */
+#define HostCmd_CMD_MEM_ACCESS 0x0086
+
+#if defined(SDIO)
+/** Host Command ID : SDIO GPIO interrupt configuration */
+#define HostCmd_CMD_SDIO_GPIO_INT_CONFIG 0x0088
+#endif
+
+/** Host Command ID : Mfg command */
+#define HostCmd_CMD_MFG_COMMAND 0x0089
+/** Host Command ID : Inactivity timeout ext */
+#define HostCmd_CMD_INACTIVITY_TIMEOUT_EXT 0x008a
+
+/** Host Command ID : DBGS configuration */
+#define HostCmd_CMD_DBGS_CFG 0x008b
+/** Host Command ID : Get memory */
+#define HostCmd_CMD_GET_MEM 0x008c
+
+/** Host Command ID : Cal data dnld */
+#define HostCmd_CMD_CFG_DATA 0x008f
+
+/** Host Command ID : SDIO pull control */
+#define HostCmd_CMD_SDIO_PULL_CTRL 0x0093
+
+/** Host Command ID : ECL system clock configuration */
+#define HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG 0x0094
+
+/** Host Command ID : Extended version */
+#define HostCmd_CMD_VERSION_EXT 0x0097
+
+/** Host Command ID : MEF configuration */
+#define HostCmd_CMD_MEF_CFG 0x009a
+/** Host Command ID : 802.11 RSSI INFO*/
+#define HostCmd_CMD_RSSI_INFO 0x00a4
+/** Host Command ID : Function initialization */
+#define HostCmd_CMD_FUNC_INIT 0x00a9
+/** Host Command ID : Function shutdown */
+#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
+
+/** Host Command ID : Robustcoex */
+#define HostCmd_CMD_802_11_ROBUSTCOEX 0x00e0
+
+/** Host Command ID :EAPOL PKT */
+#define HostCmd_CMD_802_11_EAPOL_PKT 0x012e
+
+/** Host Command ID :MIMO SWITCH **/
+#define HostCmd_CMD_802_11_MIMO_SWITCH 0x0235
+
+/** Host Command ID : 802.11 RSSI INFO EXT*/
+#define HostCmd_CMD_RSSI_INFO_EXT 0x0237
+
+#ifdef RX_PACKET_COALESCE
+/** TLV ID for RX pkt coalesce config */
+#define TLV_TYPE_RX_PKT_COAL_CONFIG (PROPRIETARY_TLV_BASE_ID + 0xC9)
+#endif
+
+#define TLV_TYPE_PREV_BSSID (PROPRIETARY_TLV_BASE_ID + 330)
+
+/** Host Command ID : Channel report request */
+#define HostCmd_CMD_CHAN_REPORT_REQUEST 0x00dd
+
+/** Host Command ID: SUPPLICANT_PMK */
+#define HostCmd_CMD_SUPPLICANT_PMK 0x00c4
+/** Host Command ID: SUPPLICANT_PROFILE */
+#define HostCmd_CMD_SUPPLICANT_PROFILE 0x00c5
+
+/** Host Command ID : Add Block Ack Request */
+#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_CFG 0x00cd
+/** Host Command ID : Add Block Ack Response */
+#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf
+/** Host Command ID : Delete a Block Ack Request */
+#define HostCmd_CMD_11N_DELBA 0x00d0
+/** Host Command ID: Configure Tx Buf size */
+#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9
+/** Host Command ID: AMSDU Aggr Ctrl */
+#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df
+/** Host Command ID: 11AC config */
+#define HostCmd_CMD_11AC_CFG 0x0112
+/** Host Command ID: Configure TX Beamforming capability */
+#define HostCmd_CMD_TX_BF_CFG 0x0104
+
+/** Host Command ID : 802.11 TX power configuration */
+#define HostCmd_CMD_TXPWR_CFG 0x00d1
+
+/** Host Command ID : Soft Reset */
+#define HostCmd_CMD_SOFT_RESET 0x00d5
+
+/** Host Command ID : 802.11 b/g/n rate configration */
+#define HostCmd_CMD_TX_RATE_CFG 0x00d6
+
+/** Host Command ID : Enhanced PS mode */
+#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4
+
+/** Host command action : Host sleep configuration */
+#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5
+
+/** Host Command ID : CAU register access */
+#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed
+
+/** Host Command ID : mgmt IE list */
+#define HostCmd_CMD_MGMT_IE_LIST 0x00f2
+
+#define HostCmd_CMD_802_11_BAND_STEERING 0x026f
+
+/** Host Command ID : TDLS configuration */
+#define HostCmd_CMD_TDLS_CONFIG 0x0100
+/** Host Command ID : TDLS operation */
+#define HostCmd_CMD_TDLS_OPERATION 0x0122
+
+#ifdef SDIO
+/** Host Command ID : SDIO single port RX aggr */
+#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
+
+/** fw_cap_info bit16 for sdio sp rx aggr flag*/
+#define SDIO_SP_RX_AGGR_ENABLE MBIT(16)
+
+#endif
+
+/* fw_cap_info bit18 for ecsa support*/
+#define FW_CAPINFO_ECSA MBIT(18)
+
+/* fw_cap_info bit20 for get log*/
+#define FW_CAPINFO_GET_LOG MBIT(20)
+
+/** fw_cap_info bit22 for embedded supplicant support*/
+#define FW_CAPINFO_SUPPLICANT_SUPPORT MBIT(21)
+
+/** fw_cap_info bit23 for embedded authenticator support*/
+#define FW_CAPINFO_AUTH_SUPPORT MBIT(22)
+
+/** fw_cap_info bit25 for adhoc support*/
+#define FW_CAPINFO_ADHOC_SUPPORT MBIT(25)
+/** Check if adhoc is supported by firmware */
+#define IS_FW_SUPPORT_ADHOC(_adapter)                                          \
+	(_adapter->fw_cap_info & FW_CAPINFO_ADHOC_SUPPORT)
+
+/** Check if supplicant is supported by firmware */
+#define IS_FW_SUPPORT_SUPPLICANT(_adapter)                                     \
+	(_adapter->fw_cap_info & FW_CAPINFO_SUPPLICANT_SUPPORT)
+
+/** Check if authenticator is supported by firmware */
+#define IS_FW_SUPPORT_AUTHENTICATOR(_adapter)                                  \
+	(_adapter->fw_cap_info & FW_CAPINFO_AUTH_SUPPORT)
+
+/** Ext fw cap info bit0 only 1x1 5G is available */
+#define FW_CAPINFO_EXT_5G_1X1_ONLY MBIT(0)
+/** Ext fw cap info bit1 1x1 5G is not available */
+#define FW_CAPINFO_EXT_NO_5G_1X1 MBIT(1)
+/** Ext fw cap info bit 2 only 1x1 2G is available */
+#define FW_CAPINFO_EXT_2G_1X1_ONLY MBIT(2)
+/**Ext fw cap info bit3 1x1 2G is not available */
+#define FW_CAPINFO_EXT_NO_2G_1X1 MBIT(3)
+/** Ext fw cap info bit4 1x1 + 1x1 5G mode is unavailable */
+#define FW_CAPINFO_EXT_NO_5G_1X1_PLUS_1X1 MBIT(4)
+/** Ext fw cap info bit5 80 + 80 MHz capability disabled */
+#define FW_CAPINFO_EXT_NO_80MHz_PLUS_80MHz MBIT(5)
+/** Ext fw cap info bit6 1024 QAM is disabled */
+#define FW_CAPINFO_EXT_NO_1024_QAM MBIT(6)
+/** FW cap info bit 7 11AX */
+#define FW_CAPINFO_EXT_802_11AX MBIT(7)
+/** FW cap info bit 8: 80MHZ disabled */
+#define FW_CAPINFO_EXT_NO_80MHZ MBIT(8)
+/** FW cap info bit 9: Multi BSSID Support */
+#define FW_CAPINFO_EXT_MULTI_BSSID MBIT(9)
+/** FW cap info bit 10: Beacon Protection Support */
+#define FW_CAPINFO_EXT_BEACON_PROT MBIT(10)
+
+/** Check if 5G 1x1 only is supported by firmware */
+#define IS_FW_SUPPORT_5G_1X1_ONLY(_adapter)                                    \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_5G_1X1_ONLY)
+/** Check if 5G 1x1 is unavailable in firmware */
+#define IS_FW_SUPPORT_NO_5G_1X1(_adapter)                                      \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_5G_1X1)
+/** Check if 2G 1x1 only is supported by firmware */
+#define IS_FW_SUPPORT_2G_1X1_ONLY(_adapter)                                    \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_2G_1X1_ONLY)
+/** Check if 2G 1x1 is unavailable in firmware */
+#define IS_FW_SUPPORT_NO_2G_1X1(_adapter)                                      \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_2G_1X1)
+/** Check if 5G 1x1 + 1x1 mode is disabled in firmware */
+#define IS_FW_SUPPORT_NO_5G_1X1_PLUS_1X1(_adapter)                             \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_5G_1X1_PLUS_1X1)
+/** Check if 80 + 80MHz is disabled in firmware */
+#define IS_FW_SUPPORT_NO_80MHz_PLUS_80MHz(_adapter)                            \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_80MHz_PLUS_80MHz)
+/** Check if 1024 QAM disabled in firmware */
+#define IS_FW_SUPPORT_NO_1024_QAM(_adapter)                                    \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_1024_QAM)
+/** Check if 80MHZ disabled in firmware */
+#define IS_FW_SUPPORT_NO_80MHZ(_adapter)                                       \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_NO_80MHZ)
+/** Check if Multi BSSID supported by firmware */
+#define IS_FW_SUPPORT_MULTIBSSID(_adapter)                                     \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_MULTI_BSSID)
+/** Check if Beacon Protection supported by firmware */
+#define IS_FW_SUPPORT_BEACON_PROT(_adapter)                                     \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_BEACON_PROT)
+
+/** MrvlIEtypes_PrevBssid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PrevBssid_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** prev_bssid **/
+	t_u8 prev_bssid[6];
+} MLAN_PACK_END MrvlIEtypes_PrevBssid_t;
+
+/** FW cap info TLV */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_cap_info_t {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+	/** Fw cap info bitmap */
+	t_u32 fw_cap_info;
+	/** Extended fw cap info bitmap */
+	t_u32 fw_cap_ext;
+} MLAN_PACK_END MrvlIEtypes_fw_cap_info_t, *pMrvlIEtypes_fw_cap_info_t;
+
+/** Check if 11AX is supported by firmware */
+#define IS_FW_SUPPORT_11AX(_adapter)                                           \
+	(_adapter->fw_cap_ext & FW_CAPINFO_EXT_802_11AX)
+
+typedef MLAN_PACK_START struct _MrvlIEtypes_Extension_t {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** payload */
+	t_u8 data[1];
+} MLAN_PACK_END MrvlIEtypes_Extension_t, *pMrvlIEtypes_Extension_t;
+
+/* HE MAC Capabilities Information field BIT 1 for TWT Req */
+#define HE_MAC_CAP_TWT_REQ_SUPPORT MBIT(1)
+/* HE MAC Capabilities Information field BIT 2 for TWT Resp*/
+#define HE_MAC_CAP_TWT_RESP_SUPPORT MBIT(2)
+typedef MLAN_PACK_START struct _MrvlIEtypes_He_cap_t {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** he mac capability info */
+	t_u8 he_mac_cap[6];
+	/** he phy capability info */
+	t_u8 he_phy_cap[11];
+    /** rx mcs for 80 */
+	t_u16 rx_mcs_80;
+    /** tx mcs for 80 */
+	t_u16 tx_mcs_80;
+    /** rx mcs for bw 160 */
+	t_u16 rx_mcs_160;
+    /** tx mcs for bw 160 */
+	t_u16 tx_mcs_160;
+    /** rx mcs for bw 80+80 */
+	t_u16 rx_mcs_80p80;
+    /** tx mcs for bw 80+80 */
+	t_u16 tx_mcs_80p80;
+	/** PPE Thresholds (optional) */
+	t_u8 val[20];
+} MLAN_PACK_END MrvlIEtypes_He_cap_t, *pMrvlIEtypes_he_cap_t;
+
+#ifdef RX_PACKET_COALESCE
+/** Host Command ID : Rx packet coalescing configuration */
+#define HostCmd_CMD_RX_PKT_COALESCE_CFG 0x012c
+#endif
+
+/** Host Command ID : Extended scan support */
+#define HostCmd_CMD_802_11_SCAN_EXT 0x0107
+
+/** Host Command ID : Forward mgmt frame */
+#define HostCmd_CMD_RX_MGMT_IND 0x010c
+
+#ifdef PCIE
+/** Host Command ID: Host buffer description */
+#define HostCmd_CMD_PCIE_HOST_BUF_DETAILS 0x00fa
+#endif
+
+/** Host Command ID : Set BSS_MODE */
+#define HostCmd_CMD_SET_BSS_MODE 0x00f7
+
+#ifdef UAP_SUPPORT
+/**  Host Command id: SYS_INFO */
+#define HOST_CMD_APCMD_SYS_INFO 0x00ae
+/** Host Command id: sys_reset */
+#define HOST_CMD_APCMD_SYS_RESET 0x00af
+/** Host Command id: SYS_CONFIGURE  */
+#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0
+/** Host Command id: BSS_START */
+#define HOST_CMD_APCMD_BSS_START 0x00b1
+/** Host Command id: BSS_STOP  */
+#define HOST_CMD_APCMD_BSS_STOP 0x00b2
+/** Host Command id: sta_list */
+#define HOST_CMD_APCMD_STA_LIST 0x00b3
+/** Host Command id: STA_DEAUTH */
+#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5
+
+/** Host Command id: REPORT_MIC */
+#define HOST_CMD_APCMD_REPORT_MIC 0x00ee
+/** Host Command id: UAP_OPER_CTRL */
+#define HOST_CMD_APCMD_OPER_CTRL 0x0233
+#endif /* UAP_SUPPORT */
+
+/** Host Command id: PMIC CONFIGURE*/
+#define HOST_CMD_PMIC_CONFIGURE 0x23E
+
+/** Host Command ID: Tx data pause */
+#define HostCmd_CMD_CFG_TX_DATA_PAUSE 0x0103
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Host Command ID: P2P PARAMS CONFIG */
+#define HOST_CMD_P2P_PARAMS_CONFIG 0x00ea
+/** Host Command ID: WIFI_DIRECT_MODE_CONFIG */
+#define HOST_CMD_WIFI_DIRECT_MODE_CONFIG 0x00eb
+#endif
+
+/** Host Command ID: GPIO TSF LATCH */
+#define HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG 0x0278
+/** Host Command ID: Remain On Channel */
+#define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL 0x010d
+
+#define HostCmd_CMD_COALESCE_CFG 0x010a
+
+/** Host Command ID: GTK REKEY OFFLOAD CFG */
+#define HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG 0x010f
+
+/** Host Command ID : OTP user data */
+#define HostCmd_CMD_OTP_READ_USER_DATA 0x0114
+
+/** Host Command ID: HS wakeup reason */
+#define HostCmd_CMD_HS_WAKEUP_REASON 0x0116
+
+/** Host Command ID: reject addba request */
+#define HostCmd_CMD_REJECT_ADDBA_REQ 0x0119
+
+#define HostCmd_CMD_FW_DUMP_EVENT 0x0125
+
+#define HostCMD_CONFIG_LOW_POWER_MODE 0x0128
+
+/** Host Command ID : Target device access */
+#define HostCmd_CMD_TARGET_ACCESS 0x012a
+
+/** Host Command ID: BCA device access */
+#define HostCmd_CMD_BCA_REG_ACCESS 0x0272
+
+/** Host Command ID: DFS repeater mode */
+#define HostCmd_DFS_REPEATER_MODE 0x012b
+
+/** Host Command ID: ACS scan */
+#define HostCMD_APCMD_ACS_SCAN 0x0224
+
+/** Host Command ID: Get sensor temp*/
+#define HostCmd_DS_GET_SENSOR_TEMP 0x0227
+
+/** Host Command ID : Configure ADHOC_OVER_IP parameters */
+#define HostCmd_CMD_WMM_PARAM_CONFIG 0x023a
+
+#define HostCmd_CMD_IPV6_RA_OFFLOAD_CFG 0x0238
+
+#ifdef STA_SUPPORT
+/** Host Command ID :  set/get sta configure */
+#define HostCmd_CMD_STA_CONFIGURE 0x023f
+#endif
+
+/** Host Command ID : GPIO independent reset configure */
+#define HostCmd_CMD_INDEPENDENT_RESET_CFG 0x0243
+
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+/* TLV type: reg type */
+#define TLV_TYPE_REG_ACCESS_CTRL (PROPRIETARY_TLV_BASE_ID + 0x13C)	/* 0x023c */
+/** MrvlIEtypes_Reg_type_t*/
+typedef MLAN_PACK_START struct _MrvlIEtypes_Reg_type_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** type: 0x81/0x82/0x83 */
+	t_u8 type;
+} MLAN_PACK_END MrvlIEtypes_Reg_type_t;
+
+#endif
+/** use to query chan region cfg setting in firmware */
+#define HostCmd_CMD_CHAN_REGION_CFG 0x0242
+/** used in hostcmd to download region power cfg setting to firmware */
+#define HostCmd_CMD_REGION_POWER_CFG 0x0249
+
+/* mod_grp */
+typedef enum _mod_grp {
+	MOD_CCK,		// 0
+	MOD_OFDM_PSK,		// 1
+	MOD_OFDM_QAM16,		// 2
+	MOD_OFDM_QAM64,		// 3
+	MOD_HT_20_PSK,		// 4
+	MOD_HT_20_QAM16,	// 5
+	MOD_HT_20_QAM64,	// 6
+	MOD_HT_40_PSK,		// 7
+	MOD_HT_40_QAM16,	// 8
+	MOD_HT_40_QAM64,	// 9
+#ifdef STREAM_2x2
+	MOD_HT2_20_PSK,		// 10
+	MOD_HT2_20_QAM16,	// 11
+	MOD_HT2_20_QAM64,	// 12
+	MOD_HT2_40_PSK,		// 13
+	MOD_HT2_40_QAM16,	// 14
+	MOD_HT2_40_QAM64,	// 15
+#endif
+
+	MOD_VHT_20_QAM256,	// 16
+	MOD_VHT_40_QAM256,	// 17
+	MOD_VHT_80_PSK,		// 18
+	MOD_VHT_80_QAM16,	// 19
+	MOD_VHT_80_QAM64,	// 20
+	MOD_VHT_80_QAM256,	// 21
+#ifdef STREAM_2x2
+	MOD_VHT2_20_QAM256,	// 22
+	MOD_VHT2_40_QAM256,	// 23
+	MOD_VHT2_80_PSK,	// 24
+	MOD_VHT2_80_QAM16,	// 25
+	MOD_VHT2_80_QAM64,	// 26
+	MOD_VHT2_80_QAM256,	// 27
+#endif
+} mod_grp;
+
+typedef MLAN_PACK_START struct _power_table_attr {
+	t_u8 rows_2g;
+	t_u8 cols_2g;
+	t_u8 rows_5g;
+	t_u8 cols_5g;
+} MLAN_PACK_END power_table_attr_t;
+
+#define FW_CFP_TABLE_MAX_ROWS_BG 14
+#define FW_CFP_TABLE_MAX_COLS_BG 17
+
+#define FW_CFP_TABLE_MAX_ROWS_A 39
+#define FW_CFP_TABLE_MAX_COLS_A 29
+
+#define HostCmd_CMD_DYN_BW 0x0252
+
+#define HostCmd_CMD_BOOT_SLEEP 0x0258
+
+#define HostCmd_CMD_RX_ABORT_CFG 0x0261
+#define HostCmd_CMD_RX_ABORT_CFG_EXT 0x0262
+#define HostCmd_CMD_TX_AMPDU_PROT_MODE 0x0263
+#define HostCmd_CMD_RATE_ADAPT_CFG 0x0264
+#define HostCmd_CMD_CCK_DESENSE_CFG 0x0265
+
+#define HostCmd_CMD_VDLL 0x0240
+#if defined(PCIE)
+#define HostCmd_CMD_SSU 0x0259
+#endif
+
+#define HostCmd_CMD_DMCS_CONFIG 0x0260
+
+/** Host Command ID: 11AX config */
+#define HostCmd_CMD_11AX_CFG 0x0266
+/** Host Command ID: 11AX command */
+#define HostCmd_CMD_11AX_CMD 0x026d
+/** Host Command ID: Range ext command */
+#define HostCmd_CMD_RANGE_EXT 0x0274
+/** Host Command ID: TWT cfg command */
+#define HostCmd_CMD_TWT_CFG 0x0270
+
+#define HostCmd_CMD_LOW_POWER_MODE_CFG 0x026e
+#define HostCmd_CMD_UAP_BEACON_STUCK_CFG    0x0271
+#define HostCmd_CMD_ARB_CONFIG 0x0273
+#define HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG 0x0275
+#define HostCmd_CMD_HAL_PHY_CFG 0x0276
+
+/** Enhanced PS modes */
+typedef enum _ENH_PS_MODES {
+	GET_PS = 0,
+	SLEEP_CONFIRM = 5,
+	DIS_AUTO_PS = 0xfe,
+	EN_AUTO_PS = 0xff,
+} ENH_PS_MODES;
+
+/** Command RET code, MSB is set to 1 */
+#define HostCmd_RET_BIT 0x8000
+
+/** General purpose action : Get */
+#define HostCmd_ACT_GEN_GET 0x0000
+/** General purpose action : Set */
+#define HostCmd_ACT_GEN_SET 0x0001
+/** General purpose action : Set Default */
+#define HostCmd_ACT_GEN_SET_DEFAULT 0x0002
+/** General purpose action : Get_Current */
+#define HostCmd_ACT_GEN_GET_CURRENT 0x0003
+/** General purpose action : Remove */
+#define HostCmd_ACT_GEN_REMOVE 0x0004
+/** General purpose action : Reset */
+#define HostCmd_ACT_GEN_RESET 0x0005
+
+/** Host command action : Set Rx */
+#define HostCmd_ACT_SET_RX 0x0001
+/** Host command action : Set Tx */
+#define HostCmd_ACT_SET_TX 0x0002
+/** Host command action : Set both Rx and Tx */
+#define HostCmd_ACT_SET_BOTH 0x0003
+/** Host command action : Get Rx */
+#define HostCmd_ACT_GET_RX 0x0004
+/** Host command action : Get Tx */
+#define HostCmd_ACT_GET_TX 0x0008
+/** Host command action : Get both Rx and Tx */
+#define HostCmd_ACT_GET_BOTH 0x000c
+
+/** General Result Code*/
+/** General result code OK */
+#define HostCmd_RESULT_OK 0x0000
+/** Genenral error */
+#define HostCmd_RESULT_ERROR 0x0001
+/** Command is not valid */
+#define HostCmd_RESULT_NOT_SUPPORT 0x0002
+/** Command is pending */
+#define HostCmd_RESULT_PENDING 0x0003
+/** System is busy (command ignored) */
+#define HostCmd_RESULT_BUSY 0x0004
+/** Data buffer is not big enough */
+#define HostCmd_RESULT_PARTIAL_DATA 0x0005
+
+/* Define action or option for HostCmd_CMD_MAC_CONTROL */
+/** MAC action : Rx on */
+#define HostCmd_ACT_MAC_RX_ON 0x0001
+/** MAC action : Tx on */
+#define HostCmd_ACT_MAC_TX_ON 0x0002
+/** MAC action : WEP enable */
+#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008
+/** MAC action : EthernetII enable */
+#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010
+/** MAC action : Promiscous mode enable */
+#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
+/** MAC action : All multicast enable */
+#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
+/** MAC action : RTS/CTS enable */
+#define HostCmd_ACT_MAC_RTS_CTS_ENABLE 0x0200
+/** MAC action : Strict protection enable */
+#define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
+/** MAC action : Force 11n protection disable */
+#define HostCmd_ACT_MAC_FORCE_11N_PROTECTION_OFF 0x0800
+/** MAC action : Ad-Hoc G protection on */
+#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000
+/** MAC action : Static-Dynamic BW enable */
+#define HostCmd_ACT_MAC_STATIC_DYNAMIC_BW_ENABLE MBIT(16)
+/** MAC action : Dynamic BW */
+#define HostCmd_ACT_MAC_DYNAMIC_BW MBIT(17)
+
+/* Define action or option for HostCmd_CMD_802_11_SCAN */
+/** Scan type : BSS */
+#define HostCmd_BSS_MODE_BSS 0x0001
+/** Scan type : IBSS */
+#define HostCmd_BSS_MODE_IBSS 0x0002
+/** Scan type : Any */
+#define HostCmd_BSS_MODE_ANY 0x0003
+
+/** Define bitmap conditions for HOST_SLEEP_CFG : GPIO FF */
+#define HOST_SLEEP_CFG_GPIO_FF 0xff
+/** Define bitmap conditions for HOST_SLEEP_CFG : GAP FF */
+#define HOST_SLEEP_CFG_GAP_FF 0xff
+
+/** Buffer Constants */
+/** Number of command buffers */
+#define MRVDRV_NUM_OF_CMD_BUFFER 40
+/** Maximum number of BSS Descriptors */
+#define MRVDRV_MAX_BSSID_LIST 200
+
+/** Host command flag in command */
+#define CMD_F_HOSTCMD (1 << 0)
+/** command cancel flag in command */
+#define CMD_F_CANCELED (1 << 1)
+/** scan command flag */
+#define CMD_F_SCAN (1 << 2)
+
+/** Host Command ID bit mask (bit 11:0) */
+#define HostCmd_CMD_ID_MASK 0x0fff
+
+/** Host Command Sequence number mask (bit 7:0) */
+#define HostCmd_SEQ_NUM_MASK 0x00ff
+
+/** Host Command BSS number mask (bit 11:8) */
+#define HostCmd_BSS_NUM_MASK 0x0f00
+
+/** Host Command BSS type mask (bit 15:12) */
+#define HostCmd_BSS_TYPE_MASK 0xf000
+
+/** Set BSS information to Host Command */
+#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type)                            \
+	((((seq)&0x00ff) | (((num)&0x000f) << 8)) | (((type)&0x000f) << 12))
+
+/** Get Sequence Number from Host Command (bit 7:0) */
+#define HostCmd_GET_SEQ_NO(seq) ((seq)&HostCmd_SEQ_NUM_MASK)
+
+/** Get BSS number from Host Command (bit 11:8) */
+#define HostCmd_GET_BSS_NO(seq) (((seq)&HostCmd_BSS_NUM_MASK) >> 8)
+
+/** Get BSS type from Host Command (bit 15:12) */
+#define HostCmd_GET_BSS_TYPE(seq) (((seq)&HostCmd_BSS_TYPE_MASK) >> 12)
+
+/** Card Event definition : Dummy host wakeup signal */
+#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001
+/** Card Event definition : Link lost */
+#define EVENT_LINK_LOST 0x00000003
+/** Card Event definition : Link sensed */
+#define EVENT_LINK_SENSED 0x00000004
+/** Card Event definition : MIB changed */
+#define EVENT_MIB_CHANGED 0x00000006
+/** Card Event definition : Init done */
+#define EVENT_INIT_DONE 0x00000007
+/** Card Event definition : Deauthenticated */
+#define EVENT_DEAUTHENTICATED 0x00000008
+/** Card Event definition : Disassociated */
+#define EVENT_DISASSOCIATED 0x00000009
+/** Card Event definition : Power save awake */
+#define EVENT_PS_AWAKE 0x0000000a
+/** Card Event definition : Power save sleep */
+#define EVENT_PS_SLEEP 0x0000000b
+/** Card Event definition : MIC error multicast */
+#define EVENT_MIC_ERR_MULTICAST 0x0000000d
+/** Card Event definition : MIC error unicast */
+#define EVENT_MIC_ERR_UNICAST 0x0000000e
+
+/** Card Event definition : Ad-Hoc BCN lost */
+#define EVENT_ADHOC_BCN_LOST 0x00000011
+
+/** Card Event definition : Stop Tx */
+#define EVENT_STOP_TX 0x00000013
+/** Card Event definition : Start Tx */
+#define EVENT_START_TX 0x00000014
+/** Card Event definition : Channel switch */
+#define EVENT_CHANNEL_SWITCH 0x00000015
+
+/** Card Event definition : MEAS report ready */
+#define EVENT_MEAS_REPORT_RDY 0x00000016
+
+/** Card Event definition : WMM status change */
+#define EVENT_WMM_STATUS_CHANGE 0x00000017
+
+/** Card Event definition : BG scan report */
+#define EVENT_BG_SCAN_REPORT 0x00000018
+/** Card Event definition : BG scan stopped */
+#define EVENT_BG_SCAN_STOPPED 0x00000065
+
+/** Card Event definition : Beacon RSSI low */
+#define EVENT_RSSI_LOW 0x00000019
+/** Card Event definition : Beacon SNR low */
+#define EVENT_SNR_LOW 0x0000001a
+/** Card Event definition : Maximum fail */
+#define EVENT_MAX_FAIL 0x0000001b
+/** Card Event definition : Beacon RSSI high */
+#define EVENT_RSSI_HIGH 0x0000001c
+/** Card Event definition : Beacon SNR high */
+#define EVENT_SNR_HIGH 0x0000001d
+
+/** Card Event definition : IBSS coalsced */
+#define EVENT_IBSS_COALESCED 0x0000001e
+
+/** Event definition : IBSS station connected */
+#define EVENT_IBSS_STATION_CONNECT 0x00000020
+/** Event definition : IBSS station dis-connected */
+#define EVENT_IBSS_STATION_DISCONNECT 0x00000021
+
+/** Card Event definition : Data RSSI low */
+#define EVENT_DATA_RSSI_LOW 0x00000024
+/** Card Event definition : Data SNR low */
+#define EVENT_DATA_SNR_LOW 0x00000025
+/** Card Event definition : Data RSSI high */
+#define EVENT_DATA_RSSI_HIGH 0x00000026
+/** Card Event definition : Data SNR high */
+#define EVENT_DATA_SNR_HIGH 0x00000027
+
+/** Card Event definition : Link Quality */
+#define EVENT_LINK_QUALITY 0x00000028
+
+/** Card Event definition : Port release event */
+#define EVENT_PORT_RELEASE 0x0000002b
+
+/** Card Event definition : Pre-Beacon Lost */
+#define EVENT_PRE_BEACON_LOST 0x00000031
+
+#define EVENT_WATCHDOG_TMOUT            0x00000032
+
+/** Card Event definition : Add BA event */
+#define EVENT_ADDBA 0x00000033
+/** Card Event definition : Del BA event */
+#define EVENT_DELBA 0x00000034
+/** Card Event definition: BA stream timeout*/
+#define EVENT_BA_STREAM_TIMEOUT 0x00000037
+
+/** Card Event definition : AMSDU aggr control */
+#define EVENT_AMSDU_AGGR_CTRL 0x00000042
+
+/** Card Event definition: WEP ICV error */
+#define EVENT_WEP_ICV_ERR 0x00000046
+
+/** Card Event definition : Host sleep enable */
+#define EVENT_HS_ACT_REQ 0x00000047
+
+/** Card Event definition : BW changed */
+#define EVENT_BW_CHANGE 0x00000048
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** WIFIDIRECT generic event */
+#define EVENT_WIFIDIRECT_GENERIC_EVENT 0x00000049
+/** WIFIDIRECT service discovery event */
+#define EVENT_WIFIDIRECT_SERVICE_DISCOVERY 0x0000004a
+#endif
+/** Remain on Channel expired event */
+#define EVENT_REMAIN_ON_CHANNEL_EXPIRED 0x0000005f
+
+/** TDLS generic event */
+#define EVENT_TDLS_GENERIC_EVENT 0x00000052
+
+#define EVENT_MEF_HOST_WAKEUP 0x0000004f
+
+/** Card Event definition: Channel switch pending announcment */
+#define EVENT_CHANNEL_SWITCH_ANN 0x00000050
+
+/** Event definition:  Radar Detected by card */
+#define EVENT_RADAR_DETECTED 0x00000053
+
+/** Event definition:  Radar Detected by card */
+#define EVENT_CHANNEL_REPORT_RDY 0x00000054
+
+/** Event definition:  Scan results through event */
+#define EVENT_EXT_SCAN_REPORT 0x00000058
+/** Enhance ext scan done event */
+#define EVENT_EXT_SCAN_STATUS_REPORT 0x0000007f
+
+/** Event definition : FW debug information */
+#define EVENT_FW_DEBUG_INFO 0x00000063
+
+/** Event definition: RXBA_SYNC */
+#define EVENT_RXBA_SYNC 0x00000059
+
+#ifdef UAP_SUPPORT
+/** Event ID: STA deauth */
+#define EVENT_MICRO_AP_STA_DEAUTH 0x0000002c
+/** Event ID: STA assoicated */
+#define EVENT_MICRO_AP_STA_ASSOC 0x0000002d
+/** Event ID: BSS started */
+#define EVENT_MICRO_AP_BSS_START 0x0000002e
+/** Event ID: BSS idle event */
+#define EVENT_MICRO_AP_BSS_IDLE 0x00000043
+/** Event ID: BSS active event */
+#define EVENT_MICRO_AP_BSS_ACTIVE 0x00000044
+
+/** Event ID: MIC countermeasures event */
+#define EVENT_MICRO_AP_MIC_COUNTERMEASURES 0x0000004c
+#endif /* UAP_SUPPORT */
+
+/** Event ID: TX data pause event */
+#define EVENT_TX_DATA_PAUSE 0x00000055
+
+/** Event ID: SAD Report */
+#define EVENT_SAD_REPORT 0x00000066
+
+/** Event ID: Tx status */
+#define EVENT_TX_STATUS_REPORT 0x00000074
+
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0x00000076
+
+#if defined(PCIE)
+#define EVENT_SSU_DUMP_DMA 0x0000008C
+#endif
+
+#define EVENT_VDLL_IND 0x00000081
+#define EVENT_EXCEED_MAX_P2P_CONN 0x00000089
+
+/** Card Event definition : RESET PN */
+
+#define EVENT_FW_HANG_REPORT 0x0000008F
+
+#define EVENT_FW_DUMP_INFO 0x00000073
+/** Event ID mask */
+#define EVENT_ID_MASK 0xffff
+
+/** BSS number mask */
+#define BSS_NUM_MASK 0xf
+
+/** Get BSS number from event cause (bit 23:16) */
+#define EVENT_GET_BSS_NUM(event_cause) (((event_cause) >> 16) & BSS_NUM_MASK)
+
+/** Get BSS type from event cause (bit 31:24) */
+#define EVENT_GET_BSS_TYPE(event_cause) (((event_cause) >> 24) & 0x00ff)
+
+/** event type for tdls setup failure */
+#define TDLS_EVENT_TYPE_SETUP_FAILURE 1
+/** event type for tdls setup request received */
+#define TDLS_EVENT_TYPE_SETUP_REQ 2
+/** event type for tdls link torn down */
+#define TDLS_EVENT_TYPE_LINK_TORN_DOWN 3
+/** event type for tdls link established */
+#define TDLS_EVENT_TYPE_LINK_ESTABLISHED 4
+/** event type for tdls debug */
+#define TDLS_EVENT_TYPE_DEBUG 5
+/** event type for tdls packet */
+#define TDLS_EVENT_TYPE_PACKET 6
+/** event type for channel switch result */
+#define TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT 7
+/** event type for start channel switch */
+#define TDLS_EVENT_TYPE_START_CHAN_SWITCH 8
+/** event type for stop channel switch */
+#define TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED 9
+
+/** Packet received on direct link */
+#define RXPD_FLAG_PKT_DIRECT_LINK MBIT(0)
+/** TDLS base channel */
+#define TDLS_BASE_CHANNEL 0
+/** TDLS off channel */
+#define TDLS_OFF_CHANNEL 1
+
+/** structure for channel switch result from TDLS FW */
+typedef MLAN_PACK_START struct _chan_switch_result {
+	/** current channel, 0 - base channel, 1 - off channel*/
+	t_u8 current_channel;
+	/** channel switch status*/
+	t_u8 status;
+	/** channel switch fauilure reason code*/
+	t_u8 reason;
+} MLAN_PACK_END chan_switch_result;
+
+typedef MLAN_PACK_START struct _ie_data {
+	/** IE Length */
+	t_u16 ie_length;
+	/** IE pointer */
+	t_u8 ie_ptr[1];
+} MLAN_PACK_END tdls_ie_data;
+
+/** Event structure for generic events from TDLS FW */
+typedef MLAN_PACK_START struct _Event_tdls_generic {
+	/** Event Type */
+	t_u16 event_type;
+	/** Peer mac address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	union {
+		/** channel switch result structure*/
+		chan_switch_result switch_result;
+		/** channel switch stop reason*/
+		t_u8 cs_stop_reason;
+		/** Reason code */
+		t_u16 reason_code;
+		/** IE data */
+		tdls_ie_data ie_data;
+	} u;
+} MLAN_PACK_END Event_tdls_generic;
+
+typedef enum _tdls_error_code_e {
+	NO_ERROR = 0,
+	INTERNAL_ERROR,
+	MAX_TDLS_LINKS_EST,
+	TDLS_LINK_EXISTS,
+	TDLS_LINK_NONEXISTENT,
+	TDLS_PEER_STA_UNREACHABLE = 25,
+} tdls_error_code_e;
+
+/** Event_WEP_ICV_ERR structure */
+typedef MLAN_PACK_START struct _Event_WEP_ICV_ERR {
+	/** Reason code */
+	t_u16 reason_code;
+	/** Source MAC address */
+	t_u8 src_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** WEP decryption used key */
+	t_u8 wep_key_index;
+	/** WEP key length */
+	t_u8 wep_key_length;
+	/** WEP key */
+	t_u8 key[MAX_WEP_KEY_SIZE];
+} MLAN_PACK_END Event_WEP_ICV_ERR;
+
+/** WLAN_802_11_FIXED_IEs */
+typedef MLAN_PACK_START struct _WLAN_802_11_FIXED_IEs {
+	/** Timestamp */
+	t_u8 time_stamp[8];
+	/** Beacon interval */
+	t_u16 beacon_interval;
+	/** Capabilities*/
+	t_u16 capabilities;
+} MLAN_PACK_END WLAN_802_11_FIXED_IEs;
+
+/** WLAN_802_11_VARIABLE_IEs */
+typedef MLAN_PACK_START struct _WLAN_802_11_VARIABLE_IEs {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 length;
+	/** IE data */
+	t_u8 data[1];
+} MLAN_PACK_END WLAN_802_11_VARIABLE_IEs;
+
+/** TLV related data structures*/
+/*TDLS TIMEOUT VALUE (seconds)*/
+#define TDLS_IDLE_TIMEOUT 60
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_TDLS_Idle_Timeout_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** value */
+	t_u16 value;
+} MLAN_PACK_END MrvlIEtypes_TDLS_Idle_Timeout_t;
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN 4
+/** AKM Suite length */
+#define AKM_SUITE_LEN 4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT 7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT 6
+#endif
+/** Bit mask for TxPD status field for null packet */
+#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
+/** Bit mask for TxPD status field for last packet */
+#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
+
+/** Bit mask for TxPD flags field for TDLS packet */
+#define MRVDRV_TxPD_FLAGS_TDLS_PACKET MBIT(4)
+
+/** Bit mask for TxPD flags field for Tx status report */
+#define MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS MBIT(5)
+
+/** Packet type: 802.11 */
+#define PKT_TYPE_802DOT11 0x05
+
+#define PKT_TYPE_MGMT_FRAME 0xE5
+/** Packet type: AMSDU */
+#define PKT_TYPE_AMSDU 0xE6
+/** Packet type: BAR */
+#define PKT_TYPE_BAR 0xE7
+
+/** Packet type: debugging */
+#define PKT_TYPE_DEBUG 0xEF
+
+/** channel number at bit 5-13 */
+#define RXPD_CHAN_MASK 0x3FE0
+/** Rate control mask  15-23 */
+#define TXPD_RATE_MASK 0xff8000
+/** enable bw ctrl in TxPD */
+#define TXPD_BW_ENABLE MBIT(20)
+/** enable tx power ctrl in TxPD */
+#define TXPD_TXPW_ENABLE MBIT(7)
+/** sign of power */
+#define TXPD_TXPW_NEGATIVE MBIT(6)
+/** Enable Rate ctrl in TxPD */
+#define TXPD_TXRATE_ENABLE MBIT(15)
+/** enable retry limit in TxPD */
+#define TXPD_RETRY_ENABLE MBIT(12)
+
+/** TxPD descriptor */
+typedef MLAN_PACK_START struct _TxPD {
+	/** BSS type */
+	t_u8 bss_type;
+	/** BSS number */
+	t_u8 bss_num;
+	/** Tx packet length */
+	t_u16 tx_pkt_length;
+	/** Tx packet offset */
+	t_u16 tx_pkt_offset;
+	/** Tx packet type */
+	t_u16 tx_pkt_type;
+	/** Tx Control */
+	t_u32 tx_control;
+	/** Pkt Priority */
+	t_u8 priority;
+	/** Transmit Pkt Flags*/
+	t_u8 flags;
+	/** Amount of time the packet has been queued
+	 * in the driver (units = 2ms)*/
+	t_u8 pkt_delay_2ms;
+	/** reserved */
+	t_u8 reserved;
+	/** Tx Control */
+	t_u32 tx_control_1;
+} MLAN_PACK_END TxPD, *PTxPD;
+
+/** RxPD Descriptor */
+typedef MLAN_PACK_START struct _RxPD {
+	/** BSS type */
+	t_u8 bss_type;
+	/** BSS number */
+	t_u8 bss_num;
+	/** Rx Packet Length */
+	t_u16 rx_pkt_length;
+	/** Rx Pkt offset */
+	t_u16 rx_pkt_offset;
+	/** Rx packet type */
+	t_u16 rx_pkt_type;
+	/** Sequence number */
+	t_u16 seq_num;
+	/** Packet Priority */
+	t_u8 priority;
+	/** Rx Packet Rate */
+	t_u8 rx_rate;
+	/** SNR */
+	t_s8 snr;
+	/** Noise Floor */
+	t_s8 nf;
+	/** [Bit 1] [Bit 0] RxRate format: legacy rate = 00 HT = 01 VHT = 10
+	 *  [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 = 00 BW40 = 01 BW80 = 10 BW160
+	 * = 11 [Bit 4] HT/VHT Guard interval LGI = 0 SGI = 1 [Bit 5] STBC
+	 * support Enabled = 1 [Bit 6] LDPC support Enabled = 1 [Bit 7] [Bit4,
+	 * Bit7] AX Guard interval, 00, 01, 10 */
+	t_u8 rate_info;
+	/** Reserved */
+	t_u8 reserved[3];
+	/** TDLS flags, bit 0: 0=InfraLink, 1=DirectLink */
+	t_u8 flags;
+	/**For SD8887 antenna info: 0 = 2.4G antenna a; 1 = 2.4G antenna b; 3 =
+	 * 5G antenna; 0xff = invalid value */
+	t_u8 antenna;
+	/* [31:0] ToA of the rx packet, [63:32] ToD of the ack for the rx packet
+	 * Both ToA and ToD are in nanoseconds */
+	t_u64 toa_tod_tstamps;
+	/** rx info */
+	t_u32 rx_info;
+
+    /** Reserved */
+	t_u8 reserved3[8];
+
+} MLAN_PACK_END RxPD, *PRxPD;
+
+/** IEEEtypes_FrameCtl_t*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t {
+	/** Order */
+	t_u8 order:1;
+	/** Wep */
+	t_u8 wep:1;
+	/** More Data */
+	t_u8 more_data:1;
+	/** Power Mgmt */
+	t_u8 pwr_mgmt:1;
+	/** Retry */
+	t_u8 retry:1;
+	/** More Frag */
+	t_u8 more_frag:1;
+	/** From DS */
+	t_u8 from_ds:1;
+	/** To DS */
+	t_u8 to_ds:1;
+	/** Sub Type */
+	t_u8 sub_type:4;
+	/** Type */
+	t_u8 type:2;
+	/** Protocol Version */
+	t_u8 protocol_version:2;
+} MLAN_PACK_END IEEEtypes_FrameCtl_t;
+#else
+typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t {
+	/** Protocol Version */
+	t_u8 protocol_version:2;
+	/** Type */
+	t_u8 type:2;
+	/** Sub Type */
+	t_u8 sub_type:4;
+	/** To DS */
+	t_u8 to_ds:1;
+	/** From DS */
+	t_u8 from_ds:1;
+	/** More Frag */
+	t_u8 more_frag:1;
+	/** Retry */
+	t_u8 retry:1;
+	/** Power Mgmt */
+	t_u8 pwr_mgmt:1;
+	/** More Data */
+	t_u8 more_data:1;
+	/** Wep */
+	t_u8 wep:1;
+	/** Order */
+	t_u8 order:1;
+} MLAN_PACK_END IEEEtypes_FrameCtl_t;
+#endif
+
+/** MrvlIETypes_MgmtFrameSet_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_MgmtFrameSet_t {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** Frame Control */
+	IEEEtypes_FrameCtl_t frame_control;
+	/* t_u8 frame_contents[]; */
+} MLAN_PACK_END MrvlIETypes_MgmtFrameSet_t;
+
+/** Beacon */
+typedef MLAN_PACK_START struct _IEEEtypes_Beacon_t {
+	/** time stamp */
+	t_u8 time_stamp[8];
+	/** beacon interval */
+	t_u16 beacon_interval;
+	/** cap info */
+	t_u16 cap_info;
+} MLAN_PACK_END IEEEtypes_Beacon_t;
+
+/** Fixed size of station association event */
+#define ASSOC_EVENT_FIX_SIZE 12
+
+/** MrvlIEtypes_channel_band_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_channel_band_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Band Configuration */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+} MLAN_PACK_END MrvlIEtypes_channel_band_t;
+
+#ifdef UAP_SUPPORT
+/** IEEEtypes_AssocRqst_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRqst_t {
+	/** Capability Info */
+	t_u16 cap_info;
+	/** Listen Interval */
+	t_u16 listen_interval;
+	/* t_u8 ie_buffer[]; */
+} MLAN_PACK_END IEEEtypes_AssocRqst_t;
+
+/** IEEEtypes_ReAssocRqst_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ReAssocRqst_t {
+	/** Capability Info */
+	t_u16 cap_info;
+	/** Listen Interval */
+	t_u16 listen_interval;
+	/** Current AP Address */
+	t_u8 current_ap_addr[MLAN_MAC_ADDR_LENGTH];
+	/* t_u8 ie_buffer[]; */
+} MLAN_PACK_END IEEEtypes_ReAssocRqst_t;
+#endif /* UAP_SUPPORT */
+
+/** wlan_802_11_header */
+typedef MLAN_PACK_START struct _wlan_802_11_header {
+	/** Frame Control */
+	t_u16 frm_ctl;
+	/** Duration ID */
+	t_u16 duration_id;
+	/** Address1 */
+	mlan_802_11_mac_addr addr1;
+	/** Address2 */
+	mlan_802_11_mac_addr addr2;
+	/** Address3 */
+	mlan_802_11_mac_addr addr3;
+	/** Sequence Control */
+	t_u16 seq_ctl;
+	/** Address4 */
+	mlan_802_11_mac_addr addr4;
+} MLAN_PACK_END wlan_802_11_header;
+
+/** wlan_802_11_header packet from FW with length */
+typedef MLAN_PACK_START struct _wlan_mgmt_pkt {
+	/** Packet Length */
+	t_u16 frm_len;
+	/** wlan_802_11_header */
+	wlan_802_11_header wlan_header;
+} MLAN_PACK_END wlan_mgmt_pkt;
+
+#ifdef STA_SUPPORT
+/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) */
+#define MAX_NO_OF_CHAN 40
+
+/** Channel-power table entries */
+typedef MLAN_PACK_START struct _chan_power_11d {
+	/** 11D channel */
+	t_u8 chan;
+	/** Band for channel */
+	t_u8 band;
+	/** 11D channel power */
+	t_u8 pwr;
+	/** AP seen on channel */
+	t_u8 ap_seen;
+} MLAN_PACK_END chan_power_11d_t;
+
+/** Region channel info */
+typedef MLAN_PACK_START struct _parsed_region_chan_11d {
+	/** 11D channel power per channel */
+	chan_power_11d_t chan_pwr[MAX_NO_OF_CHAN];
+	/** 11D number of channels */
+	t_u8 no_of_chan;
+} MLAN_PACK_END parsed_region_chan_11d_t;
+#endif /* STA_SUPPORT */
+
+/** ChanScanMode_t */
+typedef MLAN_PACK_START struct _ChanScanMode_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved_7:1;
+	/** First passive scan then active scan */
+	t_u8 passive_to_active_scan:1;
+	/** First channel in scan */
+	t_u8 first_chan:1;
+	/** Enable hidden ssid report */
+	t_u8 hidden_ssid_report:1;
+	/** Enable probe response timeout */
+	t_u8 rsp_timeout_en:1;
+	/** Multidomain scan mode */
+	t_u8 multidomain_scan:1;
+	/** Disble channel filtering flag */
+	t_u8 disable_chan_filt:1;
+	/** Channel scan mode passive flag */
+	t_u8 passive_scan:1;
+#else
+	/** Channel scan mode passive flag */
+	t_u8 passive_scan:1;
+	/** Disble channel filtering flag */
+	t_u8 disable_chan_filt:1;
+	/** Multidomain scan mode */
+	t_u8 multidomain_scan:1;
+	/** Enable probe response timeout */
+	t_u8 rsp_timeout_en:1;
+	/** Enable hidden ssid report */
+	t_u8 hidden_ssid_report:1;
+	/** First channel in scan */
+	t_u8 first_chan:1;
+	/** First passive scan then active scan */
+	t_u8 passive_to_active_scan:1;
+	/** Reserved */
+	t_u8 reserved_7:1;
+#endif
+} MLAN_PACK_END ChanScanMode_t;
+
+/** ChanScanParamSet_t */
+typedef MLAN_PACK_START struct _ChanScanParamSet_t {
+	/** Channel scan parameter : band config */
+	Band_Config_t bandcfg;
+	/** Channel scan parameter : Channel number */
+	t_u8 chan_number;
+	/** Channel scan parameter : Channel scan mode */
+	ChanScanMode_t chan_scan_mode;
+	/** Channel scan parameter : Minimum scan time */
+	t_u16 min_scan_time;
+	/** Channel scan parameter : Maximum scan time */
+	t_u16 max_scan_time;
+} MLAN_PACK_END ChanScanParamSet_t;
+
+/** MrvlIEtypes_ChanListParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChanListParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Channel scan parameters */
+	ChanScanParamSet_t chan_scan_param[1];
+} MLAN_PACK_END MrvlIEtypes_ChanListParamSet_t;
+
+/** MrvlIEtypes_EESParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_EESParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** EES scan mode */
+	t_u16 ees_mode;
+	/** EES report condition */
+	t_u16 report_cond;
+	/** EES High Period scan interval */
+	t_u16 high_period;
+	/** EES High Period scan count */
+	t_u16 high_period_count;
+	/** EES Medium Period scan interval */
+	t_u16 mid_period;
+	/** EES Medium Period scan count */
+	t_u16 mid_period_count;
+	/** EES Low Period scan interval */
+	t_u16 low_period;
+	/** EES Low Period scan count */
+	t_u16 low_period_count;
+} MLAN_PACK_END MrvlIEtypes_EESParamSet_t;
+
+/** MrvlIEtype_EESNetworkCfg_t */
+typedef MLAN_PACK_START struct _MrvlIEtype_EESNetworkCfg_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Number of networks in the list */
+	t_u8 network_count;
+	/** Maximum number of connection */
+	t_u8 max_conn_count;
+	/** Black List Exp */
+	t_u8 black_list_exp;
+} MLAN_PACK_END MrvlIEtype_EESNetworkCfg_t;
+
+/** ChanBandParamSet_t */
+typedef struct _ChanBandParamSet_t {
+	/** Channel scan parameter : band config */
+	Band_Config_t bandcfg;
+	/** Channel number */
+	t_u8 chan_number;
+} ChanBandParamSet_t;
+
+/** MrvlIEtypes_ChanBandListParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChanBandListParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Channel Band parameters */
+	ChanBandParamSet_t chan_band_param[1];
+} MLAN_PACK_END MrvlIEtypes_ChanBandListParamSet_t;
+
+/** MrvlIEtypes_RatesParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RatesParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Rates */
+	t_u8 rates[1];
+} MLAN_PACK_END MrvlIEtypes_RatesParamSet_t;
+
+/** _MrvlIEtypes_Bssid_List_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bssid_List_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_Bssid_List_t;
+
+/** MrvlIEtypes_SsIdParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SsIdParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** SSID */
+	t_u8 ssid[1];
+} MLAN_PACK_END MrvlIEtypes_SsIdParamSet_t;
+
+/**MrvlIEtypes_AssocType_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_HostMlme_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Authentication type */
+	t_u8 host_mlme;
+} MLAN_PACK_END MrvlIEtypes_HostMlme_t;
+
+/** MrvlIEtypes_NumProbes_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_NumProbes_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Number of probes */
+	t_u16 num_probes;
+} MLAN_PACK_END MrvlIEtypes_NumProbes_t;
+
+/** MrvlIEtypes_WildCardSsIdParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_WildCardSsIdParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Maximum SSID length */
+	t_u8 max_ssid_length;
+	/** SSID */
+	t_u8 ssid[1];
+} MLAN_PACK_END MrvlIEtypes_WildCardSsIdParamSet_t;
+
+/**TSF data size */
+#define TSF_DATA_SIZE 8
+/** Table of TSF values returned in the scan result */
+typedef MLAN_PACK_START struct _MrvlIEtypes_TsfTimestamp_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** the length of each TSF data is 8 bytes, could be multiple TSF here
+	 */
+	t_u8 tsf_data[1];
+} MLAN_PACK_END MrvlIEtypes_TsfTimestamp_t;
+
+/** CfParamSet_t */
+typedef MLAN_PACK_START struct _CfParamSet_t {
+	/** CF parameter : Count */
+	t_u8 cfp_cnt;
+	/** CF parameter : Period */
+	t_u8 cfp_period;
+	/** CF parameter : Duration */
+	t_u16 cfp_max_duration;
+	/** CF parameter : Duration remaining */
+	t_u16 cfp_duration_remaining;
+} MLAN_PACK_END CfParamSet_t;
+
+/** IbssParamSet_t */
+typedef MLAN_PACK_START struct _IbssParamSet_t {
+	/** ATIM window value */
+	t_u16 atim_window;
+} MLAN_PACK_END IbssParamSet_t;
+
+/** MrvlIEtypes_SsParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SsParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** CF/IBSS parameters sets */
+	union {
+		/** CF parameter set */
+		CfParamSet_t cf_param_set[1];
+		/** IBSS parameter set */
+		IbssParamSet_t ibss_param_set[1];
+	} cf_ibss;
+} MLAN_PACK_END MrvlIEtypes_SsParamSet_t;
+
+/** FhParamSet_t */
+typedef MLAN_PACK_START struct _FhParamSet_t {
+	/** FH parameter : Dwell time */
+	t_u16 dwell_time;
+	/** FH parameter : Hop set */
+	t_u8 hop_set;
+	/** FH parameter : Hop pattern */
+	t_u8 hop_pattern;
+	/** FH parameter : Hop index */
+	t_u8 hop_index;
+} MLAN_PACK_END FhParamSet_t;
+
+/** DsParamSet_t */
+typedef MLAN_PACK_START struct _DsParamSet_t {
+	/** Current channel number */
+	t_u8 current_chan;
+} MLAN_PACK_END DsParamSet_t;
+
+/** MrvlIEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PhyParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** FH/DS parameters */
+	union {
+		/** FH parameter set */
+		FhParamSet_t fh_param_set[1];
+		/** DS parameter set */
+		DsParamSet_t ds_param_set[1];
+	} fh_ds;
+} MLAN_PACK_END MrvlIEtypes_PhyParamSet_t;
+
+/* Auth type to be used in the Authentication portion of an Assoc seq */
+/** MrvlIEtypes_AuthType_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_AuthType_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Authentication type */
+	t_u16 auth_type;
+} MLAN_PACK_END MrvlIEtypes_AuthType_t;
+
+/** MrvlIEtypes_ScanChanGap_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ScanChanGap_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Time gap in units to TUs to be used between
+	 * two consecutive channels scan */
+	t_u16 gap;
+} MLAN_PACK_END MrvlIEtypes_ScanChanGap_t;
+
+/** channel statictics */
+typedef MLAN_PACK_START struct _chan_statistics_t {
+	/** channle number */
+	t_u8 chan_num;
+	/** band info */
+	Band_Config_t bandcfg;
+	/** flags */
+	t_u8 flags;
+	/** noise */
+	t_s8 noise;
+	/** total network */
+	t_u16 total_networks;
+	/** scan duration */
+	t_u16 cca_scan_duration;
+	/** busy duration */
+	t_u16 cca_busy_duration;
+} MLAN_PACK_END chan_statistics_t;
+
+/** channel statictics tlv */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ChannelStats_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** channel statictics */
+	chan_statistics_t chanStat[];
+} MLAN_PACK_END MrvlIEtypes_ChannelStats_t;
+
+/** MrvlIETypes_ActionFrame_t */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header; /**< Header */
+
+	t_u8 srcAddr[MLAN_MAC_ADDR_LENGTH];
+	t_u8 dstAddr[MLAN_MAC_ADDR_LENGTH];
+
+	IEEEtypes_ActionFrame_t actionFrame;
+
+} MLAN_PACK_END MrvlIETypes_ActionFrame_t;
+
+/** MrvlIEtypes_RxBaSync_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RxBaSync_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+	/** tid */
+	t_u8 tid;
+	/** reserved field */
+	t_u8 reserved;
+	/** start seq num */
+	t_u16 seq_num;
+	/** bitmap len */
+	t_u16 bitmap_len;
+	/** bitmap */
+	t_u8 bitmap[1];
+} MLAN_PACK_END MrvlIEtypes_RxBaSync_t;
+
+/** MrvlIEtypes_RsnParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RsnParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** RSN IE */
+	t_u8 rsn_ie[];
+} MLAN_PACK_END MrvlIEtypes_RsnParamSet_t;
+
+/** MrvlIEtypes_SecurityCfg_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SecurityCfg_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** enable 11w */
+	t_u8 use_mfp;
+} MLAN_PACK_END MrvlIEtypes_SecurityCfg_t;
+
+/** Host Command ID : _HostCmd_DS_BEACON_STUCK_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_BEACON_STUCK_CFG {
+    /** ACT_GET/ACT_SET */
+	t_u8 action;
+    /** No of beacon interval after which firmware will check if beacon Tx is going fine */
+	t_u8 beacon_stuck_detect_count;
+    /** Upon performing MAC reset, no of beacon interval after which firmware will check if recovery was successful */
+	t_u8 recovery_confirm_count;
+} MLAN_PACK_END HostCmd_DS_BEACON_STUCK_CFG;
+
+/** Key Info flag for multicast key */
+#define KEY_INFO_MCAST_KEY 0x01
+/** Key Info flag for unicast key */
+#define KEY_INFO_UCAST_KEY 0x02
+/** Key Info flag for enable key */
+#define KEY_INFO_ENABLE_KEY 0x04
+/** Key Info flag for default key */
+#define KEY_INFO_DEFAULT_KEY 0x08
+/** Key Info flag for TX key */
+#define KEY_INFO_TX_KEY 0x10
+/** Key Info flag for RX key */
+#define KEY_INFO_RX_KEY 0x20
+#define KEY_INFO_CMAC_AES_KEY 0x400
+/** PN size for WPA/WPA2 */
+#define WPA_PN_SIZE 8
+/** PN size for PMF IGTK */
+#define IGTK_PN_SIZE 8
+/** WAPI KEY size */
+#define WAPI_KEY_SIZE 32
+/** key params fix size */
+#define KEY_PARAMS_FIXED_LEN 10
+/** key index mask */
+#define KEY_INDEX_MASK 0xf
+
+/** wep_param */
+typedef MLAN_PACK_START struct _wep_param_t {
+	/** key_len */
+	t_u16 key_len;
+	/** wep key */
+	t_u8 key[MAX_WEP_KEY_SIZE];
+} MLAN_PACK_END wep_param_t;
+
+/** tkip_param */
+typedef MLAN_PACK_START struct _tkip_param {
+	/** Rx packet num */
+	t_u8 pn[WPA_PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** tkip key */
+	t_u8 key[WPA_TKIP_KEY_LEN];
+} MLAN_PACK_END tkip_param;
+
+/** aes_param */
+typedef MLAN_PACK_START struct _aes_param {
+	/** Rx packet num */
+	t_u8 pn[WPA_PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** aes key */
+	t_u8 key[WPA_AES_KEY_LEN];
+} MLAN_PACK_END aes_param;
+
+/** wapi_param */
+typedef MLAN_PACK_START struct _wapi_param {
+	/** Rx packet num */
+	t_u8 pn[PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** wapi key */
+	t_u8 key[WAPI_KEY_SIZE];
+} MLAN_PACK_END wapi_param;
+
+/** cmac_aes_param */
+typedef MLAN_PACK_START struct _cmac_aes_param {
+	/** IGTK pn */
+	t_u8 ipn[IGTK_PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** aes key */
+	t_u8 key[CMAC_AES_KEY_LEN];
+} MLAN_PACK_END cmac_aes_param;
+
+/** gmac_aes_256_param */
+typedef MLAN_PACK_START struct _gmac_aes_256_param {
+	/** IGTK pn */
+	t_u8 ipn[IGTK_PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** aes key */
+	t_u8 key[WPA_IGTK_256_KEY_LEN];
+} MLAN_PACK_END gmac_aes_256_param;
+
+/** gmac_param */
+typedef MLAN_PACK_START struct _gcmp_param {
+	/** GCMP pn */
+	t_u8 pn[WPA_PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** aes key */
+	t_u8 key[WPA_GCMP_KEY_LEN];
+} MLAN_PACK_END gcmp_param;
+
+/** ccmp256_param */
+typedef MLAN_PACK_START struct _ccmp256_param {
+	/** CCMP pn */
+	t_u8 pn[WPA_PN_SIZE];
+	/** key_len */
+	t_u16 key_len;
+	/** ccmp256 key */
+	t_u8 key[WPA_CCMP_256_KEY_LEN];
+} MLAN_PACK_END ccmp_256_param;
+
+/** MrvlIEtype_KeyParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtype_KeyParamSetV2_t {
+	/** Type ID */
+	t_u16 type;
+	/** Length of Payload */
+	t_u16 length;
+	/** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** key index */
+	t_u8 key_idx;
+	/** Type of Key: WEP=0, TKIP=1, AES=2, WAPI=3 AES_CMAC=4 */
+	t_u8 key_type;
+	/** Key Control Info specific to a key_type_id */
+	t_u16 key_info;
+	union {
+		/** wep key param */
+		wep_param_t wep;
+		/** tkip key param */
+		tkip_param tkip;
+		/** aes key param */
+		aes_param aes;
+		/** wapi key param */
+		wapi_param wapi;
+		/** IGTK key param */
+		cmac_aes_param cmac_aes;
+		/** gcmp key param */
+		gcmp_param gcmp;
+		/** ccmp 256 key parameters */
+		ccmp_256_param ccmp256;
+	} key_params;
+} MLAN_PACK_END MrvlIEtype_KeyParamSetV2_t;
+
+/** HostCmd_DS_802_11_KEY_MATERIAL */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_KEY_MATERIAL {
+	/** Action */
+	t_u16 action;
+	/** Key parameter set */
+	MrvlIEtype_KeyParamSetV2_t key_param_set;
+} MLAN_PACK_END HostCmd_DS_802_11_KEY_MATERIAL;
+
+/** HostCmd_DS_GTK_REKEY_PARAMS */
+typedef MLAN_PACK_START struct _HostCmd_DS_GTK_REKEY_PARAMS {
+	/** Action */
+	t_u16 action;
+	/** Key confirmation key */
+	t_u8 kck[MLAN_KCK_LEN];
+	/** Key encryption key */
+	t_u8 kek[MLAN_KEK_LEN];
+	/** Replay counter low 32 bit */
+	t_u32 replay_ctr_low;
+	/** Replay counter high 32 bit */
+	t_u32 replay_ctr_high;
+} MLAN_PACK_END HostCmd_DS_GTK_REKEY_PARAMS;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END WmmQosInfo_t, *pWmmQosInfo_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END WmmEcw_t, *pWmmEcw_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aifsn */
+	t_u8 aifsn:4;
+#else
+	/** Aifsn */
+	t_u8 aifsn:4;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END WmmAciAifsn_t, *pWmmAciAifsn_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _WmmAcParameters_t {
+	WmmAciAifsn_t aci_aifsn; /**< AciAifSn */
+	WmmEcw_t ecw; /**< Ecw */
+	t_u16 tx_op_limit; /**< Tx op limit */
+} MLAN_PACK_END WmmAcParameters_t, *pWmmAcParameters_t;
+
+/** Data structure of WMM parameter  */
+typedef MLAN_PACK_START struct _WmmParameter_t {
+	/** OuiType:  00:50:f2:02 */
+	t_u8 ouitype[4];
+	/** Oui subtype: 01 */
+	t_u8 ouisubtype;
+	/** version: 01 */
+	t_u8 version;
+	/** QoS information */
+	t_u8 qos_info;
+	/** Reserved */
+	t_u8 reserved;
+	/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END WmmParameter_t, *pWmmParameter_t;
+
+/** Data structure of Host command WMM_PARAM_CFG  */
+typedef MLAN_PACK_START struct _HostCmd_DS_WMM_PARAM_CONFIG {
+	/** action */
+	t_u16 action;
+	/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END HostCmd_DS_WMM_PARAM_CONFIG;
+
+/* Definition of firmware host command */
+/** HostCmd_DS_GEN */
+typedef MLAN_PACK_START struct _HostCmd_DS_GEN {
+	/** Command */
+	t_u16 command;
+	/** Size */
+	t_u16 size;
+	/** Sequence number */
+	t_u16 seq_num;
+	/** Result */
+	t_u16 result;
+} MLAN_PACK_END HostCmd_DS_GEN
+;
+
+/** Size of HostCmd_DS_GEN */
+#define S_DS_GEN sizeof(HostCmd_DS_GEN)
+
+/** mod_group_setting */
+typedef MLAN_PACK_START struct _mod_group_setting {
+	/** modulation group */
+	t_u8 mod_group;
+	/** power */
+	t_u8 power;
+} MLAN_PACK_END mod_group_setting;
+
+/** MrvlIETypes_ChanTRPCConfig_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_ChanTRPCConfig_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** start freq */
+	t_u16 start_freq;
+	/* channel width */
+	t_u8 width;
+	/** channel number */
+	t_u8 chan_num;
+	/** mode groups */
+	mod_group_setting mod_group[1];
+} MLAN_PACK_END MrvlIETypes_ChanTRPCConfig_t;
+
+/* HostCmd_DS_CHANNEL_TRPC_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CHANNEL_TRPC_CONFIG {
+	/** action */
+	t_u16 action;
+	/** 0/1/2/3 */
+	t_u16 sub_band;
+	/** chan TRPC config */
+	//MrvlIETypes_ChanTRPCConfig_t tlv[];
+} MLAN_PACK_END HostCmd_DS_CHANNEL_TRPC_CONFIG;
+
+/** Address type: broadcast */
+#define ADDR_TYPE_BROADCAST 1
+/* Address type: unicast */
+#define ADDR_TYPE_UNICAST 2
+/* Address type: multicast */
+#define ADDR_TYPE_MULTICAST 3
+
+/** Ether type: any */
+#define ETHER_TYPE_ANY 0xffff
+/** Ether type: ARP */
+#define ETHER_TYPE_ARP 0x0608
+
+/** IPv4 address any */
+#define IPV4_ADDR_ANY 0xffffffff
+
+/** Header structure for ARP filter */
+typedef MLAN_PACK_START struct _arpfilter_header {
+	/** Type */
+	t_u16 type;
+	/** TLV length */
+	t_u16 len;
+} MLAN_PACK_END arpfilter_header;
+
+/** Filter entry structure */
+typedef MLAN_PACK_START struct _filter_entry {
+	/** Address type */
+	t_u16 addr_type;
+	/** Ether type */
+	t_u16 eth_type;
+	/** IPv4 address */
+	t_u32 ipv4_addr;
+} MLAN_PACK_END filter_entry;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_MEF_CFG {
+	/** Criteria */
+	t_u32 criteria;
+	/** Number of entries */
+	t_u16 nentries;
+} MLAN_PACK_END HostCmd_DS_MEF_CFG;
+
+#define MAX_NUM_STACK_BYTES 100
+/** mef stack struct*/
+typedef MLAN_PACK_START struct _mef_stack {
+	/** length of byte*/
+	t_u16 sp;
+	/** data of filter items*/
+	t_u8 byte[MAX_NUM_STACK_BYTES];
+} MLAN_PACK_END mef_stack;
+
+/** mef entry struct */
+typedef MLAN_PACK_START struct _mef_entry_header {
+	/**mode:1->hostsleep;2->non hostsleep mode*/
+	t_u8 mode;
+	/**action=0->discard and not wake host
+	 * action=1->discard and wake host
+	 * action=3->allow and wake host*/
+	t_u8 action;
+} MLAN_PACK_END mef_entry_header;
+
+/** mef op struct is to help to generate mef data*/
+typedef MLAN_PACK_START struct _mef_op {
+	/** operand_type*/
+	t_u8 operand_type;
+	/** reserved*/
+	t_u8 rsvd[3];
+	/** data */
+	t_u8 val[MAX_NUM_BYTE_SEQ + 1];
+} MLAN_PACK_END mef_op;
+
+/* HostCmd_DS_802_11_SLEEP_PERIOD */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SLEEP_PERIOD {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+
+	/** Sleep Period in msec */
+	t_u16 sleep_pd;
+} MLAN_PACK_END HostCmd_DS_802_11_SLEEP_PERIOD;
+
+/* HostCmd_DS_802_11_SLEEP_PARAMS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SLEEP_PARAMS {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+	/** Sleep clock error in ppm */
+	t_u16 error;
+	/** Wakeup offset in usec */
+	t_u16 offset;
+	/** Clock stabilization time in usec */
+	t_u16 stable_time;
+	/** Control periodic calibration */
+	t_u8 cal_control;
+	/** Control the use of external sleep clock */
+	t_u8 external_sleep_clk;
+	/** Reserved field, should be set to zero */
+	t_u16 reserved;
+} MLAN_PACK_END HostCmd_DS_802_11_SLEEP_PARAMS;
+
+/** Sleep response control */
+typedef enum _sleep_resp_ctrl {
+	RESP_NOT_NEEDED = 0,
+	RESP_NEEDED,
+} sleep_resp_ctrl;
+
+/** Structure definition for the new ieee power save parameters*/
+typedef MLAN_PACK_START struct __ps_param {
+	/** Null packet interval */
+	t_u16 null_pkt_interval;
+	/** Num dtims */
+	t_u16 multiple_dtims;
+	/** becaon miss interval */
+	t_u16 bcn_miss_timeout;
+	/** local listen interval */
+	t_u16 local_listen_interval;
+	/** Adhoc awake period */
+	t_u16 adhoc_wake_period;
+	/** mode - (0x01 - firmware to automatically choose PS_POLL or NULL
+	 * mode, 0x02 - PS_POLL, 0x03 - NULL mode )
+	 */
+	t_u16 mode;
+	/** Delay to PS in milliseconds */
+	t_u16 delay_to_ps;
+} MLAN_PACK_END ps_param;
+
+/** Structure definition for the new auto deep sleep command */
+typedef MLAN_PACK_START struct __auto_ds_param {
+	/** Deep sleep inactivity timeout */
+	t_u16 deep_sleep_timeout;
+} MLAN_PACK_END auto_ds_param;
+
+/** Structure definition for sleep confirmation in the new ps command */
+typedef MLAN_PACK_START struct __sleep_confirm_param {
+	/** response control 0x00 - response not needed, 0x01 - response needed
+	 */
+	t_u16 resp_ctrl;
+} MLAN_PACK_END sleep_confirm_param;
+
+/** bitmap for get auto deepsleep */
+#define BITMAP_AUTO_DS 0x01
+/** bitmap for sta power save */
+#define BITMAP_STA_PS 0x10
+/** bitmap for beacon timeout */
+#define BITMAP_BCN_TMO 0x20
+/** bitmap for uap inactivity based PS */
+#define BITMAP_UAP_INACT_PS 0x100
+/** bitmap for uap DTIM PS */
+#define BITMAP_UAP_DTIM_PS 0x200
+/** Structure definition for the new ieee power save parameters*/
+typedef MLAN_PACK_START struct _auto_ps_param {
+	/** bitmap for enable power save mode */
+	t_u16 ps_bitmap;
+	/* auto deep sleep parameter,
+	 * sta power save parameter
+	 * uap inactivity parameter
+	 * uap DTIM parameter */
+} MLAN_PACK_END auto_ps_param;
+
+/** fix size for auto ps */
+#define AUTO_PS_FIX_SIZE 4
+
+/** TLV type : auto ds param */
+#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 0x71)	/* 0x0171 */
+/** TLV type : ps param */
+#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 0x72)	/* 0x0172 */
+/** TLV type : beacon timeout */
+#define TLV_TYPE_BCN_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 0x11F)	/* 0x011F */
+
+/** MrvlIEtypes_auto_ds_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auto_ds_param_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** auto ds param */
+	auto_ds_param param;
+} MLAN_PACK_END MrvlIEtypes_auto_ds_param_t;
+
+/** MrvlIEtypes_ps_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ps_param_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** ps param */
+	ps_param param;
+} MLAN_PACK_END MrvlIEtypes_ps_param_t;
+
+/** MrvlIEtypes_bcn_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bcn_timeout_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Beacon miss timeout period window */
+	t_u16 bcn_miss_tmo_window;
+	/** Beacon miss timeout period */
+	t_u16 bcn_miss_tmo_period;
+	/** Beacon reacquire timeout period window */
+	t_u16 bcn_rq_tmo_window;
+	/** Beacon reacquire timeout period */
+	t_u16 bcn_rq_tmo_period;
+} MLAN_PACK_END MrvlIEtypes_bcn_timeout_t;
+
+/** Structure definition for low power mode cfg command */
+typedef MLAN_PACK_START struct _HostCmd_DS_LOW_POWER_MODE_CFG {
+	/** Action */
+	t_u16 action;
+	/** Low power mode */
+	t_u16 lpm;
+} MLAN_PACK_END HostCmd_DS_LOW_POWER_MODE_CFG;
+
+/** Structure definition for new power save command */
+typedef MLAN_PACK_START struct _HostCmd_DS_PS_MODE_ENH {
+	/** Action */
+	t_u16 action;
+	/** Data speciifc to action */
+	/* For IEEE power save data will be as
+	 * UINT16 mode (0x01 - firmware to automatically choose PS_POLL or NULL
+	 * mode, 0x02 - PS_POLL, 0x03 - NULL mode ) UINT16 NullpacketInterval
+	 * UINT16 NumDtims
+	 * UINT16 BeaconMissInterval
+	 * UINT16 locallisteninterval
+	 * UINT16 adhocawakeperiod */
+
+	/* For auto deep sleep */
+	/* UINT16 Deep sleep inactivity timeout */
+
+	/* For PS sleep confirm
+	 * UINT16 responeCtrl - 0x00 - reponse from fw not needed, 0x01 -
+	 * response from fw is needed */
+
+	union {
+		/** PS param definition */
+		ps_param opt_ps;
+		/** Auto ds param definition */
+		auto_ds_param auto_ds;
+		/** Sleep comfirm param definition */
+		sleep_confirm_param sleep_cfm;
+		/** bitmap for get PS info and Disable PS mode */
+		t_u16 ps_bitmap;
+		/** auto ps param */
+		auto_ps_param auto_ps;
+	} params;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_MODE_ENH;
+
+/** FW VERSION tlv */
+#define TLV_TYPE_FW_VER_INFO (PROPRIETARY_TLV_BASE_ID + 0xC7)	/* 0x1C7 */
+
+/** MrvlIEtypes_fw_ver_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_fw_ver_info_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** API id */
+	t_u16 api_id;
+	/** major version */
+	t_u8 major_ver;
+	/** minor version */
+	t_u8 minor_ver;
+} MLAN_PACK_END MrvlIEtypes_fw_ver_info_t;
+
+/** API ID */
+enum API_VER_ID {
+	KEY_API_VER_ID = 1,
+	FW_API_VER_ID = 2,
+	UAP_FW_API_VER_ID = 3,
+	CHANRPT_API_VER_ID = 4,
+	FW_HOTFIX_VER_ID = 5,
+};
+
+/** FW AP V15 */
+#define HOST_API_VERSION_V15 15
+/** FW minor version 1 */
+#define FW_MINOR_VERSION_1 1
+
+/** UAP FW version 2 */
+#define UAP_FW_VERSION_2 0x2
+
+/** HostCMD_DS_APCMD_ACS_SCAN */
+typedef MLAN_PACK_START struct _HostCMD_DS_APCMD_ACS_SCAN {
+	/** band */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 chan;
+} MLAN_PACK_END HostCMD_DS_APCMD_ACS_SCAN;
+
+/** HostCmd_DS_GET_HW_SPEC */
+typedef MLAN_PACK_START struct _HostCmd_DS_GET_HW_SPEC {
+	/** HW Interface version number */
+	t_u16 hw_if_version;
+	/** HW version number */
+	t_u16 version;
+	/** Reserved field */
+	t_u16 reserved;
+	/** Max no of Multicast address  */
+	t_u16 num_of_mcast_adr;
+	/** MAC address */
+	t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Region Code */
+	t_u16 region_code;
+	/** Number of antenna used */
+	t_u16 number_of_antenna;
+	/** FW release number, example 0x1234=1.2.3.4 */
+	t_u32 fw_release_number;
+	/** Reserved field */
+	t_u32 reserved_1;
+	/** Reserved field */
+	t_u32 reserved_2;
+	/** Reserved field */
+	t_u32 reserved_3;
+	/** FW/HW Capability */
+	t_u32 fw_cap_info;
+	/** 802.11n Device Capabilities */
+	t_u32 dot_11n_dev_cap;
+	/** MIMO abstraction of MCSs supported by device */
+	t_u8 dev_mcs_support;
+	/** Valid end port at init */
+	t_u16 mp_end_port;
+	/** mgmt IE buffer count */
+	t_u16 mgmt_buf_count;
+	/** Reserved */
+	t_u32 reserved_8;
+	/** Reserved */
+	t_u32 reserved_9;
+	/** 802.11ac Device Capabilities */
+	t_u32 Dot11acDevCap;
+	/** MCSs supported by 802.11ac device */
+	t_u32 Dot11acMcsSupport;
+} MLAN_PACK_END HostCmd_DS_GET_HW_SPEC;
+
+#ifdef SDIO
+/* HostCmd_DS_SDIO_SP_RX_AGGR_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_SP_RX_AGGR_CFG {
+	t_u8 action;
+	t_u8 enable;
+	t_u16 sdio_block_size;
+} MLAN_PACK_END HostCmd_DS_SDIO_SP_RX_AGGR_CFG;
+#endif
+
+/**  HostCmd_DS_802_11_CFG_DATA */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_CFG_DATA {
+	/** Action */
+	t_u16 action;
+	/** Type */
+	t_u16 type;
+	/** Data length */
+	t_u16 data_len;
+	/** Data */
+} MLAN_PACK_END HostCmd_DS_802_11_CFG_DATA;
+
+/**  HostCmd_DS_CMD_802_11_RSSI_INFO_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RSSI_INFO_EXT {
+	/** Action */
+	t_u16 action;
+	/** Parameter used for exponential averaging for Data */
+	t_u16 ndata;
+	/** Parameter used for exponential averaging for Beacon */
+	t_u16 nbcn;
+	/** Last RSSI beacon TSF(only for Get action) */
+	t_u64 tsfbcn;
+	/** TLV info**/
+	t_u8 *tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_802_11_RSSI_INFO_EXT;
+
+/** TLV rssi info */
+#define TLV_TYPE_RSSI_INFO (PROPRIETARY_TLV_BASE_ID + 0xe5)	/* 0x01E5 */
+
+/** MrvlIEtypes_eapol_pkt_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RSSI_EXT_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Path ID
+	     [Bit1:Bit0] = [0:1]: path A
+	     [Bit1:Bit0] = [1:0]: path B
+	     [Bit1:Bit0] = [1:1]: combined signal of path A and path B
+	     [Bit7:Bit2] : Reserved
+	**/
+	t_u16 path_id;
+	/** Last Data RSSI in dBm */
+	t_s16 data_rssi_last;
+	/** Last Data NF in dBm */
+	t_s16 data_nf_last;
+	/** AVG DATA RSSI in dBm */
+	t_s16 data_rssi_avg;
+	/** AVG DATA NF in dBm */
+	t_s16 data_nf_avg;
+	/** Last BEACON RSSI in dBm */
+	t_s16 bcn_rssi_last;
+	/** Last BEACON NF in dBm */
+	t_s16 bcn_nf_last;
+	/** AVG BEACON RSSI in dBm */
+	t_s16 bcn_rssi_avg;
+	/** AVG BEACON NF in dBm */
+	t_s16 bcn_nf_avg;
+} MLAN_PACK_END MrvlIEtypes_RSSI_EXT_t;
+
+/**  HostCmd_DS_CMD_802_11_RSSI_INFO */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RSSI_INFO {
+	/** Action */
+	t_u16 action;
+	/** Parameter used for exponential averaging for Data */
+	t_u16 ndata;
+	/** Parameter used for exponential averaging for Beacon */
+	t_u16 nbcn;
+	/** Reserved field 0 */
+	t_u16 reserved[9];
+	/** Reserved field 1 */
+	t_u64 reserved_1;
+} MLAN_PACK_END HostCmd_DS_802_11_RSSI_INFO;
+
+/** HostCmd_DS_802_11_RSSI_INFO_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RSSI_INFO_RSP {
+	/** Action */
+	t_u16 action;
+	/** Parameter used for exponential averaging for Data */
+	t_u16 ndata;
+	/** Parameter used for exponential averaging for beacon */
+	t_u16 nbcn;
+	/** Last Data RSSI in dBm */
+	t_s16 data_rssi_last;
+	/** Last Data NF in dBm */
+	t_s16 data_nf_last;
+	/** AVG DATA RSSI in dBm */
+	t_s16 data_rssi_avg;
+	/** AVG DATA NF in dBm */
+	t_s16 data_nf_avg;
+	/** Last BEACON RSSI in dBm */
+	t_s16 bcn_rssi_last;
+	/** Last BEACON NF in dBm */
+	t_s16 bcn_nf_last;
+	/** AVG BEACON RSSI in dBm */
+	t_s16 bcn_rssi_avg;
+	/** AVG BEACON NF in dBm */
+	t_s16 bcn_nf_avg;
+	/** Last RSSI Beacon TSF */
+	t_u64 tsf_bcn;
+} MLAN_PACK_END HostCmd_DS_802_11_RSSI_INFO_RSP;
+
+/** HostCmd_DS_802_11_MAC_ADDRESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_MAC_ADDRESS {
+	/** Action */
+	t_u16 action;
+	/** MAC address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_802_11_MAC_ADDRESS;
+
+/** HostCmd_DS_MAC_CONTROL */
+typedef MLAN_PACK_START struct _HostCmd_DS_MAC_CONTROL {
+	/** Action */
+	t_u32 action;
+} MLAN_PACK_END HostCmd_DS_MAC_CONTROL;
+
+/** HostCmd_DS_CMD_TX_DATA_PAUSE */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_TX_DATA_PAUSE {
+	/** Action */
+	t_u16 action;
+	/** Enable/disable Tx data pause */
+	t_u8 enable_tx_pause;
+	/** Max number of TX buffers allowed for all PS clients*/
+	t_u8 pause_tx_count;
+} MLAN_PACK_END HostCmd_DS_CMD_TX_DATA_PAUSE;
+
+/** TLV type : TX pause TLV */
+#define TLV_TYPE_TX_PAUSE (PROPRIETARY_TLV_BASE_ID + 0x94)	/* 0x0194 */
+/** MrvlIEtypes_SsIdParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_tx_pause_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** peer mac address */
+	t_u8 peermac[MLAN_MAC_ADDR_LENGTH];
+	/** Tx pause state, 1--pause, 0--free flowing */
+	t_u8 tx_pause;
+	/** total packets queued for the client */
+	t_u8 pkt_cnt;
+} MLAN_PACK_END MrvlIEtypes_tx_pause_t;
+
+/**  HostCmd_CMD_MAC_MULTICAST_ADR */
+typedef MLAN_PACK_START struct _HostCmd_DS_MAC_MULTICAST_ADR {
+	/** Action */
+	t_u16 action;
+	/** Number of addresses */
+	t_u16 num_of_adrs;
+	/** List of MAC */
+	t_u8 mac_list[MLAN_MAC_ADDR_LENGTH * MLAN_MAX_MULTICAST_LIST_SIZE];
+} MLAN_PACK_END HostCmd_DS_MAC_MULTICAST_ADR;
+
+/**  HostCmd_CMD_802_11_DEAUTHENTICATE */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_DEAUTHENTICATE {
+	/** MAC address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Deauthentication resaon code */
+	t_u16 reason_code;
+} MLAN_PACK_END HostCmd_DS_802_11_DEAUTHENTICATE;
+
+/** HostCmd_DS_802_11_ASSOCIATE */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ASSOCIATE {
+	/** Peer STA address */
+	t_u8 peer_sta_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+	/** Listen interval */
+	t_u16 listen_interval;
+	/** Beacon period */
+	t_u16 beacon_period;
+	/** DTIM period */
+	t_u8 dtim_period;
+
+	/**
+	 *  MrvlIEtypes_SsIdParamSet_t  SsIdParamSet;
+	 *  MrvlIEtypes_PhyParamSet_t   PhyParamSet;
+	 *  MrvlIEtypes_SsParamSet_t    SsParamSet;
+	 *  MrvlIEtypes_RatesParamSet_t RatesParamSet;
+	 */
+} MLAN_PACK_END HostCmd_DS_802_11_ASSOCIATE;
+
+/** HostCmd_CMD_802_11_ASSOCIATE response */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ASSOCIATE_RSP {
+	/** Association response structure */
+	IEEEtypes_AssocRsp_t assoc_rsp;
+} MLAN_PACK_END HostCmd_DS_802_11_ASSOCIATE_RSP;
+
+/** HostCmd_DS_802_11_AD_HOC_START*/
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_START {
+	/** AdHoc SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+	/** BSS mode */
+	t_u8 bss_mode;
+	/** Beacon period */
+	t_u16 beacon_period;
+	/** DTIM period */
+	t_u8 dtim_period;
+	/** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+	/** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+	/** Reserved field */
+	t_u16 reserved1;
+	/** Capability information */
+	IEEEtypes_CapInfo_t cap;
+	/** Supported data rates */
+	t_u8 DataRate[HOSTCMD_SUPPORTED_RATES];
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_START;
+
+/**  HostCmd_CMD_802_11_AD_HOC_START response */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_START_RESULT {
+	/** Padding */
+	t_u8 pad[3];
+	/** AdHoc BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Padding to sync with FW structure*/
+	t_u8 pad2[2];
+	/** Result */
+	t_u8 result;
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_START_RESULT;
+
+/**  HostCmd_CMD_802_11_AD_HOC_START response */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_JOIN_RESULT {
+	/** Result */
+	t_u8 result;
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_JOIN_RESULT;
+
+/** AdHoc_BssDesc_t */
+typedef MLAN_PACK_START struct _AdHoc_BssDesc_t {
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+	/** BSS mode */
+	t_u8 bss_mode;
+	/** Beacon period */
+	t_u16 beacon_period;
+	/** DTIM period */
+	t_u8 dtim_period;
+	/** Timestamp */
+	t_u8 time_stamp[8];
+	/** Local time */
+	t_u8 local_time[8];
+	/** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+	/** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+	/** Capability information */
+	IEEEtypes_CapInfo_t cap;
+	/** Supported data rates */
+	t_u8 data_rates[HOSTCMD_SUPPORTED_RATES];
+
+	/*
+	 *  DO NOT ADD ANY FIELDS TO THIS STRUCTURE.
+	 *  It is used in the Adhoc join command and will cause a
+	 *  binary layout mismatch with the firmware
+	 */
+} MLAN_PACK_END AdHoc_BssDesc_t;
+
+/** HostCmd_DS_802_11_AD_HOC_JOIN */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_AD_HOC_JOIN {
+	/** AdHoc BSS descriptor */
+	AdHoc_BssDesc_t bss_descriptor;
+	/** Reserved field */
+	t_u16 reserved1;
+	/** Reserved field */
+	t_u16 reserved2;
+} MLAN_PACK_END HostCmd_DS_802_11_AD_HOC_JOIN;
+
+#if defined(SDIO)
+/** Interrupt Raising Edge */
+#define INT_RASING_EDGE 0
+/** Interrupt Falling Edge */
+#define INT_FALLING_EDGE 1
+
+/** Delay 1 usec */
+#define DELAY_1_US 1
+
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_GPIO_INT_CONFIG {
+	/** Action */
+	t_u16 action;
+	/** GPIO interrupt pin */
+	t_u16 gpio_pin;
+	/** GPIO interrupt edge, 1: failing edge; 0: raising edge */
+	t_u16 gpio_int_edge;
+	/** GPIO interrupt pulse widthin usec units */
+	t_u16 gpio_pulse_width;
+} MLAN_PACK_END HostCmd_DS_SDIO_GPIO_INT_CONFIG;
+#endif /* GPIO_SDIO_INT_CTRL */
+
+typedef MLAN_PACK_START struct _HostCmd_DS_SDIO_PULL_CTRL {
+	/** Action */
+	t_u16 action;
+	/** The delay of pulling up in us */
+	t_u16 pull_up;
+	/** The delay of pulling down in us */
+	t_u16 pull_down;
+} MLAN_PACK_END HostCmd_DS_SDIO_PULL_CTRL;
+
+/** HostCmd_DS_802_11_GET_LOG */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_GET_LOG {
+	/** Number of multicast transmitted frames */
+	t_u32 mcast_tx_frame;
+	/** Number of failures */
+	t_u32 failed;
+	/** Number of retries */
+	t_u32 retry;
+	/** Number of multiretries */
+	t_u32 multiretry;
+	/** Number of duplicate frames */
+	t_u32 frame_dup;
+	/** Number of RTS success */
+	t_u32 rts_success;
+	/** Number of RTS failure */
+	t_u32 rts_failure;
+	/** Number of acknowledgement failure */
+	t_u32 ack_failure;
+	/** Number of fragmented packets received */
+	t_u32 rx_frag;
+	/** Number of multicast frames received */
+	t_u32 mcast_rx_frame;
+	/** FCS error */
+	t_u32 fcs_error;
+	/** Number of transmitted frames */
+	t_u32 tx_frame;
+	/** Reserved field */
+	t_u32 reserved;
+	/** Number of WEP icv error for each key */
+	t_u32 wep_icv_err_cnt[4];
+	/** Beacon received count */
+	t_u32 bcn_rcv_cnt;
+	/** Beacon missed count */
+	t_u32 bcn_miss_cnt;
+	/** Tx frag count */
+	t_u32 tx_frag_cnt;
+	/** Qos Tx frag count */
+	t_u32 qos_tx_frag_cnt[8];
+	/** Qos failed count */
+	t_u32 qos_failed_cnt[8];
+	/** Qos retry count */
+	t_u32 qos_retry_cnt[8];
+	/** Qos multi retry count */
+	t_u32 qos_multi_retry_cnt[8];
+	/** Qos frame dup count */
+	t_u32 qos_frm_dup_cnt[8];
+	/** Qos rts success count */
+	t_u32 qos_rts_suc_cnt[8];
+	/** Qos rts failure count */
+	t_u32 qos_rts_failure_cnt[8];
+	/** Qos ack failure count */
+	t_u32 qos_ack_failure_cnt[8];
+	/** Qos Rx frag count */
+	t_u32 qos_rx_frag_cnt[8];
+	/** Qos Tx frame count */
+	t_u32 qos_tx_frm_cnt[8];
+	/** Qos discarded frame count */
+	t_u32 qos_discarded_frm_cnt[8];
+	/** Qos mpdus Rx count */
+	t_u32 qos_mpdus_rx_cnt[8];
+	/** Qos retry rx count */
+	t_u32 qos_retries_rx_cnt[8];
+	/** CMAC ICV errors count */
+	t_u32 cmacicv_errors;
+	/** CMAC replays count */
+	t_u32 cmac_replays;
+	/** mgmt CCMP replays count */
+	t_u32 mgmt_ccmp_replays;
+	/** TKIP ICV errors count */
+	t_u32 tkipicv_errors;
+	/** TKIP replays count */
+	t_u32 tkip_replays;
+	/** CCMP decrypt errors count */
+	t_u32 ccmp_decrypt_errors;
+	/** CCMP replays count */
+	t_u32 ccmp_replays;
+	/** Tx amsdu count */
+	t_u32 tx_amsdu_cnt;
+	/** failed amsdu count */
+	t_u32 failed_amsdu_cnt;
+	/** retry amsdu count */
+	t_u32 retry_amsdu_cnt;
+	/** multi-retry amsdu count */
+	t_u32 multi_retry_amsdu_cnt;
+	/** Tx octets in amsdu count */
+	t_u64 tx_octets_in_amsdu_cnt;
+	/** amsdu ack failure count */
+	t_u32 amsdu_ack_failure_cnt;
+	/** Rx amsdu count */
+	t_u32 rx_amsdu_cnt;
+	/** Rx octets in amsdu count */
+	t_u64 rx_octets_in_amsdu_cnt;
+	/** Tx ampdu count */
+	t_u32 tx_ampdu_cnt;
+	/** tx mpdus in ampdu count */
+	t_u32 tx_mpdus_in_ampdu_cnt;
+	/** tx octets in ampdu count */
+	t_u64 tx_octets_in_ampdu_cnt;
+	/** ampdu Rx count */
+	t_u32 ampdu_rx_cnt;
+	/** mpdu in Rx ampdu count */
+	t_u32 mpdu_in_rx_ampdu_cnt;
+	/** Rx octets ampdu count */
+	t_u64 rx_octets_in_ampdu_cnt;
+	/** ampdu delimiter CRC error count */
+	t_u32 ampdu_delimiter_crc_error_cnt;
+    /** Rx Stuck Related Info*/
+    /** Rx Stuck Issue count */
+	t_u32 rx_stuck_issue_cnt[2];
+    /** Rx Stuck Recovery count */
+	t_u32 rx_stuck_recovery_cnt;
+    /** Rx Stuck TSF */
+	t_u64 rx_stuck_tsf[2];
+    /** Tx Watchdog Recovery Related Info */
+    /** Tx Watchdog Recovery count */
+	t_u32 tx_watchdog_recovery_cnt;
+    /** Tx Watchdog TSF */
+	t_u64 tx_watchdog_tsf[2];
+    /** Channel Switch Related Info */
+    /** Channel Switch Announcement Sent */
+	t_u32 channel_switch_ann_sent;
+    /** Channel Switch State */
+	t_u32 channel_switch_state;
+    /** Register Class */
+	t_u32 reg_class;
+    /** Channel Number */
+	t_u32 channel_number;
+    /** Channel Switch Mode */
+	t_u32 channel_switch_mode;
+    /** Reset Rx Mac Count */
+	t_u32 rx_reset_mac_recovery_cnt;
+    /** ISR2 Not Done Count*/
+	t_u32 rx_Isr2_NotDone_Cnt;
+    /** GDMA Abort Count */
+	t_u32 gdma_abort_cnt;
+    /** Rx Reset MAC Count */
+	t_u32 g_reset_rx_mac_cnt;
+	//Ownership error counters
+	/*Error Ownership error count */
+	t_u32 dwCtlErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwBcnErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwMgtErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwDatErrCnt;
+	/*BIGTK MME good count */
+	t_u32 bigtk_mmeGoodCnt;
+	/*BIGTK Replay error count */
+	t_u32 bigtk_replayErrCnt;
+	/*BIGTK MIC error count */
+	t_u32 bigtk_micErrCnt;
+	/*BIGTK MME not included count */
+	t_u32 bigtk_mmeNotFoundCnt;
+} MLAN_PACK_END HostCmd_DS_802_11_GET_LOG;
+
+/* maln wifi rate */
+typedef MLAN_PACK_START struct _mlan_wifi_rate {
+	/** 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+	t_u8 preamble;
+	/** 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+	t_u8 nss;
+	/** 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+	t_u8 bw;
+	/** OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps
+	 */
+	/** HT/VHT it would be mcs index */
+	t_u8 rateMcsIdx;
+	/** units of 100 Kbps */
+	t_u32 bitrate;
+} MLAN_PACK_START mlan_wifi_rate;
+
+/** channel information */
+typedef MLAN_PACK_START struct {
+	/** channel width (20, 40, 80, 80+80, 160) */
+	t_u32 width;
+	/** primary 20 MHz channel */
+	t_u32 center_freq;
+	/** center frequency (MHz) first segment */
+	t_u32 center_freq0;
+	/** center frequency (MHz) second segment */
+	t_u32 center_freq1;
+} MLAN_PACK_END mlan_wifi_channel_info;
+
+/** channel statistics */
+typedef MLAN_PACK_START struct {
+	/** channel */
+	mlan_wifi_channel_info channel;
+	/** msecs the radio is awake (32 bits number accruing over time) */
+	t_u32 on_time;
+	/** msecs the CCA register is busy (32 bits number accruing over time)
+	 */
+	t_u32 cca_busy_time;
+} MLAN_PACK_END mlan_wifi_channel_stat;
+
+/** radio statistics */
+typedef MLAN_PACK_START struct {
+	/** supported wifi in case of multi radio */
+	t_u32 radio;
+	/** msecs the radio is awake */
+	t_u32 on_time;
+	/** msecs the radio is transmitting */
+	t_u32 tx_time;
+	/**  TBD: num_tx_levels: number of radio transmit power levels */
+	t_u32 reserved0;
+	/** TBD: tx_time_per_levels: pointer to an array of radio transmit per
+	 * power levels in msecs accured over time */
+	t_u32 reserved1;
+	/** msecs the radio is in active receive */
+	t_u32 rx_time;
+	/** msecs the radio is awake due to all scan */
+	t_u32 on_time_scan;
+	/** msecs the radio is awake due to NAN */
+	t_u32 on_time_nbd;
+	/** msecs the radio is awake due to G?scan */
+	t_u32 on_time_gscan;
+	/** msecs the radio is awake due to roam?scan */
+	t_u32 on_time_roam_scan;
+	/** msecs the radio is awake due to PNO scan */
+	t_u32 on_time_pno_scan;
+	/** msecs the radio is awake due to HS2.0 scans and GAS exchange */
+	t_u32 on_time_hs20;
+	/** number of channels */
+	t_u32 num_channels;
+	/** channel statistics */
+	mlan_wifi_channel_stat channels[MAX_NUM_CHAN];	// support only 1
+	// channel, so keep it.
+} MLAN_PACK_END mlan_wifi_radio_stat;
+
+/** per rate statistics */
+typedef MLAN_PACK_START struct {
+	/** rate information */
+	mlan_wifi_rate rate;
+	/** number of successfully transmitted data pkts (ACK rcvd) */
+	t_u32 tx_mpdu;
+	/** number of received data pkts */
+	t_u32 rx_mpdu;
+	/** number of data packet losses (no ACK) */
+	t_u32 mpdu_lost;
+	/** total number of data pkt retries */
+	t_u32 retries;
+	/** number of short data pkt retries */
+	t_u32 retries_short;
+	/** number of long data pkt retries */
+	t_u32 retries_long;
+} MLAN_PACK_END mlan_wifi_rate_stat;
+
+/** per peer statistics */
+typedef MLAN_PACK_START struct {
+	/** peer type (AP, TDLS, GO etc.) */
+	t_u8 type;
+	/** mac address */
+	t_u8 peer_mac_address[6];
+	/** peer WIFI_CAPABILITY_XXX */
+	t_u32 capabilities;
+	/** number of rates */
+	t_u32 num_rate;
+	/** per rate statistics, number of entries  = num_rate */
+	mlan_wifi_rate_stat rate_stats[];
+} MLAN_PACK_END mlan_wifi_peer_info;
+
+/* per access category statistics */
+typedef MLAN_PACK_START struct {
+	/** access category (VI, VO, BE, BK) */
+	t_u32 ac;
+	/** number of successfully transmitted unicast data pkts (ACK rcvd) */
+	t_u32 tx_mpdu;
+	/** number of received unicast mpdus */
+	t_u32 rx_mpdu;
+	/** number of succesfully transmitted multicast data packets */
+	/** STA case: implies ACK received from AP for the unicast packet in
+	 * which mcast pkt was sent */
+	t_u32 tx_mcast;
+	/** number of received multicast data packets */
+	t_u32 rx_mcast;
+	/** number of received unicast a-mpdus */
+	t_u32 rx_ampdu;
+	/** number of transmitted unicast a-mpdus */
+	t_u32 tx_ampdu;
+	/** number of data pkt losses (no ACK) */
+	t_u32 mpdu_lost;
+	/** total number of data pkt retries */
+	t_u32 retries;
+	/** number of short data pkt retries */
+	t_u32 retries_short;
+	/** number of long data pkt retries */
+	t_u32 retries_long;
+	/** data pkt min contention time (usecs) */
+	t_u32 contention_time_min;
+	/** data pkt max contention time (usecs) */
+	t_u32 contention_time_max;
+	/** data pkt avg contention time (usecs) */
+	t_u32 contention_time_avg;
+	/** num of data pkts used for contention statistics */
+	t_u32 contention_num_samples;
+} MLAN_PACK_END mlan_wifi_wmm_ac_stat;
+
+/** interface statistics */
+typedef MLAN_PACK_START struct {
+	/** access point beacon received count from connected AP */
+	t_u32 beacon_rx;
+	/** Average beacon offset encountered (beacon_TSF - TBTT)
+	 *    the average_tsf_offset field is used so as to calculate the
+	 *    typical beacon contention time on the channel as well may be
+	 *    used to debug beacon synchronization and related power consumption
+	 * issue
+	 */
+	t_u64 average_tsf_offset;
+	/** indicate that this AP typically leaks packets beyond the driver
+	 * guard time */
+	t_u32 leaky_ap_detected;
+	/** average number of frame leaked by AP after frame with PM bit set was
+	 * ACK'ed by AP */
+	t_u32 leaky_ap_avg_num_frames_leaked;
+	/** Guard time currently in force (when implementing IEEE power
+	 * management based on frame control PM bit), How long driver waits
+	 * before shutting down the radio and after receiving an ACK for a data
+	 * frame with PM bit set)
+	 */
+	t_u32 leaky_ap_guard_time;
+	/** access point mgmt frames received count from connected AP (including
+	 * Beacon) */
+	t_u32 mgmt_rx;
+	/** action frames received count */
+	t_u32 mgmt_action_rx;
+	/** action frames transmit count */
+	t_u32 mgmt_action_tx;
+	/** access Point Beacon and Management frames RSSI (averaged) */
+	t_u32 rssi_mgmt;
+	/** access Point Data Frames RSSI (averaged) from connected AP */
+	t_u32 rssi_data;
+	/** access Point ACK RSSI (averaged) from connected AP */
+	t_u32 rssi_ack;
+	/** per ac data packet statistics */
+	mlan_wifi_wmm_ac_stat ac[MAX_AC_QUEUES];
+	/** number of peers */
+	t_u32 num_peers;
+	/** per peer statistics */
+	mlan_wifi_peer_info peer_info[];
+} MLAN_PACK_END mlan_wifi_iface_stat;
+
+/** MrvlIETypes_llStatIface_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_llStatIface_t {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** Frame Control */
+	mlan_wifi_iface_stat ifaceStat;
+	/* t_u8 frame_contents[]; */
+} MLAN_PACK_END MrvlIETypes_llStatIface_t;
+
+/** MrvlIETypes_llStatRadio_t */
+typedef MLAN_PACK_START struct _MrvlIETypes_llStatRadio_t {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** Frame Control */
+	mlan_wifi_radio_stat radioStat[MAX_RADIO];
+	/* t_u8 frame_contents[]; */
+} MLAN_PACK_END MrvlIETypes_llStatRadio_t;
+
+#define TYPE_IFACE_STAT MBIT(0)
+#define TYPE_RADIO_STAT MBIT(1)
+#define TYPE_PEER_INFO MBIT(2)
+/** HostCmd_DS_802_11_LINK_STATISTIC */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_LINK_STATISTIC {
+	/** Action : HostCmd_ACT_GEN_GET/SET/REMOVE */
+	t_u16 action;
+	/** statistic which would be get in action HostCmd_ACT_GEN_GET :
+	 * TYPE_IFACE_STAT/RADIO_STAT/PEER_INFO */
+	t_u16 stat_type;
+	/* threshold to classify the pkts as short or long, packet size <
+	 * mpdu_size_threshold => short */
+	t_u32 mpdu_size_threshold;
+	/* set for field debug mode. Driver should collect all statistics
+	 * regardless of performance impact. */
+	t_u32 aggressive_statistics_gathering;
+	/** Value */
+	t_u8 value[];
+} MLAN_PACK_END HostCmd_DS_802_11_LINK_STATISTIC;
+
+/**_HostCmd_TX_RATE_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_TX_RATE_QUERY {
+	/** Tx rate */
+	t_u8 tx_rate;
+    /** V14 FW: Ht Info
+     * [Bit 0] RxRate format: LG=0, HT=1
+     * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1
+     * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */
+	/** Tx Rate Info:
+	 * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
+	 * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
+	 * [Bit 4]   HT/VHT Guard Interval: LGI = 0, SGI = 1
+	 * [Bit4,Bit7] AX Guard Interval: 00, 01, 02 */
+	t_u8 tx_rate_info;
+	/**
+	 * BIT0: DCM
+	 * BIT3-BIT1: tone mode
+	 **  000: 26  tone
+	 **  001: 52  tone
+	 **  010: 106 tone
+	 **  011: 242 tone
+	 **  100: 484 tone
+	 **  101: 996 tone
+	 * BIT7-BIT4: resvd
+	 **/
+	t_u8 ext_tx_rate_info;
+} MLAN_PACK_END HostCmd_TX_RATE_QUERY;
+
+typedef MLAN_PACK_START struct _hs_config_param {
+	/** bit0=1: broadcast data
+	 * bit1=1: unicast data
+	 * bit2=1: mac events
+	 * bit3=1: multicast data
+	 */
+	t_u32 conditions;
+	/** GPIO pin or 0xff for interface */
+	t_u8 gpio;
+	/** gap in milliseconds or or 0xff for special setting when
+	 *  GPIO is used to wakeup host
+	 */
+	t_u8 gap;
+} MLAN_PACK_END hs_config_param;
+
+/** HS Action 0x0001 - Configure enhanced host sleep mode,
+ * 0x0002 - Activate enhanced host sleep mode
+ */
+typedef enum _Host_Sleep_Action {
+	HS_CONFIGURE = 0x0001,
+	HS_ACTIVATE = 0x0002,
+} Host_Sleep_Action;
+
+/** Structure definition for activating enhanced hs */
+typedef MLAN_PACK_START struct __hs_activate_param {
+	/** response control 0x00 - response not needed, 0x01 - response needed
+	 */
+	t_u16 resp_ctrl;
+} MLAN_PACK_END hs_activate_param;
+
+/** HostCmd_DS_802_11_HS_CFG_ENH */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_HS_CFG_ENH {
+	/** Action 0x0001 - Configure enhanced host sleep mode,
+	 *  0x0002 - Activate enhanced host sleep mode
+	 */
+	t_u16 action;
+
+	union {
+		/** Configure enhanced hs */
+		hs_config_param hs_config;
+		/** Activate enhanced hs */
+		hs_activate_param hs_activate;
+	} params;
+} MLAN_PACK_END HostCmd_DS_802_11_HS_CFG_ENH;
+
+/** HostCmd_CMD_802_11_ROBUSTCOEX */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ROBUSTCOEX {
+	/** Action */
+	t_u16 action;
+	/** RSVD */
+	t_u16 rsvd;
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_802_11_ROBUSTCOEX;
+
+/** HostCmd_CMD_DMCS_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_DMCS_CFG {
+	/** Action */
+	t_u16 action;
+	/** SubCmd of DMCS */
+	t_u16 subcmd;
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_DMCS_CFG;
+
+#if defined(PCIE)
+/** HostCmd_CMD_SSU */
+typedef MLAN_PACK_START struct _HostCmd_DS_SSU_CFG {
+	/** Action */
+	t_u16 action;
+	/** # of FFT sample to skip */
+	t_u32 nskip;
+	/** # of FFT sample selected to dump */
+	t_u32 nsel;
+	/** Down sample ADC input for buffering */
+	t_u32 adcdownsample;
+	/** Mask Out ADC Data From Spectral Packet */
+	t_u32 mask_adc_pkt;
+	/** Enable 16-Bit FFT Output Data Precision in Spectral Packet */
+	t_u32 out_16bits;
+	/** Enable power spectrum in dB for spectral packet */
+	t_u32 spec_pwr_enable;
+	/** Enable Spectral Packet Rate Reduction in dB output format */
+	t_u32 rate_deduction;
+	/** # of Spectral packets over which spectral data to be averaged */
+	t_u32 n_pkt_avg;
+	/** ret: Calculated fft length in dw */
+	t_u32 fft_len;
+	/** ret: Calculated adc length in dw */
+	t_u32 adc_len;
+	/** ret: Calculated record length in dw */
+	t_u32 rec_len;
+	/** Mapped address of DMA buffer */
+	t_u32 buffer_base_addr[2];
+	/** Total size of allocated buffer for SSU DMA */
+	t_u32 buffer_pool_size;
+	/** ret: Calculated buffer numbers */
+	t_u32 number_of_buffers;
+	/** ret: Calculated buffer size in byte for each descriptor */
+	t_u32 buffer_size;
+} MLAN_PACK_END HostCmd_DS_SSU_CFG;
+#endif
+
+typedef MLAN_PACK_START struct _HostCmd_DS_HAL_PHY_CFG {
+	/** Action */
+	t_u16 action;
+	/** 11b pwr spectral density mask enable/disable */
+	t_u8 dot11b_psd_mask_cfg;
+	/** reserved fields for future hal/phy cfg use */
+	t_u8 reserved[7];
+} MLAN_PACK_END HostCmd_DS_HAL_PHY_CFG;
+
+/** SNMP_MIB_INDEX */
+typedef enum _SNMP_MIB_INDEX {
+	OpRateSet_i = 1,
+	DtimPeriod_i = 3,
+	RtsThresh_i = 5,
+	ShortRetryLim_i = 6,
+	LongRetryLim_i = 7,
+	FragThresh_i = 8,
+	Dot11D_i = 9,
+	Dot11H_i = 10,
+	WwsMode_i = 17,
+	Thermal_i = 34,
+	NullPktPeriod_i = 37,
+	SignalextEnable_i = 41,
+	ECSAEnable_i = 42,
+	StopDeauth_i = 44,
+} SNMP_MIB_INDEX;
+
+/** max SNMP buf size */
+#define MAX_SNMP_BUF_SIZE 128
+
+#ifdef UAP_SUPPORT
+/**  HostCmd_CMD_802_11_SNMP_MIB */
+typedef MLAN_PACK_START struct _HostCmd_DS_UAP_802_11_SNMP_MIB {
+	/** SNMP query type */
+	t_u16 query_type;
+	/** snmp oid buf */
+	t_u8 snmp_data[];
+} MLAN_PACK_END HostCmd_DS_UAP_802_11_SNMP_MIB;
+#endif
+
+/**  HostCmd_CMD_802_11_SNMP_MIB */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SNMP_MIB {
+	/** SNMP query type */
+	t_u16 query_type;
+	/** SNMP object ID */
+	t_u16 oid;
+	/** SNMP buffer size */
+	t_u16 buf_size;
+	/** Value */
+	t_u8 value[1];
+} MLAN_PACK_END HostCmd_DS_802_11_SNMP_MIB;
+
+/** Radio on */
+#define RADIO_ON 0x01
+/** Radio off */
+#define RADIO_OFF 0x00
+
+/** HostCmd_CMD_802_11_RADIO_CONTROL */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RADIO_CONTROL {
+	/** Action */
+	t_u16 action;
+	/** Control */
+	t_u16 control;
+} MLAN_PACK_END HostCmd_DS_802_11_RADIO_CONTROL;
+
+/** MrvlRateScope_t */
+typedef MLAN_PACK_START struct _MrvlRateScope_t {
+	/** Header Type */
+	t_u16 type;
+	/** Header Length */
+	t_u16 length;
+	/** Bitmap of HR/DSSS rates */
+	t_u16 hr_dsss_rate_bitmap;
+	/** Bitmap of OFDM rates */
+	t_u16 ofdm_rate_bitmap;
+	/** Bitmap of HT-MCSs allowed for initial rate */
+	t_u16 ht_mcs_rate_bitmap[8];
+	t_u16 vht_mcs_rate_bitmap[8];
+	t_u16 he_mcs_rate_bitmap[8];
+} MLAN_PACK_END MrvlRateScope_t;
+
+/** MrvlRateDropPattern_t */
+typedef MLAN_PACK_START struct _MrvlRateDropPattern_t {
+	/** Header Type */
+	t_u16 type;
+	/** Header Length */
+	t_u16 length;
+	/** Rate Drop Mode */
+	t_u32 rate_drop_mode;
+	/* MrvlRateDropControl_t RateDropControl[]; */
+} MLAN_PACK_END MrvlRateDropPattern_t;
+
+typedef MLAN_PACK_START struct _MrvlIETypes_rate_setting_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Rate Setting */
+	t_u16 rate_setting;
+} MLAN_PACK_END MrvlIETypes_rate_setting_t;
+
+/** HostCmd_DS_TX_RATE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RATE_CFG {
+	/** Action */
+	t_u16 action;
+    /** V14 FW: cfg_index */
+    /** V15+ FW: reserved_1 */
+	t_u16 cfg_index;
+	/* MrvlRateScope_t RateScope;
+	 * MrvlRateDropPattern_t RateDrop; */
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_TX_RATE_CFG;
+
+/** Power_Group_t */
+typedef MLAN_PACK_START struct _Power_Group_t {
+	/** Modulation Class */
+	t_u8 modulation_class;
+	/** MCS Code or Legacy RateID */
+	t_u8 first_rate_code;
+	/** MCS Code or Legacy RateID */
+	t_u8 last_rate_code;
+	/** Power Adjustment Step */
+	t_s8 power_step;
+	/** Minimal Tx Power Level [dBm] */
+	t_s8 power_min;
+	/** Maximal Tx Power Level [dBm] */
+	t_s8 power_max;
+	/** 0: HTBW20, 1: HTBW40 */
+	t_u8 ht_bandwidth;
+	/** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END Power_Group_t;
+
+/** MrvlTypes_Power_Group_t */
+typedef MLAN_PACK_START struct _MrvlTypes_Power_Group_t {
+	/** Header Type */
+	t_u16 type;
+	/** Header Length */
+	t_u16 length;
+	/* Power_Group_t PowerGroups */
+} MLAN_PACK_END MrvlTypes_Power_Group_t;
+
+/** HostCmd_CMD_TXPWR_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TXPWR_CFG {
+	/** Action */
+	t_u16 action;
+	/** Power group configuration index */
+	t_u16 cfg_index;
+	/** Power group configuration mode */
+	t_u32 mode;
+	/* MrvlTypes_Power_Group_t PowerGrpCfg[] */
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_TXPWR_CFG;
+
+/** HostCmd_CMD_802_11_RF_TX_POWER */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RF_TX_POWER {
+	/** Action */
+	t_u16 action;
+	/** Current power level */
+	t_s16 current_level;
+	/** Maximum power */
+	t_s8 max_power;
+	/** Minimum power */
+	t_s8 min_power;
+} MLAN_PACK_END HostCmd_DS_802_11_RF_TX_POWER;
+
+/** Connection type infra */
+#define CONNECTION_TYPE_INFRA 0
+/** Connection type adhoc */
+#define CONNECTION_TYPE_ADHOC 1
+#ifdef WIFI_DIRECT_SUPPORT
+/** BSS Mode: WIFIDIRECT Client */
+#define BSS_MODE_WIFIDIRECT_CLIENT 0
+/** BSS Mode: WIFIDIRECT GO */
+#define BSS_MODE_WIFIDIRECT_GO 2
+#endif
+/** HostCmd_DS_SET_BSS_MODE */
+typedef MLAN_PACK_START struct _HostCmd_DS_SET_BSS_MODE {
+	/** connection type */
+	t_u8 con_type;
+} MLAN_PACK_END HostCmd_DS_SET_BSS_MODE;
+
+/** HT Capabilities element */
+typedef MLAN_PACK_START struct _MrvlIETypes_HTCap_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** HTCap struct */
+	HTCap_t ht_cap;
+} MLAN_PACK_END MrvlIETypes_HTCap_t;
+/** VHT Capabilities element */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTCap_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** VHTCap struct */
+	VHT_capa_t vht_cap;
+} MLAN_PACK_END MrvlIETypes_VHTCap_t;
+
+/** HostCmd_DS_REMAIN_ON_CHANNEL */
+typedef MLAN_PACK_START struct _HostCmd_DS_REMAIN_ON_CHANNEL {
+	/** Action 0-GET, 1-SET, 4 CLEAR*/
+	t_u16 action;
+	/** Not used set to zero */
+	t_u8 status;
+	/** Not used set to zero */
+	t_u8 reserved;
+	/** Band cfg */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** remain time: Unit ms*/
+	t_u32 remain_period;
+} MLAN_PACK_END HostCmd_DS_REMAIN_ON_CHANNEL;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** HostCmd_DS_WIFI_DIRECT_MODE */
+typedef MLAN_PACK_START struct _HostCmd_DS_WIFI_DIRECT_MODE {
+	/** Action 0-GET, 1-SET*/
+	t_u16 action;
+	/**0:disable 1:listen 2:GO 3:p2p client 4:find 5:stop find*/
+	t_u16 mode;
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_MODE;
+
+/** MrvlIEtypes_NoA_setting_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_NoA_setting_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** enable/disable */
+	t_u8 enable;
+	/** index */
+	t_u16 index;
+	/** NoA count */
+	t_u8 noa_count;
+	/** NoA duration */
+	t_u32 noa_duration;
+	/** NoA interval */
+	t_u32 noa_interval;
+} MLAN_PACK_END MrvlIEtypes_NoA_setting_t;
+
+/** MrvlIEtypes_NoA_setting_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_OPP_PS_setting_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** enable/disable && ct_window */
+	t_u8 enable;
+} MLAN_PACK_END MrvlIEtypes_OPP_PS_setting_t;
+
+/** HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG {
+	/** Action 0-GET, 1-SET */
+	t_u16 action;
+	/** MrvlIEtypes_NoA_setting_t
+	 *  MrvlIEtypes_OPP_PS_setting_t
+	 */
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG;
+#endif
+
+/** MrvlIEtypes_GPIO_TSF_LATCH_CONFIG*/
+typedef MLAN_PACK_START struct _MrvlIEtypes_GPIO_TSF_LATCH_CONFIG {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/**clock sync Mode */
+	t_u8 clock_sync_mode;
+	/**clock sync Role */
+	t_u8 clock_sync_Role;
+	/**clock sync GPIO Pin Number */
+	t_u8 clock_sync_gpio_pin_number;
+	/**clock sync GPIO Level or Toggle */
+	t_u8 clock_sync_gpio_level_toggle;
+	/**clock sync GPIO Pulse Width */
+	t_u16 clock_sync_gpio_pulse_width;
+
+} MLAN_PACK_END MrvlIEtypes_GPIO_TSF_LATCH_CONFIG;
+
+/** MrvlIEtypes_GPIO_TSF_LATCH_REPORT */
+typedef MLAN_PACK_START struct _MrvlIEtypes_GPIO_TSF_LATCH_REPORT {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/**get tsf info format */
+	t_u16 tsf_format;
+	/**tsf info */
+	t_u16 tsf_info;
+	/**tsf */
+	t_u64 tsf;
+	/**Positive or negative offset in microsecond from Beacon TSF to GPIO toggle TSF  */
+	t_s32 tsf_offset;
+} MLAN_PACK_END MrvlIEtypes_GPIO_TSF_LATCH_REPORT;
+
+/** HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG {
+	/** Action 0-GET, 1-SET */
+	t_u16 action;
+	/** MrvlIEtypes_GPIO_TSF_LATCH_CONFIG
+	 *  MrvlIEtypes_GPIO_TSF_LATCH_REPORT
+	 */
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG;
+
+MLAN_PACK_START struct coalesce_filt_field_param {
+	t_u8 operation;
+	t_u8 operand_len;
+	t_u16 offset;
+	t_u8 operand_byte_stream[4];
+} MLAN_PACK_END;
+
+MLAN_PACK_START struct coalesce_receive_filt_rule {
+	MrvlIEtypesHeader_t header;
+	t_u8 num_of_fields;
+	t_u8 pkt_type;
+	t_u16 max_coalescing_delay;
+	struct coalesce_filt_field_param params[1];
+} MLAN_PACK_END;
+
+/** HostCmd_DS_COALESCE_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_COALESCE_CONFIG {
+	/** Action 0-GET, 1-SET */
+	t_u16 action;
+	t_u16 num_of_rules;
+	struct coalesce_receive_filt_rule rule[1];
+} MLAN_PACK_END HostCmd_DS_COALESCE_CONFIG;
+
+/** TLV type : FW support max connection TLV */
+#define TLV_TYPE_MAX_CONN (PROPRIETARY_TLV_BASE_ID + 0x117)	/* 0x0217 */
+/** MrvlIEtypes_Max_Conn_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Max_Conn_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** FW support max P2P connection */
+	t_u8 max_p2p_conn;
+	/** FW support max STA connection */
+	t_u8 max_sta_conn;
+} MLAN_PACK_END MrvlIEtypes_Max_Conn_t;
+
+/** exceed max p2p connection event */
+typedef MLAN_PACK_START struct _event_exceed_max_p2p_conn {
+	/** Event ID */
+	t_u16 event_id;
+	/** BSS index number for multiple BSS support */
+	t_u8 bss_index;
+	/** BSS type */
+	t_u8 bss_type;
+	/** When exceed max, the mac address who request p2p connect */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END event_exceed_max_p2p_conn;
+
+#ifdef STA_SUPPORT
+
+/**
+ * @brief Structure used internally in the wlan driver to configure a scan.
+ *
+ * Sent to the command process module to configure the firmware
+ *   scan command prepared by wlan_cmd_802_11_scan.
+ *
+ * @sa wlan_scan_networks
+ *
+ */
+typedef MLAN_PACK_START struct _wlan_scan_cmd_config {
+	/**
+	 *  BSS Type to be sent in the firmware command
+	 *
+	 *  Field can be used to restrict the types of networks returned in the
+	 *    scan.  Valid settings are:
+	 *
+	 *   - MLAN_SCAN_MODE_BSS  (infrastructure)
+	 *   - MLAN_SCAN_MODE_IBSS (adhoc)
+	 *   - MLAN_SCAN_MODE_ANY  (unrestricted, adhoc and infrastructure)
+	 */
+	t_u8 bss_mode;
+
+	/**
+	 *  Specific BSSID used to filter scan results in the firmware
+	 */
+	t_u8 specific_bssid[MLAN_MAC_ADDR_LENGTH];
+
+	/**
+	 *  Length of TLVs sent in command starting at tlvBuffer
+	 */
+	t_u32 tlv_buf_len;
+
+	/**
+	 *  SSID TLV(s) and ChanList TLVs to be sent in the firmware command
+	 *
+	 *  TLV_TYPE_CHANLIST, MrvlIEtypes_ChanListParamSet_t
+	 *  TLV_TYPE_SSID, MrvlIEtypes_SsIdParamSet_t
+	 */
+	t_u8 tlv_buf[1];	/* SSID TLV(s) and ChanList TLVs are stored here */
+} MLAN_PACK_END wlan_scan_cmd_config;
+
+/**
+ *  Sructure to retrieve the scan table
+ */
+typedef MLAN_PACK_START struct {
+	/**
+	 *  - Zero based scan entry to start retrieval in command request
+	 *  - Number of scans entries returned in command response
+	 */
+	t_u32 scan_number;
+	/**
+	 * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
+	 * structures. Each struct is padded to the nearest 32 bit boundary.
+	 */
+	t_u8 scan_table_entry_buf[1];
+} MLAN_PACK_END wlan_get_scan_table_info;
+
+/** Generic structure defined for parsing WPA/RSN IEs for GTK/PTK OUIs */
+typedef MLAN_PACK_START struct {
+	/** Group key oui */
+	t_u8 GrpKeyOui[4];
+	/** Number of PTKs */
+	t_u8 PtkCnt[2];
+	/** Ptk body starts here */
+	t_u8 PtkBody[4];
+} MLAN_PACK_END IEBody;
+#endif /* STA_SUPPORT */
+
+/*
+ * This scan handle Country Information IE(802.11d compliant)
+ * Define data structure for HostCmd_CMD_802_11_SCAN
+ */
+/** HostCmd_DS_802_11_SCAN */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SCAN {
+	/** BSS mode */
+	t_u8 bss_mode;
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** TLV buffer */
+	t_u8 tlv_buffer[1];
+	/** MrvlIEtypes_SsIdParamSet_t      SsIdParamSet;
+	 *  MrvlIEtypes_ChanListParamSet_t  ChanListParamSet;
+	 *  MrvlIEtypes_RatesParamSet_t     OpRateSet;
+	 */
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN;
+
+/** fw_cap_info bit to indicate enhance ext scan type */
+#define ENHANCE_EXT_SCAN_ENABLE MBIT(19)
+/** mlan_event_scan_result data structure */
+typedef MLAN_PACK_START struct _mlan_event_scan_result {
+	/** Event ID */
+	t_u16 event_id;
+	/** BSS index number for multiple BSS support */
+	t_u8 bss_index;
+	/** BSS type */
+	t_u8 bss_type;
+	/** More event available or not */
+	t_u8 more_event;
+	/** Reserved */
+	t_u8 reserved[3];
+	/** Size of the response buffer */
+	t_u16 buf_size;
+	/** Number of BSS in scan response */
+	t_u8 num_of_set;
+} MLAN_PACK_END mlan_event_scan_result, *pmlan_event_scan_result;
+
+/** ext scan status report event */
+typedef MLAN_PACK_START struct _mlan_event_scan_status {
+	/** Event ID */
+	t_u16 event_id;
+	/** BSS index number for multiple BSS support */
+	t_u8 bss_index;
+	/** BSS type */
+	t_u8 bss_type;
+	/** scan status */
+	t_u8 scan_status;
+	/** result */
+	t_u16 buf_len;
+	/** event buf */
+	t_u8 event_buf[];
+} MLAN_PACK_END mlan_event_scan_status, *pmlan_event_scan_status;
+
+/*
+ * This scan handle Country Information IE(802.11d compliant)
+ * Define data structure for HostCmd_CMD_802_11_SCAN_EXT
+ */
+/** HostCmd_DS_802_11_SCAN_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SCAN_EXT {
+	/** Scan type for ext scan
+	 *  0: default type: cmd resp after ext scan report event
+	 *  1: enhanced type: cmd resp before ext scan report event
+	 *  2: scan cancelled: cancel scan during scan processing
+	 */
+	t_u8 ext_scan_type;
+	/** Reserved */
+	t_u8 reserved[3];
+	/** TLV buffer */
+	t_u8 tlv_buffer[1];
+	/** MrvlIEtypes_Bssid_List_t            BssIdList;
+	 *  MrvlIEtypes_SsIdParamSet_t          SSIDParamSet;
+	 *  MrvlIEtypes_ChanListParamSet_t      ChanListParamSet;
+	 *  MrvlIEtypes_RatesParamSet_t         OpRateSet;
+	 *  MrvlIEtypes_NumProbes_t             NumProbes;
+	 *  MrvlIEtypes_WildCardSsIdParamSet_t  WildCardSSIDParamSet;
+	 *  MrvlIEtypes_BssMode_t               BssMode;
+	 */
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN_EXT;
+
+/** MrvlIEtypes_BssMode */
+typedef MLAN_PACK_START struct _MrvlIEtypes_BssMode_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/* INFRA/IBSS/AUTO */
+	t_u8 bss_mode;
+} MLAN_PACK_END MrvlIEtypes_BssMode_t;
+
+/** BSS scan Rsp */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bss_Scan_Rsp_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** BSSID of the BSS descriptor */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Beacon/Probe response buffer */
+	t_u8 frame_body[1];
+} MLAN_PACK_END MrvlIEtypes_Bss_Scan_Rsp_t;
+
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bss_Scan_Info_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** RSSI for scan entry */
+	t_s16 rssi;
+	/** Channel ANPI */
+	t_s16 anpi;
+	/** Channel load (parts per 255) */
+	t_u8 cca_busy_fraction;
+	/** Band */
+	Band_Config_t bandcfg;
+	/** Channel */
+	t_u8 channel;
+	/** Reserved */
+	t_u8 reserved;
+	/** TSF data */
+	t_u64 tsf;
+} MLAN_PACK_END MrvlIEtypes_Bss_Scan_Info_t;
+
+/** HostCmd_DS_RX_MGMT_IND */
+typedef MLAN_PACK_START struct _HostCmd_DS_RX_MGMT_IND {
+	/** Action */
+	t_u16 action;
+	/** Mgmt frame subtype mask */
+	t_u32 mgmt_subtype_mask;
+} MLAN_PACK_END HostCmd_DS_RX_MGMT_IND;
+
+/** HostCmd_DS_802_11_SCAN_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SCAN_RSP {
+	/** Size of BSS descriptor */
+	t_u16 bss_descript_size;
+	/** Numner of sets */
+	t_u8 number_of_sets;
+	/** BSS descriptor and TLV buffer */
+	t_u8 bss_desc_and_tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_802_11_SCAN_RSP;
+
+/** HostCmd_DS_802_11_BG_SCAN_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_CONFIG {
+	/** action */
+	t_u16 action;
+	/** 0: disable, 1: enable */
+	t_u8 enable;
+	/** bss type */
+	t_u8 bss_type;
+	/** num of channel per scan */
+	t_u8 chan_per_scan;
+	/** reserved field */
+	t_u8 reserved;
+	/** reserved field */
+	t_u16 reserved1;
+	/** interval between consecutive scans */
+	t_u32 scan_interval;
+	/** reserved field */
+	t_u32 reserved2;
+	/** condition to trigger report to host */
+	t_u32 report_condition;
+	/** reserved field */
+	t_u16 reserved3;
+} MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_CONFIG;
+
+/** HostCmd_DS_802_11_BG_SCAN_QUERY */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_QUERY {
+	/** Flush */
+	t_u8 flush;
+} MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_QUERY;
+
+/** HostCmd_DS_802_11_BG_SCAN_QUERY_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_QUERY_RSP {
+	/** Report condition */
+	t_u32 report_condition;
+	/** Scan response */
+	HostCmd_DS_802_11_SCAN_RSP scan_resp;
+} MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_QUERY_RSP;
+
+/** MrvlIEtypes_StartLater_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_StartLater_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/* 0 - BGScan start immediately, 1 - BGScan will start later after "Scan
+	 * Interval" */
+	t_u16 value;
+} MLAN_PACK_END MrvlIEtypes_StartLater_t;
+
+/** MrvlIEtypes_RepeatCount_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RepeatCount_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/* Repeat count */
+	t_u16 repeat_count;
+} MLAN_PACK_END MrvlIEtypes_RepeatCount_t;
+
+/** MrvlIEtypes_DomainParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_DomainParamSet {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[1];
+} MLAN_PACK_END MrvlIEtypes_DomainParamSet_t;
+
+/** HostCmd_DS_802_11D_DOMAIN_INFO */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11D_DOMAIN_INFO {
+	/** Action */
+	t_u16 action;
+	/** Domain parameter set */
+	MrvlIEtypes_DomainParamSet_t domain;
+} MLAN_PACK_END HostCmd_DS_802_11D_DOMAIN_INFO;
+
+/** HostCmd_DS_802_11D_DOMAIN_INFO_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11D_DOMAIN_INFO_RSP {
+	/** Action */
+	t_u16 action;
+	/** Domain parameter set */
+	MrvlIEtypes_DomainParamSet_t domain;
+} MLAN_PACK_END HostCmd_DS_802_11D_DOMAIN_INFO_RSP;
+
+/** HostCmd_DS_11N_ADDBA_REQ */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_ADDBA_REQ {
+	/** Result of the ADDBA Request Operation */
+	t_u8 add_req_result;
+	/** Peer MAC address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Dialog Token */
+	t_u8 dialog_token;
+	/** Block Ack Parameter Set */
+	t_u16 block_ack_param_set;
+	/** Block Act Timeout Value */
+	t_u16 block_ack_tmo;
+	/** Starting Sequence Number */
+	t_u16 ssn;
+} MLAN_PACK_END HostCmd_DS_11N_ADDBA_REQ;
+
+/** HostCmd_DS_11N_ADDBA_RSP */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_ADDBA_RSP {
+	/** Result of the ADDBA Response Operation */
+	t_u8 add_rsp_result;
+	/** Peer MAC address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Dialog Token */
+	t_u8 dialog_token;
+	/** Status Code */
+	t_u16 status_code;
+	/** Block Ack Parameter Set */
+	t_u16 block_ack_param_set;
+	/** Block Act Timeout Value */
+	t_u16 block_ack_tmo;
+	/** Starting Sequence Number */
+	t_u16 ssn;
+} MLAN_PACK_END HostCmd_DS_11N_ADDBA_RSP;
+
+/** HostCmd_DS_11N_DELBA */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_DELBA {
+	/** Result of the ADDBA Request Operation */
+	t_u8 del_result;
+	/** Peer MAC address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Delete Block Ack Parameter Set */
+	t_u16 del_ba_param_set;
+	/** Reason Code sent for DELBA */
+	t_u16 reason_code;
+	/** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END HostCmd_DS_11N_DELBA;
+
+/** HostCmd_DS_11N_BATIMEOUT */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_BATIMEOUT {
+	/** TID */
+	t_u8 tid;
+	/** Peer MAC address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Delete Block Ack Parameter Set */
+	t_u8 origninator;
+} MLAN_PACK_END HostCmd_DS_11N_BATIMEOUT;
+
+/** HostCmd_DS_11N_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11N_CFG {
+	/** Action */
+	t_u16 action;
+	/** HTTxCap */
+	t_u16 ht_tx_cap;
+	/** HTTxInfo */
+	t_u16 ht_tx_info;
+	/** Misc configuration */
+	t_u16 misc_config;
+} MLAN_PACK_END HostCmd_DS_11N_CFG;
+
+/** HostCmd_DS_11N_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_REJECT_ADDBA_REQ {
+	/** Action */
+	t_u16 action;
+	/** Bit0    : host sleep activated
+	 *  Bit1    : auto reconnect enabled
+	 *  Others  : reserved
+	 */
+	t_u32 conditions;
+} MLAN_PACK_END HostCmd_DS_REJECT_ADDBA_REQ;
+
+/** HostCmd_DS_TXBUF_CFG*/
+typedef MLAN_PACK_START struct _HostCmd_DS_TXBUF_CFG {
+	/** Action */
+	t_u16 action;
+	/** Buffer Size */
+	t_u16 buff_size;
+	/** End Port_for Multiport */
+	t_u16 mp_end_port;
+	/** Reserved */
+	t_u16 reserved3;
+} MLAN_PACK_END HostCmd_DS_TXBUF_CFG;
+
+/** HostCmd_DS_AMSDU_AGGR_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_AMSDU_AGGR_CTRL {
+	/** Action */
+	t_u16 action;
+	/** Enable */
+	t_u16 enable;
+	/** Get the current Buffer Size valid */
+	t_u16 curr_buf_size;
+} MLAN_PACK_END HostCmd_DS_AMSDU_AGGR_CTRL;
+
+/** HostCmd_DS_11AC_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11AC_CFG {
+	/** Action */
+	t_u16 action;
+	/** BandConfig */
+	t_u8 band_config;
+	/** Misc Configuration */
+	t_u8 misc_config;
+	/** VHT Capability Info */
+	t_u32 vht_cap_info;
+	/** VHT Support MCS Set */
+	t_u8 vht_supp_mcs_set[VHT_MCS_SET_LEN];
+} MLAN_PACK_END HostCmd_DS_11AC_CFG;
+
+/** HostCmd_DS_11ACTXBUF_CFG*/
+typedef MLAN_PACK_START struct _HostCmd_DS_11ACTXBUF_CFG {
+	/** Action */
+	t_u16 action;
+	/** Buffer Size */
+	t_u16 buff_size;
+	/** End Port_for Multiport */
+	t_u16 mp_end_port;
+	/** Reserved */
+	t_u16 reserved3;
+} MLAN_PACK_END HostCmd_DS_11ACTXBUF_CFG;
+
+/** HostCmd_DS_11AX_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11AX_CFG {
+	/** Action */
+	t_u16 action;
+	/** BandConfig */
+	t_u8 band_config;
+	/** TLV for HE capability or HE operation */
+	t_u8 val[];
+} MLAN_PACK_END HostCmd_DS_11AX_CFG;
+
+/** HostCmd_DS_11AX_CMD_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_11AX_CMD_CFG {
+	/** Action */
+	t_u16 action;
+	/** CMD_SUBID */
+	t_u16 sub_id;
+	/** TLV or value for cmd */
+	t_u8 val[];
+} MLAN_PACK_END HostCmd_DS_11AX_CMD_CFG;
+
+/** HostCmd_DS_RANGE_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_RANGE_EXT {
+	/** Action */
+	t_u16 action;
+	/** Range ext mode */
+	t_u8 mode;
+} MLAN_PACK_END HostCmd_DS_RANGE_EXT;
+
+/** Type definition of hostcmd_twt_setup */
+typedef struct MLAN_PACK_START _hostcmd_twt_setup {
+	/** Implicit, 0: TWT session is explicit, 1: Session is implicit */
+	t_u8 implicit;
+	/** Announced, 0: Unannounced, 1: Announced TWT */
+	t_u8 announced;
+	/** Trigger Enabled, 0: Non-Trigger enabled, 1: Trigger enabled TWT */
+	t_u8 trigger_enabled;
+	/** TWT Information Disabled, 0: TWT info enabled, 1: TWT info disabled
+	 */
+	t_u8 twt_info_disabled;
+	/** Negotiation Type, 0: Future Individual TWT SP start time, 1: Next
+	 * Wake TBTT time */
+	t_u8 negotiation_type;
+	/** TWT Wakeup Duration, time after which the TWT requesting STA can
+	 * transition to doze state */
+	t_u8 twt_wakeup_duration;
+	/** Flow Identifier. Range: [0-7]*/
+	t_u8 flow_identifier;
+	/** Hard Constraint, 0: FW can tweak the TWT setup parameters if it is
+	 *rejected by AP.
+	 ** 1: Firmware should not tweak any parameters. */
+	t_u8 hard_constraint;
+	/** TWT Exponent, Range: [0-63] */
+	t_u8 twt_exponent;
+	/** TWT Mantissa Range: [0-sizeof(UINT16)] */
+	t_u16 twt_mantissa;
+    /** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
+	t_u8 twt_request;
+	/** TWT Setup State. Set to 0 by driver, filled by FW in response*/
+	t_u8 twt_setup_state;
+	/** Reserved, set to 0. */
+	t_u8 reserved[2];
+} MLAN_PACK_END hostcmd_twt_setup, *phostcmd_twt_setup;
+
+/** Type definition of hostcmd_twt_teardown */
+typedef struct MLAN_PACK_START _hostcmd_twt_teardown {
+	/** TWT Flow Identifier. Range: [0-7] */
+	t_u8 flow_identifier;
+	/** Negotiation Type. 0: Future Individual TWT SP start time, 1: Next
+	 * Wake TBTT time */
+	t_u8 negotiation_type;
+	/** Tear down all TWT. 1: To teardown all TWT, 0 otherwise */
+	t_u8 teardown_all_twt;
+	/** TWT Teardown State. Set to 0 by driver, filled by FW in response */
+	t_u8 twt_teardown_state;
+	/** Reserved, set to 0. */
+	t_u8 reserved[3];
+} MLAN_PACK_END hostcmd_twt_teardown, *phostcmd_twt_teardown;
+
+/** HostCmd_DS_TWT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TWT_CFG {
+	/** Action */
+	t_u16 action;
+	/** CMD_SUBID */
+	t_u16 sub_id;
+	/** TWT Setup/Teardown configuration parameters */
+	union {
+		/** TWT Setup config for Sub ID: MLAN_11AX_TWT_SETUP_SUBID */
+		hostcmd_twt_setup twt_setup;
+		/** TWT Teardown config for Sub ID: MLAN_11AX_TWT_TEARDOWN_SUBID
+		 */
+		hostcmd_twt_teardown twt_teardown;
+	} param;
+} MLAN_PACK_END HostCmd_DS_TWT_CFG;
+
+/** HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG {
+	/** Action */
+	t_u16 action;
+	/** Current system clock */
+	t_u16 cur_sys_clk;
+	/** Clock type */
+	t_u16 sys_clk_type;
+	/** Length of clocks */
+	t_u16 sys_clk_len;
+	/** System clocks */
+	t_u16 sys_clk[16];
+} MLAN_PACK_END HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG;
+
+/** MrvlIEtypes_WmmParamSet_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_WmmParamSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** WMM IE */
+	t_u8 wmm_ie[1];
+} MLAN_PACK_END MrvlIEtypes_WmmParamSet_t;
+
+/** MrvlIEtypes_WmmQueueStatus_t */
+typedef MLAN_PACK_START struct {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Queue index */
+	t_u8 queue_index;
+	/** Disabled flag */
+	t_u8 disabled;
+	/** Medium time allocation in 32us units*/
+	t_u16 medium_time;
+	/** Flow required flag */
+	t_u8 flow_required;
+	/** Flow created flag */
+	t_u8 flow_created;
+	/** Reserved */
+	t_u32 reserved;
+} MLAN_PACK_END MrvlIEtypes_WmmQueueStatus_t;
+
+/** Size of a TSPEC.  Used to allocate necessary buffer space in commands */
+#define WMM_TSPEC_SIZE 63
+
+/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */
+#define WMM_ADDTS_EXTRA_IE_BYTES 256
+
+/** Extra TLV bytes allocated in messages for configuring WMM Queues */
+#define WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES 64
+
+/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */
+#define WMM_STATS_PKTS_HIST_BINS 7
+
+/**
+ *  @brief Firmware command structure to retrieve the firmware WMM status.
+ *
+ *  Used to retrieve the status of each WMM AC Queue in TLV
+ *    format (MrvlIEtypes_WmmQueueStatus_t) as well as the current WMM
+ *    parameter IE advertised by the AP.
+ *
+ *  Used in response to a EVENT_WMM_STATUS_CHANGE event signaling
+ *    a QOS change on one of the ACs or a change in the WMM Parameter in
+ *    the Beacon.
+ *
+ *  TLV based command, byte arrays used for max sizing purpose. There are no
+ *    arguments sent in the command, the TLVs are returned by the firmware.
+ */
+typedef MLAN_PACK_START struct {
+	/** Queue status TLV */
+	t_u8 queue_status_tlv[sizeof(MrvlIEtypes_WmmQueueStatus_t) *
+			      MAX_AC_QUEUES];
+	/** WMM parameter TLV */
+	t_u8 wmm_param_tlv[sizeof(IEEEtypes_WmmParameter_t) + 2];
+} MLAN_PACK_END HostCmd_DS_WMM_GET_STATUS;
+
+/**
+ *  @brief Command structure for the HostCmd_CMD_WMM_ADDTS_REQ firmware command
+ */
+typedef MLAN_PACK_START struct {
+	mlan_cmd_result_e command_result; /**< Command result */
+	t_u32 timeout_ms; /**< Timeout value in milliseconds */
+	t_u8 dialog_token; /**< Dialog token */
+	t_u8 ieee_status_code; /**< IEEE status code */
+	t_u8 tspec_data[WMM_TSPEC_SIZE]; /**< TSPEC data */
+	t_u8 addts_extra_ie_buf[WMM_ADDTS_EXTRA_IE_BYTES]; /**< Extra IE buffer
+							    */
+} MLAN_PACK_END HostCmd_DS_WMM_ADDTS_REQ;
+
+/**
+ *  @brief Command structure for the HostCmd_CMD_WMM_DELTS_REQ firmware command
+ */
+typedef MLAN_PACK_START struct {
+	mlan_cmd_result_e command_result; /**< Command result */
+	t_u8 dialog_token; /**< Dialog token */
+	t_u8 ieee_reason_code; /**< IEEE reason code */
+	t_u8 tspec_data[WMM_TSPEC_SIZE]; /**< TSPEC data */
+} MLAN_PACK_END HostCmd_DS_WMM_DELTS_REQ;
+
+/**
+ *  @brief Command structure for the HostCmd_CMD_WMM_QUEUE_CONFIG firmware cmd
+ *
+ *  Set/Get/Default the Queue parameters for a specific AC in the firmware.
+ */
+typedef MLAN_PACK_START struct {
+	mlan_wmm_queue_config_action_e action; /**< Set, Get, or Default */
+	mlan_wmm_ac_e access_category; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+	/** @brief MSDU lifetime expiry per 802.11e
+	 *
+	 *   - Ignored if 0 on a set command
+	 *   - Set to the 802.11e specified 500 TUs when defaulted
+	 */
+	t_u16 msdu_lifetime_expiry;
+	t_u8 tlv_buffer[WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES]; /**< Not supported */
+} MLAN_PACK_END HostCmd_DS_WMM_QUEUE_CONFIG;
+
+/**
+ *  @brief Command structure for the HostCmd_CMD_WMM_QUEUE_STATS firmware cmd
+ *
+ *  Turn statistical collection on/off for a given AC or retrieve the
+ *    accumulated stats for an AC and clear them in the firmware.
+ */
+typedef MLAN_PACK_START struct {
+	mlan_wmm_queue_stats_action_e action; /**< Start, Stop, or Get */
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 select_bin:7;   /**< WMM_AC_BK(0) to WMM_AC_VO(3), or TID */
+	t_u8 select_is_userpri:1;   /**< Set if select_bin is UP, Clear for AC
+				     */
+#else
+	t_u8 select_is_userpri:1;   /**< Set if select_bin is UP, Clear for AC
+				     */
+	t_u8 select_bin:7;   /**< WMM_AC_BK(0) to WMM_AC_VO(3), or TID */
+#endif
+	t_u16 pkt_count; /**< Number of successful packets transmitted */
+	t_u16 pkt_loss;	/**< Packets lost; not included in pktCount */
+	t_u32 avg_queue_delay; /**< Average Queue delay in microsec */
+	t_u32 avg_tx_delay; /**< Average Transmission delay in microsec */
+	t_u16 used_time; /**< Calc used time - units of 32 microsec */
+	t_u16 policed_time; /**< Calc policed time - units of 32 microsec */
+	/** @brief Queue Delay Histogram; number of packets per queue delay
+	 * range
+	 *
+	 *  [0] -  0ms <= delay < 5ms
+	 *  [1] -  5ms <= delay < 10ms
+	 *  [2] - 10ms <= delay < 20ms
+	 *  [3] - 20ms <= delay < 30ms
+	 *  [4] - 30ms <= delay < 40ms
+	 *  [5] - 40ms <= delay < 50ms
+	 *  [6] - 50ms <= delay < msduLifetime (TUs)
+	 */
+	t_u16 delay_histogram[WMM_STATS_PKTS_HIST_BINS];
+	/** Reserved */
+	t_u16 reserved_1;
+} MLAN_PACK_END HostCmd_DS_WMM_QUEUE_STATS;
+
+/**
+ *  @brief Command structure for the HostCmd_CMD_WMM_TS_STATUS firmware cmd
+ *
+ *  Query the firmware to get the status of the WMM Traffic Streams
+ */
+typedef MLAN_PACK_START struct {
+	/** TSID: Range: 0->7 */
+	t_u8 tid;
+	/** TSID specified is valid */
+	t_u8 valid;
+	/** AC TSID is active on */
+	t_u8 access_category;
+	/** UP specified for the TSID */
+	t_u8 user_priority;
+	/** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+	/** Uplink(1), Downlink(2), Bidirectional(3) */
+	t_u8 flow_dir;
+	/** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END HostCmd_DS_WMM_TS_STATUS;
+
+/** Firmware status for a specific AC */
+typedef MLAN_PACK_START struct {
+	/** Disabled flag */
+	t_u8 disabled;
+	/** Flow required flag */
+	t_u8 flow_required;
+	/** Flow created flag */
+	t_u8 flow_created;
+} MLAN_PACK_END WmmAcStatus_t;
+
+/**  Local Power Capability */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PowerCapability_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Minmum power */
+	t_s8 min_power;
+	/** Maximum power */
+	t_s8 max_power;
+} MLAN_PACK_END MrvlIEtypes_PowerCapability_t;
+
+/** HT Information element */
+typedef MLAN_PACK_START struct _MrvlIETypes_HTInfo_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** HTInfo struct */
+	HTInfo_t ht_info;
+} MLAN_PACK_END MrvlIETypes_HTInfo_t;
+
+/** 20/40 BSS Coexistence element */
+typedef MLAN_PACK_START struct _MrvlIETypes_2040BSSCo_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** BSSCo2040_t struct */
+	BSSCo2040_t bss_co_2040;
+} MLAN_PACK_END MrvlIETypes_2040BSSCo_t;
+
+/** Extended Capabilities element */
+typedef MLAN_PACK_START struct _MrvlIETypes_ExtCap_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** ExtCap_t struct */
+	ExtCap_t ext_cap;
+} MLAN_PACK_END MrvlIETypes_ExtCap_t;
+
+/** Supported operating classes element */
+typedef MLAN_PACK_START struct _MrvlIETypes_SuppOperClass_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Current operationg class **/
+	t_u8 current_oper_class;
+	/** Operating class list */
+	t_u8 oper_class[1];
+} MLAN_PACK_END MrvlIETypes_SuppOperClass_t;
+
+/** Oper_class channel bandwidth element */
+typedef MLAN_PACK_START struct _MrvlIEtypes_chan_bw_oper_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** channel oper bandwidth*/
+	mlan_ds_bw_chan_oper ds_chan_bw_oper;
+} MLAN_PACK_END MrvlIEtypes_chan_bw_oper_t;
+
+/** Qos Info */
+typedef MLAN_PACK_START struct _MrvlIETypes_qosinfo_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** qos_info*/
+	t_u8 qos_info;
+} MLAN_PACK_END MrvlIETypes_qosinfo_t;
+
+/** Overlapping BSS Scan Parameters element */
+typedef MLAN_PACK_START struct _MrvlIETypes_OverlapBSSScanParam_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** OBSSScanParam_t struct */
+	OBSSScanParam_t obss_scan_param;
+} MLAN_PACK_END MrvlIETypes_OverlapBSSScanParam_t;
+
+/** Set of MCS values that STA desires to use within the BSS */
+typedef MLAN_PACK_START struct _MrvlIETypes_HTOperationalMCSSet_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** Bitmap indicating MCSs that STA desires to use within the BSS */
+	t_u8 ht_operational_mcs_bitmap[16];
+} MLAN_PACK_END MrvlIETypes_HTOperationalMCSSet_t;
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTOprat_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u8 chan_width;
+	t_u8 chan_center_freq_1;
+	t_u8 chan_center_freq_2;
+	/** Basic MCS set map, each 2 bits stands for a Nss */
+	t_u16 basic_MCS_map;
+} MLAN_PACK_END MrvlIETypes_VHTOprat_t;
+
+/** VHT Transmit Power Envelope IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_VHTtxpower_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u8 max_tx_power;
+	t_u8 chan_center_freq;
+	t_u8 chan_width;
+} MLAN_PACK_END MrvlIETypes_VHTtxpower_t;
+
+/** Extended Power Constraint IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_ExtPwerCons_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** channel width */
+	t_u8 chan_width;
+	/** local power constraint */
+	t_u8 local_power_cons;
+} MLAN_PACK_END MrvlIETypes_ExtPwerCons_t;
+
+/** Extended BSS Load IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_ExtBSSload_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u8 MU_MIMO_capa_count;
+	t_u8 stream_underutilization;
+	t_u8 VHT40_util;
+	t_u8 VHT80_util;
+	t_u8 VHT160_util;
+} MLAN_PACK_END MrvlIETypes_ExtBSSload_t;
+
+/** Quiet Channel IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_QuietChan_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u8 AP_quiet_mode;
+	t_u8 quiet_count;
+	t_u8 quiet_period;
+	t_u16 quiet_dur;
+	t_u16 quiet_offset;
+} MLAN_PACK_END MrvlIETypes_QuietChan_t;
+
+/** Wide Bandwidth Channel Switch IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_BWSwitch_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	t_u8 new_chan_width;
+	t_u8 new_chan_center_freq_1;
+	t_u8 new_chan_center_freq_2;
+} MLAN_PACK_END MrvlIETypes_BWSwitch_t;
+
+/** AID IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_AID_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** AID number */
+	t_u16 AID;
+} MLAN_PACK_END MrvlIETypes_AID_t;
+
+/** Operating Mode Notification IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_OperModeNtf_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** operating mdoe */
+	t_u8 oper_mode;
+} MLAN_PACK_END MrvlIETypes_OperModeNtf_t;
+
+/** bf global args */
+typedef struct MLAN_PACK_START _bf_global_cfg_args {
+	/** Global enable/disable bf */
+	t_u8 bf_enbl;
+	/** Global enable/disable sounding */
+	t_u8 sounding_enbl;
+	/** FB Type */
+	t_u8 fb_type;
+	/** SNR Threshold */
+	t_u8 snr_threshold;
+	/** Sounding interval */
+	t_u16 sounding_interval;
+	/** BF mode */
+	t_u8 bf_mode;
+	/** Reserved */
+	t_u8 reserved;
+} MLAN_PACK_END bf_global_cfg_args;
+
+/** bf_trigger_sound_args_t */
+typedef MLAN_PACK_START struct _bf_trigger_sound_args_t {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Status */
+	t_u8 status;
+} MLAN_PACK_END bf_trigger_sound_args_t;
+
+/** bf periodicity args */
+typedef MLAN_PACK_START struct _bf_periodicity_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Current Tx BF Interval */
+	t_u16 interval;
+	/** Status */
+	t_u8 status;
+} MLAN_PACK_END bf_periodicity_args;
+
+/** bf peer configuration args */
+typedef struct MLAN_PACK_START _bf_peer_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Reserved */
+	t_u16 reserved;
+	/** Enable/Disable Beamforming */
+	t_u8 bf_enbl;
+	/** Enable/Disable sounding */
+	t_u8 sounding_enbl;
+	/** FB Type */
+	t_u8 fb_type;
+} MLAN_PACK_END bf_peer_args;
+
+/** bf_snr_thr_t */
+typedef MLAN_PACK_START struct _bf_snr_thr_t {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** SNR */
+	t_u8 snr;
+} MLAN_PACK_END bf_snr_thr_t;
+
+/** HostCmd_DS_TX_BF_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_BF_CFG {
+	/* Beamforming action */
+	t_u16 bf_action;
+	/* action - SET/GET */
+	t_u16 action;
+
+	MLAN_PACK_START union {
+		bf_global_cfg_args bf_global_cfg;
+		bf_trigger_sound_args_t bf_sound_args;
+		bf_periodicity_args bf_periodicity;
+		bf_peer_args tx_bf_peer;
+		bf_snr_thr_t bf_snr;
+	} MLAN_PACK_END body;
+} MLAN_PACK_END HostCmd_DS_TX_BF_CFG;
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** MrvlIEtypes_psk_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_psk_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** PSK */
+	t_u8 psk[MLAN_MAX_KEY_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_psk_t;
+#endif /* WIFI_DIRECT_SUPPORT */
+
+/** Data structure for Link ID */
+typedef MLAN_PACK_START struct _MrvlIETypes_LinkIDElement_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** initial sta address*/
+	t_u8 init_sta[MLAN_MAC_ADDR_LENGTH];
+	/** respose sta address */
+	t_u8 resp_sta[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIETypes_LinkIDElement_t;
+
+/** MrvlIEtypes_PMK_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PMK_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** PMK */
+	t_u8 pmk[1];
+} MLAN_PACK_END MrvlIEtypes_PMK_t;
+
+/** MrvlIEtypes_Passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Passphrase_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Passphrase */
+	char passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_Passphrase_t;
+
+/** MrvlIEtypes_SAE_Password_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SAE_Password_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** SAE Password */
+	char sae_password[1];
+} MLAN_PACK_END MrvlIEtypes_SAE_Password_t;
+
+/** MrvlIEtypes_SAE_PWE_Mode_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_SAE_PWE_Mode_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** WPA3 SAE mechanism for PWE derivation */
+	char pwe[1];
+} MLAN_PACK_END MrvlIEtypes_SAE_PWE_Mode_t;
+
+/** SAE H2E capability bit in RSNX */
+#define SAE_H2E_BIT 5
+
+/* rsnMode -
+ *      Bit 0    : No RSN
+ *      Bit 1-2  : RFU
+ *      Bit 3    : WPA
+ *      Bit 4    : WPA-NONE
+ *      Bit 5    : WPA2
+ *      Bit 6    : AES CCKM
+ *      Bit 7-15 : RFU
+ */
+/** MrvlIEtypes_EncrProto_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_EncrProto_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** EncrProto */
+	t_u16 rsn_mode;
+} MLAN_PACK_END MrvlIEtypes_EncrProto_t;
+
+/** MrvlIEtypes_Bssid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Bssid_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_Bssid_t;
+
+/*
+ * This struct will handle GET,SET,CLEAR function for embedded
+ * supplicant.
+ * Define data structure for HostCmd_CMD_802_11_SUPPLICANT_PMK
+ */
+/** HostCmd_DS_802_11_SUPPLICANT_PMK */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SUPPLICANT_PMK {
+	/** CMD Action GET/SET/CLEAR */
+	t_u16 action;
+	/** CacheResult initialized to 0 */
+	t_u16 cache_result;
+	/** TLV Buffer */
+	t_u8 tlv_buffer[1];
+	/** MrvlIEtypes_SsidParamSet_t  SsidParamSet;
+	 * MrvlIEtypes_PMK_t           Pmk;
+	 * MrvlIEtypes_Passphrase_t    Passphrase;
+	 * MrvlIEtypes_Bssid_t         Bssid;
+	 **/
+} MLAN_PACK_END HostCmd_DS_802_11_SUPPLICANT_PMK;
+
+/*
+ * This struct will GET the Supplicant supported bitmaps
+ * The GET_CURRENT action will get the network profile used
+ * for the current assocation.
+ * Define data structure for HostCmd_CMD_802_11_SUPPLICANT_PROFILE
+ */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_SUPPLICANT_PROFILE {
+	/** GET/SET/GET_CURRENT */
+	t_u16 action;
+	/** Reserved */
+	t_u16 reserved;
+	/** TLVBuffer */
+	t_u8 tlv_buf[1];
+	/* MrvlIEtypes_EncrProto_t */
+} MLAN_PACK_END HostCmd_DS_802_11_SUPPLICANT_PROFILE;
+
+/* unicastCipher -
+ *      Bit 0   : RFU
+ *      Bit 1   : RFU
+ *      Bit 2   : TKIP
+ *      Bit 3   : AES CCKM
+ *      Bit 2-7 : RFU
+ * multicastCipher -
+ *      Bit 0   : WEP40
+ *      Bit 1   : WEP104
+ *      Bit 2   : TKIP
+ *      Bit 3   : AES
+ *      Bit 4-7 : Reserved for now
+ */
+/** MrvlIEtypes_Cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Cipher_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** PairCipher */
+	t_u8 pair_cipher;
+	/** GroupCipher */
+	t_u8 group_cipher;
+} MLAN_PACK_END MrvlIEtypes_Cipher_t;
+
+/** RFType */
+typedef MLAN_PACK_START struct _RFType_t {
+	/** band info */
+	Band_Config_t bandcfg;
+	/** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END RFType_t;
+
+/** HostCmd_CMD_802_11_RF_CHANNEL */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RF_CHANNEL {
+	/** Action */
+	t_u16 action;
+	/** Current channel */
+	t_u16 current_channel;
+	/** RF type */
+	RFType_t rf_type;
+	/** Reserved field */
+	t_u16 reserved;
+#ifdef STA_SUPPORT
+	/** Reserved */
+	t_u8 reserved_1[32];
+#else				/* STA_SUPPORT */
+	/** List of channels */
+	t_u8 channel_list[32];
+#endif				/* !STA_SUPPORT */
+} MLAN_PACK_END HostCmd_DS_802_11_RF_CHANNEL;
+
+/** HostCmd_DS_VERSION_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_VERSION_EXT {
+	/** Selected version string */
+	t_u8 version_str_sel;
+	/** Version string */
+	char version_str[128];
+} MLAN_PACK_END HostCmd_DS_VERSION_EXT;
+
+#define TLV_TYPE_CHAN_ATTR_CFG (PROPRIETARY_TLV_BASE_ID + 237)
+#define TLV_TYPE_REGION_INFO (PROPRIETARY_TLV_BASE_ID + 238)
+#define TLV_TYPE_POWER_TABLE (PROPRIETARY_TLV_BASE_ID + 262)
+#define TLV_TYPE_POWER_TABLE_ATTR (PROPRIETARY_TLV_BASE_ID + 317)
+/** HostCmd_DS_CHAN_REGION_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CHAN_REGION_CFG {
+	/** Action */
+	t_u16 action;
+} MLAN_PACK_END HostCmd_DS_CHAN_REGION_CFG;
+
+/** HostCmd_CMD_CW_MODE_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_CW_MODE_CTRL {
+	/** Action for CW Tone Control */
+	t_u16 action;
+	/** Mode of Operation 0: Disbale 1: Tx Continuous Packet 2: Tx
+	 * Continuous Wave */
+	t_u8 mode;
+	/** channel */
+	t_u8 channel;
+	/** channel info*/
+	t_u8 chanInfo;
+	/** Tx Power level in dBm */
+	t_u16 txPower;
+	/** Packet Length */
+	t_u16 pktLength;
+	/** bit rate Info */
+	t_u32 rateInfo;
+} MLAN_PACK_END HostCmd_DS_CW_MODE_CTRL;
+
+/** HostCmd_CMD_802_11_RF_ANTENNA */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_RF_ANTENNA {
+	/** Action for Tx antenna */
+	t_u16 action_tx;
+	/** Tx antenna mode Bit0:1, Bit1:2, Bit0-1:1+2, 0xffff: diversity */
+	t_u16 tx_antenna_mode;
+	/** Action for Rx antenna */
+	t_u16 action_rx;
+	/** Rx antenna mode Bit0:1, Bit1:2, Bit0-1:1+2, 0xffff: diversity */
+	t_u16 rx_antenna_mode;
+} MLAN_PACK_END HostCmd_DS_802_11_RF_ANTENNA;
+
+/** HostCmd_DS_802_11_IBSS_STATUS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_IBSS_STATUS {
+	/** Action */
+	t_u16 action;
+	/** Enable */
+	t_u16 enable;
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Beacon interval */
+	t_u16 beacon_interval;
+	/** ATIM window interval */
+	t_u16 atim_window;
+	/** User G rate protection */
+	t_u16 use_g_rate_protect;
+} MLAN_PACK_END HostCmd_DS_802_11_IBSS_STATUS;
+
+/** HostCmd_DS_MGMT_IE_LIST_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_MGMT_IE_LIST {
+	/** Action */
+	t_u16 action;
+	/** Get/Set mgmt IE */
+	mlan_ds_misc_custom_ie ds_mgmt_ie;
+} MLAN_PACK_END HostCmd_DS_MGMT_IE_LIST_CFG;
+
+/** HostCmd_DS_TDLS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_TDLS_CONFIG {
+	/** Set TDLS configuration */
+	mlan_ds_misc_tdls_config tdls_info;
+} MLAN_PACK_END HostCmd_DS_TDLS_CONFIG;
+
+/**Action ID for TDLS delete link*/
+#define TDLS_DELETE 0x00
+/**Action ID for TDLS create link*/
+#define TDLS_CREATE 0x01
+/**Action ID for TDLS config link*/
+#define TDLS_CONFIG 0x02
+/** HostCmd_DS_TDLS_OPER */
+typedef MLAN_PACK_START struct _HostCmd_DS_TDLS_OPER {
+	/** Action */
+	t_u16 tdls_action;
+	/**reason*/
+	t_u16 reason;
+	/** peer mac */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_TDLS_OPER;
+
+/** HostCmd_CMD_MAC_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_MAC_REG_ACCESS {
+	/** Action */
+	t_u16 action;
+	/** MAC register offset */
+	t_u16 offset;
+	/** MAC register value */
+	t_u32 value;
+} MLAN_PACK_END HostCmd_DS_MAC_REG_ACCESS;
+
+/** HostCmd_CMD_BCA_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_BCA_REG_ACCESS {
+	/** Action */
+	t_u16 action;
+	/** BCA register offset */
+	t_u16 offset;
+	/** BCA register value */
+	t_u32 value;
+} MLAN_PACK_END HostCmd_DS_BCA_REG_ACCESS;
+
+/** HostCmd_CMD_BBP_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_BBP_REG_ACCESS {
+	/** Acion */
+	t_u16 action;
+	/** BBP register offset */
+	t_u16 offset;
+	/** BBP register value */
+	t_u8 value;
+	/** Reserved field */
+	t_u8 reserved[3];
+} MLAN_PACK_END HostCmd_DS_BBP_REG_ACCESS;
+
+/**  HostCmd_CMD_RF_REG_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_RF_REG_ACCESS {
+	/** Action */
+	t_u16 action;
+	/** RF register offset */
+	t_u16 offset;
+	/** RF register value */
+	t_u8 value;
+	/** Reserved field */
+	t_u8 reserved[3];
+} MLAN_PACK_END HostCmd_DS_RF_REG_ACCESS;
+
+/** HostCmd_DS_802_11_EEPROM_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_EEPROM_ACCESS {
+	/** Action */
+	t_u16 action;
+
+	/** multiple 4 */
+	t_u16 offset;
+	/** Number of bytes */
+	t_u16 byte_count;
+	/** Value */
+	t_u8 value;
+} MLAN_PACK_END HostCmd_DS_802_11_EEPROM_ACCESS;
+
+/** HostCmd_DS_MEM_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_MEM_ACCESS {
+	/** Action */
+	t_u16 action;
+	/** Reserved field */
+	t_u16 reserved;
+	/** Address */
+	t_u32 addr;
+	/** Value */
+	t_u32 value;
+} MLAN_PACK_END HostCmd_DS_MEM_ACCESS;
+
+/** HostCmd_DS_TARGET_ACCESS */
+typedef MLAN_PACK_START struct _HostCmd_DS_TARGET_ACCESS {
+	/** Action */
+	t_u16 action;
+	/** CSU Target Device. 1: CSU, 2: PSU */
+	t_u16 csu_target;
+	/** Target Device Address */
+	t_u16 address;
+	/** Data */
+	t_u8 data;
+} MLAN_PACK_END HostCmd_DS_TARGET_ACCESS;
+
+/** HostCmd_DS_SUBSCRIBE_EVENT */
+typedef MLAN_PACK_START struct _HostCmd_DS_SUBSCRIBE_EVENT {
+	/** Action */
+	t_u16 action;
+	/** Bitmap of subscribed events */
+	t_u16 event_bitmap;
+} MLAN_PACK_END HostCmd_DS_SUBSCRIBE_EVENT;
+
+/** HostCmd_DS_OTP_USER_DATA */
+typedef MLAN_PACK_START struct _HostCmd_DS_OTP_USER_DATA {
+	/** Action */
+	t_u16 action;
+	/** Reserved field */
+	t_u16 reserved;
+	/** User data length */
+	t_u16 user_data_length;
+	/** User data */
+	t_u8 user_data[1];
+} MLAN_PACK_END HostCmd_DS_OTP_USER_DATA;
+
+/** HostCmd_CMD_HS_WAKEUP_REASON */
+typedef MLAN_PACK_START struct _HostCmd_DS_HS_WAKEUP_REASON {
+	/** wakeupReason:
+	 * 0: unknown
+	 * 1: Broadcast data matched
+	 * 2: Multicast data matched
+	 * 3: Unicast data matched
+	 * 4: Maskable event matched
+	 * 5. Non-maskable event matched
+	 * 6: Non-maskable condition matched (EAPoL rekey)
+	 * 7: Magic pattern matched
+	 * Others: reserved. (set to 0) */
+	t_u16 wakeup_reason;
+} MLAN_PACK_END HostCmd_DS_HS_WAKEUP_REASON;
+
+/** MrvlIEtypes_HsWakeHoldoff_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_HsWakeHoldoff_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Minimum delay between HsActive and HostWake (in msec) */
+	t_u16 min_wake_holdoff;
+} MLAN_PACK_END MrvlIEtypes_HsWakeHoldoff_t;
+
+/** MrvlIEtypes_PsParamsInHs_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_PsParamsInHs_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Host sleep wake interval(in msec) */
+	t_u32 hs_wake_interval;
+	/** Host sleep inactivity timeout (in msec) */
+	t_u32 hs_inactivity_timeout;
+} MLAN_PACK_END MrvlIEtypes_PsParamsInHs_t;
+
+/** MrvlIEtypes_WakeupSourceGPIO_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_WakeupSourceGPIO_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** GPIO for indication of wakeup source */
+	t_u8 ind_gpio;
+	/** Level on ind_gpio for normal wakeup source */
+	t_u8 level;
+} MLAN_PACK_END MrvlIEtypes_WakeupSourceGPIO_t;
+
+/** MrvlIEtypes_RobustcoexSourceGPIO_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_RobustcoexSourceGPIO_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** GPIO cfg for external bt request */
+	t_u8 enable;
+	/** GPIO number */
+	t_u8 gpio_num;
+	/** GPIO Polarity */
+	t_u8 gpio_polarity;
+} MLAN_PACK_END MrvlIEtypes_RobustcoexSourceGPIO_t;
+
+#define MAX_NUM_MAC 2
+
+typedef MLAN_PACK_START struct _dmcs_chan_status {
+	/** Channel number */
+	t_u8 channel;
+	/** Number of AP on this channel */
+	t_u8 ap_count;
+	/** Number of STA on this channel*/
+	t_u8 sta_count;
+} MLAN_PACK_END dmcs_chan_status;
+
+typedef MLAN_PACK_START struct _dmcs_status_data {
+	/** radio ID */
+	t_u8 radio_id;
+	/** Running mode
+	 ** 0 - Idle
+	 ** 1 - DBC
+	 ** 2 - DRCS
+	 */
+	t_u8 running_mode;
+	/** Channel status of this radio */
+	dmcs_chan_status chan_status[2];
+} MLAN_PACK_END dmcs_status_data;
+
+/** MrvlIEtypes_DmcsConfig_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_DmcsConfig_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Mapping policy */
+	t_u8 mapping_policy;
+	/** Radio status of DMCS */
+	dmcs_status_data radio_status[MAX_NUM_MAC];
+} MLAN_PACK_END MrvlIEtypes_DmcsStatus_t;
+
+#define ANTMODE_FW_DECISION 0xff
+/** MrvlIEtypes_HS_Antmode_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_HS_Antmode_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Tx Path antenna mode*/
+	t_u8 txpath_antmode;
+	/** Rx Path antenna mode */
+	t_u8 rxpath_antmode;
+} MLAN_PACK_END MrvlIEtypes_HS_Antmode_t;
+
+typedef MLAN_PACK_START struct _MrvlIEtypes_WakeupExtend_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Events that will be forced ignore **/
+	t_u32 event_force_ignore;
+	/** Events that will use extend gap to inform host*/
+	t_u32 event_use_ext_gap;
+	/** Extend gap*/
+	t_u8 ext_gap;
+	/** GPIO wave level*/
+	t_u8 gpio_wave;
+} MLAN_PACK_END MrvlIEtypes_WakeupExtend_t;
+
+#define EVENT_MANAGEMENT_FRAME_WAKEUP 136
+typedef MLAN_PACK_START struct _mgmt_frame_filter {
+	/** action - bitmap
+	 ** On matching rx'd pkt and filter during NON_HOSTSLEEP mode:
+	 **   Action[1]=0  Discard
+	 **   Action[1]=1  Allow
+	 ** Note that default action on non-match is "Allow".
+	 **
+	 ** On matching rx'd pkt and filter during HOSTSLEEP mode:
+	 **   Action[1:0]=00  Discard and Not Wake host
+	 **   Action[1:0]=01  Discard and Wake host
+	 **   Action[1:0]=10  Invalid
+	 ** Note that default action on non-match is "Discard and Not Wake
+	 *host".
+	 **/
+	t_u8 action;
+	/** Frame type(p2p...)
+	 ** type=0: invalid
+	 ** type=1: p2p
+	 ** type=0xff: management frames(assoc req/rsp, probe req/rsp,...)
+	 ** type=others: reserved
+	 **/
+	t_u8 type;
+	/** Frame mask according to each type
+	 ** When type=1 for p2p, frame-mask have following define:
+	 **    Bit      Frame
+	 **     0       GO Negotiation Request
+	 **     1       GO Negotiation Response
+	 **     2       GO Negotiation Confirmation
+	 **     3       P2P Invitation Request
+	 **     4       P2P Invitation Response
+	 **     5       Device Discoverability Request
+	 **     6       Device Discoverability Response
+	 **     7       Provision Discovery Request
+	 **     8       Provision Discovery Response
+	 **     9       Notice of Absence
+	 **     10      P2P Presence Request
+	 **     11      P2P Presence Response
+	 **     12      GO Discoverability Request
+	 **     13-31   Reserved
+	 **
+	 ** When type=others, frame-mask is reserved.
+	 **/
+	t_u32 frame_mask;
+} MLAN_PACK_END mgmt_frame_filter;
+
+#define MAX_MGMT_FRAME_FILTER 2
+/** MrvlIEtypes_MgmtFrameFilter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_MgmtFrameFilter_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** management frame filters */
+	mgmt_frame_filter filter[MAX_MGMT_FRAME_FILTER];
+} MLAN_PACK_END MrvlIEtypes_MgmtFrameFilter_t;
+
+/** HostCmd_DS_INACTIVITY_TIMEOUT_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_INACTIVITY_TIMEOUT_EXT {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+	/** uS, 0 means 1000uS(1ms) */
+	t_u16 timeout_unit;
+	/** Inactivity timeout for unicast data */
+	t_u16 unicast_timeout;
+	/** Inactivity timeout for multicast data */
+	t_u16 mcast_timeout;
+	/** Timeout for additional RX traffic after Null PM1 packet exchange */
+	t_u16 ps_entry_timeout;
+	/** Reserved to further expansion */
+	t_u16 reserved;
+} MLAN_PACK_END HostCmd_DS_INACTIVITY_TIMEOUT_EXT;
+
+/** HostCmd_DS_INDEPENDENT_RESET_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_INDEPENDENT_RESET_CFG {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+	/** out band independent reset */
+	t_u8 ir_mode;
+	/** gpio pin */
+	t_u8 gpio_pin;
+} MLAN_PACK_END HostCmd_DS_INDEPENDENT_RESET_CFG;
+
+/** HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+	/** ps inactivity timeout value */
+	t_u16 inact_tmo;
+} MLAN_PACK_END HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT;
+
+/** TLV type : STA Mac address */
+#define TLV_TYPE_STA_MAC_ADDRESS (PROPRIETARY_TLV_BASE_ID + 0x20)	/* 0x0120 */
+
+#define TLV_TYPE_RANDOM_MAC (PROPRIETARY_TLV_BASE_ID + 0xEC)	/*0x01EC */
+
+/** MrvlIEtypes_MacAddr_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_MacAddr_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END MrvlIEtypes_MacAddr_t;
+
+/** Assoc Request */
+#define SUBTYPE_ASSOC_REQUEST 0
+/** ReAssoc Request */
+#define SUBTYPE_REASSOC_REQUEST 2
+/** Probe Resp */
+#define SUBTYPE_PROBE_RESP 5
+/** Disassoc Request */
+#define SUBTYPE_DISASSOC 10
+/** Auth Request */
+#define SUBTYPE_AUTH 11
+/** Deauth Request */
+#define SUBTYPE_DEAUTH 12
+/** Action frame */
+#define SUBTYPE_ACTION 13
+/** beacon */
+#define SUBTYPE_BEACON 8
+
+#ifdef UAP_SUPPORT
+/** TLV type : AP Channel band Config */
+#define TLV_TYPE_UAP_CHAN_BAND_CONFIG                                          \
+	(PROPRIETARY_TLV_BASE_ID + 0x2a)	/* 0x012a */
+/** TLV type : AP Mac address */
+#define TLV_TYPE_UAP_MAC_ADDRESS (PROPRIETARY_TLV_BASE_ID + 0x2b)	/* 0x012b */
+/** TLV type : AP Beacon period */
+#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 0x2c)	/* 0x012c  \
+									 */
+/** TLV type : AP DTIM period */
+#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 0x2d)	/* 0x012d */
+/** TLV type : AP Tx power */
+#define TLV_TYPE_UAP_TX_POWER (PROPRIETARY_TLV_BASE_ID + 0x2f)	/* 0x012f */
+/** TLV type : AP SSID broadcast control */
+#define TLV_TYPE_UAP_BCAST_SSID_CTL                                            \
+	(PROPRIETARY_TLV_BASE_ID + 0x30)	/* 0x0130 */
+/** TLV type : AP Preamble control */
+#define TLV_TYPE_UAP_PREAMBLE_CTL (PROPRIETARY_TLV_BASE_ID + 0x31)	/* 0x0131   \
+									 */
+/** TLV type : AP Antenna control */
+#define TLV_TYPE_UAP_ANTENNA_CTL (PROPRIETARY_TLV_BASE_ID + 0x32)	/* 0x0132 */
+/** TLV type : AP RTS threshold */
+#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 0x33)	/* 0x0133  \
+									 */
+/** TLV type : AP Tx data rate */
+#define TLV_TYPE_UAP_TX_DATA_RATE (PROPRIETARY_TLV_BASE_ID + 0x35)	/* 0x0135   \
+									 */
+/** TLV type: AP Packet forwarding control */
+#define TLV_TYPE_UAP_PKT_FWD_CTL (PROPRIETARY_TLV_BASE_ID + 0x36)	/* 0x0136 */
+/** TLV type: STA information */
+#define TLV_TYPE_UAP_STA_INFO (PROPRIETARY_TLV_BASE_ID + 0x37)	/* 0x0137 */
+/** TLV type: AP STA MAC address filter */
+#define TLV_TYPE_UAP_STA_MAC_ADDR_FILTER                                       \
+	(PROPRIETARY_TLV_BASE_ID + 0x38)	/* 0x0138 */
+/** TLV type: AP STA ageout timer */
+#define TLV_TYPE_UAP_STA_AGEOUT_TIMER                                          \
+	(PROPRIETARY_TLV_BASE_ID + 0x39)	/* 0x0139 */
+/** TLV type: AP WEP keys */
+#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 0x3b)	/* 0x013b */
+/** TLV type: AP WPA passphrase */
+#define TLV_TYPE_UAP_WPA_PASSPHRASE                                            \
+	(PROPRIETARY_TLV_BASE_ID + 0x3c)	/* 0x013c */
+/** TLV type: AP protocol */
+#define TLV_TYPE_UAP_ENCRYPT_PROTOCOL                                          \
+	(PROPRIETARY_TLV_BASE_ID + 0x40)	/* 0x0140 */
+/** TLV type: AP AKMP */
+#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 0x41)	/* 0x0141 */
+/** TLV type: AP Fragment threshold */
+#define TLV_TYPE_UAP_FRAG_THRESHOLD                                            \
+	(PROPRIETARY_TLV_BASE_ID + 0x46)	/* 0x0146 */
+/** TLV type: AP Group rekey timer */
+#define TLV_TYPE_UAP_GRP_REKEY_TIME                                            \
+	(PROPRIETARY_TLV_BASE_ID + 0x47)	/* 0x0147 */
+/**TLV type : AP Max Station number */
+#define TLV_TYPE_UAP_MAX_STA_CNT (PROPRIETARY_TLV_BASE_ID + 0x55)	/* 0x0155 */
+/**TLV type : AP Max Station number per chip */
+#define TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP                                      \
+	(PROPRIETARY_TLV_BASE_ID + 0x140)	/* 0x0240 */
+/**TLV type : AP Retry limit */
+#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 0x5d)	/* 0x015d */
+/** TLV type : AP MCBC data rate */
+#define TLV_TYPE_UAP_MCBC_DATA_RATE                                            \
+	(PROPRIETARY_TLV_BASE_ID + 0x62)	/* 0x0162 */
+/**TLV type: AP RSN replay protection */
+#define TLV_TYPE_UAP_RSN_REPLAY_PROTECT                                        \
+	(PROPRIETARY_TLV_BASE_ID + 0x64)	/* 0x0164 */
+/**TLV type: AP mgmt IE passthru mask */
+#define TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK                                     \
+	(PROPRIETARY_TLV_BASE_ID + 0x70)	/* 0x0170 */
+
+/**TLV type: AP pairwise handshake timeout */
+#define TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT                                     \
+	(PROPRIETARY_TLV_BASE_ID + 0x75)	/* 0x0175 */
+/**TLV type: AP pairwise handshake retries */
+#define TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES                                     \
+	(PROPRIETARY_TLV_BASE_ID + 0x76)	/* 0x0176 */
+/**TLV type: AP groupwise handshake timeout */
+#define TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT                                     \
+	(PROPRIETARY_TLV_BASE_ID + 0x77)	/* 0x0177 */
+/**TLV type: AP groupwise handshake retries */
+#define TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES                                     \
+	(PROPRIETARY_TLV_BASE_ID + 0x78)	/* 0x0178 */
+/** TLV type: AP PS STA ageout timer */
+#define TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER                                       \
+	(PROPRIETARY_TLV_BASE_ID + 0x7b)	/* 0x017b */
+/** TLV type : Pairwise Cipher */
+#define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 0x91)	/* 0x0191 */
+/** TLV type : Group Cipher */
+#define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 0x92)	/* 0x0192 */
+/** TLV type : BSS Status */
+#define TLV_TYPE_BSS_STATUS (PROPRIETARY_TLV_BASE_ID + 0x93)	/* 0x0193 */
+/** TLV type :  AP WMM params */
+#define TLV_TYPE_AP_WMM_PARAM (PROPRIETARY_TLV_BASE_ID + 0xd0)	/* 0x01d0 */
+/** TLV type : AP Tx beacon rate */
+#define TLV_TYPE_UAP_TX_BEACON_RATE (PROPRIETARY_TLV_BASE_ID + 288)	/* 0x0220  \
+									 */
+
+/** MrvlIEtypes_beacon_period_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_beacon_period_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** beacon period */
+	t_u16 beacon_period;
+} MLAN_PACK_END MrvlIEtypes_beacon_period_t;
+
+/** MrvlIEtypes_dtim_period_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_dtim_period_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** DTIM period */
+	t_u8 dtim_period;
+} MLAN_PACK_END MrvlIEtypes_dtim_period_t;
+
+/** MrvlIEtypes_tx_rate_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_tx_rate_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** tx data rate */
+	t_u16 tx_data_rate;
+} MLAN_PACK_END MrvlIEtypes_tx_rate_t;
+
+/** MrvlIEtypes_mcbc_rate_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mcbc_rate_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** mcbc data rate */
+	t_u16 mcbc_data_rate;
+} MLAN_PACK_END MrvlIEtypes_mcbc_rate_t;
+
+/** MrvlIEtypes_tx_power_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_tx_power_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** tx power */
+	t_u8 tx_power;
+} MLAN_PACK_END MrvlIEtypes_tx_power_t;
+
+/** MrvlIEtypes_bcast_ssid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bcast_ssid_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** bcast ssid control*/
+	t_u8 bcast_ssid_ctl;
+} MLAN_PACK_END MrvlIEtypes_bcast_ssid_t;
+
+/** MrvlIEtypes_antenna_mode_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_antenna_mode_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** which antenna */
+	t_u8 which_antenna;
+	/** antenna mode*/
+	t_u8 antenna_mode;
+} MLAN_PACK_END MrvlIEtypes_antenna_mode_t;
+
+/** MrvlIEtypes_pkt_forward_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pkt_forward_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** pkt foward control */
+	t_u8 pkt_forward_ctl;
+} MLAN_PACK_END MrvlIEtypes_pkt_forward_t;
+
+/** MrvlIEtypes_max_sta_count_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_max_sta_count_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** max station count */
+	t_u16 max_sta_count;
+} MLAN_PACK_END MrvlIEtypes_max_sta_count_t;
+
+/** MrvlIEtypes_uap_max_sta_cnt */
+typedef MLAN_PACK_START struct _MrvlIEtypes_uap_max_sta_cnt_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** max station count */
+	t_u16 uap_max_sta;
+} MLAN_PACK_END MrvlIEtypes_uap_max_sta_cnt_t;
+
+#define MRVL_ACTION_CHAN_SWITCH_ANNOUNCE        (PROPRIETARY_TLV_BASE_ID + 0x341)
+
+/** MrvlIEtypes_uap_chan_switch */
+typedef MLAN_PACK_START struct _MrvlIEtypes_action_chan_switch_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/* 0 send broadcast CSA action frame, 1 send unicast CSA action frame */
+	t_u32 mode;
+    /**ie buf*/
+	t_u8 ie_buf[];
+} MLAN_PACK_END MrvlIEtypes_action_chan_switch_t;
+
+/** MrvlIEtypes_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_ageout_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** station age out timer */
+	t_u32 sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_sta_ageout_t;
+
+/** MrvlIEtypes_rts_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rts_threshold_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** rts threshold */
+	t_u16 rts_threshold;
+} MLAN_PACK_END MrvlIEtypes_rts_threshold_t;
+
+/** MrvlIEtypes_frag_threshold_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_frag_threshold_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** frag threshold */
+	t_u16 frag_threshold;
+} MLAN_PACK_END MrvlIEtypes_frag_threshold_t;
+
+/** MrvlIEtypes_retry_limit_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_retry_limit_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** retry limit */
+	t_u8 retry_limit;
+} MLAN_PACK_END MrvlIEtypes_retry_limit_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_timeout_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_pwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pwk_hsk_retries_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** pairwise handshake retries */
+	t_u32 pwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_pwk_hsk_retries_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_timeout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_timeout_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_timeout_t;
+
+/** MrvlIEtypes_eapol_gwk_hsk_retries_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_gwk_hsk_retries_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** groupwise handshake retries */
+	t_u32 gwk_retries;
+} MLAN_PACK_END MrvlIEtypes_eapol_gwk_hsk_retries_t;
+
+/** MrvlIEtypes_mgmt_ie_passthru_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mgmt_ie_passthru_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** mgmt IE mask value */
+	t_u32 mgmt_ie_mask;
+} MLAN_PACK_END MrvlIEtypes_mgmt_ie_passthru_t;
+
+/** MrvlIEtypes_mac_filter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_mac_filter_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Filter mode */
+	t_u8 filter_mode;
+	/** Number of STA MACs */
+	t_u8 count;
+	/** STA MAC addresses buffer */
+	t_u8 mac_address[1];
+} MLAN_PACK_END MrvlIEtypes_mac_filter_t;
+
+/** MrvlIEtypes_auth_type_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_auth_type_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Authentication type */
+	t_u8 auth_type;
+} MLAN_PACK_END MrvlIEtypes_auth_type_t;
+
+/** MrvlIEtypes_encrypt_protocol_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_encrypt_protocol_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** encryption protocol */
+	t_u16 protocol;
+} MLAN_PACK_END MrvlIEtypes_encrypt_protocol_t;
+
+/** MrvlIEtypes_pwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_pwk_cipher_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** protocol */
+	t_u16 protocol;
+	/** pairwise cipher */
+	t_u8 pairwise_cipher;
+	/** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_pwk_cipher_t;
+
+/** MrvlIEtypes_gwk_cipher_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_gwk_cipher_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** group cipher */
+	t_u8 group_cipher;
+	/** reserved */
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIEtypes_gwk_cipher_t;
+
+/** MrvlIEtypes_akmp_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_akmp_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** key management */
+	t_u16 key_mgmt;
+	/** key management operation */
+	t_u16 key_mgmt_operation;
+} MLAN_PACK_END MrvlIEtypes_akmp_t;
+
+/** MrvlIEtypes_passphrase_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_passphrase_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** passphrase */
+	t_u8 passphrase[1];
+} MLAN_PACK_END MrvlIEtypes_passphrase_t;
+
+/** MrvlIEtypes_rsn_replay_prot_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_rsn_replay_prot_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** rsn replay proection */
+	t_u8 rsn_replay_prot;
+} MLAN_PACK_END MrvlIEtypes_rsn_replay_prot_t;
+
+/** MrvlIEtypes_group_rekey_time_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_group_rekey_time_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** group key rekey time */
+	t_u32 gk_rekey_time;
+} MLAN_PACK_END MrvlIEtypes_group_rekey_time_t;
+
+/** MrvlIEtypes_wep_key_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wep_key_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** key index */
+	t_u8 key_index;
+	/** is default */
+	t_u8 is_default;
+	/** key data */
+	t_u8 key[1];
+} MLAN_PACK_END MrvlIEtypes_wep_key_t;
+
+/** MrvlIEtypes_bss_status_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_bss_status_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** BSS status, READ only */
+	t_u16 bss_status;
+} MLAN_PACK_END MrvlIEtypes_bss_status_t;
+
+/** MrvlIEtypes_preamble_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_preamble_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** preamble type, READ only */
+	t_u8 preamble_type;
+} MLAN_PACK_END MrvlIEtypes_preamble_t;
+
+/** MrvlIEtypes_wmm_parameter_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wmm_parameter_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** WMM parameter */
+	WmmParameter_t wmm_para;
+} MLAN_PACK_END MrvlIEtypes_wmm_parameter_t;
+
+/** MrvlIEtypes_wacp_mode_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wacp_mode_t {
+    /** Header */
+	MrvlIEtypesHeader_t header;
+    /** wacp_mode */
+	t_u8 wacp_mode;
+} MLAN_PACK_END MrvlIEtypes_wacp_mode_t;
+
+/** SNMP_MIB_UAP_INDEX */
+typedef enum _SNMP_MIB_UAP_INDEX {
+	tkip_mic_failures = 0x0b,
+	ccmp_decrypt_errors = 0x0c,
+	wep_undecryptable_count = 0x0d,
+	wep_icv_error_count = 0x0e,
+	decrypt_failure_count = 0xf,
+	dot11_failed_count = 0x12,
+	dot11_retry_count = 0x13,
+	dot11_multi_retry_count = 0x14,
+	dot11_frame_dup_count = 0x15,
+	dot11_rts_success_count = 0x16,
+	dot11_rts_failure_count = 0x17,
+	dot11_ack_failure_count = 0x18,
+	dot11_rx_fragment_count = 0x19,
+	dot11_mcast_rx_frame_count = 0x1a,
+	dot11_fcs_error_count = 0x1b,
+	dot11_tx_frame_count = 0x1c,
+	dot11_rsna_tkip_cm_invoked = 0x1d,
+	dot11_rsna_4way_hshk_failures = 0x1e,
+	dot11_mcast_tx_count = 0x1f,
+} SNMP_MIB_UAP_INDEX;
+
+/** MrvlIEtypes_snmp_oid_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_snmp_oid_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** data */
+	t_u32 data;
+} MLAN_PACK_END MrvlIEtypes_snmp_oid_t;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_CONFIG {
+	/** CMD Action GET/SET*/
+	t_u16 action;
+	/** Tlv buffer */
+	t_u8 tlv_buffer[1];
+} MLAN_PACK_END HostCmd_DS_SYS_CONFIG;
+
+/** HostCmd_SYS_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_SYS_INFO {
+	/** sys info */
+	t_u8 sys_info[64];
+} MLAN_PACK_END HostCmd_DS_SYS_INFO;
+
+/** HostCmd_DS_STA_DEAUTH */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_DEAUTH {
+	/** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+	/** reason code */
+	t_u16 reason;
+} MLAN_PACK_END HostCmd_DS_STA_DEAUTH;
+
+/** HostCmd_DS_REPORT_MIC */
+typedef MLAN_PACK_START struct _HostCmd_DS_REPORT_MIC {
+	/** mac address */
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END HostCmd_DS_REPORT_MIC;
+
+/** HostCmd_UAP_OPER_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_UAP_OPER_CTRL {
+	/** CMD Action GET/SET*/
+	t_u16 action;
+	/** control*/
+	t_u16 ctrl;
+	/**channel operation*/
+	t_u16 chan_opt;
+	/**channel band tlv*/
+	MrvlIEtypes_channel_band_t channel_band;
+} MLAN_PACK_END HostCmd_DS_UAP_OPER_CTRL;
+
+/** Host Command id: POWER_MGMT  */
+#define HOST_CMD_POWER_MGMT_EXT 0x00ef
+/** TLV type: AP Sleep param */
+#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 0x6a)	/* 0x016a */
+/** TLV type: AP Inactivity Sleep param */
+#define TLV_TYPE_AP_INACT_SLEEP_PARAM                                          \
+	(PROPRIETARY_TLV_BASE_ID + 0x6b)	/* 0x016b */
+
+/** MrvlIEtypes_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sleep_param_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** control bitmap */
+	t_u32 ctrl_bitmap;
+	/** min_sleep */
+	t_u32 min_sleep;
+	/** max_sleep */
+	t_u32 max_sleep;
+} MLAN_PACK_END MrvlIEtypes_sleep_param_t;
+
+/** MrvlIEtypes_inact_sleep_param_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_inact_sleep_param_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** inactivity timeout */
+	t_u32 inactivity_to;
+
+	/** min_awake */
+	t_u32 min_awake;
+	/** max_awake */
+	t_u32 max_awake;
+} MLAN_PACK_END MrvlIEtypes_inact_sleep_param_t;
+
+/** HostCmd_DS_POWER_MGMT */
+typedef MLAN_PACK_START struct _HostCmd_DS_POWER_MGMT_EXT {
+	/** CMD Action Get/Set*/
+	t_u16 action;
+	/** power mode */
+	t_u16 power_mode;
+} MLAN_PACK_END HostCmd_DS_POWER_MGMT_EXT;
+
+/** MrvlIEtypes_ps_sta_ageout_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_ps_sta_ageout_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** station age out timer */
+	t_u32 ps_sta_ageout_timer;
+} MLAN_PACK_END MrvlIEtypes_ps_sta_ageout_t;
+
+/** MrvlIEtypes_sta_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_sta_info_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+	/** Power Mgmt status */
+	t_u8 power_mgmt_status;
+	/** RSSI */
+	t_s8 rssi;
+	/** ie_buf */
+	t_u8 ie_buf[];
+} MLAN_PACK_END MrvlIEtypes_sta_info_t;
+
+/** HostCmd_DS_STA_LIST */
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_LIST {
+	/** Number of STAs */
+	t_u16 sta_count;
+	/* MrvlIEtypes_sta_info_t sta_info[]; */
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_STA_LIST;
+
+/** TLV ID : WAPI Information */
+#define TLV_TYPE_AP_WAPI_INFO (PROPRIETARY_TLV_BASE_ID + 0x67)	/* 0x0167 */
+
+/** MrvlIEtypes_sta_info_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_wapi_info_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Multicast PN */
+	t_u8 multicast_PN[16];
+} MLAN_PACK_END MrvlIEtypes_wapi_info_t;
+#endif /* UAP_SUPPORT */
+
+/** HostCmd_DS_TX_RX_HISTOGRAM */
+typedef MLAN_PACK_START struct _HostCmd_DS_TX_RX_HISTOGRAM {
+	/**  Enable or disable  */
+	t_u8 enable;
+	/** Choose to get TX, RX or both */
+	t_u16 action;
+} MLAN_PACK_END HostCmd_DS_TX_RX_HISTOGRAM;
+
+/** TLV buffer : 2040 coex config */
+typedef MLAN_PACK_START struct _MrvlIEtypes_2040_coex_enable_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Enable */
+	t_u8 enable_2040coex;
+} MLAN_PACK_END MrvlIEtypes_2040_coex_enable_t;
+
+/**BT coexit scan time setting*/
+typedef MLAN_PACK_START struct _MrvlIEtypes_BtCoexScanTime_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/**coex scan state  0: disable 1: enable*/
+	t_u8 coex_scan;
+	/**reserved*/
+	t_u8 reserved;
+	/**min scan time*/
+	t_u16 min_scan_time;
+	/**max scan time*/
+	t_u16 max_scan_time;
+} MLAN_PACK_END MrvlIEtypes_BtCoexScanTime_t;
+
+/**BT coexit aggr win size */
+typedef MLAN_PACK_START struct _MrvlIETypes_BtCoexAggrWinSize_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/**winsize  0: restore default winsize, 1: use below winsize */
+	t_u8 coex_win_size;
+	/**tx win size*/
+	t_u8 tx_win_size;
+	/**rx win size*/
+	t_u8 rx_win_size;
+	/**reserved*/
+	t_u8 reserved;
+} MLAN_PACK_END MrvlIETypes_BtCoexAggrWinSize_t;
+
+/** MrvlIEtypes_eapol_pkt_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_eapol_pkt_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** eapol pkt buf */
+	t_u8 pkt_buf[];
+} MLAN_PACK_END MrvlIEtypes_eapol_pkt_t;
+
+/** HostCmd_DS_EAPOL_PKT */
+typedef MLAN_PACK_START struct _HostCmd_DS_EAPOL_PKT {
+	/** Action */
+	t_u16 action;
+	/** TLV buffer */
+	MrvlIEtypes_eapol_pkt_t tlv_eapol;
+} MLAN_PACK_END HostCmd_DS_EAPOL_PKT;
+
+/** HostCmd_DS_OXYGEN_MIMO_SWITCH */
+typedef MLAN_PACK_START struct _HostCmd_DS_MIMO_SWITCH {
+	/** Tx path antanne mode */
+	t_u8 txpath_antmode;
+	/** Rx path antanne mode */
+	t_u8 rxpath_antmode;
+} MLAN_PACK_END HostCmd_DS_MIMO_SWITCH;
+
+#ifdef RX_PACKET_COALESCE
+typedef MLAN_PACK_START struct _HostCmd_DS_RX_PKT_COAL_CFG {
+	/** Action */
+	t_u16 action;
+	/** Packet threshold */
+	t_u32 packet_threshold;
+	/** Timeout */
+	t_u16 delay;
+} MLAN_PACK_END HostCmd_DS_RX_PKT_COAL_CFG;
+#endif
+
+/** HostCmd_DS_DYN_BW */
+typedef MLAN_PACK_START struct _HostCmd_DS_DYN_BW {
+	/** Action */
+	t_u16 action;
+	/** Dynamic bandwidth */
+	t_u16 dyn_bw;
+} MLAN_PACK_END HostCmd_DS_DYN_BW;
+
+/** Host Command ID : Packet aggregation CTRL */
+#define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
+
+/** HostCmd_DS_PACKET_AGGR_CTRL */
+typedef MLAN_PACK_START struct _HostCmd_DS_PACKET_AGGR_AGGR_CTRL {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+	/** enable aggregation, BIT(0) TX, BIT(1)RX */
+	t_u16 aggr_enable;
+	/** Tx aggregation alignment */
+	t_u16 tx_aggr_max_size;
+	/** Tx aggregation max packet number */
+	t_u16 tx_aggr_max_num;
+	/** Tx aggregation alignment */
+	t_u16 tx_aggr_align;
+} MLAN_PACK_END HostCmd_DS_PACKET_AGGR_CTRL;
+
+#ifdef USB
+/** Host Command ID : Packet aggregation over host interface */
+#define HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE 0x0117
+
+/** TLV ID : USB Aggregation parameters */
+#define MRVL_USB_AGGR_PARAM_TLV_ID (PROPRIETARY_TLV_BASE_ID + 0xB1)	/* 0x1B1   \
+									 */
+
+/** TLV size : USB Aggregation parameters, except header */
+#define MRVL_USB_AGGR_PARAM_TLV_LEN (14)
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _MrvlIETypes_USBAggrParam_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/** Enable */
+	t_u16 enable;
+	/** Rx aggregation mode */
+	t_u16 rx_aggr_mode;
+	/** Rx aggregation alignment */
+	t_u16 rx_aggr_align;
+	/** Rx aggregation max packet/size */
+	t_u16 rx_aggr_max;
+	/** Rx aggrgation timeout, in microseconds */
+	t_u16 rx_aggr_tmo;
+	/** Tx aggregation mode */
+	t_u16 tx_aggr_mode;
+	/** Tx aggregation alignment */
+	t_u16 tx_aggr_align;
+} MLAN_PACK_END MrvlIETypes_USBAggrParam_t;
+
+/** HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE */
+typedef MLAN_PACK_START struct _HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE {
+	/** ACT_GET/ACT_SET */
+	t_u16 action;
+	/**
+	 *  Host interface aggregation control TLV(s) to be sent in the firmware
+	 * command
+	 *
+	 *  TLV_USB_AGGR_PARAM, MrvlIETypes_USBAggrParam_t
+	 */
+	t_u8 tlv_buf[1];
+} MLAN_PACK_END HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE;
+#endif /* USB */
+
+/** HostCmd_CONFIG_LOW_PWR_MODE */
+typedef MLAN_PACK_START struct _HostCmd_CONFIG_LOW_PWR_MODE {
+	/** Enable LPM */
+	t_u8 enable;
+} MLAN_PACK_END HostCmd_CONFIG_LOW_PWR_MODE;
+
+/** HostCmd_CMD_GET_TSF */
+typedef MLAN_PACK_START struct _HostCmd_DS_TSF {
+	/** tsf value*/
+	t_u64 tsf;
+} MLAN_PACK_END HostCmd_DS_TSF;
+/* WLAN_GET_TSF*/
+
+typedef struct _HostCmd_DS_DFS_REPEATER_MODE {
+	/** Set or Get */
+	t_u16 action;
+	/** 1 on or 0 off */
+	t_u16 mode;
+} HostCmd_DS_DFS_REPEATER_MODE;
+
+/** HostCmd_DS_BOOT_SLEEP */
+typedef MLAN_PACK_START struct _HostCmd_DS_BOOT_SLEEP {
+	/** Set or Get */
+	t_u16 action;
+	/** 1 on or 0 off */
+	t_u16 enable;
+} MLAN_PACK_END HostCmd_DS_BOOT_SLEEP;
+
+/**
+ * @brief 802.11h Local Power Constraint NXP extended TLV
+ */
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header; /**< NXP TLV header: ID/Len */
+	t_u8 chan; /**< Channel local constraint applies to */
+
+	/** Power constraint included in beacons
+	 *  and used by fw to offset 11d info
+	 */
+	t_u8 constraint;
+
+} MLAN_PACK_END MrvlIEtypes_LocalPowerConstraint_t;
+
+/*
+ *
+ * Data structures for driver/firmware command processing
+ *
+ */
+
+/**  TPC Info structure sent in CMD_802_11_TPC_INFO command to firmware */
+typedef MLAN_PACK_START struct {
+	/**< Local constraint */
+	MrvlIEtypes_LocalPowerConstraint_t local_constraint;
+	/**< Power Capability */
+	MrvlIEtypes_PowerCapability_t power_cap;
+
+} MLAN_PACK_END HostCmd_DS_802_11_TPC_INFO;
+
+/**  TPC Request structure sent in CMD_802_11_TPC_ADAPT_REQ
+ *  command to firmware
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 dest_mac[MLAN_MAC_ADDR_LENGTH]; /**< Destination STA address  */
+	t_u16 timeout; /**< Response timeout in ms */
+	t_u8 rate_index; /**< IEEE Rate index to send request */
+
+} MLAN_PACK_END HostCmd_TpcRequest;
+
+/**  TPC Response structure received from the
+ *   CMD_802_11_TPC_ADAPT_REQ command
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 tpc_ret_code; /**< Firmware command result status code */
+	t_s8 tx_power; /**< Reported TX Power from the TPC Report element */
+	t_s8 link_margin; /**< Reported link margin from the TPC Report element
+			   */
+	t_s8 rssi; /**< RSSI of the received TPC Report frame */
+
+} MLAN_PACK_END HostCmd_TpcResponse;
+
+/**  CMD_802_11_TPC_ADAPT_REQ substruct.
+ *   Union of the TPC request and response
+ */
+typedef MLAN_PACK_START union {
+	HostCmd_TpcRequest req;	/**< Request struct sent to firmware */
+	HostCmd_TpcResponse resp; /**< Response struct received from firmware */
+
+} MLAN_PACK_END HostCmd_DS_802_11_TPC_ADAPT_REQ;
+
+/**  CMD_802_11_CHAN_SW_ANN firmware command substructure */
+typedef MLAN_PACK_START struct {
+	t_u8 switch_mode; /**< Set to 1 for a quiet switch request, no STA tx */
+	t_u8 new_chan; /**< Requested new channel */
+	t_u8 switch_count; /**< Number of TBTTs until the switch is to occur */
+} MLAN_PACK_END HostCmd_DS_802_11_CHAN_SW_ANN;
+
+/**
+ * @brief Enumeration of measurement types, including max supported
+ *        enum for 11h/11k
+ */
+typedef MLAN_PACK_START enum _MeasType_t {
+	WLAN_MEAS_BASIC = 0, /**< 11h: Basic */
+	WLAN_MEAS_NUM_TYPES, /**< Number of enumerated measurements */
+	WLAN_MEAS_11H_MAX_TYPE = WLAN_MEAS_BASIC, /**< Max 11h measurement */
+
+} MLAN_PACK_END MeasType_t;
+
+/**
+ * @brief Mode octet of the measurement request element (7.3.2.21)
+ */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	/**< Reserved */
+	t_u8 rsvd5_7:3;
+	/**< 11k: duration spec. for meas. is mandatory */
+	t_u8 duration_mandatory:1;
+	/**< 11h: en/disable report rcpt. of spec. type */
+	t_u8 report:1;
+	/**< 11h: en/disable requests of specified type */
+	t_u8 request:1;
+	/**< 11h: enable report/request bits */
+	t_u8 enable:1;
+	/**< 11k: series or parallel with previous meas */
+	t_u8 parallel:1;
+#else
+	/**< 11k: series or parallel with previous meas */
+	t_u8 parallel:1;
+	/**< 11h: enable report/request bits */
+	t_u8 enable:1;
+	/**< 11h: en/disable requests of specified type */
+	t_u8 request:1;
+	/**< 11h: en/disable report rcpt. of spec. type */
+	t_u8 report:1;
+	/**< 11k: duration spec. for meas. is mandatory */
+	t_u8 duration_mandatory:1;
+	/**< Reserved */
+	t_u8 rsvd5_7:3;
+#endif				/* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasReqMode_t;
+
+/**
+ * @brief Common measurement request structure (7.3.2.21.1 to 7.3.2.21.3)
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel; /**< Channel to measure */
+	t_u64 start_time; /**< TSF Start time of measurement (0 for immediate)
+			   */
+	t_u16 duration;	/**< TU duration of the measurement */
+
+} MLAN_PACK_END MeasReqCommonFormat_t;
+
+/**
+ * @brief Basic measurement request structure (7.3.2.21.1)
+ */
+typedef MeasReqCommonFormat_t MeasReqBasic_t;
+
+/**
+ * @brief CCA measurement request structure (7.3.2.21.2)
+ */
+typedef MeasReqCommonFormat_t MeasReqCCA_t;
+
+/**
+ * @brief RPI measurement request structure (7.3.2.21.3)
+ */
+typedef MeasReqCommonFormat_t MeasReqRPI_t;
+
+/**
+ * @brief Union of the availble measurement request types.  Passed in the
+ *        driver/firmware interface.
+ */
+typedef union {
+	MeasReqBasic_t basic; /**< Basic measurement request */
+	MeasReqCCA_t cca; /**< CCA measurement request */
+	MeasReqRPI_t rpi; /**< RPI measurement request */
+
+} MeasRequest_t;
+
+/**
+ * @brief Mode octet of the measurement report element (7.3.2.22)
+ */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 rsvd3_7:5;	  /**< Reserved */
+	t_u8 refused:1;	  /**< Measurement refused */
+	t_u8 incapable:1;   /**< Incapable of performing measurement */
+	t_u8 late:1;   /**< Start TSF time missed for measurement */
+#else
+	t_u8 late:1;   /**< Start TSF time missed for measurement */
+	t_u8 incapable:1;   /**< Incapable of performing measurement */
+	t_u8 refused:1;	  /**< Measurement refused */
+	t_u8 rsvd3_7:5;	  /**< Reserved */
+#endif				/* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptMode_t;
+
+/**
+ * @brief Basic measurement report (7.3.2.22.1)
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel; /**< Channel to measured */
+	t_u64 start_time; /**< Start time (TSF) of measurement */
+	t_u16 duration;	/**< Duration of measurement in TUs */
+	MeasRptBasicMap_t map; /**< Basic measurement report */
+
+} MLAN_PACK_END MeasRptBasic_t;
+
+/**
+ * @brief CCA measurement report (7.3.2.22.2)
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel; /**< Channel to measured */
+	t_u64 start_time; /**< Start time (TSF) of measurement */
+	t_u16 duration;	/**< Duration of measurement in TUs  */
+	t_u8 busy_fraction; /**< Fractional duration CCA indicated chan busy */
+
+} MLAN_PACK_END MeasRptCCA_t;
+
+/**
+ * @brief RPI measurement report (7.3.2.22.3)
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel; /**< Channel to measured  */
+	t_u64 start_time; /**< Start time (TSF) of measurement */
+	t_u16 duration;	/**< Duration of measurement in TUs  */
+	t_u8 density[8]; /**< RPI Density histogram report */
+
+} MLAN_PACK_END MeasRptRPI_t;
+
+/**
+ * @brief Union of the availble measurement report types.  Passed in the
+ *        driver/firmware interface.
+ */
+typedef union {
+	MeasRptBasic_t basic; /**< Basic measurement report */
+	MeasRptCCA_t cca; /**< CCA measurement report */
+	MeasRptRPI_t rpi; /**< RPI measurement report */
+
+} MeasReport_t;
+
+/**
+ * @brief Structure passed to firmware to perform a measurement
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; /**< Reporting STA address */
+	t_u8 dialog_token; /**< Measurement dialog toke */
+	MeasReqMode_t req_mode;	/**< Report mode  */
+	MeasType_t meas_type; /**< Measurement type */
+	MeasRequest_t req; /**< Measurement request data */
+
+} MLAN_PACK_END HostCmd_DS_MEASUREMENT_REQUEST,
+	*pHostCmd_DS_MEASUREMENT_REQUEST;
+
+/**
+ * @brief Structure passed back from firmware with a measurement report,
+ *        also can be to send a measurement report to another STA
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; /**< Reporting STA address */
+	t_u8 dialog_token; /**< Measurement dialog token */
+	MeasRptMode_t rpt_mode;	/**< Report mode */
+	MeasType_t meas_type; /**< Measurement type */
+	MeasReport_t rpt; /**< Measurement report data */
+
+} MLAN_PACK_END HostCmd_DS_MEASUREMENT_REPORT, *pHostCmd_DS_MEASUREMENT_REPORT;
+
+typedef MLAN_PACK_START struct {
+	t_u16 startFreq;
+	Band_Config_t bandcfg;
+	t_u8 chanNum;
+
+} MLAN_PACK_END MrvlChannelDesc_t;
+
+#ifdef OPCHAN
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header; /**< Header */
+
+	MrvlChannelDesc_t chanDesc;
+
+	t_u16 controlFlags;
+	t_u16 reserved;
+
+	t_u8 actPower;
+	t_u8 mdMinPower;
+	t_u8 mdMaxPower;
+	t_u8 mdPower;
+
+} MLAN_PACK_END MrvlIEtypes_ChanControlDesc_t;
+
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t header; /**< Header */
+
+	t_u16 chanGroupBitmap;
+	ChanScanMode_t scanMode;
+	t_u8 numChan;
+
+	MrvlChannelDesc_t chanDesc[50];
+
+} MLAN_PACK_END MrvlIEtypes_ChanGroupControl_t;
+
+typedef MLAN_PACK_START struct {
+	t_u16 action; /**< CMD Action Get/Set*/
+
+	t_u8 tlv_buffer[1];
+
+} MLAN_PACK_END HostCmd_DS_OPCHAN_CONFIG;
+
+typedef MLAN_PACK_START struct {
+	t_u16 action; /**< CMD Action Get/Set*/
+
+	t_u8 tlv_buffer[1];
+
+} MLAN_PACK_END HostCmd_DS_OPCHAN_CHANGROUP_CONFIG;
+
+#define HostCmd_CMD_OPCHAN_CONFIG 0x00f8
+#define HostCmd_CMD_OPCHAN_CHANGROUP_CONFIG 0x00f9
+#endif
+
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t Header; /**< Header */
+
+	MeasRptBasicMap_t map; /**< IEEE 802.11h basic meas report */
+} MLAN_PACK_END MrvlIEtypes_ChanRpt11hBasic_t;
+
+/* MrvlIEtypes_DfsW53Cfg_t*/
+typedef MLAN_PACK_START struct {
+	/* header */
+	MrvlIEtypesHeader_t Header;
+	/** df53cfg vlue*/
+	t_u8 dfs53cfg;
+} MLAN_PACK_END MrvlIEtypes_DfsW53Cfg_t;
+
+typedef MLAN_PACK_START struct {
+	MrvlChannelDesc_t chan_desc; /**< Channel band, number */
+	t_u32 millisec_dwell_time; /**< Channel dwell time in milliseconds */
+} MLAN_PACK_END HostCmd_DS_CHAN_RPT_REQ;
+
+typedef MLAN_PACK_START struct {
+	t_u32 cmd_result; /**< Rpt request command result (0 == SUCCESS) */
+	t_u64 start_tsf; /**< TSF Measurement started */
+	t_u32 duration;	/**< Duration of measurement in microsecs */
+	t_u8 tlv_buffer[1]; /**< TLV Buffer */
+} MLAN_PACK_END HostCmd_DS_CHAN_RPT_RSP;
+
+/** statistics threshold */
+typedef MLAN_PACK_START struct {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** value */
+	t_u8 value;
+	/** reporting frequency */
+	t_u8 frequency;
+} MLAN_PACK_END MrvlIEtypes_BeaconHighRssiThreshold_t,
+	MrvlIEtypes_BeaconLowRssiThreshold_t,
+	MrvlIEtypes_BeaconHighSnrThreshold_t,
+	MrvlIEtypes_BeaconLowSnrThreshold_t, MrvlIEtypes_FailureCount_t,
+	MrvlIEtypes_DataLowRssiThreshold_t, MrvlIEtypes_DataHighRssiThreshold_t,
+	MrvlIEtypes_DataLowSnrThreshold_t, MrvlIEtypes_DataHighSnrThreshold_t,
+	MrvlIETypes_PreBeaconMissed_t, MrvlIEtypes_BeaconsMissed_t;
+
+/** statistics threshold for LinkQuality */
+typedef MLAN_PACK_START struct {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Link SNR threshold (dB) */
+	t_u16 link_snr;
+	/** Link SNR frequency */
+	t_u16 link_snr_freq;
+	/* Second minimum rate value as per the rate table below */
+	t_u16 link_rate;
+	/* Second minimum rate frequency */
+	t_u16 link_rate_freq;
+	/* Tx latency value (us) */
+	t_u16 link_tx_latency;
+	/* Tx latency frequency */
+	t_u16 link_tx_lantency_freq;
+} MLAN_PACK_END MrvlIEtypes_LinkQualityThreshold_t;
+
+#ifdef PCIE
+/** PCIE dual descriptor for data/event */
+typedef MLAN_PACK_START struct _dual_desc_buf {
+	/** buf size */
+	t_u16 len;
+	/** buffer descriptor flags */
+	t_u16 flags;
+	/** pkt size */
+	t_u16 pkt_size;
+	/** reserved */
+	t_u16 reserved;
+	/** Physical address of the buffer */
+	t_u64 paddr;
+} MLAN_PACK_END adma_dual_desc_buf, *padma_dual_desc_buf;
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/** PCIE ring buffer description for DATA */
+typedef MLAN_PACK_START struct _mlan_pcie_data_buf {
+	/** Buffer descriptor flags */
+	t_u16 flags;
+	/** Offset of fragment/pkt to start of ip header */
+	t_u16 offset;
+	/** Fragment length of the buffer */
+	t_u16 frag_len;
+	/** Length of the buffer */
+	t_u16 len;
+	/** Physical address of the buffer */
+	t_u64 paddr;
+	/** Reserved */
+	t_u32 reserved;
+} MLAN_PACK_END mlan_pcie_data_buf, *pmlan_pcie_data_buf;
+
+/** PCIE ring buffer description for EVENT */
+typedef MLAN_PACK_START struct _mlan_pcie_evt_buf {
+	/** Physical address of the buffer */
+	t_u64 paddr;
+	/** Length of the buffer */
+	t_u16 len;
+	/** Buffer descriptor flags */
+	t_u16 flags;
+} MLAN_PACK_END mlan_pcie_evt_buf, *pmlan_pcie_evt_buf;
+
+/** PCIE host buffer configuration */
+typedef MLAN_PACK_START struct _HostCmd_DS_PCIE_HOST_BUF_DETAILS {
+	/** TX buffer descriptor ring address */
+	t_u32 txbd_addr_lo;
+	t_u32 txbd_addr_hi;
+	/** TX buffer descriptor ring count */
+	t_u32 txbd_count;
+
+	/** RX buffer descriptor ring address */
+	t_u32 rxbd_addr_lo;
+	t_u32 rxbd_addr_hi;
+	/** RX buffer descriptor ring count */
+	t_u32 rxbd_count;
+
+	/** Event buffer descriptor ring address */
+	t_u32 evtbd_addr_lo;
+	t_u32 evtbd_addr_hi;
+	/** Event buffer descriptor ring count */
+	t_u32 evtbd_count;
+} HostCmd_DS_PCIE_HOST_BUF_DETAILS;
+#endif
+#endif
+
+typedef MLAN_PACK_START struct _HostCmd_DS_SENSOR_TEMP {
+	t_u32 temperature;
+} MLAN_PACK_END HostCmd_DS_SENSOR_TEMP;
+
+#define TLV_TYPE_IPV6_RA_OFFLOAD (PROPRIETARY_TLV_BASE_ID + 0xE6) /** 0x1E6*/
+typedef MLAN_PACK_START struct {
+	MrvlIEtypesHeader_t Header;
+	t_u8 ipv6_addr[16];
+} MLAN_PACK_END MrvlIETypes_IPv6AddrParamSet_t;
+
+typedef MLAN_PACK_START struct _HostCmd_DS_IPV6_RA_OFFLOAD {
+	/** 0x0000: Get IPv6 RA Offload configuration
+	 *  0x0001: Set IPv6 RA Offload configuration
+	 */
+	t_u16 action;
+	/** 0x00: disable IPv6 RA Offload; 0x01: enable IPv6 RA offload */
+	t_u8 enable;
+	MrvlIETypes_IPv6AddrParamSet_t ipv6_addr_param;
+} MLAN_PACK_END HostCmd_DS_IPV6_RA_OFFLOAD;
+
+#ifdef STA_SUPPORT
+typedef MLAN_PACK_START struct _HostCmd_DS_STA_CONFIGURE {
+	/** Action Set or get */
+	t_u16 action;
+	/** Tlv buffer */
+	t_u8 tlv_buffer[];
+	/**MrvlIEtypes_channel_band_t band_channel; */
+} MLAN_PACK_END HostCmd_DS_STA_CONFIGURE;
+#endif
+
+/** HostCmd_DS_AUTO_TX structure */
+typedef MLAN_PACK_START struct _HostCmd_DS_AUTO_TX {
+	/** Action Set or get */
+	t_u16 action;
+	/** Tlv buffer */
+	t_u8 tlv_buffer[];
+} MLAN_PACK_END HostCmd_DS_AUTO_TX;
+
+#define OID_CLOUD_KEEP_ALIVE 0
+#define EVENT_CLOUD_KEEP_ALIVE_RETRY_FAIL 133
+/** TLV for cloud keep alive control info */
+#define TLV_TYPE_CLOUD_KEEP_ALIVE                                              \
+	(PROPRIETARY_TLV_BASE_ID + 0x102)	/* 0x0100 + 258 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Cloud_Keep_Alive_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** ID for cloud keep alive */
+	t_u8 keep_alive_id;
+	/** Enable/disable for this ID */
+	t_u8 enable;
+	/** TLV buffer */
+	t_u8 tlv[];
+} MLAN_PACK_END MrvlIEtypes_Cloud_Keep_Alive_t;
+
+/** TLV for cloud keep alive control info */
+#define TLV_TYPE_KEEP_ALIVE_CTRL                                               \
+	(PROPRIETARY_TLV_BASE_ID + 0x103)	/* 0x0100 + 259 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Keep_Alive_Ctrl_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** period to send keep alive packet */
+	t_u32 snd_interval;
+	/** period to send retry packet */
+	t_u16 retry_interval;
+	/** count to send retry packet */
+	t_u16 retry_count;
+} MLAN_PACK_END MrvlIEtypes_Keep_Alive_Ctrl_t;
+
+/** TLV for cloud keep alive packet */
+#define TLV_TYPE_KEEP_ALIVE_PKT                                                \
+	(PROPRIETARY_TLV_BASE_ID + 0x104)	/* 0x0100 + 260 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Keep_Alive_Pkt_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Ethernet Header */
+	Eth803Hdr_t eth_header;
+	/** packet buffer*/
+	t_u8 ip_packet[];
+} MLAN_PACK_END MrvlIEtypes_Keep_Alive_Pkt_t;
+
+/** TLV to indicate firmware only keep probe response while scan */
+#define TLV_TYPE_ONLYPROBERESP (PROPRIETARY_TLV_BASE_ID + 0xE9)	/* 0x01E9 */
+typedef MLAN_PACK_START struct _MrvlIEtypes_OnlyProberesp_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** only keep probe response */
+	t_u8 proberesp_only;
+} MLAN_PACK_END MrvlIEtypes_OnlyProberesp_t;
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#define HostCmd_CMD_CRYPTO 0x025e
+
+#define HostCmd_CMD_CRYPTO_SUBCMD_PRF_HMAC_SHA1 (0x1)
+#define HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA1 (0x2)
+#define HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA256 (0x3)
+#define HostCmd_CMD_CRYPTO_SUBCMD_SHA256 (0x4)
+#define HostCmd_CMD_CRYPTO_SUBCMD_RIJNDAEL (0x5)
+#define HostCmd_CMD_CRYPTO_SUBCMD_RC4 (0x6)
+#define HostCmd_CMD_CRYPTO_SUBCMD_MD5 (0x7)
+#define HostCmd_CMD_CRYPTO_SUBCMD_MRVL_F (0x8)
+#define HostCmd_CMD_CRYPTO_SUBCMD_SHA256_KDF (0x9)
+
+#define TLV_TYPE_CRYPTO_KEY (PROPRIETARY_TLV_BASE_ID + 308)
+#define TLV_TYPE_CRYPTO_KEY_IV (PROPRIETARY_TLV_BASE_ID + 309)
+#define TLV_TYPE_CRYPTO_KEY_PREFIX (PROPRIETARY_TLV_BASE_ID + 310)
+#define TLV_TYPE_CRYPTO_KEY_DATA_BLK (PROPRIETARY_TLV_BASE_ID + 311)
+
+/** MrvlIEParamSet_t */
+typedef MLAN_PACK_START struct {
+	/** Type */
+	t_u16 Type;
+	/** Length */
+	t_u16 Length;
+} MLAN_PACK_END MrvlIEParamSet_t;
+
+/** HostCmd_DS_CRYPTO */
+typedef MLAN_PACK_START struct _HostCmd_DS_CRYPTO {
+	/** action */
+	t_u16 action;
+	/** subCmdCode */
+	t_u8 subCmdCode;
+	/** subCmd start */
+	t_u8 subCmd[];
+} MLAN_PACK_END HostCmd_DS_CRYPTO;
+
+/** subcmd_prf_hmac_sha1 used by prf_hmac_sha1, md5 and sha256_kdf */
+typedef MLAN_PACK_START struct _subcmd_prf_hmac_sha1 {
+	/** output_len */
+	t_u16 output_len;
+	/** tlv start */
+	t_u8 tlv[];
+} MLAN_PACK_END subcmd_prf_hmac_sha1_t, subcmd_md5_t, subcmd_sha256_kdf_t;
+
+/** subcmd_hmac_sha1 used by hmac_sha1, hmac_sha256, sha256 */
+typedef MLAN_PACK_START struct _subcmd_hmac_sha1 {
+	/** output_len */
+	t_u16 output_len;
+	/** number of data blocks */
+	t_u16 data_blks_nr;
+	/** tlv start */
+	t_u8 tlv[];
+} MLAN_PACK_END subcmd_hmac_sha1_t, subcmd_hmac_sha256_t, subcmd_sha256_t;
+
+/** subcmd_rijndael, used by rijndael */
+typedef MLAN_PACK_START struct _subcmd_rijndael {
+	/** output_len */
+	t_u16 output_len;
+	/** sub action code */
+	t_u8 sub_action_code;
+	/** tlv start */
+	t_u8 tlv[];
+} MLAN_PACK_END subcmd_rijndael_t;
+
+/** subcmd_rc4, used by rc4 */
+typedef MLAN_PACK_START struct _subcmd_rc4 {
+	/** output_len */
+	t_u16 output_len;
+	/** skip bytes */
+	t_u16 skip_bytes;
+	/** tlv start */
+	t_u8 tlv[];
+} MLAN_PACK_END subcmd_rc4_t;
+
+/** subcmd_mrvf_f, used by mrvl_f*/
+typedef MLAN_PACK_START struct _subcmd_mrvf_f {
+	/** output_len */
+	t_u16 output_len;
+	/** iterations */
+	t_u32 iterations;
+	/** count */
+	t_u32 count;
+	/** tlv start */
+	t_u8 tlv[];
+} MLAN_PACK_END subcmd_mrvl_f_t;
+
+#endif
+
+#ifdef UAP_SUPPORT
+/** action add station */
+#define HostCmd_ACT_ADD_STA 0x1
+/** remove station */
+#define HostCmd_ACT_REMOVE_STA 0x0
+/** HostCmd_DS_ADD_STATION */
+typedef MLAN_PACK_START struct _HostCmd_DS_ADD_STATION {
+	/** 1 -add, 0 --delete */
+	t_u16 action;
+	/** aid */
+	t_u16 aid;
+	/** peer_mac */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Listen Interval */
+	int listen_interval;
+	/** Capability Info */
+	t_u16 cap_info;
+	/** tlv start */
+	t_u8 tlv[];
+} MLAN_PACK_END HostCmd_DS_ADD_STATION;
+
+/** Host Command ID : Add New Station */
+#define HostCmd_CMD_ADD_NEW_STATION 0x025f
+/** TLV id: station flag */
+#define TLV_TYPE_UAP_STA_FLAGS (PROPRIETARY_TLV_BASE_ID + 313)
+/**MrvlIEtypes_Sta_Flag_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_StaFlag_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** station flag     */
+	t_u32 sta_flags;
+} MLAN_PACK_END MrvlIEtypes_StaFlag_t;
+#endif
+
+/** Host Command ID : _HostCmd_DS_BAND_STEERING */
+typedef MLAN_PACK_START struct _HostCmd_DS_BAND_STEERING {
+	/** ACT_GET/ACT_SET */
+	t_u8 action;
+	/** State */
+	t_u8 state;
+	/** probe requests to be blocked on 2g */
+	t_u8 block_2g_prb_req;
+	/** limit the btm request sent to STA at <max_btm_req_allowed>*/
+	t_u8 max_btm_req_allowed;
+} MLAN_PACK_END HostCmd_DS_BAND_STEERING;
+
+/** HostCmd_CMD_RX_ABORT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_RX_ABORT_CFG {
+	/** Action */
+	t_u16 action;
+	/** Enable/disable rx abort on weak pkt rssi */
+	t_u8 enable;
+	/** rx weak rssi pkt threshold */
+	t_s8 rssi_threshold;
+} MLAN_PACK_END HostCmd_DS_CMD_RX_ABORT_CFG;
+/** HostCmd_CMD_RX_ABORT_CFG_EXT */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_RX_ABORT_CFG_EXT {
+	/** Action */
+	t_u16 action;
+	/** Enable/disable dyn rx abort on weak pkt rssi */
+	t_u8 enable;
+	/** specify rssi margin */
+	t_s8 rssi_margin;
+	/** specify ceil rssi threshold */
+	t_s8 ceil_rssi_threshold;
+} MLAN_PACK_END HostCmd_DS_CMD_RX_ABORT_CFG_EXT;
+
+/** HostCmd_CMD_ARB_CONFIG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_ARB_CONFIG {
+	/** Action */
+	t_u16 action;
+	/** 0-4 */
+	t_u32 arb_mode;
+	/** 1: use FW enhancement, 0: use FW default */
+	t_u32 reserved;
+} MLAN_PACK_END HostCmd_DS_CMD_ARB_CONFIG;
+
+/** HostCmd_DS_CMD_TX_AMPDU_PROT_MODE */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_TX_AMPDU_PROT_MODE {
+	/** Action */
+	t_u16 action;
+	/** Prot mode */
+	t_u16 mode;
+} MLAN_PACK_END HostCmd_DS_CMD_TX_AMPDU_PROT_MODE;
+
+/** HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG {
+	/** Action */
+	t_u16 action;
+	/** Cfg state */
+	t_u16 state;
+} MLAN_PACK_END HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG;
+
+/** HostCmd_CMD_RATE_ADAPT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_RATE_ADAPT_CFG {
+	/** Action */
+	t_u16 action;
+	/** SR Rateadapt*/
+	t_u8 sr_rateadapt;
+	/** set low threshold */
+	t_u8 ra_low_thresh;
+	/** set high threshold */
+	t_u8 ra_high_thresh;
+	/** set interval */
+	t_u16 ra_interval;
+} MLAN_PACK_END HostCmd_DS_CMD_RATE_ADAPT_CFG;
+
+/** HostCmd_CMD_CCK_DESENSE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_CMD_CCK_DESENSE_CFG {
+	/** Action */
+	t_u16 action;
+	/** cck desense mode: 0:disable 1:normal 2:dynamic */
+	t_u16 mode;
+	/** specify rssi margin */
+	t_s8 margin;
+	/** specify ceil rssi threshold */
+	t_s8 ceil_thresh;
+	/** cck desense "on" interval count */
+	t_u8 num_on_intervals;
+	/** cck desense "off" interval count */
+	t_u8 num_off_intervals;
+} MLAN_PACK_END HostCmd_DS_CMD_CCK_DESENSE_CFG;
+
+/** HostCmd_DS_COMMAND */
+typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
+	/** Command Header : Command */
+	t_u16 command;
+	/** Command Header : Size */
+	t_u16 size;
+	/** Command Header : Sequence number */
+	t_u16 seq_num;
+	/** Command Header : Result */
+	t_u16 result;
+	/** Command Body */
+	union {
+		/** Hardware specifications */
+		HostCmd_DS_GET_HW_SPEC hw_spec;
+#ifdef SDIO
+		HostCmd_DS_SDIO_SP_RX_AGGR_CFG sdio_rx_aggr;
+#endif
+		/** Cfg data */
+		HostCmd_DS_802_11_CFG_DATA cfg_data;
+		/** MAC control */
+		HostCmd_DS_MAC_CONTROL mac_ctrl;
+		/** MAC address */
+		HostCmd_DS_802_11_MAC_ADDRESS mac_addr;
+		/** MAC muticast address */
+		HostCmd_DS_MAC_MULTICAST_ADR mc_addr;
+		/** Get log */
+		HostCmd_DS_802_11_GET_LOG get_log;
+		/** Get link layer statistic */
+		HostCmd_DS_802_11_LINK_STATISTIC get_link_statistic;
+		/** RSSI information */
+		HostCmd_DS_802_11_RSSI_INFO_EXT rssi_info_ext;
+		/** RSSI information */
+		HostCmd_DS_802_11_RSSI_INFO rssi_info;
+		/** RSSI information response */
+		HostCmd_DS_802_11_RSSI_INFO_RSP rssi_info_rsp;
+		/** SNMP MIB */
+		HostCmd_DS_802_11_SNMP_MIB smib;
+#ifdef UAP_SUPPORT
+		/** UAP SNMP MIB */
+		HostCmd_DS_UAP_802_11_SNMP_MIB uap_smib;
+#endif
+		/** Radio control */
+		HostCmd_DS_802_11_RADIO_CONTROL radio;
+		/** RF channel */
+		HostCmd_DS_802_11_RF_CHANNEL rf_channel;
+		/** Tx rate query */
+		HostCmd_TX_RATE_QUERY tx_rate;
+		/** Tx rate configuration */
+		HostCmd_DS_TX_RATE_CFG tx_rate_cfg;
+		/** Tx power configuration */
+		HostCmd_DS_TXPWR_CFG txp_cfg;
+		/** RF Tx power configuration */
+		HostCmd_DS_802_11_RF_TX_POWER txp;
+
+		/** RF antenna */
+		HostCmd_DS_802_11_RF_ANTENNA antenna;
+
+		/** CW Mode: Tx CW Level control */
+		HostCmd_DS_CW_MODE_CTRL cwmode;
+		/** Enhanced power save command */
+		HostCmd_DS_802_11_PS_MODE_ENH psmode_enh;
+		HostCmd_DS_802_11_HS_CFG_ENH opt_hs_cfg;
+		/** Scan */
+		HostCmd_DS_802_11_SCAN scan;
+		/** Extended Scan */
+		HostCmd_DS_802_11_SCAN_EXT ext_scan;
+
+		/** Mgmt frame subtype mask */
+		HostCmd_DS_RX_MGMT_IND rx_mgmt_ind;
+		/** Scan response */
+		HostCmd_DS_802_11_SCAN_RSP scan_resp;
+
+		HostCmd_DS_802_11_BG_SCAN_CONFIG bg_scan_config;
+		HostCmd_DS_802_11_BG_SCAN_QUERY bg_scan_query;
+		HostCmd_DS_802_11_BG_SCAN_QUERY_RSP bg_scan_query_resp;
+		HostCmd_DS_SUBSCRIBE_EVENT subscribe_event;
+		HostCmd_DS_OTP_USER_DATA otp_user_data;
+		/** Associate */
+		HostCmd_DS_802_11_ASSOCIATE associate;
+
+		/** Associate response */
+		HostCmd_DS_802_11_ASSOCIATE_RSP associate_rsp;
+		/** Deauthenticate */
+		HostCmd_DS_802_11_DEAUTHENTICATE deauth;
+		/** Ad-Hoc start */
+		HostCmd_DS_802_11_AD_HOC_START adhoc_start;
+		/** Ad-Hoc start result */
+		HostCmd_DS_802_11_AD_HOC_START_RESULT adhoc_start_result;
+		/** Ad-Hoc join result */
+		HostCmd_DS_802_11_AD_HOC_JOIN_RESULT adhoc_join_result;
+		/** Ad-Hoc join */
+		HostCmd_DS_802_11_AD_HOC_JOIN adhoc_join;
+		/** Domain information */
+		HostCmd_DS_802_11D_DOMAIN_INFO domain_info;
+		/** Domain information response */
+		HostCmd_DS_802_11D_DOMAIN_INFO_RSP domain_info_resp;
+		HostCmd_DS_802_11_TPC_ADAPT_REQ tpc_req;
+		HostCmd_DS_802_11_TPC_INFO tpc_info;
+		HostCmd_DS_802_11_CHAN_SW_ANN chan_sw_ann;
+		HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
+		HostCmd_DS_MEASUREMENT_REQUEST meas_req;
+		HostCmd_DS_MEASUREMENT_REPORT meas_rpt;
+		/** Add BA request */
+		HostCmd_DS_11N_ADDBA_REQ add_ba_req;
+		/** Add BA response */
+		HostCmd_DS_11N_ADDBA_RSP add_ba_rsp;
+		/** Delete BA entry */
+		HostCmd_DS_11N_DELBA del_ba;
+		/** Tx buffer configuration */
+		HostCmd_DS_TXBUF_CFG tx_buf;
+		/** AMSDU Aggr Ctrl configuration */
+		HostCmd_DS_AMSDU_AGGR_CTRL amsdu_aggr_ctrl;
+		/** 11n configuration */
+		HostCmd_DS_11N_CFG htcfg;
+		/** reject addba req conditions configuration */
+		HostCmd_DS_REJECT_ADDBA_REQ rejectaddbareq;
+		/* RANDYTODO need add more */
+		/** HostCmd_DS_11AC_CFG */
+		HostCmd_DS_11AC_CFG vhtcfg;
+		/** HostCmd_DS_11ACTXBUF_CFG*/
+		HostCmd_DS_11ACTXBUF_CFG ac_tx_buf;
+		/** 11n configuration */
+		HostCmd_DS_TX_BF_CFG tx_bf_cfg;
+		/** WMM status get */
+		HostCmd_DS_WMM_GET_STATUS get_wmm_status;
+		/** WMM ADDTS */
+		HostCmd_DS_WMM_ADDTS_REQ add_ts;
+		/** WMM DELTS */
+		HostCmd_DS_WMM_DELTS_REQ del_ts;
+		/** WMM set/get queue config */
+		HostCmd_DS_WMM_QUEUE_CONFIG queue_config;
+		/** WMM param config*/
+		HostCmd_DS_WMM_PARAM_CONFIG param_config;
+		/** WMM on/of/get queue statistics */
+		HostCmd_DS_WMM_QUEUE_STATS queue_stats;
+		/** WMM get traffic stream status */
+		HostCmd_DS_WMM_TS_STATUS ts_status;
+		/** Key material */
+		HostCmd_DS_802_11_KEY_MATERIAL key_material;
+		/** GTK Rekey parameters */
+		HostCmd_DS_GTK_REKEY_PARAMS gtk_rekey;
+		/** E-Supplicant PSK */
+		HostCmd_DS_802_11_SUPPLICANT_PMK esupplicant_psk;
+		/** E-Supplicant profile */
+		HostCmd_DS_802_11_SUPPLICANT_PROFILE esupplicant_profile;
+		/** Extended version */
+		HostCmd_DS_VERSION_EXT verext;
+		/** Adhoc Coalescing */
+		HostCmd_DS_802_11_IBSS_STATUS ibss_coalescing;
+		/** Mgmt IE list configuration */
+		HostCmd_DS_MGMT_IE_LIST_CFG mgmt_ie_list;
+		/** TDLS configuration command */
+		HostCmd_DS_TDLS_CONFIG tdls_config_data;
+		/** TDLS operation command */
+		HostCmd_DS_TDLS_OPER tdls_oper_data;
+		/** System clock configuration */
+		HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG sys_clock_cfg;
+		/** MAC register access */
+		HostCmd_DS_MAC_REG_ACCESS mac_reg;
+		/** BBP register access */
+		HostCmd_DS_BBP_REG_ACCESS bbp_reg;
+		/** RF register access */
+		HostCmd_DS_RF_REG_ACCESS rf_reg;
+		/** EEPROM register access */
+		HostCmd_DS_802_11_EEPROM_ACCESS eeprom;
+		/** Memory access */
+		HostCmd_DS_MEM_ACCESS mem;
+		/** Target device access */
+		HostCmd_DS_TARGET_ACCESS target;
+		/** BCA register access */
+		HostCmd_DS_BCA_REG_ACCESS bca_reg;
+		/** Inactivity timeout extend */
+		HostCmd_DS_INACTIVITY_TIMEOUT_EXT inactivity_to;
+#ifdef UAP_SUPPORT
+		HostCmd_DS_SYS_CONFIG sys_config;
+		HostCmd_DS_SYS_INFO sys_info;
+		HostCmd_DS_STA_DEAUTH sta_deauth;
+		HostCmd_DS_STA_LIST sta_list;
+		HostCmd_DS_POWER_MGMT_EXT pm_cfg;
+		HostCmd_DS_REPORT_MIC report_mic;
+		HostCmd_DS_UAP_OPER_CTRL uap_oper_ctrl;
+#endif				/* UAP_SUPPORT */
+		HostCmd_DS_TX_RX_HISTOGRAM tx_rx_histogram;
+
+		/** Sleep period command */
+		HostCmd_DS_802_11_SLEEP_PERIOD sleep_pd;
+		/** Sleep params command */
+		HostCmd_DS_802_11_SLEEP_PARAMS sleep_param;
+
+#ifdef SDIO
+		/** SDIO GPIO interrupt config command */
+		HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_gpio_int;
+		HostCmd_DS_SDIO_PULL_CTRL sdio_pull_ctl;
+#endif
+		HostCmd_DS_SET_BSS_MODE bss_mode;
+		HostCmd_DS_CMD_TX_DATA_PAUSE tx_data_pause;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+		HostCmd_DS_PCIE_HOST_BUF_DETAILS pcie_host_spec;
+#endif
+#endif
+		HostCmd_DS_REMAIN_ON_CHANNEL remain_on_chan;
+#ifdef WIFI_DIRECT_SUPPORT
+		HostCmd_DS_WIFI_DIRECT_MODE wifi_direct_mode;
+		HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG p2p_params_config;
+#endif
+		HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG gpio_tsf_latch;
+		HostCmd_DS_COALESCE_CONFIG coalesce_config;
+		HostCmd_DS_HS_WAKEUP_REASON hs_wakeup_reason;
+		HostCmd_DS_PACKET_AGGR_CTRL aggr_ctrl;
+#ifdef USB
+		HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE packet_aggr;
+#endif
+		HostCmd_CONFIG_LOW_PWR_MODE low_pwr_mode_cfg;
+		HostCmd_DS_TSF tsf;
+		HostCmd_DS_DFS_REPEATER_MODE dfs_repeater;
+#ifdef RX_PACKET_COALESCE
+		HostCmd_DS_RX_PKT_COAL_CFG rx_pkt_coal_cfg;
+#endif
+		HostCmd_DS_EAPOL_PKT eapol_pkt;
+		HostCmd_DS_SENSOR_TEMP temp_sensor;
+		HostCMD_DS_APCMD_ACS_SCAN acs_scan;
+		HostCmd_DS_MIMO_SWITCH mimo_switch;
+		HostCmd_DS_IPV6_RA_OFFLOAD ipv6_ra_offload;
+#ifdef STA_SUPPORT
+		HostCmd_DS_STA_CONFIGURE sta_cfg;
+#endif
+		/** GPIO Independent reset configure */
+		HostCmd_DS_INDEPENDENT_RESET_CFG ind_rst_cfg;
+		HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT ps_inact_tmo;
+		HostCmd_DS_CHAN_REGION_CFG reg_cfg;
+		HostCmd_DS_AUTO_TX auto_tx;
+		HostCmd_DS_DYN_BW dyn_bw;
+		HostCmd_DS_802_11_ROBUSTCOEX robustcoexparams;
+		HostCmd_DS_DMCS_CFG dmcs;
+#if defined(PCIE)
+		HostCmd_DS_SSU_CFG ssu_params;
+#endif
+		/** boot sleep configure */
+		HostCmd_DS_BOOT_SLEEP boot_sleep;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+		/** crypto cmd */
+		HostCmd_DS_CRYPTO crypto_cmd;
+#endif
+#ifdef UAP_SUPPORT
+		/** Add station cmd */
+		HostCmd_DS_ADD_STATION sta_info;
+#endif
+		/** HostCmd_DS_11AX_CFG */
+		HostCmd_DS_11AX_CFG axcfg;
+		/** HostCmd_DS_11AX_CMD_CFG */
+		HostCmd_DS_11AX_CMD_CFG axcmd;
+		HostCmd_DS_RANGE_EXT range_ext;
+		/** HostCmd_DS_TWT_CFG */
+		HostCmd_DS_TWT_CFG twtcfg;
+
+		HostCmd_DS_CMD_RX_ABORT_CFG rx_abort_cfg;
+		HostCmd_DS_CMD_RX_ABORT_CFG_EXT rx_abort_cfg_ext;
+		HostCmd_DS_CMD_TX_AMPDU_PROT_MODE tx_ampdu_prot_mode;
+		HostCmd_DS_CMD_RATE_ADAPT_CFG rate_adapt_cfg;
+		HostCmd_DS_CMD_CCK_DESENSE_CFG cck_desense_cfg;
+		/** trpc_config */
+		HostCmd_DS_CHANNEL_TRPC_CONFIG ch_trpc_config;
+		HostCmd_DS_LOW_POWER_MODE_CFG lpm_cfg;
+		HostCmd_DS_BAND_STEERING band_steer_info;
+		HostCmd_DS_BEACON_STUCK_CFG beacon_stuck_cfg;
+		struct mfg_cmd_generic_cfg mfg_generic_cfg;
+		struct mfg_cmd_tx_cont mfg_tx_cont;
+		struct mfg_cmd_tx_frame2 mfg_tx_frame2;
+		struct mfg_Cmd_HE_TBTx_t mfg_he_power;
+		HostCmd_DS_CMD_ARB_CONFIG arb_cfg;
+		HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG dot11mc_unassoc_ftm_cfg;
+		HostCmd_DS_HAL_PHY_CFG hal_phy_cfg_params;
+	} params;
+} MLAN_PACK_END HostCmd_DS_COMMAND, *pHostCmd_DS_COMMAND;
+
+/** PS_CMD_ConfirmSleep */
+typedef MLAN_PACK_START struct _OPT_Confirm_Sleep {
+	/** Command */
+	t_u16 command;
+	/** Size */
+	t_u16 size;
+	/** Sequence number */
+	t_u16 seq_num;
+	/** Result */
+	t_u16 result;
+	/** Action */
+	t_u16 action;
+	/** Sleep comfirm param definition */
+	sleep_confirm_param sleep_cfm;
+} MLAN_PACK_END OPT_Confirm_Sleep;
+
+typedef struct MLAN_PACK_START _opt_sleep_confirm_buffer {
+	/** Header for interface */
+	t_u32 hdr;
+	/** New power save command used to send
+	 *  sleep confirmation to the firmware */
+	OPT_Confirm_Sleep ps_cfm_sleep;
+} MLAN_PACK_END opt_sleep_confirm_buffer;
+
+/** req host side download vdll block */
+#define VDLL_IND_TYPE_REQ 0
+/** notify vdll start offset in firmware image */
+#define VDLL_IND_TYPE_OFFSET 1
+/** notify vdll download error: signature error */
+#define VDLL_IND_TYPE_ERR_SIG 2
+/** notify vdll download error: ID error */
+#define VDLL_IND_TYPE_ERR_ID 3
+
+/** vdll indicate event structure */
+typedef MLAN_PACK_START struct _vdll_ind {
+	/*VDLL ind type */
+	t_u16 type;
+	/*reserved */
+	t_u16 reserved;
+	/*indicate the offset downloaded so far */
+	t_u32 offset;
+	/*VDLL block size */
+	t_u16 block_len;
+} MLAN_PACK_END vdll_ind, *pvdll_ind;
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+#endif /* !_MLAN_FW_H_ */
diff --git a/wlan_sd8987/mlan/mlan_ieee.h b/wlan_sd8987/mlan/mlan_ieee.h
new file mode 100755
index 0000000..aec54d5
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_ieee.h
@@ -0,0 +1,2003 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    11/03/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_IEEE_H_
+#define _MLAN_IEEE_H_
+
+/** FIX IES size in beacon buffer */
+#define WLAN_802_11_FIXED_IE_SIZE 12
+/** WLAN supported rates */
+#define WLAN_SUPPORTED_RATES 14
+
+/** WLAN supported rates extension */
+#define WLAN_SUPPORTED_RATES_EXT 60
+
+/** Enumeration definition*/
+/** WLAN_802_11_NETWORK_TYPE */
+typedef enum _WLAN_802_11_NETWORK_TYPE {
+	Wlan802_11FH,
+	Wlan802_11DS,
+	/* Defined as upper bound */
+	Wlan802_11NetworkTypeMax
+} WLAN_802_11_NETWORK_TYPE;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Frame control: Type Mgmt frame */
+#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x3000
+/** Frame control: SubType Mgmt frame */
+#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc)&0xF000) >> 12)
+#else
+/** Frame control: Type Mgmt frame */
+#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x000C
+/** Frame control: SubType Mgmt frame */
+#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc)&0x00F0) >> 4)
+#endif
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/* Reason codes */
+#define IEEE_80211_REASONCODE_UNSPECIFIED 1
+
+typedef enum _IEEEtypes_Ext_ElementId_e {
+	HE_CAPABILITY = 35,
+	HE_OPERATION = 36
+} IEEEtypes_Ext_ElementId_e;
+
+/** IEEE Type definitions  */
+typedef MLAN_PACK_START enum _IEEEtypes_ElementId_e {
+	SSID = 0,
+	SUPPORTED_RATES = 1,
+
+	FH_PARAM_SET = 2,
+	DS_PARAM_SET = 3,
+	CF_PARAM_SET = 4,
+
+	IBSS_PARAM_SET = 6,
+	COUNTRY_INFO = 7,
+	POWER_CONSTRAINT = 32,
+	POWER_CAPABILITY = 33,
+	TPC_REQUEST = 34,
+	TPC_REPORT = 35,
+	CHANNEL_SWITCH_ANN = 37,
+	EXTEND_CHANNEL_SWITCH_ANN = 60,
+	QUIET = 40,
+	IBSS_DFS = 41,
+	SUPPORTED_CHANNELS = 36,
+	REGULATORY_CLASS = 59,
+	HT_CAPABILITY = 45,
+	QOS_INFO = 46,
+	HT_OPERATION = 61,
+	MULTI_BSSID = 71,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	NONTX_BSSID_CAP = 83,
+	MBSSID_INDEX = 85,
+	EXT_CAPABILITY = 127,
+	LINK_ID = 101,
+	/*IEEE802.11r */
+	MOBILITY_DOMAIN = 54,
+	FAST_BSS_TRANSITION = 55,
+	TIMEOUT_INTERVAL = 56,
+	RIC = 57,
+	QOS_MAPPING = 110,
+	VHT_CAPABILITY = 191,
+	VHT_OPERATION = 192,
+	EXT_BSS_LOAD = 193,
+	BW_CHANNEL_SWITCH = 194,
+	VHT_TX_POWER_ENV = 195,
+	EXT_POWER_CONSTR = 196,
+	AID_INFO = 197,
+	QUIET_CHAN = 198,
+	OPER_MODE_NTF = 199,
+
+	ERP_INFO = 42,
+
+	EXTENDED_SUPPORTED_RATES = 50,
+
+	VENDOR_SPECIFIC_221 = 221,
+	WMM_IE = VENDOR_SPECIFIC_221,
+
+	WPS_IE = VENDOR_SPECIFIC_221,
+	/* WPA */
+	WPA_IE = VENDOR_SPECIFIC_221,
+	/* WPA2 */
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+	FRAGMENT = 242,
+	RSNX_IE = 244,
+	EXTENSION = 255
+} MLAN_PACK_END IEEEtypes_ElementId_e;
+
+/** IEEE IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_Header_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+} MLAN_PACK_END IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** Vendor specific IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorHeader_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** OUI */
+	t_u8 oui[3];
+	/** OUI type */
+	t_u8 oui_type;
+	/** OUI subtype */
+	t_u8 oui_subtype;
+	/** Version */
+	t_u8 version;
+} MLAN_PACK_END IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorSpecific_t {
+	/** Vendor specific IE header */
+	IEEEtypes_VendorHeader_t vend_hdr;
+	/** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)];
+} MLAN_PACK_END IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Generic_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)];
+} MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+/**ft capability policy*/
+typedef MLAN_PACK_START struct _IEEEtypes_FtCapPolicy_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:6;
+	/** RIC support */
+	t_u8 ric:1;
+	/** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+#else
+	/** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+	/** RIC support */
+	t_u8 ric:1;
+	/** Reserved */
+	t_u8 reserved:6;
+#endif
+} MLAN_PACK_END IEEEtypes_FtCapPolicy_t;
+
+/** Mobility domain IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MobilityDomain_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Mobility Domain ID */
+	t_u16 mdid;
+	/** FT Capability policy */
+	t_u8 ft_cap;
+} MLAN_PACK_END IEEEtypes_MobilityDomain_t;
+
+/**FT MIC Control*/
+typedef MLAN_PACK_START struct _IEEEtypes_FT_MICControl_t {
+	/** reserved */
+	t_u8 reserved;
+	/** element count */
+	t_u8 element_count;
+} MLAN_PACK_END IEEEtypes_FT_MICControl_t;
+
+/** FTIE MIC LEN */
+#define FTIE_MIC_LEN 16
+
+/**FT IE*/
+typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** mic control */
+	IEEEtypes_FT_MICControl_t mic_control;
+	/** mic */
+	t_u8 mic[FTIE_MIC_LEN];
+	/** ANonce */
+	t_u8 a_nonce[32];
+	/** SNonce */
+	t_u8 s_nonce[32];
+	/** sub element */
+	t_u8 sub_element[1];
+} MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
+
+/*Category for FT*/
+#define FT_CATEGORY 6
+/** FT ACTION request */
+#define FT_ACTION_REQUEST 1
+/** FT ACTION response */
+#define FT_ACTION_RESPONSE 2
+
+/*FT response and FT ack*/
+typedef MLAN_PACK_START struct {
+	/** category */
+	t_u8 category;
+	/** action */
+	t_u8 action;
+	/** sta address */
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	/** target ap address */
+	t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+	/** status code */
+	t_u16 status_code;
+	/** varible */
+	t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Ft_action_response;
+
+/**FT request */
+typedef MLAN_PACK_START struct {
+	/** category */
+	t_u8 category;
+	/** action */
+	t_u8 action;
+	/** sta address */
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	/** target ap address */
+	t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+	/** varible */
+	t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/** auth frame body*/
+typedef MLAN_PACK_START struct {
+	/** auth alg */
+	t_u16 auth_alg;
+	/** auth transaction */
+	t_u16 auth_transaction;
+	/** status code */
+	t_u16 status_code;
+	/** variable */
+	t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/** associate request frame */
+typedef MLAN_PACK_START struct {
+	t_u16 capab_info;
+	t_u16 listen_interval;
+	/** followed by SSID and Supported rates */
+	t_u8 variablep[];
+} MLAN_PACK_END IEEEtypes_assoc_req;
+
+/*Mgmt frame*/
+typedef MLAN_PACK_START struct {
+	/** frame control */
+	t_u16 frame_control;
+	/** duration */
+	t_u16 duration;
+	/** dest address */
+	t_u8 da[MLAN_MAC_ADDR_LENGTH];
+	/** source address */
+	t_u8 sa[MLAN_MAC_ADDR_LENGTH];
+	/** bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** seq control */
+	t_u16 seq_ctrl;
+	/** address 4 */
+	t_u8 addr4[MLAN_MAC_ADDR_LENGTH];
+	union {
+		IEEEtypes_Auth_framebody auth;
+		IEEEtypes_assoc_req assoc_req;
+		IEEEtypes_Ft_action_response ft_resp;
+		IEEEtypes_Ft_action_request ft_req;
+	} u;
+} MLAN_PACK_END IEEE80211_MGMT;
+
+/** TLV header */
+typedef MLAN_PACK_START struct _TLV_Generic_t {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+} MLAN_PACK_END TLV_Generic_t, *pTLV_Generic_t;
+
+/** Capability information mask */
+#define CAPINFO_MASK (~(MBIT(15) | MBIT(14) | MBIT(11) | MBIT(9)))
+
+/** Capability Bit Map*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t {
+	t_u8 rsrvd1:2;
+	t_u8 dsss_ofdm:1;
+	t_u8 radio_measurement:1;
+	t_u8 rsvrd2:1;
+	t_u8 short_slot_time:1;
+	t_u8 rsrvd3:1;
+	t_u8 spectrum_mgmt:1;
+	t_u8 chan_agility:1;
+	t_u8 pbcc:1;
+	t_u8 short_preamble:1;
+	t_u8 privacy:1;
+	t_u8 cf_poll_rqst:1;
+	t_u8 cf_pollable:1;
+	t_u8 ibss:1;
+	t_u8 ess:1;
+} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#else
+typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t {
+	/** Capability Bit Map : ESS */
+	t_u8 ess:1;
+	/** Capability Bit Map : IBSS */
+	t_u8 ibss:1;
+	/** Capability Bit Map : CF pollable */
+	t_u8 cf_pollable:1;
+	/** Capability Bit Map : CF poll request */
+	t_u8 cf_poll_rqst:1;
+	/** Capability Bit Map : privacy */
+	t_u8 privacy:1;
+	/** Capability Bit Map : Short preamble */
+	t_u8 short_preamble:1;
+	/** Capability Bit Map : PBCC */
+	t_u8 pbcc:1;
+	/** Capability Bit Map : Channel agility */
+	t_u8 chan_agility:1;
+	/** Capability Bit Map : Spectrum management */
+	t_u8 spectrum_mgmt:1;
+	/** Capability Bit Map : Reserved */
+	t_u8 rsrvd3:1;
+	/** Capability Bit Map : Short slot time */
+	t_u8 short_slot_time:1;
+	/** Capability Bit Map : APSD */
+	t_u8 Apsd:1;
+	/** Capability Bit Map : Reserved */
+	t_u8 rsvrd2:1;
+	/** Capability Bit Map : DSS OFDM */
+	t_u8 dsss_ofdm:1;
+	/** Capability Bit Map : Reserved */
+	t_u8 rsrvd1:2;
+} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** IEEEtypes_Ssid_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Ssid_t {
+	/** SSID: Element ID */
+	t_u8 element_id;
+	/** SSID : Length */
+	t_u8 len;
+	/** ssid */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+} MLAN_PACK_END IEEEtypes_Ssid_t, *pIEEEtypes_Ssid_t;
+
+/** IEEEtypes_CfParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_CfParamSet_t {
+	/** CF peremeter : Element ID */
+	t_u8 element_id;
+	/** CF peremeter : Length */
+	t_u8 len;
+	/** CF peremeter : Count */
+	t_u8 cfp_cnt;
+	/** CF peremeter : Period */
+	t_u8 cfp_period;
+	/** CF peremeter : Maximum duration */
+	t_u16 cfp_max_duration;
+	/** CF peremeter : Remaining duration */
+	t_u16 cfp_duration_remaining;
+} MLAN_PACK_END IEEEtypes_CfParamSet_t, *pIEEEtypes_CfParamSet_t;
+
+/** IEEEtypes_IbssParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_IbssParamSet_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** ATIM window value in milliseconds */
+	t_u16 atim_window;
+} MLAN_PACK_END IEEEtypes_IbssParamSet_t, *pIEEEtypes_IbssParamSet_t;
+
+/** IEEEtypes_SsParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_SsParamSet_t {
+	/** SS parameter : CF parameter set */
+	IEEEtypes_CfParamSet_t cf_param_set;
+	/** SS parameter : IBSS parameter set */
+	IEEEtypes_IbssParamSet_t ibss_param_set;
+} MLAN_PACK_END IEEEtypes_SsParamSet_t, *pIEEEtypes_SsParamSet_t;
+
+/** IEEEtypes_FhParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_FhParamSet_t {
+	/** FH parameter : Element ID */
+	t_u8 element_id;
+	/** FH parameter : Length */
+	t_u8 len;
+	/** FH parameter : Dwell time in milliseconds */
+	t_u16 dwell_time;
+	/** FH parameter : Hop set */
+	t_u8 hop_set;
+	/** FH parameter : Hop pattern */
+	t_u8 hop_pattern;
+	/** FH parameter : Hop index */
+	t_u8 hop_index;
+} MLAN_PACK_END IEEEtypes_FhParamSet_t, *pIEEEtypes_FhParamSet_t;
+
+/** IEEEtypes_DsParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_DsParamSet_t {
+	/** DS parameter : Element ID */
+	t_u8 element_id;
+	/** DS parameter : Length */
+	t_u8 len;
+	/** DS parameter : Current channel */
+	t_u8 current_chan;
+} MLAN_PACK_END IEEEtypes_DsParamSet_t, *pIEEEtypes_DsParamSet_t;
+
+/** IEEEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_PhyParamSet_t {
+	/** FH parameter set */
+	IEEEtypes_FhParamSet_t fh_param_set;
+	/** DS parameter set */
+	IEEEtypes_DsParamSet_t ds_param_set;
+} MLAN_PACK_END IEEEtypes_PhyParamSet_t, *pIEEEtypes_PhyParamSet_t;
+
+/** IEEEtypes_ERPInfo_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ERPInfo_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** ERP flags */
+	t_u8 erp_flags;
+} MLAN_PACK_END IEEEtypes_ERPInfo_t, *pIEEEtypes_ERPInfo_t;
+
+/** IEEEtypes_AId_t */
+typedef t_u16 IEEEtypes_AId_t;
+
+/** IEEEtypes_StatusCode_t */
+typedef t_u16 IEEEtypes_StatusCode_t;
+
+/** Fixed size in assoc_resp */
+#define ASSOC_RESP_FIXED_SIZE 6
+
+/** IEEEtypes_SeqCtl_t */
+typedef MLAN_PACK_START struct _IEEEtypes_SeqCtl_t {
+	/** Fragment Number */
+	t_u16 FragNum:4;
+	/** Sequence Number */
+	t_u16 SeqNum:12;
+} MLAN_PACK_END IEEEtypes_SeqCtl_t;
+
+/** IEEEtypes_MgmtHdr_t */
+typedef MLAN_PACK_START struct _IEEEtypes_MgmtHdr_t {
+	/** FrmCtl*/
+	t_u16 FrmCtl;
+	/** Duration*/
+	t_u16 Duration;
+	/** Destination Addr*/
+	t_u8 DestAddr[6];
+	/** Source Addr*/
+	t_u8 SrcAddr[6];
+	/** BSSID */
+	t_u8 BssId[6];
+	/** IEEEtypes_SeqCtl_t */
+	IEEEtypes_SeqCtl_t SeqCtl;
+} MLAN_PACK_END IEEEtypes_MgmtHdr_t;
+
+/** IEEEtypes_AssocRsp_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
+	/** Capability information */
+	IEEEtypes_CapInfo_t capability;
+	/** Association response status code */
+	IEEEtypes_StatusCode_t status_code;
+	/** Association ID */
+	IEEEtypes_AId_t a_id;
+	/** IE data buffer */
+	t_u8 ie_buffer[1];
+} MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
+
+/** 802.11 supported rates */
+typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES];
+
+/** cipher TKIP */
+#define WPA_CIPHER_TKIP 2
+/** cipher AES */
+#define WPA_CIPHER_AES_CCM 4
+/** AKM: 8021x */
+#define RSN_AKM_8021X 1
+/** AKM: PSK */
+#define RSN_AKM_PSK 2
+/** AKM: PSK SHA256 */
+#define RSN_AKM_PSK_SHA256 6
+
+/** AKM: PSK SHA256 */
+#define RSN_AKM_SAE 8
+/** AKM: PSK SHA256 */
+#define RSN_AKM_OWE 18
+
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN 4
+/** AKM Suite length */
+#define AKM_SUITE_LEN 4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT 7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT 6
+/** PMF ORing mask */
+#define PMF_MASK 0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+	/** OUI */
+	t_u8 oui[3];
+	/** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+	/** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+	/** Rsn : Element ID */
+	t_u8 element_id;
+	/** Rsn : Length */
+	t_u8 len;
+	/** Rsn : version */
+	t_u16 version;
+	/** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+	/** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+	/** Wpa : Element ID */
+	t_u8 element_id;
+	/** Wpa : Length */
+	t_u8 len;
+	/** Wpa : oui */
+	t_u8 oui[4];
+	/** version */
+	t_u16 version;
+	/** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+	/** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aifsn */
+	t_u8 aifsn:4;
+#else
+	/** Aifsn */
+	t_u8 aifsn:4;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn; /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;	/**< Ecw */
+	t_u16 tx_op_limit; /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+	/**
+	 * WMM Info IE - Vendor Specific Header:
+	 *   element_id  [221/0xdd]
+	 *   Len         [7]
+	 *   Oui         [00:50:f2]
+	 *   OuiType     [2]
+	 *   OuiSubType  [0]
+	 *   Version     [1]
+	 */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+	/** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+	/**
+	 * WMM Parameter IE - Vendor Specific Header:
+	 *   element_id  [221/0xdd]
+	 *   Len         [24]
+	 *   Oui         [00:50:f2]
+	 *   OuiType     [2]
+	 *   OuiSubType  [1]
+	 *   Version     [1]
+	 */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+	/** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+	/** Reserved */
+	t_u8 reserved;
+
+	/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	//IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior : 1; /* !Legacy/Trigg*/
+	t_u8 PowerSaveBehavior:1;
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	//IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType : 1;
+	t_u8 TrafficType:1;
+#else
+	//IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType : 1;
+	t_u8 TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	//IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior : 1; /* ! Legacy/Trigg*/
+	t_u8 PowerSaveBehavior:1;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is
+				   nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is
+				   nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+	t_u16 MaximumMSDUSize;
+	t_u32 MinServiceInterval;
+	t_u32 MaxServiceInterval;
+	t_u32 InactivityInterval;
+	t_u32 SuspensionInterval;
+	t_u32 ServiceStartTime;
+	t_u32 MinimumDataRate;
+	t_u32 MeanDataRate;
+	t_u32 PeakDataRate;
+	t_u32 MaxBurstSize;
+	t_u32 DelayBound;
+	t_u32 MinPHYRate;
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+	t_u8 ElementId;
+	t_u8 Len;
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+	t_u8 OuiSubType;	/* 01 */
+	t_u8 Version;
+
+	IEEEtypes_WMM_TSPEC_Body_t TspecBody;
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_t;
+
+/** WMM Action Category values */
+typedef MLAN_PACK_START enum _IEEEtypes_ActionCategory_e {
+
+	IEEE_MGMT_ACTION_CATEGORY_SPECTRUM_MGMT = 0,
+	IEEE_MGMT_ACTION_CATEGORY_QOS = 1,
+	IEEE_MGMT_ACTION_CATEGORY_DLS = 2,
+	IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK = 3,
+	IEEE_MGMT_ACTION_CATEGORY_PUBLIC = 4,
+	IEEE_MGMT_ACTION_CATEGORY_RADIO_RSRC = 5,
+	IEEE_MGMT_ACTION_CATEGORY_FAST_BSS_TRANS = 6,
+	IEEE_MGMT_ACTION_CATEGORY_HT = 7,
+
+	IEEE_MGMT_ACTION_CATEGORY_WNM = 10,
+	IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM = 11,
+
+	IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC = 17
+} MLAN_PACK_END IEEEtypes_ActionCategory_e;
+
+/** WMM TSPEC operations */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_Tspec_Action_e {
+
+	TSPEC_ACTION_CODE_ADDTS_REQ = 0,
+	TSPEC_ACTION_CODE_ADDTS_RSP = 1,
+	TSPEC_ACTION_CODE_DELTS = 2,
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_e;
+
+/** WMM TSPEC Category Action Base */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_ActionCategory_e category;
+	IEEEtypes_WMM_Tspec_Action_e action;
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+	t_u8 statusCode;
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+	/* Place holder for additional elements after the TSPEC */
+	t_u8 subElem[256];
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsReq_t;
+
+/** WMM TSPEC AddTS response structure */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+	t_u8 statusCode;
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+	/* Place holder for additional elements after the TSPEC */
+	t_u8 subElem[256];
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsRsp_t;
+
+/** WMM TSPEC DelTS structure */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+	t_u8 reasonCode;
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+	IEEEtypes_ActionCategory_e category;
+
+	IEEEtypes_Action_WMMAC_t wmmAc;
+
+} MLAN_PACK_END IEEEtypes_ActionFrame_t;
+
+/** Data structure for subband set */
+typedef MLAN_PACK_START struct _IEEEtypes_SubbandSet_t {
+	/** First channel */
+	t_u8 first_chan;
+	/** Number of channels */
+	t_u8 no_of_chan;
+	/** Maximum Tx power in dBm */
+	t_u8 max_tx_pwr;
+} MLAN_PACK_END IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t;
+
+#ifdef STA_SUPPORT
+/** Data structure for Country IE */
+typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoSet_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[1];
+} MLAN_PACK_END IEEEtypes_CountryInfoSet_t, *pIEEEtypes_CountryInfoSet_t;
+
+/** Data structure for Country IE full set */
+typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoFullSet_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} MLAN_PACK_END IEEEtypes_CountryInfoFullSet_t,
+	*pIEEEtypes_CountryInfoFullSet_t;
+
+#endif /* STA_SUPPORT */
+
+/** Data structure for Link ID */
+typedef MLAN_PACK_START struct _IEEEtypes_LinkIDElement_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** initial sta address */
+	t_u8 init_sta[MLAN_MAC_ADDR_LENGTH];
+	/** respose sta address */
+	t_u8 resp_sta[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END IEEEtypes_LinkIDElement_t, *pIEEEtypes_LinkIDElement_t;
+
+/** HT Capabilities Data */
+typedef struct MLAN_PACK_START _HTCap_t {
+	/** HT Capabilities Info field */
+	t_u16 ht_cap_info;
+	/** A-MPDU Parameters field */
+	t_u8 ampdu_param;
+	/** Supported MCS Set field */
+	t_u8 supported_mcs_set[16];
+	/** HT Extended Capabilities field */
+	t_u16 ht_ext_cap;
+	/** Transmit Beamforming Capabilities field */
+	t_u32 tx_bf_cap;
+	/** Antenna Selection Capability field */
+	t_u8 asel;
+} MLAN_PACK_END HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+typedef struct MLAN_PACK_START _HTInfo_t {
+	/** Primary channel */
+	t_u8 pri_chan;
+	/** Field 2 */
+	t_u8 field2;
+	/** Field 3 */
+	t_u16 field3;
+	/** Field 4 */
+	t_u16 field4;
+	/** Bitmap indicating MCSs supported by all HT STAs in the BSS */
+	t_u8 basic_mcs_set[16];
+} MLAN_PACK_END HTInfo_t, *pHTInfo_t;
+
+/** 20/40 BSS Coexistence Data */
+typedef struct MLAN_PACK_START _BSSCo2040_t {
+	/** 20/40 BSS Coexistence value */
+	t_u8 bss_co_2040_value;
+} MLAN_PACK_END BSSCo2040_t, *pBSSCo2040_t;
+
+#define MAX_DSCP_EXCEPTION_NUM 21
+/** DSCP Range */
+typedef struct MLAN_PACK_START _DSCP_Exception_t {
+	/* DSCP value 0 to 63 or ff */
+	t_u8 dscp_value;
+	/* user priority 0-7 */
+	t_u8 user_priority;
+} MLAN_PACK_END DSCP_Exception_t, *pDSCP_Exception_t;
+
+/** DSCP Range */
+typedef struct MLAN_PACK_START _DSCP_Range_t {
+	/* DSCP low value */
+	t_u8 dscp_low_value;
+	/* DSCP high value */
+	t_u8 dscp_high_value;
+} MLAN_PACK_END DSCP_Range_t, *pDSCP_Range_t;
+
+/** Overlapping BSS Scan Parameters Data */
+typedef struct MLAN_PACK_START _OverlapBSSScanParam_t {
+	/** OBSS Scan Passive Dwell in milliseconds */
+	t_u16 obss_scan_passive_dwell;
+	/** OBSS Scan Active Dwell in milliseconds */
+	t_u16 obss_scan_active_dwell;
+	/** BSS Channel Width Trigger Scan Interval in seconds */
+	t_u16 bss_chan_width_trigger_scan_int;
+	/** OBSS Scan Passive Total Per Channel */
+	t_u16 obss_scan_passive_total;
+	/** OBSS Scan Active Total Per Channel */
+	t_u16 obss_scan_active_total;
+	/** BSS Width Channel Transition Delay Factor */
+	t_u16 bss_width_chan_trans_delay;
+	/** OBSS Scan Activity Threshold */
+	t_u16 obss_scan_active_threshold;
+} MLAN_PACK_END OBSSScanParam_t, *pOBSSScanParam_t;
+
+/** HT Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_HTCap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** HTCap struct */
+	HTCap_t ht_cap;
+} MLAN_PACK_END IEEEtypes_HTCap_t, *pIEEEtypes_HTCap_t;
+
+/** HT Information IE */
+typedef MLAN_PACK_START struct _IEEEtypes_HTInfo_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** HTInfo struct */
+	HTInfo_t ht_info;
+} MLAN_PACK_END IEEEtypes_HTInfo_t, *pIEEEtypes_HTInfo_t;
+
+/** the AP which send the multi_bssid IE */
+#define MULTI_BSSID_AP 1
+/** the AP which don't send beacon */
+#define MULTI_BSSID_SUB_AP 2
+/** IEEEtypes_NotxBssCap_t */
+typedef MLAN_PACK_START struct _IEEEtypes_NotxBssCap_t {
+	/** Nontransmitted BSSID Capability: Element ID */
+	t_u8 element_id;
+	/** Nontransmitted BSSID Capability : Length */
+	t_u8 len;
+	/** capability */
+	t_u16 cap;
+} MLAN_PACK_END IEEEtypes_NotxBssCap_t, *pIEEEtypes_NotxBssCap_t;
+
+/** Multi BSSID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MultiBSSIDIndex_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** BSSID Index */
+	t_u8 bssid_index;
+	/** DTIM Period (Optional, not Present in ProbeRsp) */
+	t_u8 dtim_period;
+	/** DTIM Count (Optional, not Present in ProbeRsp) */
+	t_u8 dtim_count;
+} MLAN_PACK_END IEEEtypes_MultiBSSIDIndex_t, *pIEEEtypes_MultiBSSIDIndex_t;
+
+/** NonTransmitted BSSID Profile Subelement IE */
+/** SUBID for IEEEtypes_NonTransBSSIDCap_t */
+#define NONTRANS_BSSID_PROFILE_SUBELEM_ID 0
+
+/** NonTransmitted BSSID Capability IE */
+typedef MLAN_PACK_START struct _IEEEtypes_NonTransBSSIDProfile_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 profile_data[];
+} MLAN_PACK_END IEEEtypes_NonTransBSSIDProfile_t,
+	*pIEEEtypes_NonTransBSSIDProfile_t;
+
+/** Multi BSSID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MultiBSSID_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Max BSSID Indicator */
+	t_u8 max_bssid_indicator;
+	/** Optional Subelement data*/
+	t_u8 sub_elem_data[];
+} MLAN_PACK_END IEEEtypes_MultiBSSID_t, *pIEEEtypes_MultiBSSID_t;
+/** 20/40 BSS Coexistence IE */
+typedef MLAN_PACK_START struct _IEEEtypes_2040BSSCo_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** BSSCo2040_t struct */
+	BSSCo2040_t bss_co_2040;
+} MLAN_PACK_END IEEEtypes_2040BSSCo_t, *pIEEEtypes_2040BSSCo_t;
+
+/** Extended Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtCap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** ExtCap_t struct */
+	ExtCap_t ext_cap;
+} MLAN_PACK_END IEEEtypes_ExtCap_t, *pIEEEtypes_ExtCap_t;
+
+/** Overlapping BSS Scan Parameters IE */
+typedef MLAN_PACK_START struct _IEEEtypes_OverlapBSSScanParam_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** OBSSScanParam_t struct */
+	OBSSScanParam_t obss_scan_param;
+} MLAN_PACK_END IEEEtypes_OverlapBSSScanParam_t,
+	*pIEEEtypes_OverlapBSSScanParam_t;
+
+/** VHT MCS rate set field, refer to 802.11ac */
+typedef MLAN_PACK_START struct _VHT_MCS_set {
+	t_u16 rx_mcs_map;
+	t_u16 rx_max_rate;	/* bit 29-31 reserved */
+	t_u16 tx_mcs_map;
+	t_u16 tx_max_rate;	/* bit 61-63 reserved */
+} MLAN_PACK_END VHT_MCS_set_t, *pVHT_MCS_set_t;
+
+/** VHT Capabilities info field, reference 802.11ac D1.4 p89 */
+typedef MLAN_PACK_START struct _VHT_capa {
+#if 0
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 mpdu_max_len:2;
+	t_u8 chan_width:2;
+	t_u8 rx_LDPC:1;
+	t_u8 sgi_80:1;
+	t_u8 sgi_160:1;
+	t_u8 tx_STBC:1;
+	t_u8 rx_STBC:3;
+	t_u8 SU_beamformer_capa:1;
+	t_u8 SU_beamformee_capa:1;
+	t_u8 beamformer_ante_num:3;
+	t_u8 sounding_dim_num:3;
+	t_u8 MU_beamformer_capa:1;
+	t_u8 MU_beamformee_capa:1;
+	t_u8 VHT_TXOP_ps:1;
+	t_u8 HTC_VHT_capa:1;
+	t_u8 max_ampdu_len:3;
+	t_u8 link_apapt_capa:2;
+	t_u8 reserved_1:4;
+#else
+	t_u8 reserved_1:4;
+	t_u8 link_apapt_capa:2;
+	t_u8 max_ampdu_len:3;
+	t_u8 HTC_VHT_capa:1;
+	t_u8 VHT_TXOP_ps:1;
+	t_u8 MU_beamformee_capa:1;
+	t_u8 MU_beamformer_capa:1;
+	t_u8 sounding_dim_num:3;
+	t_u8 beamformer_ante_num:3;
+	t_u8 SU_beamformee_capa:1;
+	t_u8 SU_beamformer_capa:1;
+	t_u8 rx_STBC:3;
+	t_u8 tx_STBC:1;
+	t_u8 sgi_160:1;
+	t_u8 sgi_80:1;
+	t_u8 rx_LDPC:1;
+	t_u8 chan_width:2;
+	t_u8 mpdu_max_len:2;
+#endif				/* BIG_ENDIAN_SUPPORT */
+#endif
+	t_u32 vht_cap_info;
+	VHT_MCS_set_t mcs_sets;
+} MLAN_PACK_END VHT_capa_t, *pVHT_capa_t;
+
+/** VHT Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTCap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	VHT_capa_t vht_cap;
+} MLAN_PACK_END IEEEtypes_VHTCap_t, *pIEEEtypes_VHTCap_t;
+
+#define VHT_CAP_CHWD_80MHZ 0
+#define VHT_CAP_CHWD_160MHZ 1
+#define VHT_CAP_CHWD_80_80MHZ 2
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTOprat_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 chan_width;
+	t_u8 chan_center_freq_1;
+	t_u8 chan_center_freq_2;
+	/** Basic MCS set map, each 2 bits stands for a Nss */
+	t_u16 basic_MCS_map;
+} MLAN_PACK_END IEEEtypes_VHTOprat_t, *pIEEEtypes_VHTOprat_t;
+
+#define VHT_OPER_CHWD_20_40MHZ 0
+#define VHT_OPER_CHWD_80MHZ 1
+#define VHT_OPER_CHWD_160MHZ 2
+#define VHT_OPER_CHWD_80_80MHZ 3
+
+/** VHT Transmit Power Envelope IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTtxpower_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 max_tx_power;
+	t_u8 chan_center_freq;
+	t_u8 chan_width;
+} MLAN_PACK_END IEEEtypes_VHTtxpower_t, *pIEEEtypes_VHTtxpower_t;
+
+/** Extended Power Constraint IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtPwerCons_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** channel width */
+	t_u8 chan_width;
+	/** local power constraint */
+	t_u8 local_power_cons;
+} MLAN_PACK_END IEEEtypes_ExtPwerCons_t, *pIEEEtypes_ExtPwerCons_t;
+
+/** Extended BSS Load IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtBSSload_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 MU_MIMO_capa_count;
+	t_u8 stream_underutilization;
+	t_u8 VHT40_util;
+	t_u8 VHT80_util;
+	t_u8 VHT160_util;
+} MLAN_PACK_END IEEEtypes_ExtBSSload_t, *pIEEEtypes_ExtBSSload_t;
+
+/** Quiet Channel IE */
+typedef MLAN_PACK_START struct _IEEEtypes_QuietChan_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 AP_quiet_mode;
+	t_u8 quiet_count;
+	t_u8 quiet_period;
+	t_u16 quiet_dur;
+	t_u16 quiet_offset;
+} MLAN_PACK_END IEEEtypes_QuietChan_t, *pIEEEtypes_QuietChan_t;
+
+/** Wide Bandwidth Channel Switch IE */
+typedef MLAN_PACK_START struct _IEEEtypes_BWSwitch_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 new_chan_width;
+	t_u8 new_chan_center_freq_1;
+	t_u8 new_chan_center_freq_2;
+} MLAN_PACK_END IEEEtypes_BWSwitch_t, *pIEEEtypes_BWSwitch_t;
+
+/** AID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_AID_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** AID number */
+	t_u16 AID;
+} MLAN_PACK_END IEEEtypes_AID_t, *pIEEEtypes_AID_t;
+
+/** Operating Mode Notificaton IE */
+typedef MLAN_PACK_START struct _IEEEtypes_OperModeNtf_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Operating Mode */
+	t_u8 oper_mode;
+} MLAN_PACK_END IEEEtypes_OperModeNtf_t, *pIEEEtypes_OperModeNtf_t;
+
+typedef MLAN_PACK_START struct _IEEEtypes_Extension_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** payload */
+	t_u8 data[];
+} MLAN_PACK_END IEEEtypes_Extension_t, *pIEEEtypes_Extension_t;
+
+typedef MLAN_PACK_START struct _IEEEtypes_HECap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** he mac capability info */
+	t_u8 he_mac_cap[6];
+	/** he phy capability info */
+	t_u8 he_phy_cap[11];
+	/** he txrx mcs support , size would be 4 or 8 or 12 */
+	t_u8 he_txrx_mcs_support[4];
+	/** PPE Thresholds (optional) */
+} MLAN_PACK_END IEEEtypes_HECap_t, *pIEEEtypes_HECap_t;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT 5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 37 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 chan_switch_mode; /**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num; /**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+	/** IEEE element ID = 60 */
+	t_u8 element_id;
+	/** Element length after id and len, set to 4 */
+	t_u8 len;
+	/** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+	/** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+	/** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+	/** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/** Maximum number of subbands in the IEEEtypes_SupportedChannels_t structure */
+#define WLAN_11H_MAX_SUBBANDS 5
+/** Maximum number of DFS channels configured in IEEEtypes_IBSS_DFS_t */
+#define WLAN_11H_MAX_IBSS_DFS_CHANNELS 25
+
+/**  IEEE Power Constraint element (7.3.2.15) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 32 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 local_constraint; /**< Local power constraint applied to 11d
+				chan info */
+} MLAN_PACK_END IEEEtypes_PowerConstraint_t;
+
+/**  IEEE Power Capability element (7.3.2.16) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 33 */
+	t_u8 len; /**< Element length after id and len */
+	t_s8 min_tx_power_capability; /**< Minimum Transmit power (dBm) */
+	t_s8 max_tx_power_capability; /**< Maximum Transmit power (dBm) */
+} MLAN_PACK_END IEEEtypes_PowerCapability_t;
+
+/**  IEEE TPC Report element (7.3.2.18) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 35 */
+	t_u8 len; /**< Element length after id and len */
+	t_s8 tx_power; /**< Max power used to transmit the TPC Report frame
+			  (dBm) */
+	t_s8 link_margin; /**< Link margin when TPC Request received (dB) */
+} MLAN_PACK_END IEEEtypes_TPCReport_t;
+
+/*  IEEE Supported Channel sub-band description (7.3.2.19) */
+/**
+ *  Sub-band description used in the supported channels element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 start_chan; /**< Starting channel in the subband */
+	t_u8 num_chans;	/**< Number of channels in the subband */
+
+} MLAN_PACK_END IEEEtypes_SupportChan_Subband_t;
+
+/*  IEEE Supported Channel element (7.3.2.19) */
+/**
+ *  Sent in association requests. Details the sub-bands and number
+ *    of channels supported in each subband
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 36 */
+	t_u8 len; /**< Element length after id and len */
+
+	/** Configured sub-bands information in the element */
+	IEEEtypes_SupportChan_Subband_t subband[WLAN_11H_MAX_SUBBANDS];
+
+} MLAN_PACK_END IEEEtypes_SupportedChannels_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+	/** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 new_channel_width;
+	t_u8 new_channel_center_freq0;
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+	/** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info; /**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz; /**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz; /**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz; /**< Local Maximum Transmit Power for 80 MHZ>*/
+	t_u8 local_max_tp_160mhz_80_80mhz; /**< Local Maximum Transmit Power for 160/80+80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/*  IEEE Quiet Period Element (7.3.2.23) */
+/**
+ *  Provided in beacons and probe responses.  Indicates times during
+ *    which the STA should not be transmitting data.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a quiet element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 40 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 quiet_count; /**< Number of TBTTs until beacon with the quiet
+			     period */
+	t_u8 quiet_period; /**< Regular quiet period, # of TBTTS between periods
+			    */
+	t_u16 quiet_duration; /**< Duration of the quiet period in TUs */
+	t_u16 quiet_offset; /**< Offset in TUs from the TBTT for the quiet
+			       period */
+
+} MLAN_PACK_END IEEEtypes_Quiet_t;
+
+/**
+***  @brief Map octet of the basic measurement report (7.3.2.22.1)
+**/
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	/**< Reserved */
+	t_u8 rsvd5_7:3;
+	/**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+	/**< Radar detected on channel */
+	t_u8 radar:1;
+	/**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+	/**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+	/**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+#else
+	/**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+	/**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+	/**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+	/**< Radar detected on channel */
+	t_u8 radar:1;
+	/**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+	/**< Reserved */
+	t_u8 rsvd5_7:3;
+#endif				/* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptBasicMap_t;
+
+/*  IEEE DFS Channel Map field (7.3.2.24) */
+/**
+ *  Used to list supported channels and provide a octet "map" field which
+ *    contains a basic measurement report for that channel in the
+ *    IEEEtypes_IBSS_DFS_t element
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel_number; /**< Channel number */
+	MeasRptBasicMap_t rpt_map; /**< Basic measurement report for the channel
+				    */
+
+} MLAN_PACK_END IEEEtypes_ChannelMap_t;
+
+/*  IEEE IBSS DFS Element (7.3.2.24) */
+/**
+ *  IBSS DFS element included in ad hoc beacons and probe responses.
+ *    Provides information regarding the IBSS DFS Owner as well as the
+ *    originating STAs supported channels and basic measurement results.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 41 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 dfs_owner[MLAN_MAC_ADDR_LENGTH]; /**< DFS Owner STA Address */
+	t_u8 dfs_recovery_interval; /**< DFS Recovery time in TBTTs */
+
+	/** Variable length map field, one Map entry for each supported channel
+	 */
+	IEEEtypes_ChannelMap_t channel_map[WLAN_11H_MAX_IBSS_DFS_CHANNELS];
+
+} MLAN_PACK_END IEEEtypes_IBSS_DFS_t;
+
+/* 802.11h BSS information kept for each BSSID received in scan results */
+/**
+ * IEEE BSS information needed from scan results for later processing in
+ *    join commands
+ */
+typedef struct {
+	t_u8 sensed_11h; /**< Capability bit set or 11h IE found in this BSS */
+
+	IEEEtypes_PowerConstraint_t power_constraint; /**< Power Constraint IE
+						       */
+	IEEEtypes_PowerCapability_t power_capability; /**< Power Capability IE
+						       */
+	IEEEtypes_TPCReport_t tpc_report; /**< TPC Report IE */
+	IEEEtypes_ChanSwitchAnn_t chan_switch_ann; /**< Channel Switch
+						      Announcement IE */
+	IEEEtypes_Quiet_t quiet; /**< Quiet IE */
+	IEEEtypes_IBSS_DFS_t ibss_dfs; /**< IBSS DFS Element IE */
+
+} wlan_11h_bss_info_t;
+
+/** Ethernet packet type for TDLS */
+#define MLAN_ETHER_PKT_TYPE_TDLS_ACTION (0x890D)
+
+/*802.11z  TDLS action frame type and strcuct */
+typedef MLAN_PACK_START struct {
+	/*link indentifier ie =101 */
+	t_u8 element_id;
+	/*len = 18 */
+	t_u8 len;
+	/** bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** init sta mac address */
+	t_u8 init_sta[MLAN_MAC_ADDR_LENGTH];
+	/** resp sta mac address */
+	t_u8 resp_sta[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END IEEEtypes_tdls_linkie;
+
+/** action code for tdls setup request */
+#define TDLS_SETUP_REQUEST 0
+/** action code for tdls setup response */
+#define TDLS_SETUP_RESPONSE 1
+/** action code for tdls setup confirm */
+#define TDLS_SETUP_CONFIRM 2
+/** action code for tdls tear down */
+#define TDLS_TEARDOWN 3
+/** action code for tdls traffic indication */
+#define TDLS_PEER_TRAFFIC_INDICATION 4
+/** action code for tdls channel switch request */
+#define TDLS_CHANNEL_SWITCH_REQUEST 5
+/** action code for tdls channel switch response */
+#define TDLS_CHANNEL_SWITCH_RESPONSE 6
+/** action code for tdls psm request */
+#define TDLS_PEER_PSM_REQUEST 7
+/** action code for tdls psm response */
+#define TDLS_PEER_PSM_RESPONSE 8
+/** action code for tdls traffic response */
+#define TDLS_PEER_TRAFFIC_RESPONSE 9
+/** action code for tdls discovery request */
+#define TDLS_DISCOVERY_REQUEST 10
+/** action code for TDLS discovery response */
+#define TDLS_DISCOVERY_RESPONSE 14
+/** category public */
+#define CATEGORY_PUBLIC 4
+
+/** action code for 20/40 BSS Coexsitence Management frame */
+#define BSS_20_40_COEX 0
+
+#ifdef STA_SUPPORT
+/** Macro for maximum size of scan response buffer */
+#define MAX_SCAN_RSP_BUF (16 * 1024)
+
+/** Maximum number of channels that can be sent in user scan config */
+#define WLAN_USER_SCAN_CHAN_MAX 50
+/** Maximum length of SSID list */
+#define MRVDRV_MAX_SSID_LIST_LENGTH 10
+
+/** Maximum length of BSSID list */
+#define MAX_BSSID_FILTER_LIST 5
+
+/** Scan all the channels in specified band */
+#define BAND_SPECIFIED 0x80
+
+/**
+ *  IOCTL SSID List sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ *  Used to specify SSID specific filters as well as SSID pattern matching
+ *    filters for scan result processing in firmware.
+ */
+typedef MLAN_PACK_START struct _wlan_user_scan_ssid {
+	/** SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1];
+	/** Maximum length of SSID */
+	t_u8 max_len;
+} MLAN_PACK_END wlan_user_scan_ssid;
+
+/**
+ *  @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ *  Multiple instances of this structure are included in the IOCTL command
+ *   to configure a instance of a scan on the specific channel.
+ */
+typedef MLAN_PACK_START struct _wlan_user_scan_chan {
+	/** Channel Number to scan */
+	t_u8 chan_number;
+	/** Radio type: 'B/G' Band = 0, 'A' Band = 1 */
+	t_u8 radio_type;
+	/** Scan type: Active = 1, Passive = 2 */
+	t_u8 scan_type;
+	/** Reserved */
+	t_u8 reserved;
+	/** Scan duration in milliseconds; if 0 default used */
+	t_u32 scan_time;
+} MLAN_PACK_END wlan_user_scan_chan;
+
+/** channel statictics */
+typedef MLAN_PACK_START struct _ChanStatistics_t {
+	/** channle number */
+	t_u8 chan_num;
+	/** band info */
+	Band_Config_t bandcfg;
+	/** flags */
+	t_u8 flags;
+	/** noise */
+	t_s8 noise;
+	/** total network */
+	t_u16 total_networks;
+	/** scan duration */
+	t_u16 cca_scan_duration;
+	/** busy duration */
+	t_u16 cca_busy_duration;
+	/** min rss */
+	t_u8 min_rss;
+	/** max rssi */
+	t_u8 max_rss;
+} MLAN_PACK_END ChanStatistics_t;
+
+/** Enhance ext scan type defination */
+typedef enum _MLAN_EXT_SCAN_TYPE {
+	EXT_SCAN_DEFAULT,
+	EXT_SCAN_ENHANCE,
+	EXT_SCAN_CANCEL,
+} MLAN_EXT_SCAN_TYPE;
+
+/**
+ *  Input structure to configure an immediate scan cmd to firmware
+ *
+ *  Specifies a number of parameters to be used in general for the scan
+ *    as well as a channel list (wlan_user_scan_chan) for each scan period
+ *    desired.
+ */
+typedef MLAN_PACK_START struct {
+	/**
+	 *  Flag set to keep the previous scan table intact
+	 *
+	 *  If set, the scan results will accumulate, replacing any previous
+	 *   matched entries for a BSS with the new scan data
+	 */
+	t_u8 keep_previous_scan;
+	/**
+	 *  BSS mode to be sent in the firmware command
+	 *
+	 *  Field can be used to restrict the types of networks returned in the
+	 *    scan.  Valid settings are:
+	 *
+	 *   - MLAN_SCAN_MODE_BSS  (infrastructure)
+	 *   - MLAN_SCAN_MODE_IBSS (adhoc)
+	 *   - MLAN_SCAN_MODE_ANY  (unrestricted, adhoc and infrastructure)
+	 */
+	t_u8 bss_mode;
+	/**
+	 *  Configure the number of probe requests for active chan scans
+	 */
+	t_u8 num_probes;
+	/**
+	 *  @brief ssid filter flag
+	 */
+	t_u8 ssid_filter;
+	/**
+	 *  @brief BSSID filter sent in the firmware command to limit the
+	 * results
+	 */
+	t_u8 specific_bssid[MLAN_MAC_ADDR_LENGTH];
+	/**
+	 *  SSID filter list used in the to limit the scan results
+	 */
+	wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+	/**
+	 *  Variable number (fixed maximum) of channels to scan up
+	 */
+	wlan_user_scan_chan chan_list[WLAN_USER_SCAN_CHAN_MAX];
+	/** scan channel gap */
+	t_u16 scan_chan_gap;
+	/** scan type: 0 legacy, 1: enhance scan*/
+	t_u8 ext_scan_type;
+	/** flag to filer only probe response */
+	t_u8 proberesp_only;
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Number of BSSIDs to be filtered */
+	t_u8 bssid_num;
+	/** BSSID filter list used in the to limit the scan results */
+	mlan_802_11_mac_addr bssid_list[MAX_BSSID_FILTER_LIST];
+} MLAN_PACK_END wlan_user_scan_cfg;
+
+/** Default scan interval in millisecond*/
+#define DEFAULT_BGSCAN_INTERVAL 30000
+
+/** action get all, except pps/uapsd config */
+#define BG_SCAN_ACT_GET 0x0000
+/** action set all, except pps/uapsd config */
+#define BG_SCAN_ACT_SET 0x0001
+/** action get pps/uapsd config */
+#define BG_SCAN_ACT_GET_PPS_UAPSD 0x0100
+/** action set pps/uapsd config */
+#define BG_SCAN_ACT_SET_PPS_UAPSD 0x0101
+/** action set all */
+#define BG_SCAN_ACT_SET_ALL 0xff01
+/** ssid match */
+#define BG_SCAN_SSID_MATCH 0x0001
+/** ssid match and RSSI exceeded */
+#define BG_SCAN_SSID_RSSI_MATCH 0x0004
+/**wait for all channel scan to complete to report scan result*/
+#define BG_SCAN_WAIT_ALL_CHAN_DONE 0x80000000
+/** Maximum number of channels that can be sent in bg scan config */
+#define WLAN_BG_SCAN_CHAN_MAX 38
+
+/** Enumeration definition */
+/** EES MODE */
+typedef enum {
+	/** EES MODE: LOW */
+	EES_MODE_LOW = 0,
+	/** EES MODE: MID */
+	EES_MODE_MID,
+	/** EES MODE: HIGH */
+	EES_MODE_HIGH,
+	/** EES MODE: OFF */
+	EES_MODE_OFF,
+	/** EES MODE: LOOP */
+	EES_MODE_LOOP = 15,
+} ees_modes;
+
+/** EES Maximum SSID */
+#define EES_MAX_SSIDS 2
+
+/** ees_ssid_config */
+typedef MLAN_PACK_START struct {
+	/** SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1];
+	/** Maximum length of SSID */
+	t_u8 max_len;
+	/** PairCipher */
+	t_u8 pair_cipher;
+	/** GroupCipher */
+	t_u8 group_cipher;
+} MLAN_PACK_END ees_ssid_config;
+
+/**
+ *  Input structure to configure bs scan cmd to firmware
+ */
+typedef MLAN_PACK_START struct {
+	/** action */
+	t_u16 action;
+	/** enable/disable */
+	t_u8 enable;
+	/**  BSS type:
+	 *   MLAN_SCAN_MODE_BSS  (infrastructure)
+	 *   MLAN_SCAN_MODE_IBSS (adhoc)
+	 *   MLAN_SCAN_MODE_ANY  (unrestricted, adhoc and infrastructure)
+	 */
+	t_u8 bss_type;
+	/** number of channel scanned during each scan */
+	t_u8 chan_per_scan;
+	/** interval between consecutive scan */
+	t_u32 scan_interval;
+	/** bit 0: ssid match bit 1: ssid match and SNR exceeded
+	 *  bit 2: ssid match and RSSI exceeded
+	 *  bit 31: wait for all channel scan to complete to report scan result
+	 */
+	t_u32 report_condition;
+	/*  Configure the number of probe requests for active chan scans */
+	t_u8 num_probes;
+	/** RSSI threshold */
+	t_u8 rssi_threshold;
+	/** SNR threshold */
+	t_u8 snr_threshold;
+	/** repeat count */
+	t_u16 repeat_count;
+	/** start later flag */
+	t_u16 start_later;
+	/** SSID filter list used in the to limit the scan results */
+	wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+	/** Variable number (fixed maximum) of channels to scan up */
+	wlan_user_scan_chan chan_list[WLAN_BG_SCAN_CHAN_MAX];
+	/** scan channel gap */
+	t_u16 scan_chan_gap;
+	/** Enable EES configuration */
+	t_u8 config_ees;
+	/** EES scan mode */
+	t_u16 ees_mode;
+	/** EES report condition */
+	t_u16 report_cond;
+	/** EES High Period scan interval */
+	t_u16 high_period;
+	/** EES High Period scan count */
+	t_u16 high_period_count;
+	/** EES Medium Period scan interval */
+	t_u16 mid_period;
+	/** EES Medium Period scan count */
+	t_u16 mid_period_count;
+	/** EES Low Period scan interval */
+	t_u16 low_period;
+	/** EES Low Period scan count */
+	t_u16 low_period_count;
+	/** Number of networks in the list */
+	t_u8 network_count;
+	/** Maximum number of connection count */
+	t_u8 max_conn_count;
+	/** Black List Exp */
+	t_u8 black_list_exp;
+	/** Array of ees config struct */
+	ees_ssid_config ees_ssid_cfg[EES_MAX_SSIDS];
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+/** BSSDescriptor_t
+ *    Structure used to store information for beacon/probe response
+ */
+typedef struct _BSSDescriptor_t {
+	/** MAC address */
+	mlan_802_11_mac_addr mac_address;
+
+	/** SSID */
+	mlan_802_11_ssid ssid;
+
+	/** WEP encryption requirement */
+	t_u32 privacy;
+
+	/** Receive signal strength in dBm */
+	t_s32 rssi;
+	/** channel load */
+	t_u8 chan_load;
+	/** Channel */
+	t_u32 channel;
+
+	/** Freq */
+	t_u32 freq;
+
+	/** Beacon period */
+	t_u16 beacon_period;
+
+	/** ATIM window */
+	t_u32 atim_window;
+
+	/** ERP flags */
+	t_u8 erp_flags;
+
+	/** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+	/** Network infrastructure mode */
+	t_u32 bss_mode;
+
+	/** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+	/** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+	/** Current channel bandwidth
+	 *  0 : 20MHZ
+	 *  1 : 40MHZ
+	 *  2 : 80MHZ
+	 *  3 : 160MHZ
+	 */
+	t_u8 curr_bandwidth;
+
+	/** Network band.
+	 * BAND_B(0x01): 'b' band
+	 * BAND_G(0x02): 'g' band
+	 * BAND_A(0X04): 'a' band
+	 */
+	t_u16 bss_band;
+
+	/** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+	/** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+	/** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+	/** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+	/** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+	/** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+	/** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+	/** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+	/** 802.11n BSS information */
+	/** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+	/** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+	/** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+	/** HT Information Offset */
+	t_u16 ht_info_offset;
+	/** Flag to indicate this is multi_bssid_ap */
+	t_u8 multi_bssid_ap;
+	/** the mac address of multi-bssid AP */
+	mlan_802_11_mac_addr multi_bssid_ap_addr;
+	/** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+	/** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+	/** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+	/** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+	/** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+	/** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+	/** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+	/** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+	/** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+	/** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+	/** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+	/** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+	/** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+	/** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+	/** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+	/** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+	/** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+	/** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+	/** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+	/** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+	/** HE Capability IE */
+	IEEEtypes_HECap_t *phe_cap;
+	/** HE Capability IE offset */
+	t_u16 he_cap_offset;
+	/** HE operation IE */
+	IEEEtypes_Extension_t *phe_oprat;
+	/** HE operation IE offset */
+	t_u16 he_oprat_offset;
+#ifdef STA_SUPPORT
+	/** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+	/** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+	/** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+	/** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+	/** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+	/** RSNX IE */
+	IEEEtypes_Generic_t *prsnx_ie;
+	/** RSNX IE offset in the beacon buffer */
+	t_u16 rsnx_offset;
+#ifdef STA_SUPPORT
+	/** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+	/** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Hotspot 2.0 OSEN AKM  IE */
+	IEEEtypes_Generic_t *posen_ie;
+	/** osen IE offset in the beacon buffer */
+	t_u16 osen_offset;
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+	/** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+	/** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+	/** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+    /** scan age in secs */
+	t_u32 age_in_secs;
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8987/mlan/mlan_init.c b/wlan_sd8987/mlan/mlan_init.c
new file mode 100755
index 0000000..6c29d90
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_init.c
@@ -0,0 +1,2112 @@
+/** @file mlan_init.c
+ *
+ *  @brief This file contains the initialization for FW
+ *  and HW.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11h.h"
+#include "mlan_meas.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#include "hostsa_init.h"
+#endif
+#include "mlan_11ax.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/*******************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function adds a BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_add_bsspriotbl(pmlan_private priv)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	status = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						  sizeof(mlan_bssprio_node),
+						  MLAN_MEM_DEF,
+						  (t_u8 **)&pbssprio);
+	if (status) {
+		PRINTM(MERROR, "Failed to allocate bsspriotbl\n");
+		LEAVE();
+		return status;
+	}
+
+	pbssprio->priv = priv;
+
+	util_init_list((pmlan_linked_list)pbssprio);
+
+	if (!pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur)
+		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+			pbssprio;
+
+	util_enqueue_list_tail(pmadapter->pmoal_handle,
+			       &pmadapter->bssprio_tbl[priv->bss_priority].
+			       bssprio_head, (pmlan_linked_list)pbssprio,
+			       pmadapter->callbacks.moal_spin_lock,
+			       pmadapter->callbacks.moal_spin_unlock);
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function deletes the BSS priority table
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+static t_void
+wlan_delete_bsspriotbl(pmlan_private priv)
+{
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL,
+		**ppcur = MNULL;
+	pmlan_list_head phead;
+
+	ENTER();
+
+	for (i = 0; i < pmadapter->priv_num; ++i) {
+		phead = &pmadapter->bssprio_tbl[i].bssprio_head;
+		ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur;
+		PRINTM(MINFO,
+		       "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n",
+		       priv->bss_index, i, phead, *ppcur);
+		if (*ppcur) {
+			pbssprio_node =
+				(mlan_bssprio_node *)util_peek_list(pmadapter->
+								    pmoal_handle,
+								    phead,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_lock,
+								    pmadapter->
+								    callbacks.
+								    moal_spin_unlock);
+			while (pbssprio_node &&
+			       ((pmlan_list_head)pbssprio_node != phead)) {
+				ptmp_node = pbssprio_node->pnext;
+				if (pbssprio_node->priv == priv) {
+					PRINTM(MINFO,
+					       "Delete node, pnode = %p, pnext = %p\n",
+					       pbssprio_node, ptmp_node);
+					util_unlink_list(pmadapter->
+							 pmoal_handle, phead,
+							 (pmlan_linked_list)
+							 pbssprio_node,
+							 pmadapter->callbacks.
+							 moal_spin_lock,
+							 pmadapter->callbacks.
+							 moal_spin_unlock);
+					pmadapter->callbacks.
+						moal_mfree(pmadapter->
+							   pmoal_handle,
+							   (t_u8 *)
+							   pbssprio_node);
+				}
+				pbssprio_node = ptmp_node;
+			}
+			*ppcur = (mlan_bssprio_node *)phead;
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief The function handles VDLL init
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ *
+ */
+static mlan_status
+vdll_init(pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
+
+	ENTER();
+	memset(pmadapter, ctrl, 0, sizeof(vdll_dnld_ctrl));
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type)) {
+		ctrl->cmd_buf =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       MRVDRV_SIZE_OF_CMD_BUFFER, 0,
+					       MOAL_MALLOC_BUFFER);
+		if (!ctrl->cmd_buf) {
+			PRINTM(MERROR,
+			       "vdll init: fail to alloc command buffer");
+			status = MLAN_STATUS_FAILURE;
+		}
+	}
+#endif
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief The function handles VDLL deinit
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ *
+ */
+static t_void
+vdll_deinit(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	if (pmadapter->vdll_ctrl.vdll_mem != MNULL) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->vdll_ctrl.vdll_mem);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->vdll_ctrl.vdll_mem);
+		pmadapter->vdll_ctrl.vdll_mem = MNULL;
+		pmadapter->vdll_ctrl.vdll_len = 0;
+	}
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type) &&
+	    pmadapter->vdll_ctrl.cmd_buf != MNULL) {
+		wlan_free_mlan_buffer(pmadapter, pmadapter->vdll_ctrl.cmd_buf);
+		pmadapter->vdll_ctrl.cmd_buf = MNULL;
+	}
+#endif
+	LEAVE();
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function allocates buffer for the members of adapter
+ *          structure like command buffer and BSSID list.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_allocate_adapter(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef STA_SUPPORT
+	t_u32 beacon_buffer_size;
+	t_u32 buf_size;
+	BSSDescriptor_t *ptemp_scan_table = MNULL;
+	t_u8 chan_2g[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
+	t_u8 chan_5g[] = { 12, 16, 34, 38, 42, 46, 36, 40,
+		44, 48, 52, 56, 60, 64, 100, 104,
+		108, 112, 116, 120, 124, 128, 132, 136,
+		140, 144, 149, 153, 157, 161, 165
+	};
+#endif
+#ifdef SDIO
+	t_u32 max_mp_regs = 0;
+	t_u32 mp_tx_aggr_buf_size = 0;
+	t_u32 mp_rx_aggr_buf_size = 0;
+#endif
+
+	ENTER();
+
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs;
+		mp_tx_aggr_buf_size = pmadapter->pcard_sd->mp_tx_aggr_buf_size;
+		mp_rx_aggr_buf_size = pmadapter->pcard_sd->mp_rx_aggr_buf_size;
+	}
+#endif
+
+#ifdef STA_SUPPORT
+	/* Allocate buffer to store the BSSID list */
+	buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)
+							&ptemp_scan_table);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)
+						       &ptemp_scan_table);
+	if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) {
+		PRINTM(MERROR, "Failed to allocate scan table\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pscan_table = ptemp_scan_table;
+
+	if (pmadapter->fixed_beacon_buffer)
+		beacon_buffer_size = MAX_SCAN_BEACON_BUFFER;
+	else
+		beacon_buffer_size = DEFAULT_SCAN_BEACON_BUFFER;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							beacon_buffer_size,
+							(t_u8 **)&pmadapter->
+							bcn_buf);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       beacon_buffer_size,
+						       MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       bcn_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) {
+		PRINTM(MERROR, "Failed to allocate bcn buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->bcn_buf_size = beacon_buffer_size;
+
+	pmadapter->num_in_chan_stats = sizeof(chan_2g);
+	pmadapter->num_in_chan_stats += sizeof(chan_5g);
+	buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats;
+	if (pmadapter->callbacks.moal_vmalloc &&
+	    pmadapter->callbacks.moal_vfree)
+		ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle,
+							buf_size,
+							(t_u8 **)&pmadapter->
+							pchan_stats);
+	else
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       buf_size, MLAN_MEM_DEF,
+						       (t_u8 **)&pmadapter->
+						       pchan_stats);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) {
+		PRINTM(MERROR, "Failed to allocate channel statistics\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#endif
+
+	/* Allocate command buffer */
+	ret = wlan_alloc_cmd_buffer(pmadapter);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to allocate command buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       max_mp_regs +
+						       DMA_ALIGNMENT,
+						       MLAN_MEM_DEF |
+						       MLAN_MEM_DMA,
+						       (t_u8 **)&pmadapter->
+						       pcard_sd->mp_regs_buf);
+		if (ret != MLAN_STATUS_SUCCESS ||
+		    !pmadapter->pcard_sd->mp_regs_buf) {
+			PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmadapter->pcard_sd->mp_regs =
+			(t_u8 *)ALIGN_ADDR(pmadapter->pcard_sd->mp_regs_buf,
+					   DMA_ALIGNMENT);
+
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       MAX_SUPPORT_AMSDU_SIZE,
+						       MLAN_MEM_DEF |
+						       MLAN_MEM_DMA,
+						       (t_u8 **)&pmadapter->
+						       pcard_sd->rx_buffer);
+
+		if (ret != MLAN_STATUS_SUCCESS ||
+		    !pmadapter->pcard_sd->rx_buffer) {
+			PRINTM(MERROR, "Failed to allocate receive buffer\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmadapter->pcard_sd->rx_buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->pcard_sd->rx_buffer,
+					   DMA_ALIGNMENT);
+
+		pmadapter->pcard_sd->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE;
+		pmadapter->pcard_sd->max_sp_rx_size = MAX_SUPPORT_AMSDU_SIZE;
+		ret = wlan_alloc_sdio_mpa_buffers(pmadapter,
+						  mp_tx_aggr_buf_size,
+						  mp_rx_aggr_buf_size);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "Failed to allocate sdio mp-a buffers\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#ifdef DEBUG_LEVEL1
+		if (mlan_drvdbg & MMPA_D) {
+			pmadapter->pcard_sd->mpa_buf_size =
+				SDIO_MP_DBG_NUM *
+				pmadapter->pcard_sd->mp_aggr_pkt_limit *
+				MLAN_SDIO_BLOCK_SIZE;
+			if (pmadapter->callbacks.moal_vmalloc &&
+			    pmadapter->callbacks.moal_vfree)
+				ret = pmadapter->callbacks.
+					moal_vmalloc(pmadapter->pmoal_handle,
+						     pmadapter->pcard_sd->
+						     mpa_buf_size,
+						     (t_u8 **)&pmadapter->
+						     pcard_sd->mpa_buf);
+			else
+				ret = pmadapter->callbacks.
+					moal_malloc(pmadapter->pmoal_handle,
+						    pmadapter->pcard_sd->
+						    mpa_buf_size, MLAN_MEM_DEF,
+						    (t_u8 **)&pmadapter->
+						    pcard_sd->mpa_buf);
+			if (ret != MLAN_STATUS_SUCCESS ||
+			    !pmadapter->pcard_sd->mpa_buf) {
+				PRINTM(MERROR, "Failed to allocate mpa buf\n");
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+#endif
+	}
+#endif
+
+	pmadapter->psleep_cfm =
+		wlan_alloc_mlan_buffer(pmadapter,
+				       sizeof(opt_sleep_confirm_buffer), 0,
+				       MOAL_MALLOC_BUFFER);
+
+#ifdef PCIE
+	/* Initialize PCIE ring buffer */
+	if (IS_PCIE(pmadapter->card_type)) {
+		ret = wlan_alloc_pcie_ring_buf(pmadapter);
+		if (MLAN_STATUS_SUCCESS != ret) {
+			PRINTM(MERROR,
+			       "Failed to allocate PCIE host buffers\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+#endif /* PCIE */
+
+	vdll_init(pmadapter);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes the private structure
+ *          and sets default values to the members of mlan_private.
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_init_priv(pmlan_private priv)
+{
+	t_u32 i;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef USB
+	pusb_tx_aggr_params pusb_tx_aggr = MNULL;
+#endif
+
+	ENTER();
+
+	priv->media_connected = MFALSE;
+	memset(pmadapter, priv->curr_addr, 0xff, MLAN_MAC_ADDR_LENGTH);
+
+#ifdef STA_SUPPORT
+	priv->pkt_tx_ctrl = 0;
+	priv->bss_mode = MLAN_BSS_MODE_INFRA;
+	priv->data_rate = 0;	/* Initially indicate the rate as auto */
+	priv->is_data_rate_auto = MTRUE;
+	priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
+	priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
+
+	priv->sec_info.wep_status = Wlan802_11WEPDisabled;
+	priv->sec_info.authentication_mode = MLAN_AUTH_MODE_AUTO;
+	priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;
+	for (i = 0; i < MRVL_NUM_WEP_KEY; i++)
+		memset(pmadapter, &priv->wep_key[i], 0, sizeof(mrvl_wep_key_t));
+	priv->wep_key_curr_index = 0;
+	priv->ewpa_query = MFALSE;
+	priv->curr_pkt_filter =
+		HostCmd_ACT_MAC_STATIC_DYNAMIC_BW_ENABLE |
+		HostCmd_ACT_MAC_RTS_CTS_ENABLE |
+		HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
+		HostCmd_ACT_MAC_ETHERNETII_ENABLE;
+
+	priv->beacon_period = MLAN_BEACON_INTERVAL;
+	priv->pattempted_bss_desc = MNULL;
+	memset(pmadapter, &priv->gtk_rekey, 0,
+	       sizeof(mlan_ds_misc_gtk_rekey_data));
+	memset(pmadapter, &priv->curr_bss_params, 0,
+	       sizeof(priv->curr_bss_params));
+	priv->listen_interval = MLAN_DEFAULT_LISTEN_INTERVAL;
+
+	memset(pmadapter, &priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf));
+	priv->assoc_rsp_size = 0;
+
+	wlan_11d_priv_init(priv);
+	wlan_11h_priv_init(priv);
+
+#ifdef UAP_SUPPORT
+	priv->is_11n_enabled = MFALSE;
+	priv->is_11ac_enabled = MFALSE;
+	priv->is_11ax_enabled = MFALSE;
+	priv->uap_bss_started = MFALSE;
+	priv->uap_host_based = MFALSE;
+	memset(pmadapter, &priv->uap_state_chan_cb, 0,
+	       sizeof(priv->uap_state_chan_cb));
+#endif
+#ifdef UAP_SUPPORT
+	priv->num_drop_pkts = 0;
+#endif
+#if defined(STA_SUPPORT)
+	priv->adhoc_state_prev = ADHOC_IDLE;
+	memset(pmadapter, &priv->adhoc_last_start_ssid, 0,
+	       sizeof(priv->adhoc_last_start_ssid));
+#endif
+	priv->atim_window = 0;
+	priv->adhoc_state = ADHOC_IDLE;
+	priv->tx_power_level = 0;
+	priv->max_tx_power_level = 0;
+	priv->min_tx_power_level = 0;
+	priv->tx_rate = 0;
+	priv->rxpd_rate_info = 0;
+	priv->rx_pkt_info = MFALSE;
+	/* refer to V15 CMD_TX_RATE_QUERY */
+	priv->rxpd_vhtinfo = 0;
+	priv->rxpd_rate = 0;
+	priv->data_rssi_last = 0;
+	priv->data_rssi_avg = 0;
+	priv->data_nf_avg = 0;
+	priv->data_nf_last = 0;
+	priv->bcn_rssi_last = 0;
+	priv->bcn_rssi_avg = 0;
+	priv->bcn_nf_avg = 0;
+	priv->bcn_nf_last = 0;
+	priv->sec_info.ewpa_enabled = MFALSE;
+	priv->sec_info.wpa_enabled = MFALSE;
+	priv->sec_info.wpa2_enabled = MFALSE;
+	memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+	memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key));
+	priv->wpa_ie_len = 0;
+	priv->wpa_is_gtk_set = MFALSE;
+#if defined(STA_SUPPORT)
+	priv->pmfcfg.mfpc = 0;
+	priv->pmfcfg.mfpr = 0;
+	memset(pmadapter, &priv->pmfcfg, 0, sizeof(priv->pmfcfg));
+#endif
+	priv->sec_info.wapi_enabled = MFALSE;
+	priv->wapi_ie_len = 0;
+	priv->sec_info.wapi_key_on = MFALSE;
+	priv->osen_ie_len = 0;
+	memset(pmadapter, &priv->osen_ie, 0, sizeof(priv->osen_ie));
+
+	memset(pmadapter, &priv->wps, 0, sizeof(priv->wps));
+	memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf));
+	priv->gen_ie_buf_len = 0;
+#endif /* STA_SUPPORT */
+	priv->wmm_required = MTRUE;
+	priv->wmm_enabled = MFALSE;
+	priv->disconnect_reason_code = 0;
+	priv->wmm_qosinfo = 0;
+	priv->saved_wmm_qosinfo = 0;
+	priv->host_tdls_cs_support = MTRUE;
+	priv->host_tdls_uapsd_support = MTRUE;
+	priv->tdls_cs_channel = 0;
+	priv->supp_regulatory_class_len = 0;
+	priv->chan_supp_len = 0;
+	memset(pmadapter, &priv->chan_supp, 0, sizeof(priv->chan_supp));
+	memset(pmadapter, &priv->supp_regulatory_class, 0,
+	       sizeof(priv->supp_regulatory_class));
+	priv->tdls_idle_time = TDLS_IDLE_TIMEOUT;
+	priv->txaggrctrl = MTRUE;
+	for (i = 0; i < MAX_MGMT_IE_INDEX; i++)
+		memset(pmadapter, &priv->mgmt_ie[i], 0, sizeof(custom_ie));
+	priv->mgmt_frame_passthru_mask = 0;
+#ifdef STA_SUPPORT
+	priv->pcurr_bcn_buf = MNULL;
+	priv->curr_bcn_size = 0;
+	memset(pmadapter, &priv->ext_cap, 0, sizeof(priv->ext_cap));
+
+	SET_EXTCAP_OPERMODENTF(priv->ext_cap);
+	SET_EXTCAP_TDLS(priv->ext_cap);
+	SET_EXTCAP_QOS_MAP(priv->ext_cap);
+	/* Save default Extended Capability */
+	memcpy_ext(priv->adapter, &priv->def_ext_cap, &priv->ext_cap,
+		   sizeof(priv->ext_cap), sizeof(priv->def_ext_cap));
+#endif /* STA_SUPPORT */
+
+	priv->amsdu_rx_cnt = 0;
+	priv->msdu_in_rx_amsdu_cnt = 0;
+	priv->amsdu_tx_cnt = 0;
+	priv->msdu_in_tx_amsdu_cnt = 0;
+	for (i = 0; i < MAX_NUM_TID; i++)
+		priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT;
+	priv->addba_reject[7] = ADDBA_RSP_STATUS_REJECT;
+	memcpy_ext(priv->adapter, priv->ibss_addba_reject, priv->addba_reject,
+		   sizeof(priv->addba_reject), sizeof(priv->ibss_addba_reject));
+	priv->max_amsdu = 0;
+#ifdef STA_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+		priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE;
+	}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		priv->add_ba_param.tx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+		priv->add_ba_param.rx_win_size = MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+	}
+#endif
+#ifdef UAP_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+		priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+		priv->aggr_prio_tbl[6].ampdu_user =
+			priv->aggr_prio_tbl[7].ampdu_user =
+			BA_STREAM_NOT_ALLOWED;
+	}
+#endif
+	priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+	memset(pmadapter, priv->rx_seq, 0, sizeof(priv->rx_seq));
+	priv->port_ctrl_mode = MTRUE;
+	priv->port_open = MFALSE;
+	priv->prior_port_status = MFALSE;
+	priv->tx_pause = MFALSE;
+	priv->hotspot_cfg = 0;
+
+	priv->intf_hr_len = pmadapter->ops.intf_header_len;
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		pusb_tx_aggr =
+			wlan_get_usb_tx_aggr_params(pmadapter, priv->port);
+		if (pusb_tx_aggr && pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+		    MLAN_USB_AGGR_MODE_LEN_V2) {
+			priv->intf_hr_len = MLAN_USB_TX_AGGR_HEADER;
+		}
+		priv->port = pmadapter->tx_data_ep;
+	}
+#endif
+	ret = wlan_add_bsspriotbl(priv);
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	hostsa_init(priv);
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes the adapter structure
+ *          and sets default values to the members of adapter.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_init_adapter(pmlan_adapter pmadapter)
+{
+	opt_sleep_confirm_buffer *sleep_cfm_buf = MNULL;
+#ifdef USB
+	t_s32 i = 0;
+#endif
+	ENTER();
+
+	if (pmadapter->psleep_cfm) {
+		sleep_cfm_buf = (opt_sleep_confirm_buffer
+				 *)(pmadapter->psleep_cfm->pbuf +
+				    pmadapter->psleep_cfm->data_offset);
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->init_para.mfg_mode == MLAN_INIT_PARA_DISABLED)
+		pmadapter->mfg_mode = MFALSE;
+	else
+		pmadapter->mfg_mode = pmadapter->init_para.mfg_mode;
+#endif
+
+#ifdef STA_SUPPORT
+	pmadapter->pwarm_reset_ioctl_req = MNULL;
+#endif
+	pmadapter->pscan_ioctl_req = MNULL;
+	pmadapter->cmd_sent = MFALSE;
+	pmadapter->mlan_processing = MFALSE;
+	pmadapter->main_process_cnt = 0;
+	pmadapter->mlan_rx_processing = MFALSE;
+	pmadapter->more_rx_task_flag = MFALSE;
+	pmadapter->more_task_flag = MFALSE;
+	pmadapter->delay_task_flag = MFALSE;
+	pmadapter->data_sent = MFALSE;
+	pmadapter->data_sent_cnt = 0;
+
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		pmadapter->pcard_sd->int_mode = pmadapter->init_para.int_mode;
+		pmadapter->pcard_sd->gpio_pin = pmadapter->init_para.gpio_pin;
+		pmadapter->data_sent = MTRUE;
+		pmadapter->pcard_sd->mp_rd_bitmap = 0;
+		pmadapter->pcard_sd->mp_wr_bitmap = 0;
+		pmadapter->pcard_sd->curr_rd_port =
+			pmadapter->pcard_sd->reg->start_rd_port;
+		pmadapter->pcard_sd->curr_wr_port =
+			pmadapter->pcard_sd->reg->start_wr_port;
+		pmadapter->pcard_sd->mp_data_port_mask =
+			pmadapter->pcard_sd->reg->data_port_mask;
+		pmadapter->pcard_sd->mp_invalid_update = 0;
+		memset(pmadapter, pmadapter->pcard_sd->mp_update, 0,
+		       sizeof(pmadapter->pcard_sd->mp_update));
+		pmadapter->pcard_sd->mpa_tx.buf_len = 0;
+		pmadapter->pcard_sd->mpa_tx.pkt_cnt = 0;
+		pmadapter->pcard_sd->mpa_tx.start_port =
+			pmadapter->pcard_sd->reg->start_wr_port;
+
+		if (!pmadapter->init_para.mpa_tx_cfg)
+			pmadapter->pcard_sd->mpa_tx.enabled = MFALSE;
+		else if (pmadapter->init_para.mpa_tx_cfg ==
+			 MLAN_INIT_PARA_DISABLED)
+			pmadapter->pcard_sd->mpa_tx.enabled = MFALSE;
+		else
+			pmadapter->pcard_sd->mpa_tx.enabled = MTRUE;
+		pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+			pmadapter->pcard_sd->mp_aggr_pkt_limit;
+
+		pmadapter->pcard_sd->mpa_rx.buf_len = 0;
+		pmadapter->pcard_sd->mpa_rx.pkt_cnt = 0;
+		pmadapter->pcard_sd->mpa_rx.start_port =
+			pmadapter->pcard_sd->reg->start_rd_port;
+
+		if (!pmadapter->init_para.mpa_rx_cfg)
+			pmadapter->pcard_sd->mpa_rx.enabled = MFALSE;
+		else if (pmadapter->init_para.mpa_rx_cfg ==
+			 MLAN_INIT_PARA_DISABLED)
+			pmadapter->pcard_sd->mpa_rx.enabled = MFALSE;
+		else
+			pmadapter->pcard_sd->mpa_rx.enabled = MTRUE;
+		pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit =
+			pmadapter->pcard_sd->mp_aggr_pkt_limit;
+	}
+#endif
+
+	pmadapter->rx_pkts_queued = 0;
+	pmadapter->cmd_resp_received = MFALSE;
+	pmadapter->event_received = MFALSE;
+	pmadapter->data_received = MFALSE;
+	pmadapter->seq_num = 0;
+	pmadapter->num_cmd_timeout = 0;
+	pmadapter->last_init_cmd = 0;
+	pmadapter->pending_ioctl = MFALSE;
+	pmadapter->scan_processing = MFALSE;
+	pmadapter->cmd_timer_is_set = MFALSE;
+	pmadapter->dnld_cmd_in_secs = 0;
+
+	/* PnP and power profile */
+	pmadapter->surprise_removed = MFALSE;
+	/* FW hang report */
+	pmadapter->fw_hang_report = MFALSE;
+	pmadapter->ecsa_enable = MFALSE;
+	pmadapter->getlog_enable = MFALSE;
+
+	if (!pmadapter->init_para.ps_mode) {
+		pmadapter->ps_mode = DEFAULT_PS_MODE;
+	} else if (pmadapter->init_para.ps_mode == MLAN_INIT_PARA_DISABLED)
+		pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+	else
+		pmadapter->ps_mode = Wlan802_11PowerModePSP;
+	pmadapter->ps_state = PS_STATE_AWAKE;
+	pmadapter->need_to_wakeup = MFALSE;
+
+#ifdef STA_SUPPORT
+	pmadapter->scan_block = MFALSE;
+	/* Scan type */
+	pmadapter->scan_type = MLAN_SCAN_TYPE_ACTIVE;
+	/* Scan mode */
+	pmadapter->scan_mode = HostCmd_BSS_MODE_ANY;
+	/* Scan time */
+	pmadapter->specific_scan_time = MRVDRV_SPECIFIC_SCAN_CHAN_TIME;
+	pmadapter->active_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
+	pmadapter->passive_scan_time = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
+	if (!pmadapter->init_para.passive_to_active_scan)
+		pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN;
+	else if (pmadapter->init_para.passive_to_active_scan ==
+		 MLAN_INIT_PARA_DISABLED)
+		pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_DIS;
+	else
+		pmadapter->passive_to_active_scan = MLAN_PASS_TO_ACT_SCAN_EN;
+
+	pmadapter->scan_chan_gap = 0;
+	pmadapter->num_in_scan_table = 0;
+	memset(pmadapter, pmadapter->pscan_table, 0,
+	       (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+	pmadapter->active_scan_triggered = MFALSE;
+	if (!pmadapter->init_para.ext_scan)
+		pmadapter->ext_scan = EXT_SCAN_TYPE_ENH;
+	else if (pmadapter->init_para.ext_scan == EXT_SCAN_TYPE_ENH)
+		pmadapter->ext_scan = EXT_SCAN_TYPE_ENH;
+	else
+		pmadapter->ext_scan = MTRUE;
+	pmadapter->ext_scan_enh = MFALSE;
+	pmadapter->ext_scan_timeout = MFALSE;
+	pmadapter->scan_probes = DEFAULT_PROBES;
+
+	memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
+	pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+	pmadapter->radio_on = RADIO_ON;
+	if (!pmadapter->multiple_dtim)
+		pmadapter->multiple_dtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
+
+	pmadapter->local_listen_interval = 0;	/* default value in firmware will
+						   be used */
+#endif /* STA_SUPPORT */
+
+	pmadapter->is_deep_sleep = MFALSE;
+	pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME;
+	if (!pmadapter->init_para.auto_ds)
+		pmadapter->init_auto_ds = DEFAULT_AUTO_DS_MODE;
+	else if (pmadapter->init_para.auto_ds == MLAN_INIT_PARA_DISABLED)
+		pmadapter->init_auto_ds = MFALSE;
+	else
+		pmadapter->init_auto_ds = MTRUE;
+
+	pmadapter->delay_null_pkt = MFALSE;
+	pmadapter->delay_to_ps = DELAY_TO_PS_DEFAULT;
+	pmadapter->enhanced_ps_mode = PS_MODE_AUTO;
+
+	pmadapter->gen_null_pkt = MFALSE;	/* Disable NULL Pkt generation-default
+						 */
+	pmadapter->pps_uapsd_mode = MFALSE;	/* Disable pps/uapsd mode -default
+						 */
+
+	pmadapter->pm_wakeup_card_req = MFALSE;
+	pmadapter->pm_wakeup_timeout = 0;
+
+	pmadapter->pm_wakeup_fw_try = MFALSE;
+
+	if (!pmadapter->init_para.max_tx_buf)
+		pmadapter->max_tx_buf_size =
+			pmadapter->pcard_info->max_tx_buf_size;
+	else
+		pmadapter->max_tx_buf_size =
+			(t_u16)pmadapter->init_para.max_tx_buf;
+	pmadapter->tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K;
+	pmadapter->curr_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K;
+
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+			pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable =
+				MFALSE;
+			pmadapter->pcard_usb->usb_tx_aggr[i]
+				.aggr_ctrl.aggr_mode =
+				MLAN_USB_AGGR_MODE_LEN_V2;
+			pmadapter->pcard_usb->usb_tx_aggr[i]
+				.aggr_ctrl.aggr_align =
+				MLAN_USB_TX_AGGR_V2_ALIGN;
+			pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.
+				aggr_max = MLAN_USB_TX_AGGR_MAX_LEN;
+			pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.
+				aggr_tmo = MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
+
+			pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr = MNULL;
+			pmadapter->pcard_usb->usb_tx_aggr[i].aggr_len = 0;
+			pmadapter->pcard_usb->usb_tx_aggr[i].hold_timeout_msec =
+				MLAN_USB_TX_AGGR_TIMEOUT_MSEC;
+			pmadapter->pcard_usb->usb_tx_aggr[i].port =
+				pmadapter->tx_data_ep;
+			pmadapter->pcard_usb->usb_tx_aggr[i].phandle =
+				(t_void *)pmadapter;
+		}
+
+		pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable = MFALSE;
+		pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_mode =
+			MLAN_USB_AGGR_MODE_NUM;
+		pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align =
+			MLAN_USB_RX_ALIGN_SIZE;
+		pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_max =
+			MLAN_USB_RX_MAX_AGGR_NUM;
+		pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_tmo =
+			MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
+
+		pmadapter->pcard_usb->fw_usb_aggr = MTRUE;
+	}
+#endif
+
+	pmadapter->is_hs_configured = MFALSE;
+	pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND;
+	pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO;
+	pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP;
+	pmadapter->hs_activated = MFALSE;
+	pmadapter->min_wake_holdoff = HOST_SLEEP_DEF_WAKE_HOLDOFF;
+	pmadapter->hs_inactivity_timeout = HOST_SLEEP_DEF_INACTIVITY_TIMEOUT;
+
+	memset(pmadapter, pmadapter->event_body, 0,
+	       sizeof(pmadapter->event_body));
+	pmadapter->hw_dot_11n_dev_cap = 0;
+	pmadapter->hw_dev_mcs_support = 0;
+	pmadapter->coex_rx_winsize = 1;
+#ifdef STA_SUPPORT
+	pmadapter->chan_bandwidth = 0;
+	pmadapter->tdls_status = TDLS_NOT_SETUP;
+#endif /* STA_SUPPORT */
+
+	pmadapter->min_ba_threshold = MIN_BA_THRESHOLD;
+	pmadapter->hw_dot_11ac_dev_cap = 0;
+	pmadapter->hw_dot_11ac_mcs_support = 0;
+	pmadapter->max_sta_conn = 0;
+	/* Initialize 802.11d */
+	wlan_11d_init(pmadapter);
+
+	wlan_11h_init(pmadapter);
+
+	wlan_wmm_init(pmadapter);
+	wlan_init_wmm_param(pmadapter);
+	pmadapter->bypass_pkt_count = 0;
+	if (pmadapter->psleep_cfm) {
+		pmadapter->psleep_cfm->buf_type = MLAN_BUF_TYPE_CMD;
+		pmadapter->psleep_cfm->data_len = sizeof(OPT_Confirm_Sleep);
+		memset(pmadapter, &sleep_cfm_buf->ps_cfm_sleep, 0,
+		       sizeof(OPT_Confirm_Sleep));
+		sleep_cfm_buf->ps_cfm_sleep.command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
+		sleep_cfm_buf->ps_cfm_sleep.size =
+			wlan_cpu_to_le16(sizeof(OPT_Confirm_Sleep));
+		sleep_cfm_buf->ps_cfm_sleep.result = 0;
+		sleep_cfm_buf->ps_cfm_sleep.action =
+			wlan_cpu_to_le16(SLEEP_CONFIRM);
+		sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl =
+			wlan_cpu_to_le16(RESP_NEEDED);
+#ifdef USB
+		if (IS_USB(pmadapter->card_type)) {
+			sleep_cfm_buf->hdr =
+				wlan_cpu_to_le32(MLAN_USB_TYPE_CMD);
+			pmadapter->psleep_cfm->data_len += MLAN_TYPE_LEN;
+		}
+#endif
+	}
+	memset(pmadapter, &pmadapter->sleep_params, 0,
+	       sizeof(pmadapter->sleep_params));
+	memset(pmadapter, &pmadapter->sleep_period, 0,
+	       sizeof(pmadapter->sleep_period));
+	memset(pmadapter, &pmadapter->saved_sleep_period, 0,
+	       sizeof(pmadapter->saved_sleep_period));
+	pmadapter->tx_lock_flag = MFALSE;
+	pmadapter->rx_lock_flag = MFALSE;
+	pmadapter->main_lock_flag = MFALSE;
+	pmadapter->null_pkt_interval = 0;
+	pmadapter->fw_bands = 0;
+	pmadapter->config_bands = 0;
+	pmadapter->adhoc_start_band = 0;
+	pmadapter->pscan_channels = MNULL;
+	pmadapter->fw_release_number = 0;
+	pmadapter->fw_cap_info = 0;
+	memset(pmadapter, &pmadapter->upld_buf, 0, sizeof(pmadapter->upld_buf));
+	pmadapter->upld_len = 0;
+	pmadapter->event_cause = 0;
+	pmadapter->pmlan_buffer_event = MNULL;
+	memset(pmadapter, &pmadapter->region_channel, 0,
+	       sizeof(pmadapter->region_channel));
+	pmadapter->region_code = 0;
+	memcpy_ext(pmadapter, pmadapter->country_code,
+		   MRVDRV_DEFAULT_COUNTRY_CODE, COUNTRY_CODE_LEN,
+		   COUNTRY_CODE_LEN);
+	pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
+#ifdef STA_SUPPORT
+	memset(pmadapter, &pmadapter->arp_filter, 0,
+	       sizeof(pmadapter->arp_filter));
+	pmadapter->arp_filter_size = 0;
+#endif /* STA_SUPPORT */
+
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type)) {
+		pmadapter->pcard_pcie->txbd_wrptr = 0;
+		pmadapter->pcard_pcie->txbd_rdptr = 0;
+		pmadapter->pcard_pcie->rxbd_rdptr = 0;
+		pmadapter->pcard_pcie->evtbd_rdptr = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			pmadapter->pcard_pcie->rxbd_wrptr =
+				pmadapter->pcard_pcie->reg->
+				txrx_rw_ptr_rollover_ind;
+			pmadapter->pcard_pcie->evtbd_wrptr =
+				EVT_RW_PTR_ROLLOVER_IND;
+		}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			pmadapter->pcard_pcie->rxbd_wrptr =
+				pmadapter->pcard_pcie->txrx_bd_size;
+			pmadapter->pcard_pcie->evtbd_wrptr = MLAN_MAX_EVT_BD;
+		}
+#endif
+	}
+#endif
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function intializes the lock variables and
+ *  the list heads for interface
+ *
+ *  @param pmadapter  A pointer to a mlan_adapter structure
+ *  @param start_index   start index of mlan private
+ *
+ *  @return           MLAN_STATUS_SUCCESS -- on success,
+ *                    otherwise MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_init_priv_lock_list(pmlan_adapter pmadapter, t_u8 start_index)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_s32 i = 0;
+	t_u32 j = 0;
+	for (i = start_index; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+						&priv->rx_pkt_lock) !=
+			    MLAN_STATUS_SUCCESS) {
+				ret = MLAN_STATUS_FAILURE;
+				goto error;
+			}
+			if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+						&priv->wmm.ra_list_spinlock) !=
+			    MLAN_STATUS_SUCCESS) {
+				ret = MLAN_STATUS_FAILURE;
+				goto error;
+			}
+#ifdef STA_SUPPORT
+			if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+						&priv->curr_bcn_buf_lock) !=
+			    MLAN_STATUS_SUCCESS) {
+				ret = MLAN_STATUS_FAILURE;
+				goto error;
+			}
+#endif
+		}
+	}
+	for (i = start_index; i < pmadapter->priv_num; ++i) {
+		util_init_list_head((t_void *)pmadapter->pmoal_handle,
+				    &pmadapter->bssprio_tbl[i].bssprio_head,
+				    MTRUE, pmadapter->callbacks.moal_init_lock);
+		pmadapter->bssprio_tbl[i].bssprio_cur = MNULL;
+	}
+
+	for (i = start_index; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			for (j = 0; j < MAX_NUM_TID; ++j) {
+				util_init_list_head((t_void *)pmadapter->
+						    pmoal_handle,
+						    &priv->wmm.tid_tbl_ptr[j].
+						    ra_list, MTRUE,
+						    priv->adapter->callbacks.
+						    moal_init_lock);
+			}
+			util_init_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->tx_ba_stream_tbl_ptr, MTRUE,
+					    pmadapter->callbacks.
+					    moal_init_lock);
+			util_init_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->rx_reorder_tbl_ptr, MTRUE,
+					    pmadapter->callbacks.
+					    moal_init_lock);
+			util_scalar_init((t_void *)pmadapter->pmoal_handle,
+					 &priv->wmm.tx_pkts_queued, 0,
+					 priv->wmm.ra_list_spinlock,
+					 pmadapter->callbacks.moal_init_lock);
+			util_scalar_init((t_void *)pmadapter->pmoal_handle,
+					 &priv->wmm.highest_queued_prio,
+					 HIGH_PRIO_TID,
+					 priv->wmm.ra_list_spinlock,
+					 pmadapter->callbacks.moal_init_lock);
+			util_init_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->sta_list, MTRUE,
+					    pmadapter->callbacks.
+					    moal_init_lock);
+			/* Initialize tdls_pending_txq */
+			util_init_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->tdls_pending_txq, MTRUE,
+					    pmadapter->callbacks.
+					    moal_init_lock);
+			/* Initialize bypass_txq */
+			util_init_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->bypass_txq, MTRUE,
+					    pmadapter->callbacks.
+					    moal_init_lock);
+		}
+	}
+error:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function intializes the lock variables and
+ *  the list heads.
+ *
+ *  @param pmadapter  A pointer to a mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS -- on success,
+ *                    otherwise MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_init_lock_list(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(USB)
+	t_s32 i = 0;
+#endif
+	ENTER();
+
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+				&pmadapter->pmlan_lock) !=
+	    MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type)) {
+		if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+					&pmadapter->pint_lock) !=
+		    MLAN_STATUS_SUCCESS) {
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+	}
+#endif
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+				&pmadapter->pmain_proc_lock) !=
+	    MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+				&pmadapter->prx_proc_lock) !=
+	    MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+				&pmadapter->pmlan_cmd_lock) !=
+	    MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type)) {
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+			if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+						&pmadapter->pcard_usb->
+						usb_tx_aggr[i]
+						.paggr_lock) !=
+			    MLAN_STATUS_SUCCESS) {
+				ret = MLAN_STATUS_FAILURE;
+				goto error;
+			}
+		}
+	}
+#endif
+
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->rx_data_queue, MTRUE,
+			    pmadapter->callbacks.moal_init_lock);
+	util_scalar_init((t_void *)pmadapter->pmoal_handle,
+			 &pmadapter->pending_bridge_pkts, 0, MNULL,
+			 pmadapter->callbacks.moal_init_lock);
+	/* Initialize cmd_free_q */
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->cmd_free_q, MTRUE,
+			    pmadapter->callbacks.moal_init_lock);
+	/* Initialize cmd_pending_q */
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->cmd_pending_q, MTRUE,
+			    pmadapter->callbacks.moal_init_lock);
+	/* Initialize scan_pending_q */
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->scan_pending_q, MTRUE,
+			    pmadapter->callbacks.moal_init_lock);
+
+	/* Initialize ioctl_pending_q */
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->ioctl_pending_q, MTRUE,
+			    pmadapter->callbacks.moal_init_lock);
+
+error:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function releases the lock variables
+ *
+ *  @param pmadapter  A pointer to a mlan_adapter structure
+ *
+ *  @return           None
+ *
+ */
+t_void
+wlan_free_lock_list(pmlan_adapter pmadapter)
+{
+	pmlan_private priv = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_s32 i = 0;
+	t_s32 j = 0;
+
+	ENTER();
+
+	if (pmadapter->pmlan_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pmlan_lock);
+#if defined(SDIO) || defined(PCIE)
+	if (!IS_USB(pmadapter->card_type) && pmadapter->pint_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+#endif
+	if (pmadapter->prx_proc_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->prx_proc_lock);
+	if (pmadapter->pmain_proc_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pmain_proc_lock);
+	if (pmadapter->pmlan_cmd_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pmlan_cmd_lock);
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type)) {
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+			if (pmadapter->pcard_usb->usb_tx_aggr[i].paggr_lock)
+				pcb->moal_free_lock(pmadapter->pmoal_handle,
+						    pmadapter->pcard_usb->
+						    usb_tx_aggr[i]
+						    .paggr_lock);
+		}
+	}
+#endif
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			if (priv->rx_pkt_lock)
+				pcb->moal_free_lock(pmadapter->pmoal_handle,
+						    priv->rx_pkt_lock);
+			if (priv->wmm.ra_list_spinlock)
+				pcb->moal_free_lock(pmadapter->pmoal_handle,
+						    priv->wmm.ra_list_spinlock);
+#ifdef STA_SUPPORT
+			if (priv->curr_bcn_buf_lock)
+				pcb->moal_free_lock(pmadapter->pmoal_handle,
+						    priv->curr_bcn_buf_lock);
+#endif
+		}
+	}
+
+	/* Free lists */
+	util_free_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->rx_data_queue, pcb->moal_free_lock);
+
+	util_scalar_free((t_void *)pmadapter->pmoal_handle,
+			 &pmadapter->pending_bridge_pkts, pcb->moal_free_lock);
+	util_free_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->cmd_free_q,
+			    pmadapter->callbacks.moal_free_lock);
+
+	util_free_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->cmd_pending_q,
+			    pmadapter->callbacks.moal_free_lock);
+
+	util_free_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->scan_pending_q,
+			    pmadapter->callbacks.moal_free_lock);
+
+	util_free_list_head((t_void *)pmadapter->pmoal_handle,
+			    &pmadapter->ioctl_pending_q,
+			    pmadapter->callbacks.moal_free_lock);
+
+	for (i = 0; i < pmadapter->priv_num; i++)
+		util_free_list_head((t_void *)pmadapter->pmoal_handle,
+				    &pmadapter->bssprio_tbl[i].bssprio_head,
+				    pcb->moal_free_lock);
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+			util_free_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->sta_list,
+					    priv->adapter->callbacks.
+					    moal_free_lock);
+			util_free_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->tdls_pending_txq,
+					    pmadapter->callbacks.
+					    moal_free_lock);
+			util_free_list_head((t_void *)pmadapter->pmoal_handle,
+					    &priv->bypass_txq,
+					    pmadapter->callbacks.
+					    moal_free_lock);
+			for (j = 0; j < MAX_NUM_TID; ++j)
+				util_free_list_head((t_void *)priv->adapter->
+						    pmoal_handle,
+						    &priv->wmm.tid_tbl_ptr[j].
+						    ra_list,
+						    priv->adapter->callbacks.
+						    moal_free_lock);
+			util_free_list_head((t_void *)priv->adapter->
+					    pmoal_handle,
+					    &priv->tx_ba_stream_tbl_ptr,
+					    priv->adapter->callbacks.
+					    moal_free_lock);
+			util_free_list_head((t_void *)priv->adapter->
+					    pmoal_handle,
+					    &priv->rx_reorder_tbl_ptr,
+					    priv->adapter->callbacks.
+					    moal_free_lock);
+			util_scalar_free((t_void *)priv->adapter->pmoal_handle,
+					 &priv->wmm.tx_pkts_queued,
+					 priv->adapter->callbacks.
+					 moal_free_lock);
+			util_scalar_free((t_void *)priv->adapter->pmoal_handle,
+					 &priv->wmm.highest_queued_prio,
+					 priv->adapter->callbacks.
+					 moal_free_lock);
+		}
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function intializes the timers
+ *
+ *  @param pmadapter  A pointer to a mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS -- on success,
+ *                    otherwise MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_init_timer(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(USB)
+	t_s32 i = 0;
+#endif
+	ENTER();
+
+	if (pcb->
+	    moal_init_timer(pmadapter->pmoal_handle,
+			    &pmadapter->pmlan_cmd_timer, wlan_cmd_timeout_func,
+			    pmadapter) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type)) {
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+			if (pcb->moal_init_timer(pmadapter->pmoal_handle,
+						 &pmadapter->pcard_usb->
+						 usb_tx_aggr[i]
+						 .paggr_hold_timer,
+						 wlan_usb_tx_aggr_timeout_func,
+						 &pmadapter->pcard_usb->
+						 usb_tx_aggr[i]) !=
+			    MLAN_STATUS_SUCCESS) {
+				ret = MLAN_STATUS_FAILURE;
+				goto error;
+			}
+		}
+	}
+#endif
+	if (pcb->moal_init_timer(pmadapter->pmoal_handle,
+				 &pmadapter->pwakeup_fw_timer,
+				 wlan_wakeup_card_timeout_func,
+				 pmadapter) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	pmadapter->wakeup_fw_timer_is_set = MFALSE;
+error:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function releases the timers
+ *
+ *  @param pmadapter  A pointer to a mlan_adapter structure
+ *
+ *  @return           None
+ *
+ */
+t_void
+wlan_free_timer(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(USB)
+	t_s32 i = 0;
+#endif
+	ENTER();
+
+	if (pmadapter->pmlan_cmd_timer)
+		pcb->moal_free_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_timer);
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type)) {
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+			if (pmadapter->pcard_usb->usb_tx_aggr[i]
+			    .paggr_hold_timer)
+				pcb->moal_free_timer(pmadapter->pmoal_handle,
+						     pmadapter->pcard_usb->
+						     usb_tx_aggr[i]
+						     .paggr_hold_timer);
+		}
+	}
+#endif
+
+	if (pmadapter->pwakeup_fw_timer)
+		pcb->moal_free_timer(pmadapter->pmoal_handle,
+				     pmadapter->pwakeup_fw_timer);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief  This function initializes firmware
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or
+ * MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_init_fw(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef PCIE
+	pmlan_private priv = pmadapter->priv[0];
+#endif
+	ENTER();
+	/* Initialize adapter structure */
+	wlan_init_adapter(pmadapter);
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode != MTRUE) {
+#endif
+		wlan_adapter_get_hw_spec(pmadapter);
+#ifdef MFG_CMD_SUPPORT
+	}
+#ifdef PCIE
+	else if (IS_PCIE(pmadapter->card_type)) {
+		if (MLAN_STATUS_SUCCESS != wlan_set_pcie_buf_config(priv)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#endif /* PCIE */
+#endif /* MFG_CMD_SUPPORT */
+	if (wlan_is_cmd_pending(pmadapter)) {
+		/* Send the first command in queue and return */
+		if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE)
+			ret = MLAN_STATUS_FAILURE;
+		else
+			ret = MLAN_STATUS_PENDING;
+#if defined(MFG_CMD_SUPPORT) && defined(PCIE)
+		if (IS_PCIE(pmadapter->card_type) && pmadapter->mfg_mode) {
+			ret = MLAN_STATUS_SUCCESS;
+		}
+#endif
+	}
+#ifdef PCIE
+done:
+#endif
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode == MTRUE) {
+		pmadapter->hw_status = WlanHardwareStatusInitializing;
+		ret = wlan_get_hw_spec_complete(pmadapter);
+	}
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function udpate hw spec info to each interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or
+ * MLAN_STATUS_FAILURE
+ */
+static void
+wlan_update_hw_spec(pmlan_adapter pmadapter)
+{
+	t_u32 i;
+
+	ENTER();
+
+#ifdef STA_SUPPORT
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter))
+		pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter);
+	else
+		pmadapter->fw_bands = BAND_B;
+
+	if ((pmadapter->fw_bands & BAND_A) && (pmadapter->fw_bands & BAND_GN))
+		pmadapter->fw_bands |= BAND_AN;
+	if (!(pmadapter->fw_bands & BAND_G) && (pmadapter->fw_bands & BAND_GN))
+		pmadapter->fw_bands &= ~BAND_GN;
+
+	pmadapter->config_bands = pmadapter->fw_bands;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
+		}
+	}
+
+	if (pmadapter->fw_bands & BAND_A) {
+		if (pmadapter->fw_bands & BAND_AN) {
+			pmadapter->config_bands |= BAND_AN;
+			for (i = 0; i < pmadapter->priv_num; i++) {
+				if (pmadapter->priv[i])
+					pmadapter->priv[i]->config_bands |=
+						BAND_AN;
+			}
+		}
+		if (pmadapter->fw_bands & BAND_AAC) {
+			pmadapter->config_bands |= BAND_AAC;
+			for (i = 0; i < pmadapter->priv_num; i++) {
+				if (pmadapter->priv[i])
+					pmadapter->priv[i]->config_bands |=
+						BAND_AAC;
+			}
+		}
+		pmadapter->adhoc_start_band = BAND_A;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL_A;
+		}
+	} else if (pmadapter->fw_bands & BAND_G) {
+		pmadapter->adhoc_start_band = BAND_G | BAND_B;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL;
+		}
+	} else if (pmadapter->fw_bands & BAND_B) {
+		pmadapter->adhoc_start_band = BAND_B;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL;
+		}
+	}
+#endif /* STA_SUPPORT */
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]->curr_addr[0] == 0xff)
+			memmove(pmadapter, pmadapter->priv[i]->curr_addr,
+				pmadapter->permanent_addr,
+				MLAN_MAC_ADDR_LENGTH);
+	}
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11n_cap(pmadapter->priv[i]);
+	}
+	if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) {
+		PRINTM(MCMND, "Enable Beamforming\n");
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i])
+				pmadapter->priv[i]->tx_bf_cap =
+					pmadapter->pcard_info->
+					default_11n_tx_bf_cap;
+		}
+	}
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_update_11ac_cap(pmadapter->priv[i]);
+	}
+	if (IS_FW_SUPPORT_11AX(pmadapter)) {
+		if (pmadapter->hw_2g_hecap_len) {
+			pmadapter->fw_bands |= BAND_GAX;
+			pmadapter->config_bands |= BAND_GAX;
+		}
+		if (pmadapter->hw_hecap_len) {
+			pmadapter->fw_bands |= BAND_AAX;
+			pmadapter->config_bands |= BAND_AAX;
+		}
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i]) {
+				pmadapter->priv[i]->config_bands =
+					pmadapter->config_bands;
+				pmadapter->priv[i]->user_2g_hecap_len =
+					pmadapter->hw_2g_hecap_len;
+				memcpy_ext(pmadapter,
+					   pmadapter->priv[i]->user_2g_he_cap,
+					   pmadapter->hw_2g_he_cap,
+					   pmadapter->hw_2g_hecap_len,
+					   sizeof(pmadapter->priv[i]
+						  ->user_2g_he_cap));
+				pmadapter->priv[i]->user_hecap_len =
+					pmadapter->hw_hecap_len;
+				memcpy_ext(pmadapter,
+					   pmadapter->priv[i]->user_he_cap,
+					   pmadapter->hw_he_cap,
+					   pmadapter->hw_hecap_len,
+					   sizeof(pmadapter->priv[i]->
+						  user_he_cap));
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief  This function initializes firmware for interface
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or
+ * MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_init_priv_fw(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = MNULL;
+	t_u8 i = 0;
+
+	ENTER();
+
+	wlan_init_priv_lock_list(pmadapter, 1);
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i]) {
+			priv = pmadapter->priv[i];
+
+			/* Initialize private structure */
+			ret = wlan_init_priv(priv);
+			if (ret) {
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode != MTRUE) {
+#endif
+		wlan_update_hw_spec(pmadapter);
+		/* Issue firmware initialize commands for first BSS,
+		 * for other interfaces it will be called after getting
+		 * the last init command response of previous interface
+		 */
+		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+		if (!priv) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		ret = priv->ops.init_cmd(priv, MTRUE);
+		if (ret == MLAN_STATUS_FAILURE)
+			goto done;
+#ifdef MFG_CMD_SUPPORT
+	}
+#endif /* MFG_CMD_SUPPORT */
+
+	if (wlan_is_cmd_pending(pmadapter)) {
+		/* Send the first command in queue and return */
+		if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE)
+			ret = MLAN_STATUS_FAILURE;
+		else
+			ret = MLAN_STATUS_PENDING;
+#if defined(MFG_CMD_SUPPORT) && defined(PCIE)
+		if (IS_PCIE(pmadapter->card_type) && pmadapter->mfg_mode) {
+			ret = MLAN_STATUS_SUCCESS;
+			pmadapter->hw_status = WlanHardwareStatusReady;
+		}
+#endif
+	} else {
+		pmadapter->hw_status = WlanHardwareStatusReady;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the structure of adapter
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_free_adapter(pmlan_adapter pmadapter)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+#if defined(USB)
+	t_s32 i = 0;
+#endif
+	ENTER();
+
+	if (!pmadapter) {
+		PRINTM(MERROR, "The adapter is NULL\n");
+		LEAVE();
+		return;
+	}
+
+	wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
+	/* Free command buffer */
+	PRINTM(MINFO, "Free Command buffer\n");
+	wlan_free_cmd_buffer(pmadapter);
+
+	if (pmadapter->cmd_timer_is_set) {
+		/* Cancel command timeout timer */
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_timer);
+		pmadapter->cmd_timer_is_set = MFALSE;
+	}
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type)) {
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+			if (pmadapter->pcard_usb->usb_tx_aggr[i]
+			    .aggr_hold_timer_is_set) {
+				/* Cancel usb_tx_aggregation timeout timer */
+				pcb->moal_stop_timer(pmadapter->pmoal_handle,
+						     pmadapter->pcard_usb->
+						     usb_tx_aggr[i]
+						     .paggr_hold_timer);
+				pmadapter->pcard_usb->usb_tx_aggr[i]
+					.aggr_hold_timer_is_set = MFALSE;
+			}
+		}
+	}
+#endif
+	if (pmadapter->wakeup_fw_timer_is_set) {
+		/* Cancel wakeup card timer */
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pmadapter->pwakeup_fw_timer);
+		pmadapter->wakeup_fw_timer_is_set = MFALSE;
+	}
+	wlan_free_fw_cfp_tables(pmadapter);
+#ifdef STA_SUPPORT
+	PRINTM(MINFO, "Free ScanTable\n");
+	if (pmadapter->pscan_table) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pscan_table);
+		pmadapter->pscan_table = MNULL;
+	}
+	if (pmadapter->pchan_stats) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pchan_stats);
+		pmadapter->pchan_stats = MNULL;
+	}
+	if (pmadapter->bcn_buf) {
+		if (pcb->moal_vmalloc && pcb->moal_vfree)
+			pcb->moal_vfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->bcn_buf);
+		else
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->bcn_buf);
+		pmadapter->bcn_buf = MNULL;
+	}
+#endif
+
+	wlan_11h_cleanup(pmadapter);
+
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		if (pmadapter->pcard_sd->mp_regs_buf) {
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pcard_sd->
+					mp_regs_buf);
+			pmadapter->pcard_sd->mp_regs_buf = MNULL;
+			pmadapter->pcard_sd->mp_regs = MNULL;
+		}
+		if (pmadapter->pcard_sd->rx_buffer) {
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pcard_sd->rx_buffer);
+			pmadapter->pcard_sd->rx_buffer = MNULL;
+			pmadapter->pcard_sd->rx_buf = MNULL;
+		}
+		wlan_free_sdio_mpa_buffers(pmadapter);
+#ifdef DEBUG_LEVEL1
+		if (pmadapter->pcard_sd->mpa_buf) {
+			if (pcb->moal_vmalloc && pcb->moal_vfree)
+				pcb->moal_vfree(pmadapter->pmoal_handle,
+						(t_u8 *)pmadapter->pcard_sd->
+						mpa_buf);
+			else
+				pcb->moal_mfree(pmadapter->pmoal_handle,
+						(t_u8 *)pmadapter->pcard_sd->
+						mpa_buf);
+			pmadapter->pcard_sd->mpa_buf = MNULL;
+			pmadapter->pcard_sd->mpa_buf_size = 0;
+		}
+#endif
+	}
+#endif
+
+	wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
+	pmadapter->psleep_cfm = MNULL;
+
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type)) {
+		/* Free ssu dma buffer just in case  */
+		wlan_free_ssu_pcie_buf(pmadapter);
+		/* Free PCIE ring buffers */
+		wlan_free_pcie_ring_buf(pmadapter);
+	}
+#endif
+
+	/* Free timers */
+	wlan_free_timer(pmadapter);
+
+	/* Free lock variables */
+	wlan_free_lock_list(pmadapter);
+
+#ifdef SDIO
+	if (pmadapter->pcard_sd) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->pcard_sd);
+		pmadapter->pcard_sd = MNULL;
+	}
+#endif
+#ifdef PCIE
+	if (pmadapter->pcard_pcie) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->pcard_pcie);
+		pmadapter->pcard_pcie = MNULL;
+	}
+#endif
+#ifdef USB
+	if (pmadapter->pcard_usb) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->pcard_usb);
+		pmadapter->pcard_usb = MNULL;
+	}
+#endif
+	vdll_deinit(pmadapter);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function frees the structure of priv
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *
+ *  @return         N/A
+ */
+t_void
+wlan_free_priv(mlan_private *pmpriv)
+{
+	ENTER();
+	wlan_clean_txrx(pmpriv);
+	wlan_delete_bsspriotbl(pmpriv);
+
+#ifdef STA_SUPPORT
+	wlan_free_curr_bcn(pmpriv);
+#endif /* STA_SUPPORT */
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	hostsa_cleanup(pmpriv);
+#endif /*EMBEDDED AUTHENTICATOR */
+
+	wlan_delete_station_list(pmpriv);
+	LEAVE();
+}
+
+/**
+ *  @brief This function init interface based on pmadapter's bss_attr table
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+static mlan_status
+wlan_init_interface(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = MNULL;
+	t_u8 i = 0;
+	t_u32 j = 0;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+	for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
+		if (pmadapter->bss_attr[i].active == MTRUE) {
+			if (!pmadapter->priv[i]) {
+				/* For valid bss_attr, allocate memory for
+				 * private structure */
+				if (pcb->moal_vmalloc && pcb->moal_vfree)
+					ret = pcb->moal_vmalloc(pmadapter->
+								pmoal_handle,
+								sizeof
+								(mlan_private),
+								(t_u8 **)
+								&pmadapter->
+								priv[i]);
+				else
+					ret = pcb->moal_malloc(pmadapter->
+							       pmoal_handle,
+							       sizeof
+							       (mlan_private),
+							       MLAN_MEM_DEF,
+							       (t_u8 **)
+							       &pmadapter->
+							       priv[i]);
+				if (ret != MLAN_STATUS_SUCCESS ||
+				    !pmadapter->priv[i]) {
+					ret = MLAN_STATUS_FAILURE;
+					goto error;
+				}
+
+				pmadapter->priv_num++;
+				memset(pmadapter, pmadapter->priv[i], 0,
+				       sizeof(mlan_private));
+			}
+			pmadapter->priv[i]->adapter = pmadapter;
+
+			/* Save bss_type, frame_type & bss_priority */
+			pmadapter->priv[i]->bss_type =
+				(t_u8)pmadapter->bss_attr[i].bss_type;
+			pmadapter->priv[i]->frame_type =
+				(t_u8)pmadapter->bss_attr[i].frame_type;
+			pmadapter->priv[i]->bss_priority =
+				(t_u8)pmadapter->bss_attr[i].bss_priority;
+			if (pmadapter->bss_attr[i].bss_type ==
+			    MLAN_BSS_TYPE_STA)
+				pmadapter->priv[i]->bss_role =
+					MLAN_BSS_ROLE_STA;
+			else if (pmadapter->bss_attr[i].bss_type ==
+				 MLAN_BSS_TYPE_UAP)
+				pmadapter->priv[i]->bss_role =
+					MLAN_BSS_ROLE_UAP;
+#ifdef WIFI_DIRECT_SUPPORT
+			else if (pmadapter->bss_attr[i].bss_type ==
+				 MLAN_BSS_TYPE_WIFIDIRECT) {
+				pmadapter->priv[i]->bss_role =
+					MLAN_BSS_ROLE_STA;
+				if (pmadapter->bss_attr[i].bss_virtual)
+					pmadapter->priv[i]->bss_virtual = MTRUE;
+			}
+#endif
+			/* Save bss_index and bss_num */
+			pmadapter->priv[i]->bss_index = i;
+			pmadapter->priv[i]->bss_num =
+				(t_u8)pmadapter->bss_attr[i].bss_num;
+
+			/* init function table */
+			for (j = 0; mlan_ops[j]; j++) {
+				if (mlan_ops[j]->bss_role ==
+				    GET_BSS_ROLE(pmadapter->priv[i])) {
+					memcpy_ext(pmadapter,
+						   &pmadapter->priv[i]->ops,
+						   mlan_ops[j],
+						   sizeof(mlan_operations),
+						   sizeof(mlan_operations));
+					break;
+				}
+			}
+		}
+	}
+	/*wmm init */
+	wlan_wmm_init(pmadapter);
+	/* Initialize firmware, may return PENDING */
+	ret = wlan_init_priv_fw(pmadapter);
+	PRINTM(MINFO, "wlan_init_priv_fw returned ret=0x%x\n", ret);
+error:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief The cmdresp handler calls this function for init_fw_complete callback
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return		MLAN_STATUS_SUCCESS
+ *              The firmware initialization callback succeeded.
+ */
+mlan_status
+wlan_get_hw_spec_complete(pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_hw_info info;
+	mlan_bss_tbl bss_tbl;
+
+	ENTER();
+#ifdef MFG_CMD_SUPPORT
+	if (pmadapter->mfg_mode != MTRUE) {
+#endif
+		/* Check if hardware is ready */
+		if (pmadapter->hw_status != WlanHardwareStatusInitializing)
+			status = MLAN_STATUS_FAILURE;
+		else {
+			memset(pmadapter, &info, 0, sizeof(info));
+			info.fw_cap = pmadapter->fw_cap_info;
+			info.fw_cap_ext = pmadapter->fw_cap_ext;
+			memset(pmadapter, &bss_tbl, 0, sizeof(bss_tbl));
+			memcpy_ext(pmadapter, bss_tbl.bss_attr,
+				   pmadapter->bss_attr, sizeof(mlan_bss_tbl),
+				   sizeof(mlan_bss_tbl));
+		}
+		/* Invoke callback */
+		ret = pcb->moal_get_hw_spec_complete(pmadapter->pmoal_handle,
+						     status, &info, &bss_tbl);
+		if (ret == MLAN_STATUS_SUCCESS && status == MLAN_STATUS_SUCCESS)
+			memcpy_ext(pmadapter, pmadapter->bss_attr,
+				   bss_tbl.bss_attr, sizeof(mlan_bss_tbl),
+				   sizeof(mlan_bss_tbl));
+		else {
+			pmadapter->hw_status = WlanHardwareStatusNotReady;
+			wlan_init_fw_complete(pmadapter);
+		}
+#ifdef MFG_CMD_SUPPORT
+	}
+#endif
+	if (pmadapter->hw_status == WlanHardwareStatusInitializing)
+		ret = wlan_init_interface(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief The cmdresp handler calls this function for init_fw_complete callback
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return		MLAN_STATUS_SUCCESS
+ *              The firmware initialization callback succeeded.
+ */
+mlan_status
+wlan_init_fw_complete(pmlan_adapter pmadapter)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_private *pmpriv = MNULL;
+
+	ENTER();
+
+	/* Check if hardware is ready */
+	if (pmadapter->hw_status != WlanHardwareStatusReady)
+		status = MLAN_STATUS_FAILURE;
+
+	/* Reconfigure wmm parameter */
+	if (status == MLAN_STATUS_SUCCESS) {
+		pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
+		if (pmpriv)
+			status = wlan_prepare_cmd(pmpriv,
+						  HostCmd_CMD_WMM_PARAM_CONFIG,
+						  HostCmd_ACT_GEN_SET, 0,
+						  MNULL, &pmadapter->ac_params);
+	}
+	/* Invoke callback */
+	ret = pcb->moal_init_fw_complete(pmadapter->pmoal_handle, status);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief The cmdresp handler calls this function
+ *          for shutdown_fw_complete callback
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ *                      The firmware shutdown callback succeeded.
+ */
+mlan_status
+wlan_shutdown_fw_complete(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pmadapter->hw_status = WlanHardwareStatusNotReady;
+	/* Invoke callback */
+	ret = pcb->moal_shutdown_fw_complete(pmadapter->pmoal_handle, status);
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_init.h b/wlan_sd8987/mlan/mlan_init.h
new file mode 100755
index 0000000..f8e1738
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_init.h
@@ -0,0 +1,125 @@
+/** @file mlan_init.h
+ *
+ *  @brief This file defines the FW initialization data
+ *  structures.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_INIT_H_
+#define _MLAN_INIT_H_
+
+/** Tx buffer size for firmware download*/
+#define FW_DNLD_TX_BUF_SIZE 2312
+/** Rx buffer size for firmware download*/
+#define FW_DNLD_RX_BUF_SIZE 2048
+/** Max firmware retry */
+#define MAX_FW_RETRY 3
+
+/** Firmware has last block */
+#define FW_HAS_LAST_BLOCK 0x00000004
+/** CMD id for CMD4 */
+#define FW_CMD_4 0x00000004
+/** CMD id for CMD6 */
+#define FW_CMD_6 0x00000006
+/** CMD id for CMD7 */
+#define FW_CMD_7 0x00000007
+/** CMD id for CMD10 */
+#define FW_CMD_10 0x0000000a
+
+/** Firmware data transmit size */
+#define FW_DATA_XMIT_SIZE (sizeof(FWHeader) + DataLength + sizeof(t_u32))
+
+/** FWHeader */
+typedef MLAN_PACK_START struct _FWHeader {
+	/** FW download command */
+	t_u32 dnld_cmd;
+	/** FW base address */
+	t_u32 base_addr;
+	/** FW data length */
+	t_u32 data_length;
+	/** FW CRC */
+	t_u32 crc;
+} MLAN_PACK_END FWHeader;
+
+/** FWData */
+typedef MLAN_PACK_START struct _FWData {
+	/** FW data header */
+	FWHeader fw_header;
+	/** FW data sequence number */
+	t_u32 seq_num;
+	/** FW data buffer */
+	t_u8 data[1];
+} MLAN_PACK_END FWData;
+
+/** FWSyncHeader */
+typedef MLAN_PACK_START struct _FWSyncHeader {
+	/** FW sync header command */
+	t_u32 cmd;
+	/** FW sync header sequence number */
+	t_u32 seq_num;
+	/** Extended header */
+	t_u32 magic;
+	/** Chip rev */
+	t_u32 chip_rev;
+	/** Strap */
+	t_u32 strap;
+	/** Status */
+	t_u32 status;
+	/** Offset */
+	t_u32 offset;
+} MLAN_PACK_END FWSyncHeader;
+
+/** FW Sync pkt */
+typedef MLAN_PACK_START struct _FWSyncPkt {
+	/** pkt type */
+	t_u32 pkt_type;
+	/** FW sync header command */
+	t_u32 cmd;
+	/** FW sync header sequence number */
+	t_u32 seq_num;
+	/** chip rev */
+	t_u32 chip_rev;
+	/** fw status */
+	t_u32 fw_ready;
+} MLAN_PACK_END FWSyncPkt;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert sequence number and command fields
+ *  of fwheader to correct endian format
+ */
+#define endian_convert_syncfwheader(x)                                         \
+	{                                                                      \
+		(x)->cmd = wlan_le32_to_cpu((x)->cmd);                         \
+		(x)->seq_num = wlan_le32_to_cpu((x)->seq_num);                 \
+		(x)->status = wlan_le32_to_cpu((x)->status);                   \
+		(x)->offset = wlan_le32_to_cpu((x)->offset);                   \
+	}
+#else
+/** Convert sequence number and command fields
+ *  of fwheader to correct endian format
+ */
+#define endian_convert_syncfwheader(x)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+#endif /* _MLAN_INIT_H_ */
diff --git a/wlan_sd8987/mlan/mlan_ioctl.h b/wlan_sd8987/mlan/mlan_ioctl.h
new file mode 100755
index 0000000..09c11a1
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_ioctl.h
@@ -0,0 +1,5450 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_IOCTL_H_
+#define _MLAN_IOCTL_H_
+
+/** Enumeration for IOCTL request ID */
+enum _mlan_ioctl_req_id {
+	/* Scan Group */
+	MLAN_IOCTL_SCAN = 0x00010000,
+	MLAN_OID_SCAN_NORMAL = 0x00010001,
+	MLAN_OID_SCAN_SPECIFIC_SSID = 0x00010002,
+	MLAN_OID_SCAN_USER_CONFIG = 0x00010003,
+	MLAN_OID_SCAN_CONFIG = 0x00010004,
+	MLAN_OID_SCAN_GET_CURRENT_BSS = 0x00010005,
+	MLAN_OID_SCAN_CANCEL = 0x00010006,
+	MLAN_OID_SCAN_TABLE_FLUSH = 0x0001000A,
+	MLAN_OID_SCAN_BGSCAN_CONFIG = 0x0001000B,
+	/* BSS Configuration Group */
+	MLAN_IOCTL_BSS = 0x00020000,
+	MLAN_OID_BSS_START = 0x00020001,
+	MLAN_OID_BSS_STOP = 0x00020002,
+	MLAN_OID_BSS_MODE = 0x00020003,
+	MLAN_OID_BSS_CHANNEL = 0x00020004,
+	MLAN_OID_BSS_CHANNEL_LIST = 0x00020005,
+	MLAN_OID_BSS_MAC_ADDR = 0x00020006,
+	MLAN_OID_BSS_MULTICAST_LIST = 0x00020007,
+	MLAN_OID_BSS_FIND_BSS = 0x00020008,
+	MLAN_OID_IBSS_BCN_INTERVAL = 0x00020009,
+	MLAN_OID_IBSS_ATIM_WINDOW = 0x0002000A,
+	MLAN_OID_IBSS_CHANNEL = 0x0002000B,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_BSS_CONFIG = 0x0002000C,
+	MLAN_OID_UAP_DEAUTH_STA = 0x0002000D,
+	MLAN_OID_UAP_BSS_RESET = 0x0002000E,
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	MLAN_OID_BSS_ROLE = 0x0002000F,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	MLAN_OID_WIFI_DIRECT_MODE = 0x00020010,
+#endif
+#ifdef STA_SUPPORT
+	MLAN_OID_BSS_LISTEN_INTERVAL = 0x00020011,
+#endif
+	MLAN_OID_BSS_REMOVE = 0x00020014,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_CFG_WMM_PARAM = 0x00020015,
+#endif
+	MLAN_OID_BSS_11D_CHECK_CHANNEL = 0x00020016,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_ACS_SCAN = 0x00020017,
+	MLAN_OID_UAP_SCAN_CHANNELS = 0x00020018,
+	MLAN_OID_UAP_CHANNEL = 0x00020019,
+	MLAN_OID_UAP_OPER_CTRL = 0x0002001A,
+#endif
+#ifdef STA_SUPPORT
+	MLAN_OID_BSS_CHAN_INFO = 0x0002001B,
+#endif
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_ADD_STATION = 0x0002001C,
+#endif
+
+	MLAN_OID_BSS_FIND_BSSID = 0x0002001D,
+#ifdef UAP_SUPPORT
+	MLAN_OID_ACTION_CHAN_SWITCH = 0x0002001E,
+#endif
+
+	/* Radio Configuration Group */
+	MLAN_IOCTL_RADIO_CFG = 0x00030000,
+	MLAN_OID_RADIO_CTRL = 0x00030001,
+	MLAN_OID_BAND_CFG = 0x00030002,
+	MLAN_OID_ANT_CFG = 0x00030003,
+	MLAN_OID_REMAIN_CHAN_CFG = 0x00030004,
+	MLAN_OID_MIMO_SWITCH = 0x00030005,
+
+	/* SNMP MIB Group */
+	MLAN_IOCTL_SNMP_MIB = 0x00040000,
+	MLAN_OID_SNMP_MIB_RTS_THRESHOLD = 0x00040001,
+	MLAN_OID_SNMP_MIB_FRAG_THRESHOLD = 0x00040002,
+	MLAN_OID_SNMP_MIB_RETRY_COUNT = 0x00040003,
+	MLAN_OID_SNMP_MIB_DOT11D = 0x00040004,
+#if defined(UAP_SUPPORT)
+	MLAN_OID_SNMP_MIB_DOT11H = 0x00040005,
+#endif
+	MLAN_OID_SNMP_MIB_DTIM_PERIOD = 0x00040006,
+	MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE = 0x00040007,
+	MLAN_OID_SNMP_MIB_CTRL_DEAUTH = 0x00040008,
+
+	/* Status Information Group */
+	MLAN_IOCTL_GET_INFO = 0x00050000,
+	MLAN_OID_GET_STATS = 0x00050001,
+	MLAN_OID_GET_SIGNAL = 0x00050002,
+	MLAN_OID_GET_FW_INFO = 0x00050003,
+	MLAN_OID_GET_VER_EXT = 0x00050004,
+	MLAN_OID_GET_BSS_INFO = 0x00050005,
+	MLAN_OID_GET_DEBUG_INFO = 0x00050006,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_STA_LIST = 0x00050007,
+#endif
+	MLAN_OID_GET_SIGNAL_EXT = 0x00050008,
+	MLAN_OID_LINK_STATS = 0x00050009,
+	MLAN_OID_GET_UAP_STATS_LOG = 0x0005000A,
+	/* Security Configuration Group */
+	MLAN_IOCTL_SEC_CFG = 0x00060000,
+	MLAN_OID_SEC_CFG_AUTH_MODE = 0x00060001,
+	MLAN_OID_SEC_CFG_ENCRYPT_MODE = 0x00060002,
+	MLAN_OID_SEC_CFG_WPA_ENABLED = 0x00060003,
+	MLAN_OID_SEC_CFG_ENCRYPT_KEY = 0x00060004,
+	MLAN_OID_SEC_CFG_PASSPHRASE = 0x00060005,
+	MLAN_OID_SEC_CFG_EWPA_ENABLED = 0x00060006,
+	MLAN_OID_SEC_CFG_ESUPP_MODE = 0x00060007,
+	MLAN_OID_SEC_CFG_WAPI_ENABLED = 0x00060009,
+	MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED = 0x0006000A,
+#ifdef UAP_SUPPORT
+	MLAN_OID_SEC_CFG_REPORT_MIC_ERR = 0x0006000B,
+#endif
+	MLAN_OID_SEC_QUERY_KEY = 0x0006000C,
+
+	/* Rate Group */
+	MLAN_IOCTL_RATE = 0x00070000,
+	MLAN_OID_RATE_CFG = 0x00070001,
+	MLAN_OID_GET_DATA_RATE = 0x00070002,
+	MLAN_OID_SUPPORTED_RATES = 0x00070003,
+
+	/* Power Configuration Group */
+	MLAN_IOCTL_POWER_CFG = 0x00080000,
+	MLAN_OID_POWER_CFG = 0x00080001,
+	MLAN_OID_POWER_CFG_EXT = 0x00080002,
+	MLAN_OID_POWER_LOW_POWER_MODE = 0x00080003,
+
+	/* Power Management Configuration Group */
+	MLAN_IOCTL_PM_CFG = 0x00090000,
+	MLAN_OID_PM_CFG_IEEE_PS = 0x00090001,
+	MLAN_OID_PM_CFG_HS_CFG = 0x00090002,
+	MLAN_OID_PM_CFG_INACTIVITY_TO = 0x00090003,
+	MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004,
+	MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005,
+	MLAN_OID_PM_CFG_PS_CFG = 0x00090006,
+	MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008,
+#ifdef UAP_SUPPORT
+	MLAN_OID_PM_CFG_PS_MODE = 0x00090009,
+#endif /* UAP_SUPPORT */
+	MLAN_OID_PM_INFO = 0x0009000A,
+	MLAN_OID_PM_HS_WAKEUP_REASON = 0x0009000B,
+	MLAN_OID_PM_MGMT_FILTER = 0x0009000C,
+	MLAN_OID_PM_CFG_BCN_TIMEOUT = 0x0009000D,
+
+	/* WMM Configuration Group */
+	MLAN_IOCTL_WMM_CFG = 0x000A0000,
+	MLAN_OID_WMM_CFG_ENABLE = 0x000A0001,
+	MLAN_OID_WMM_CFG_QOS = 0x000A0002,
+	MLAN_OID_WMM_CFG_ADDTS = 0x000A0003,
+	MLAN_OID_WMM_CFG_DELTS = 0x000A0004,
+	MLAN_OID_WMM_CFG_QUEUE_CONFIG = 0x000A0005,
+	MLAN_OID_WMM_CFG_QUEUE_STATS = 0x000A0006,
+	MLAN_OID_WMM_CFG_QUEUE_STATUS = 0x000A0007,
+	MLAN_OID_WMM_CFG_TS_STATUS = 0x000A0008,
+
+	/* WPS Configuration Group */
+	MLAN_IOCTL_WPS_CFG = 0x000B0000,
+	MLAN_OID_WPS_CFG_SESSION = 0x000B0001,
+
+	/* 802.11n Configuration Group */
+	MLAN_IOCTL_11N_CFG = 0x000C0000,
+	MLAN_OID_11N_CFG_TX = 0x000C0001,
+	MLAN_OID_11N_HTCAP_CFG = 0x000C0002,
+	MLAN_OID_11N_CFG_ADDBA_REJECT = 0x000C0003,
+	MLAN_OID_11N_CFG_AGGR_PRIO_TBL = 0x000C0004,
+	MLAN_OID_11N_CFG_ADDBA_PARAM = 0x000C0005,
+	MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE = 0x000C0006,
+	MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL = 0x000C0007,
+	MLAN_OID_11N_CFG_SUPPORTED_MCS_SET = 0x000C0008,
+	MLAN_OID_11N_CFG_TX_BF_CAP = 0x000C0009,
+	MLAN_OID_11N_CFG_TX_BF_CFG = 0x000C000A,
+	MLAN_OID_11N_CFG_STREAM_CFG = 0x000C000B,
+	MLAN_OID_11N_CFG_DELBA = 0x000C000C,
+	MLAN_OID_11N_CFG_REJECT_ADDBA_REQ = 0x000C000D,
+	MLAN_OID_11N_CFG_COEX_RX_WINSIZE = 0x000C000E,
+	MLAN_OID_11N_CFG_TX_AGGR_CTRL = 0x000C000F,
+	MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM = 0x000C0010,
+	MLAN_OID_11N_CFG_MIN_BA_THRESHOLD = 0x000C0011,
+
+	/* 802.11d Configuration Group */
+	MLAN_IOCTL_11D_CFG = 0x000D0000,
+#ifdef STA_SUPPORT
+	MLAN_OID_11D_CFG_ENABLE = 0x000D0001,
+	MLAN_OID_11D_CLR_CHAN_TABLE = 0x000D0002,
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	MLAN_OID_11D_DOMAIN_INFO = 0x000D0003,
+#endif
+	MLAN_OID_11D_DOMAIN_INFO_EXT = 0x000D0004,
+
+	/* Register Memory Access Group */
+	MLAN_IOCTL_REG_MEM = 0x000E0000,
+	MLAN_OID_REG_RW = 0x000E0001,
+	MLAN_OID_EEPROM_RD = 0x000E0002,
+	MLAN_OID_MEM_RW = 0x000E0003,
+
+	/* Multi-Radio Configuration Group */
+	MLAN_IOCTL_MFR_CFG = 0x00100000,
+	/* 802.11h Configuration Group */
+	MLAN_IOCTL_11H_CFG = 0x00110000,
+	MLAN_OID_11H_CHANNEL_CHECK = 0x00110001,
+	MLAN_OID_11H_LOCAL_POWER_CONSTRAINT = 0x00110002,
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+	MLAN_OID_11H_DFS_W53_CFG = 0x00110008,
+
+	/* 802.11n Configuration Group RANDYTODO for value assign */
+	MLAN_IOCTL_11AC_CFG = 0x00120000,
+	MLAN_OID_11AC_VHT_CFG = 0x00120001,
+	MLAN_OID_11AC_CFG_SUPPORTED_MCS_SET = 0x00120002,
+	MLAN_OID_11AC_OPERMODE_CFG = 0x00120003,
+
+	/* 802.11ax Configuration Group  */
+	MLAN_IOCTL_11AX_CFG = 0x00170000,
+	MLAN_OID_11AX_HE_CFG = 0x00170001,
+	MLAN_OID_11AX_CMD_CFG = 0x00170002,
+	MLAN_OID_11AX_TWT_CFG = 0x00170003,
+
+	/* Miscellaneous Configuration Group */
+	MLAN_IOCTL_MISC_CFG = 0x00200000,
+	MLAN_OID_MISC_GEN_IE = 0x00200001,
+	MLAN_OID_MISC_REGION = 0x00200002,
+	MLAN_OID_MISC_WARM_RESET = 0x00200003,
+#ifdef SDIO
+	MLAN_OID_MISC_SDIO_MPA_CTRL = 0x00200006,
+#endif
+	MLAN_OID_MISC_HOST_CMD = 0x00200007,
+	MLAN_OID_MISC_SYS_CLOCK = 0x00200009,
+	MLAN_OID_MISC_SOFT_RESET = 0x0020000A,
+	MLAN_OID_MISC_WWS = 0x0020000B,
+	MLAN_OID_MISC_ASSOC_RSP = 0x0020000C,
+	MLAN_OID_MISC_INIT_SHUTDOWN = 0x0020000D,
+	MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+	MLAN_OID_MISC_TDLS_CONFIG = 0x00200010,
+	MLAN_OID_MISC_TX_DATAPAUSE = 0x00200012,
+	MLAN_OID_MISC_IP_ADDR = 0x00200013,
+	MLAN_OID_MISC_MAC_CONTROL = 0x00200014,
+	MLAN_OID_MISC_MEF_CFG = 0x00200015,
+	MLAN_OID_MISC_CFP_CODE = 0x00200016,
+	MLAN_OID_MISC_COUNTRY_CODE = 0x00200017,
+	MLAN_OID_MISC_THERMAL = 0x00200018,
+	MLAN_OID_MISC_RX_MGMT_IND = 0x00200019,
+	MLAN_OID_MISC_SUBSCRIBE_EVENT = 0x0020001A,
+#ifdef DEBUG_LEVEL1
+	MLAN_OID_MISC_DRVDBG = 0x0020001B,
+#endif
+	MLAN_OID_MISC_HOTSPOT_CFG = 0x0020001C,
+	MLAN_OID_MISC_OTP_USER_DATA = 0x0020001D,
+#ifdef USB
+	MLAN_OID_MISC_USB_AGGR_CTRL = 0x0020001F,
+#endif
+	MLAN_OID_MISC_TXCONTROL = 0x00200020,
+#ifdef STA_SUPPORT
+	MLAN_OID_MISC_EXT_CAP_CFG = 0x00200021,
+#endif
+#if defined(STA_SUPPORT)
+	MLAN_OID_MISC_PMFCFG = 0x00200022,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	MLAN_OID_MISC_WIFI_DIRECT_CONFIG = 0x00200025,
+#endif
+	MLAN_OID_MISC_TDLS_OPER = 0x00200026,
+	MLAN_OID_MISC_GET_TDLS_IES = 0x00200027,
+	MLAN_OID_MISC_LOW_PWR_MODE = 0x00200029,
+	MLAN_OID_MISC_MEF_FLT_CFG = 0x0020002A,
+	MLAN_OID_MISC_DFS_REAPTER_MODE = 0x0020002B,
+#ifdef RX_PACKET_COALESCE
+	MLAN_OID_MISC_RX_PACKET_COALESCE = 0x0020002C,
+#endif
+	MLAN_OID_MISC_TDLS_CS_CHANNEL = 0x0020002D,
+	MLAN_OID_MISC_COALESCE_CFG = 0x0020002E,
+	MLAN_OID_MISC_TDLS_IDLE_TIME = 0x0020002F,
+	MLAN_OID_MISC_GET_SENSOR_TEMP = 0x00200030,
+	MLAN_OID_MISC_IPV6_RA_OFFLOAD = 0x00200036,
+	MLAN_OID_MISC_GTK_REKEY_OFFLOAD = 0x00200037,
+	MLAN_OID_MISC_OPER_CLASS = 0x00200038,
+	MLAN_OID_MISC_PMIC_CFG = 0x00200039,
+	MLAN_OID_MISC_IND_RST_CFG = 0x00200040,
+	MLAN_OID_MISC_GET_TSF = 0x00200045,
+	MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+	MLAN_OID_MISC_CLOUD_KEEP_ALIVE = 0x00200048,
+	MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	MLAN_OID_MISC_AGGR_CTRL = 0x00200052,
+	MLAN_OID_MISC_DYN_BW = 0x00200053,
+	MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+	MLAN_OID_MISC_PER_PKT_CFG = 0x00200055,
+
+	MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+	MLAN_OID_MISC_GET_TX_RX_HISTOGRAM = 0x00200057,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+#if defined(PCIE)
+	MLAN_OID_MISC_SSU = 0x00200062,
+#endif
+	MLAN_OID_MISC_DMCS_CONFIG = 0x00200065,
+	MLAN_OID_MISC_RX_ABORT_CFG = 0x00200066,
+	MLAN_OID_MISC_RX_ABORT_CFG_EXT = 0x00200067,
+	MLAN_OID_MISC_TX_AMPDU_PROT_MODE = 0x00200068,
+	MLAN_OID_MISC_RATE_ADAPT_CFG = 0x00200069,
+	MLAN_OID_MISC_CCK_DESENSE_CFG = 0x00200070,
+	MLAN_OID_MISC_GET_CHAN_TRPC_CFG = 0x00200072,
+	MLAN_OID_MISC_BAND_STEERING = 0x00200073,
+	MLAN_OID_MISC_GET_REGIONPWR_CFG = 0x00200074,
+	MLAN_OID_MISC_RF_TEST_GENERIC = 0x00200075,
+	MLAN_OID_MISC_RF_TEST_TX_CONT = 0x00200076,
+	MLAN_OID_MISC_RF_TEST_TX_FRAME = 0x00200077,
+	MLAN_OID_MISC_ARB_CONFIG = 0x00200078,
+	MLAN_OID_MISC_BEACON_STUCK = 0x00200079,
+	MLAN_OID_MISC_CFP_TABLE = 0x0020007A,
+	MLAN_OID_MISC_RANGE_EXT = 0x0020007B,
+	MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG = 0x0020007C,
+	MLAN_OID_MISC_TP_STATE = 0x0020007D,
+	MLAN_OID_MISC_HAL_PHY_CFG = 0x0020007E,
+	MLAN_OID_MISC_RF_TEST_HE_POWER = 0X0020007F,
+#ifdef UAP_SUPPORT
+	MLAN_OID_MISC_WACP_MODE = 0x00200081,
+#endif
+	MLAN_OID_MISC_GPIO_TSF_LATCH = 0x00200082,
+	MLAN_OID_MISC_GET_TSF_INFO = 0x00200083,
+};
+
+/** Sub command size */
+#define MLAN_SUB_COMMAND_SIZE 4
+
+/** Enumeration for the action of IOCTL request */
+enum _mlan_act_ioctl {
+	MLAN_ACT_SET = 1,
+	MLAN_ACT_GET,
+	MLAN_ACT_CANCEL,
+	MLAN_ACT_CLEAR,
+	MLAN_ACT_RESET,
+	MLAN_ACT_DEFAULT
+};
+
+/** Enumeration for generic enable/disable */
+enum _mlan_act_generic { MLAN_ACT_DISABLE = 0, MLAN_ACT_ENABLE = 1 };
+
+/** Enumeration for scan mode */
+enum _mlan_scan_mode {
+	MLAN_SCAN_MODE_UNCHANGED = 0,
+	MLAN_SCAN_MODE_BSS,
+	MLAN_SCAN_MODE_IBSS,
+	MLAN_SCAN_MODE_ANY
+};
+
+/** Enumeration for scan type */
+enum _mlan_scan_type {
+	MLAN_SCAN_TYPE_UNCHANGED = 0,
+	MLAN_SCAN_TYPE_ACTIVE,
+	MLAN_SCAN_TYPE_PASSIVE,
+	MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE
+};
+
+/** Enumeration for passive to active scan */
+enum _mlan_pass_to_act_scan {
+	MLAN_PASS_TO_ACT_SCAN_UNCHANGED = 0,
+	MLAN_PASS_TO_ACT_SCAN_EN,
+	MLAN_PASS_TO_ACT_SCAN_DIS
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES 32
+
+/** Mrvl Proprietary Tlv base */
+#define PROPRIETARY_TLV_BASE_ID 0x100
+
+/** RSSI scan */
+#define SCAN_RSSI(RSSI) (0x100 - ((t_u8)(RSSI)))
+
+/** Max passive scan time for each channel in milliseconds */
+#define MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME 2000
+
+/** Max active scan time for each channel in milliseconds  */
+#define MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME 500
+/** Max gap time between 2 scan in milliseconds  */
+#define MRVDRV_MAX_SCAN_CHAN_GAP_TIME 500
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES 5
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES 4
+
+/**
+ *  @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS
+ *
+ *  Fixed field information returned for the scan response in the IOCTL
+ *    response.
+ */
+typedef struct _wlan_get_scan_table_fixed {
+	/** BSSID of this network */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Channel this beacon/probe response was detected */
+	t_u8 channel;
+	/** RSSI for the received packet */
+	t_u8 rssi;
+	/** channel load */
+	t_u8 chan_load;
+	/** TSF value in microseconds from the firmware at packet reception */
+	t_u64 network_tsf;
+} wlan_get_scan_table_fixed;
+
+/** mlan_802_11_ssid data structure */
+typedef struct _mlan_802_11_ssid {
+	/** SSID Length */
+	t_u32 ssid_len;
+	/** SSID information field */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+} mlan_802_11_ssid, *pmlan_802_11_ssid;
+
+typedef MLAN_PACK_START struct _tx_status_event {
+	/** packet type */
+	t_u8 packet_type;
+	/** tx_token_id */
+	t_u8 tx_token_id;
+	/** 0--success, 1--fail, 2--watchdogtimeout */
+	t_u8 status;
+} MLAN_PACK_END tx_status_event;
+
+/**
+ *  Sructure to retrieve the scan table
+ */
+typedef struct {
+	/**
+	 *  - Zero based scan entry to start retrieval in command request
+	 *  - Number of scans entries returned in command response
+	 */
+	t_u32 scan_number;
+	/**
+	 * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
+	 * structures. Each struct is padded to the nearest 32 bit boundary.
+	 */
+	t_u8 scan_table_entry_buf[1];
+} wlan_ioctl_get_scan_table_info;
+
+/**
+ *  Structure passed in the wlan_ioctl_get_scan_table_info for each
+ *    BSS returned in the WLAN_GET_SCAN_RESP IOCTL
+ */
+typedef struct _wlan_ioctl_get_scan_table_entry {
+	/**
+	 *  Fixed field length included in the response.
+	 *
+	 *  Length value is included so future fixed fields can be added to the
+	 *   response without breaking backwards compatibility.  Use the length
+	 *   to find the offset for the bssInfoLength field, not a sizeof()
+	 * calc.
+	 */
+	t_u32 fixed_field_length;
+
+	/**
+	 *  Length of the BSS Information (probe resp or beacon) that
+	 *    follows after the fixed_field_length
+	 */
+	t_u32 bss_info_length;
+
+	/**
+	 *  Always present, fixed length data fields for the BSS
+	 */
+	wlan_get_scan_table_fixed fixed_fields;
+
+	/*
+	 * Probe response or beacon scanned for the BSS.
+	 *
+	 * Field layout:
+	 *  - TSF              8 octets
+	 *  - Beacon Interval  2 octets
+	 *  - Capability Info  2 octets
+	 *
+	 *  - IEEE Infomation Elements; variable number & length per 802.11 spec
+	 */
+	/* t_u8  bss_info_buffer[]; */
+} wlan_ioctl_get_scan_table_entry;
+
+/** Type definition of mlan_scan_time_params */
+typedef struct _mlan_scan_time_params {
+	/** Scan channel time for specific scan in milliseconds */
+	t_u32 specific_scan_time;
+	/** Scan channel time for active scan in milliseconds */
+	t_u32 active_scan_time;
+	/** Scan channel time for passive scan in milliseconds */
+	t_u32 passive_scan_time;
+} mlan_scan_time_params, *pmlan_scan_time_params;
+
+/** Type definition of mlan_user_scan */
+typedef struct _mlan_user_scan {
+	/** Length of scan_cfg_buf */
+	t_u32 scan_cfg_len;
+	/** Buffer of scan config */
+	t_u8 scan_cfg_buf[1];
+} mlan_user_scan, *pmlan_user_scan;
+
+/** Type definition of mlan_scan_req */
+typedef struct _mlan_scan_req {
+	/** BSS mode for scanning */
+	t_u32 scan_mode;
+	/** Scan type */
+	t_u32 scan_type;
+	/** SSID */
+	mlan_802_11_ssid scan_ssid;
+	/** Scan time parameters */
+	mlan_scan_time_params scan_time;
+	/** Scan config parameters in user scan */
+	mlan_user_scan user_scan;
+} mlan_scan_req, *pmlan_scan_req;
+
+/** Type defnition of mlan_scan_resp */
+typedef struct _mlan_scan_resp {
+	/** Number of scan result */
+	t_u32 num_in_scan_table;
+	/** Scan table */
+	t_u8 *pscan_table;
+	/* Age in seconds */
+	t_u32 age_in_secs;
+	/** channel statstics */
+	t_u8 *pchan_stats;
+	/** Number of records in the chan_stats */
+	t_u32 num_in_chan_stats;
+} mlan_scan_resp, *pmlan_scan_resp;
+
+#define EXT_SCAN_TYPE_ENH 2
+/** Type definition of mlan_scan_cfg */
+typedef struct _mlan_scan_cfg {
+	/** Scan type */
+	t_u32 scan_type;
+	/** BSS mode for scanning */
+	t_u32 scan_mode;
+	/** Scan probe */
+	t_u32 scan_probe;
+	/** Scan time parameters */
+	mlan_scan_time_params scan_time;
+	/** First passive scan then active scan */
+	t_u8 passive_to_active_scan;
+	/** Ext_scan:  0 disable, 1: enable, 2: enhance scan*/
+	t_u32 ext_scan;
+	/** scan channel gap */
+	t_u32 scan_chan_gap;
+} mlan_scan_cfg, *pmlan_scan_cfg;
+
+/** Type defnition of mlan_ds_scan for MLAN_IOCTL_SCAN */
+typedef struct _mlan_ds_scan {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Scan request/response */
+	union {
+		/** Scan request */
+		mlan_scan_req scan_req;
+		/** Scan response */
+		mlan_scan_resp scan_resp;
+		/** Scan config parameters in user scan */
+		mlan_user_scan user_scan;
+		/** Scan config parameters */
+		mlan_scan_cfg scan_cfg;
+	} param;
+} mlan_ds_scan, *pmlan_ds_scan;
+
+/*-----------------------------------------------------------------*/
+/** BSS Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for BSS mode */
+enum _mlan_bss_mode {
+	MLAN_BSS_MODE_INFRA = 1,
+	MLAN_BSS_MODE_IBSS,
+	MLAN_BSS_MODE_AUTO
+};
+
+/** Maximum key length */
+#define MLAN_MAX_KEY_LENGTH 32
+
+/** Maximum atim window in milliseconds */
+#define MLAN_MAX_ATIM_WINDOW 50
+
+/** Minimum beacon interval */
+#define MLAN_MIN_BEACON_INTERVAL 20
+/** Maximum beacon interval */
+#define MLAN_MAX_BEACON_INTERVAL 1000
+/** Default beacon interval */
+#define MLAN_BEACON_INTERVAL 100
+
+/** Receive all packets */
+#define MLAN_PROMISC_MODE 1
+/** Receive multicast packets in multicast list */
+#define MLAN_MULTICAST_MODE 2
+/** Receive all multicast packets */
+#define MLAN_ALL_MULTI_MODE 4
+
+/** Maximum size of multicast list */
+#define MLAN_MAX_MULTICAST_LIST_SIZE 32
+
+/** mlan_multicast_list data structure for MLAN_OID_BSS_MULTICAST_LIST */
+typedef struct _mlan_multicast_list {
+	/** Multicast mode */
+	t_u32 mode;
+	/** Number of multicast addresses in the list */
+	t_u32 num_multicast_addr;
+	/** Multicast address list */
+	mlan_802_11_mac_addr mac_list[MLAN_MAX_MULTICAST_LIST_SIZE];
+} mlan_multicast_list, *pmlan_multicast_list;
+
+/** Max channel */
+#define MLAN_MAX_CHANNEL 165
+/** Maximum number of channels in table */
+#define MLAN_MAX_CHANNEL_NUM 128
+
+/** Channel/frequence for MLAN_OID_BSS_CHANNEL */
+typedef struct _chan_freq {
+	/** Channel Number */
+	t_u32 channel;
+	/** Frequency of this Channel */
+	t_u32 freq;
+} chan_freq;
+
+/** mlan_chan_list data structure for MLAN_OID_BSS_CHANNEL_LIST */
+typedef struct _mlan_chan_list {
+	/** Number of channel */
+	t_u32 num_of_chan;
+	/** Channel-Frequency table */
+	chan_freq cf[MLAN_MAX_CHANNEL_NUM];
+} mlan_chan_list;
+
+/* This channel is disabled.*/
+#define CHAN_FLAGS_DISABLED MBIT(0)
+/* do not initiate radiation, this includes sending probe requests or beaconing
+ */
+#define CHAN_FLAGS_NO_IR MBIT(1)
+/* Radar detection is required on this channel */
+#define CHAN_FLAGS_RADAR MBIT(3)
+/* extension channel above this channel is not permitted */
+#define CHAN_FLAGS_NO_HT40PLUS MBIT(4)
+/* extension channel below this channel is not permitted */
+#define CHAN_FLAGS_NO_HT40MINUS MBIT(5)
+/* OFDM is not allowed on this channel */
+#define CHAN_FLAGS_NO_OFDM MBIT(6)
+/** 80Mhz can not used on this channel */
+#define CHAN_FLAGS_NO_80MHZ MBIT(7)
+/** 180Mhz can not used on this channel */
+#define CHAN_FLAGS_NO_160MHZ MBIT(8)
+/* Only indoor use is permitted on this channel */
+#define CHAN_FLAGS_INDOOR_ONLY MBIT(9)
+/* IR operation is allowed on this channel if it's
+ * connected concurrently to a BSS on the same channel on
+ * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz
+ * band), and IEEE80211_CHAN_RADAR is not set */
+#define CHAN_FLAGS_IR_CONCURRENT MBIT(10)
+/* 20 MHz operation is not allowed on this channel */
+#define CHAN_FLAGS_20MHZ MBIT(11)
+/* 10 MHz operation is not allowed on this channel */
+#define CHAN_FLAGS_NO_10MHZ MBIT(12)
+/** This channel's flag is valid */
+#define CHAN_FLAGS_MAX MBIT(31)
+
+/** Maximum response buffer length */
+#define ASSOC_RSP_BUF_SIZE 500
+
+/** Type definition of mlan_ds_misc_assoc_rsp for MLAN_OID_MISC_ASSOC_RSP */
+typedef struct _mlan_ds_misc_assoc_rsp {
+	/** Associate response buffer */
+	t_u8 assoc_resp_buf[ASSOC_RSP_BUF_SIZE];
+	/** Response buffer length */
+	t_u32 assoc_resp_len;
+} mlan_ds_misc_assoc_rsp, *pmlan_ds_misc_assoc_rsp;
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+	/** SSID */
+	mlan_802_11_ssid ssid;
+	/** BSSID */
+	mlan_802_11_mac_addr bssid;
+	/** index in BSSID list, start from 1 */
+	t_u32 idx;
+	/** Receive signal strength in dBm */
+	t_s32 rssi;
+	/* previous bssid */
+	mlan_802_11_mac_addr prev_bssid;
+	/**channel*/
+	t_u16 channel;
+	/**mobility domain value*/
+	t_u16 ft_md;
+	/**ft capability*/
+	t_u8 ft_cap;
+	/**band*/
+	t_u16 bss_band;
+	/** channel flag */
+	t_u32 channel_flags;
+	/** host mlme flag*/
+	t_u8 host_mlme;
+	/** assoicate resp frame/ie from firmware */
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+} mlan_ssid_bssid, *pmlan_ssid_bssid;
+
+/** Data structure of WMM ECW */
+typedef struct _wmm_ecw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} wmm_ecw_t, *pwmm_ecw_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef struct _wmm_aci_aifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aifsn */
+	t_u8 aifsn:4;
+#else
+	/** Aifsn */
+	t_u8 aifsn:4;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} wmm_aci_aifsn_t, *pwmm_aci_aifsn_t;
+
+/** Data structure of WMM AC parameters  */
+typedef struct _wmm_ac_parameters_t {
+	wmm_aci_aifsn_t aci_aifsn; /**< AciAifSn */
+	wmm_ecw_t ecw; /**< Ecw */
+	t_u16 tx_op_limit; /**< Tx op limit */
+} wmm_ac_parameters_t, *pwmm_ac_parameters_t;
+
+/** mlan_deauth_param */
+typedef struct _mlan_deauth_param {
+	/** STA mac addr */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** deauth reason */
+	t_u16 reason_code;
+} mlan_deauth_param;
+
+#ifdef UAP_SUPPORT
+/** UAP FLAG: Host based */
+#define UAP_FLAG_HOST_BASED MBIT(0)
+/** UAP FLAG: Host mlme */
+#define UAP_FLAG_HOST_MLME MBIT(1)
+
+/** Maximum packet forward control value */
+#define MAX_PKT_FWD_CTRL 15
+/** Maximum BEACON period */
+#define MAX_BEACON_PERIOD 4000
+/** Minimum BEACON period */
+#define MIN_BEACON_PERIOD 50
+/** Maximum DTIM period */
+#define MAX_DTIM_PERIOD 100
+/** Minimum DTIM period */
+#define MIN_DTIM_PERIOD 1
+/** Maximum TX Power Limit */
+#define MAX_TX_POWER 20
+/** Minimum TX Power Limit */
+#define MIN_TX_POWER 0
+/** MAX station count */
+#define MAX_STA_COUNT 64
+/** Maximum RTS threshold */
+#define MAX_RTS_THRESHOLD 2347
+/** Maximum fragmentation threshold */
+#define MAX_FRAG_THRESHOLD 2346
+/** Minimum fragmentation threshold */
+#define MIN_FRAG_THRESHOLD 256
+/** data rate 54 M */
+#define DATA_RATE_54M 108
+/** Maximum value of bcast_ssid_ctl */
+#define MAX_BCAST_SSID_CTL 2
+/** antenna A */
+#define ANTENNA_MODE_A 0
+/** antenna B */
+#define ANTENNA_MODE_B 1
+/** transmit antenna */
+#define TX_ANTENNA 1
+/** receive antenna */
+#define RX_ANTENNA 0
+/** Maximum stage out time */
+#define MAX_STAGE_OUT_TIME 864000
+/** Minimum stage out time */
+#define MIN_STAGE_OUT_TIME 50
+/** Maximum Retry Limit */
+#define MAX_RETRY_LIMIT 14
+
+/** Maximum group key timer in seconds */
+#define MAX_GRP_TIMER 86400
+
+/** Maximum value of 4 byte configuration */
+#define MAX_VALID_DWORD 0x7FFFFFFF	/*  (1 << 31) - 1 */
+
+/** default UAP BAND 2.4G */
+#define DEFAULT_UAP_BAND 0
+/** default UAP channel 6 */
+#define DEFAULT_UAP_CHANNEL 6
+
+/** Maximum data rates */
+#define MAX_DATA_RATES 14
+
+/** auto data rate */
+#define DATA_RATE_AUTO 0
+
+/**filter mode: disable */
+#define MAC_FILTER_MODE_DISABLE 0
+/**filter mode: block mac address */
+#define MAC_FILTER_MODE_ALLOW_MAC 1
+/**filter mode: block mac address */
+#define MAC_FILTER_MODE_BLOCK_MAC 2
+/** Maximum mac filter num */
+#define MAX_MAC_FILTER_NUM 64
+
+/* Bitmap for protocol to use */
+/** No security */
+#define PROTOCOL_NO_SECURITY 0x01
+/** Static WEP */
+#define PROTOCOL_STATIC_WEP 0x02
+/** WPA */
+#define PROTOCOL_WPA 0x08
+/** WPA2 */
+#define PROTOCOL_WPA2 0x20
+/** WP2 Mixed */
+#define PROTOCOL_WPA2_MIXED 0x28
+/** EAP */
+#define PROTOCOL_EAP 0x40
+/** WAPI */
+#define PROTOCOL_WAPI 0x80
+/** WPA3 SAE */
+#define PROTOCOL_WPA3_SAE 0x100
+
+/** Key_mgmt_psk */
+#define KEY_MGMT_NONE 0x04
+/** Key_mgmt_none */
+#define KEY_MGMT_PSK 0x02
+/** Key_mgmt_eap  */
+#define KEY_MGMT_EAP 0x01
+/** Key_mgmt_psk_sha256 */
+#define KEY_MGMT_PSK_SHA256 0x100
+/** Key_mgmt_sae */
+#define KEY_MGMT_SAE 0x400
+/** Key_mgmt_owe */
+#define KEY_MGMT_OWE 0x200
+
+/** TKIP */
+#define CIPHER_TKIP 0x04
+/** AES CCMP */
+#define CIPHER_AES_CCMP 0x08
+
+/** Valid cipher bitmap */
+#define VALID_CIPHER_BITMAP 0x0c
+
+/** Packet forwarding to be done by FW or host */
+#define PKT_FWD_FW_BIT 0x01
+/** Intra-BSS broadcast packet forwarding allow bit */
+#define PKT_FWD_INTRA_BCAST 0x02
+/** Intra-BSS unicast packet forwarding allow bit */
+#define PKT_FWD_INTRA_UCAST 0x04
+/** Inter-BSS unicast packet forwarding allow bit */
+#define PKT_FWD_INTER_UCAST 0x08
+/** Intra-BSS unicast packet */
+#define PKT_INTRA_UCAST 0x01
+/** Inter-BSS unicast packet */
+#define PKT_INTER_UCAST 0x02
+/** Enable Host PKT forwarding */
+#define PKT_FWD_ENABLE_BIT 0x01
+
+/** Channel List Entry */
+typedef struct _channel_list {
+	/** Channel Number */
+	t_u8 chan_number;
+	/** Band Config */
+	Band_Config_t bandcfg;
+} scan_chan_list;
+
+/** mac_filter data structure */
+typedef struct _mac_filter {
+	/** mac filter mode */
+	t_u16 filter_mode;
+	/** mac adress count */
+	t_u16 mac_count;
+	/** mac address list */
+	mlan_802_11_mac_addr mac_list[MAX_MAC_FILTER_NUM];
+} mac_filter;
+
+/** wpa parameter */
+typedef struct _wpa_param {
+	/** Pairwise cipher WPA */
+	t_u8 pairwise_cipher_wpa;
+	/** Pairwise cipher WPA2 */
+	t_u8 pairwise_cipher_wpa2;
+	/** group cipher */
+	t_u8 group_cipher;
+	/** RSN replay protection */
+	t_u8 rsn_protection;
+	/** passphrase length */
+	t_u32 length;
+	/** passphrase */
+	t_u8 passphrase[64];
+	/**group key rekey time in seconds */
+	t_u32 gk_rekey_time;
+} wpa_param;
+
+/** wep key */
+typedef struct _wep_key {
+	/** key index 0-3 */
+	t_u8 key_index;
+	/** is default */
+	t_u8 is_default;
+	/** length */
+	t_u16 length;
+	/** key data */
+	t_u8 key[26];
+} wep_key;
+
+/** wep param */
+typedef struct _wep_param {
+	/** key 0 */
+	wep_key key0;
+	/** key 1 */
+	wep_key key1;
+	/** key 2 */
+	wep_key key2;
+	/** key 3 */
+	wep_key key3;
+} wep_param;
+
+/** Data structure of WMM QoS information */
+typedef struct _wmm_qos_info_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} wmm_qos_info_t, *pwmm_qos_info_t;
+
+/** Data structure of WMM parameter IE  */
+typedef struct _wmm_parameter_t {
+	/** OuiType:  00:50:f2:02 */
+	t_u8 ouitype[4];
+	/** Oui subtype: 01 */
+	t_u8 ouisubtype;
+	/** version: 01 */
+	t_u8 version;
+	/** QoS information */
+	t_u8 qos_info;
+	/** Reserved */
+	t_u8 reserved;
+	/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+} wmm_parameter_t, *pwmm_parameter_t;
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+/** mlan_bss_param
+ * Note: For each entry you must enter an invalid value
+ * in the MOAL function woal_set_sys_config_invalid_data().
+ * Otherwise for a valid data an unwanted TLV will be
+ * added to that command.
+ */
+typedef struct _mlan_uap_bss_param {
+	/** AP mac addr */
+	mlan_802_11_mac_addr mac_addr;
+	/** SSID */
+	mlan_802_11_ssid ssid;
+	/** Broadcast ssid control */
+	t_u8 bcast_ssid_ctl;
+	/** Radio control: on/off */
+	t_u8 radio_ctl;
+	/** dtim period */
+	t_u8 dtim_period;
+	/** beacon period */
+	t_u16 beacon_period;
+	/** rates */
+	t_u8 rates[MAX_DATA_RATES];
+	/** Tx data rate */
+	t_u16 tx_data_rate;
+	/** Tx beacon rate */
+	t_u16 tx_beacon_rate;
+	/** multicast/broadcast data rate */
+	t_u16 mcbc_data_rate;
+	/** Tx power level in dBm */
+	t_u8 tx_power_level;
+	/** Tx antenna */
+	t_u8 tx_antenna;
+	/** Rx antenna */
+	t_u8 rx_antenna;
+	/** packet forward control */
+	t_u8 pkt_forward_ctl;
+	/** max station count */
+	t_u16 max_sta_count;
+	/** mac filter */
+	mac_filter filter;
+	/** station ageout timer in unit of 100ms  */
+	t_u32 sta_ageout_timer;
+	/** PS station ageout timer in unit of 100ms  */
+	t_u32 ps_sta_ageout_timer;
+	/** RTS threshold */
+	t_u16 rts_threshold;
+	/** fragmentation threshold */
+	t_u16 frag_threshold;
+	/**  retry_limit */
+	t_u16 retry_limit;
+	/**  pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+	/** pairwise handshake retries */
+	t_u32 pwk_retries;
+	/**  groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+	/** groupwise handshake retries */
+	t_u32 gwk_retries;
+	/** preamble type */
+	t_u8 preamble_type;
+	/** band cfg */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** auth mode */
+	t_u16 auth_mode;
+	/** encryption protocol */
+	t_u16 protocol;
+	/** key managment type */
+	t_u16 key_mgmt;
+	/** wep param */
+	wep_param wep_cfg;
+	/** wpa param */
+	wpa_param wpa_cfg;
+	/** Mgmt IE passthru mask */
+	t_u32 mgmt_ie_passthru_mask;
+	/*
+	 * 11n HT Cap  HTCap_t  ht_cap
+	 */
+	/** HT Capabilities Info field */
+	t_u16 ht_cap_info;
+	/** A-MPDU Parameters field */
+	t_u8 ampdu_param;
+	/** Supported MCS Set field */
+	t_u8 supported_mcs_set[16];
+	/** HT Extended Capabilities field */
+	t_u16 ht_ext_cap;
+	/** Transmit Beamforming Capabilities field */
+	t_u32 tx_bf_cap;
+	/** Antenna Selection Capability field */
+	t_u8 asel;
+	/** Enable 2040 Coex */
+	t_u8 enable_2040coex;
+	/** key management operation */
+	t_u16 key_mgmt_operation;
+	/** BSS status */
+	t_u16 bss_status;
+#ifdef WIFI_DIRECT_SUPPORT
+	/* pre shared key */
+	t_u8 psk[MLAN_MAX_KEY_LENGTH];
+#endif				/* WIFI_DIRECT_SUPPORT */
+	/** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+	/** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+	/** Wmm parameters */
+	wmm_parameter_t wmm_para;
+
+	/** uap host based config */
+	t_u32 uap_host_based_config;
+} mlan_uap_bss_param, *pmlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+	/** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+	/** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+	/** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_chan_switch_param */
+typedef struct _mlan_action_chan_switch {
+	/** mode*/
+	t_u8 mode;
+	/** switch mode*/
+	t_u8 chan_switch_mode;
+	/** oper class*/
+	t_u8 new_oper_class;
+    /** new channel */
+	t_u8 new_channel_num;
+    /** chan_switch_count */
+	t_u8 chan_switch_count;
+} mlan_action_chan_switch;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+	/** control value
+	 *  0: do nothing,
+	 *  2: uap stops and restarts automaticaly
+	 */
+	t_u16 ctrl_value;
+	/** channel opt
+	 *  1: uap restart on default 2.4G/channel 6
+	 *  2: uap restart on the band/channel configured by driver previously
+	 *  3: uap restart on the band/channel specified by band_cfg and channel
+	 */
+	t_u16 chan_opt;
+	/** band cfg   0
+	 *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+	 */
+	t_u8 band_cfg;
+	/** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+/** mlan_uap_acs_scan */
+typedef struct _mlan_uap_acs_scan {
+	/** band */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 chan;
+} mlan_uap_acs_scan;
+
+/** station is authorized (802.1X) */
+#define STA_FLAG_AUTHORIZED MBIT(1)
+/** Station is capable of receiving frames with short barker preamble */
+#define STA_FLAG_SHORT_PREAMBLE MBIT(2)
+/** station is WME/QoS capable */
+#define STA_FLAG_WME MBIT(3)
+/** station uses management frame protection */
+#define STA_FLAG_MFP MBIT(4)
+/** station is authenticated */
+#define STA_FLAG_AUTHENTICATED MBIT(5)
+/** station is a TDLS peer */
+#define STA_FLAG_TDLS_PEER MBIT(6)
+/** station is associated */
+#define STA_FLAG_ASSOCIATED MBIT(7)
+/** mlan_ds_sta_info */
+typedef struct _mlan_ds_sta_info {
+	/** aid */
+	t_u16 aid;
+	/** peer_mac */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Listen Interval */
+	int listen_interval;
+	/** Capability Info */
+	t_u16 cap_info;
+	/** station flag */
+	t_u32 sta_flags;
+	/** tlv len */
+	t_u16 tlv_len;
+	/** tlv start */
+	t_u8 tlv[];
+} mlan_ds_sta_info;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** mode: disable wifi direct */
+#define WIFI_DIRECT_MODE_DISABLE 0
+/** mode: listen */
+#define WIFI_DIRECT_MODE_LISTEN 1
+/** mode: GO */
+#define WIFI_DIRECT_MODE_GO 2
+/** mode: client */
+#define WIFI_DIRECT_MODE_CLIENT 3
+/** mode: find */
+#define WIFI_DIRECT_MODE_FIND 4
+/** mode: stop find */
+#define WIFI_DIRECT_MODE_STOP_FIND 5
+#endif
+
+/** Type definition of mlan_ds_bss for MLAN_IOCTL_BSS */
+typedef struct _mlan_ds_bss {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** BSS parameter */
+	union {
+		/** SSID-BSSID for MLAN_OID_BSS_START */
+		mlan_ssid_bssid ssid_bssid;
+		/** BSSID for MLAN_OID_BSS_STOP */
+		mlan_802_11_mac_addr bssid;
+		/** BSS mode for MLAN_OID_BSS_MODE */
+		t_u32 bss_mode;
+		/** BSS channel/frequency for MLAN_OID_BSS_CHANNEL */
+		chan_freq bss_chan;
+		/** BSS channel list for MLAN_OID_BSS_CHANNEL_LIST */
+		mlan_chan_list chanlist;
+		/** MAC address for MLAN_OID_BSS_MAC_ADDR */
+		mlan_802_11_mac_addr mac_addr;
+		/** Multicast list for MLAN_OID_BSS_MULTICAST_LIST */
+		mlan_multicast_list multicast_list;
+		/** Beacon interval for MLAN_OID_IBSS_BCN_INTERVAL */
+		t_u32 bcn_interval;
+		/** ATIM window for MLAN_OID_IBSS_ATIM_WINDOW */
+		t_u32 atim_window;
+		/** deauth param for MLAN_OID_BSS_STOP & MLAN_OID_UAP_DEAUTH_STA
+		 */
+		mlan_deauth_param deauth_param;
+#ifdef UAP_SUPPORT
+		/** host based flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+		/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+		/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+		/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** channel switch for MLAN_OID_UAP_CHAN_SWITCH */
+		mlan_action_chan_switch chanswitch;
+		/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+		/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+		/** AP acs scan 	    MLAN_OID_UAP_ACS_SCAN */
+		mlan_uap_acs_scan ap_acs_scan;
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		/** BSS role for MLAN_OID_BSS_ROLE */
+		t_u8 bss_role;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		/** wifi direct mode for MLAN_OID_WIFI_DIRECT_MODE */
+		t_u16 wfd_mode;
+#endif
+#ifdef STA_SUPPORT
+		/** Listen interval for MLAN_OID_BSS_LISTEN_INTERVAL */
+		t_u16 listen_interval;
+		/** STA channel info for MLAN_OID_BSS_CHAN_INFO */
+		chan_band_info sta_channel;
+#endif
+#ifdef UAP_SUPPORT
+		/** STA info for MLAN_OID_UAP_ADD_STATION */
+		mlan_ds_sta_info sta_info;
+#endif
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/* OTP Region info */
+typedef MLAN_PACK_START struct _otp_region_info {
+	t_u8 country_code[2];
+	t_u8 region_code;
+	t_u8 environment;
+	t_u8 force_reg:1;
+	t_u8 reserved:7;
+	t_u8 dfs_region;
+} MLAN_PACK_END otp_region_info_t;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+	otp_region_info_t region;
+	/** num of 2g channels in custom_reg_domain */
+	t_u8 num_bg_chan;
+	/** num of 5g channels in custom_reg_domain */
+	t_u8 num_a_chan;
+	/** cfp table */
+	chan_freq_power_t cfp_tbl[];
+} mlan_ds_custom_reg_domain;
+/*-----------------------------------------------------------------*/
+/** Radio Control Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for band */
+enum _mlan_band_def {
+	BAND_B = 1,
+	BAND_G = 2,
+	BAND_A = 4,
+	BAND_GN = 8,
+	BAND_AN = 16,
+	BAND_GAC = 32,
+	BAND_AAC = 64,
+	BAND_GAX = 256,
+	BAND_AAX = 512,
+
+};
+
+/** Channel bandwidth */
+#define CHANNEL_BW_20MHZ 0
+#define CHANNEL_BW_40MHZ_ABOVE 1
+#define CHANNEL_BW_40MHZ_BELOW 3
+/** secondary channel is 80Mhz bandwidth for 11ac */
+#define CHANNEL_BW_80MHZ 4
+#define CHANNEL_BW_160MHZ 5
+
+/** RF antenna selection */
+#define RF_ANTENNA_MASK(n) ((1 << (n)) - 1)
+/** RF antenna auto select */
+#define RF_ANTENNA_AUTO 0xFFFF
+
+/** Type definition of mlan_ds_band_cfg for MLAN_OID_BAND_CFG */
+typedef struct _mlan_ds_band_cfg {
+	/** Infra band */
+	t_u32 config_bands;
+	/** Ad-hoc start band */
+	t_u32 adhoc_start_band;
+	/** Ad-hoc start channel */
+	t_u32 adhoc_channel;
+	/** fw supported band */
+	t_u32 fw_bands;
+} mlan_ds_band_cfg;
+
+/** Type definition of mlan_ds_ant_cfg for MLAN_OID_ANT_CFG */
+typedef struct _mlan_ds_ant_cfg {
+	/** Tx antenna mode */
+	t_u32 tx_antenna;
+	/** Rx antenna mode */
+	t_u32 rx_antenna;
+} mlan_ds_ant_cfg, *pmlan_ds_ant_cfg;
+/** Type definition of mlan_ds_mimo_switch for MLAN_OID_MIMO_SWITCH */
+typedef struct _mlan_ds_mimo_switch {
+	/** Tx antenna mode */
+	t_u8 txpath_antmode;
+	/** Rx antenna mode */
+	t_u8 rxpath_antmode;
+} mlan_ds_mimo_switch, *pmlan_ds_mimo_switch;
+/** Type definition of mlan_ds_ant_cfg_1x1 for MLAN_OID_ANT_CFG */
+typedef struct _mlan_ds_ant_cfg_1x1 {
+	/** Antenna mode */
+	t_u32 antenna;
+	/** Evaluate time */
+	t_u16 evaluate_time;
+	/** Current antenna */
+	t_u16 current_antenna;
+} mlan_ds_ant_cfg_1x1, *pmlan_ds_ant_cfg_1x1;
+
+/** Type definition of mlan_ds_remain_chan for MLAN_OID_REMAIN_CHAN_CFG */
+typedef struct _mlan_ds_remain_chan {
+	/** remove flag */
+	t_u16 remove;
+	/** status */
+	t_u8 status;
+	/** Band cfg */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** remain time: Unit ms*/
+	t_u32 remain_period;
+} mlan_ds_remain_chan, *pmlan_ds_remain_chan;
+
+/** Type definition of mlan_ds_radio_cfg for MLAN_IOCTL_RADIO_CFG */
+typedef struct _mlan_ds_radio_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Radio control parameter */
+	union {
+		/** Radio on/off for MLAN_OID_RADIO_CTRL */
+		t_u32 radio_on_off;
+		/** Band info for MLAN_OID_BAND_CFG */
+		mlan_ds_band_cfg band_cfg;
+		/** Antenna info for MLAN_OID_ANT_CFG */
+		mlan_ds_ant_cfg ant_cfg;
+		/** Antenna mode for MLAN_OID_MIMO_SWITCH */
+		mlan_ds_mimo_switch mimo_switch_cfg;
+		/** Antenna info for MLAN_OID_ANT_CFG */
+		mlan_ds_ant_cfg_1x1 ant_cfg_1x1;
+		/** remain on channel for MLAN_OID_REMAIN_CHAN_CFG */
+		mlan_ds_remain_chan remain_chan;
+	} param;
+} mlan_ds_radio_cfg, *pmlan_ds_radio_cfg;
+
+enum COALESCE_OPERATION {
+	RECV_FILTER_MATCH_TYPE_EQ = 0x80,
+	RECV_FILTER_MATCH_TYPE_NE,
+};
+
+enum COALESCE_PACKET_TYPE {
+	PACKET_TYPE_UNICAST = 1,
+	PACKET_TYPE_MULTICAST = 2,
+	PACKET_TYPE_BROADCAST = 3
+};
+
+#define COALESCE_MAX_RULES 8
+#define COALESCE_MAX_BYTESEQ 4	/* non-adjustable */
+#define COALESCE_MAX_FILTERS 4
+#define MAX_COALESCING_DELAY 100	/* in msecs */
+#define MAX_PATTERN_LEN 20
+#define MAX_OFFSET_LEN 100
+
+struct filt_field_param {
+	t_u8 operation;
+	t_u8 operand_len;
+	t_u16 offset;
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+struct coalesce_rule {
+	t_u16 max_coalescing_delay;
+	t_u8 num_of_fields;
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+typedef struct _mlan_ds_coalesce_cfg {
+	t_u16 num_of_rules;
+	struct coalesce_rule rule[COALESCE_MAX_RULES];
+} mlan_ds_coalesce_cfg;
+
+/*-----------------------------------------------------------------*/
+/** SNMP MIB Group */
+/*-----------------------------------------------------------------*/
+/** Type definition of mlan_ds_snmp_mib for MLAN_IOCTL_SNMP_MIB */
+typedef struct _mlan_ds_snmp_mib {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** SNMP MIB parameter */
+	union {
+		/** RTS threshold for MLAN_OID_SNMP_MIB_RTS_THRESHOLD */
+		t_u32 rts_threshold;
+		/** Fragment threshold for MLAN_OID_SNMP_MIB_FRAG_THRESHOLD */
+		t_u32 frag_threshold;
+		/** Retry count for MLAN_OID_SNMP_MIB_RETRY_COUNT */
+		t_u32 retry_count;
+		/** OID value for MLAN_OID_SNMP_MIB_DOT11D/H */
+		t_u32 oid_value;
+		/** DTIM period for MLAN_OID_SNMP_MIB_DTIM_PERIOD */
+		t_u32 dtim_period;
+		/** Singal_ext Enable for MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE */
+		t_u8 signalext_enable;
+		/** Control deauth when uap switch channel */
+		t_u8 deauthctrl;
+	} param;
+} mlan_ds_snmp_mib, *pmlan_ds_snmp_mib;
+
+/*-----------------------------------------------------------------*/
+/** Status Information Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for ad-hoc status */
+enum _mlan_adhoc_status {
+	ADHOC_IDLE,
+	ADHOC_STARTED,
+	ADHOC_JOINED,
+	ADHOC_COALESCED,
+	ADHOC_STARTING
+};
+
+typedef struct _mlan_ds_get_stats_org {
+	/** Statistics counter */
+	/** Multicast transmitted frame count */
+	t_u32 mcast_tx_frame;
+	/** Failure count */
+	t_u32 failed;
+	/** Retry count */
+	t_u32 retry;
+	/** Multi entry count */
+	t_u32 multi_retry;
+	/** Duplicate frame count */
+	t_u32 frame_dup;
+	/** RTS success count */
+	t_u32 rts_success;
+	/** RTS failure count */
+	t_u32 rts_failure;
+	/** Ack failure count */
+	t_u32 ack_failure;
+	/** Rx fragmentation count */
+	t_u32 rx_frag;
+	/** Multicast Tx frame count */
+	t_u32 mcast_rx_frame;
+	/** FCS error count */
+	t_u32 fcs_error;
+	/** Tx frame count */
+	t_u32 tx_frame;
+	/** WEP ICV error count */
+	t_u32 wep_icv_error[4];
+	/** beacon recv count */
+	t_u32 bcn_rcv_cnt;
+	/** beacon miss count */
+	t_u32 bcn_miss_cnt;
+	/** received amsdu count*/
+	t_u32 amsdu_rx_cnt;
+	/** received msdu count in amsdu*/
+	t_u32 msdu_in_rx_amsdu_cnt;
+	/** tx amsdu count*/
+	t_u32 amsdu_tx_cnt;
+	/** tx msdu count in amsdu*/
+	t_u32 msdu_in_tx_amsdu_cnt;
+} mlan_ds_get_stats_org;
+
+/** Type definition of mlan_ds_get_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_get_stats {
+	/** Statistics counter */
+	/** Multicast transmitted frame count */
+	t_u32 mcast_tx_frame;
+	/** Failure count */
+	t_u32 failed;
+	/** Retry count */
+	t_u32 retry;
+	/** Multi entry count */
+	t_u32 multi_retry;
+	/** Duplicate frame count */
+	t_u32 frame_dup;
+	/** RTS success count */
+	t_u32 rts_success;
+	/** RTS failure count */
+	t_u32 rts_failure;
+	/** Ack failure count */
+	t_u32 ack_failure;
+	/** Rx fragmentation count */
+	t_u32 rx_frag;
+	/** Multicast Tx frame count */
+	t_u32 mcast_rx_frame;
+	/** FCS error count */
+	t_u32 fcs_error;
+	/** Tx frame count */
+	t_u32 tx_frame;
+	/** WEP ICV error count */
+	t_u32 wep_icv_error[4];
+	/** beacon recv count */
+	t_u32 bcn_rcv_cnt;
+	/** beacon miss count */
+	t_u32 bcn_miss_cnt;
+	/** received amsdu count*/
+	t_u32 amsdu_rx_cnt;
+	/** received msdu count in amsdu*/
+	t_u32 msdu_in_rx_amsdu_cnt;
+	/** tx amsdu count*/
+	t_u32 amsdu_tx_cnt;
+	/** tx msdu count in amsdu*/
+	t_u32 msdu_in_tx_amsdu_cnt;
+
+	/** Tx frag count */
+	t_u32 tx_frag_cnt;
+	/** Qos Tx frag count */
+	t_u32 qos_tx_frag_cnt[8];
+	/** Qos failed count */
+	t_u32 qos_failed_cnt[8];
+	/** Qos retry count */
+	t_u32 qos_retry_cnt[8];
+	/** Qos multi retry count */
+	t_u32 qos_multi_retry_cnt[8];
+	/** Qos frame dup count */
+	t_u32 qos_frm_dup_cnt[8];
+	/** Qos rts success count */
+	t_u32 qos_rts_suc_cnt[8];
+	/** Qos rts failure count */
+	t_u32 qos_rts_failure_cnt[8];
+	/** Qos ack failure count */
+	t_u32 qos_ack_failure_cnt[8];
+	/** Qos Rx frag count */
+	t_u32 qos_rx_frag_cnt[8];
+	/** Qos Tx frame count */
+	t_u32 qos_tx_frm_cnt[8];
+	/** Qos discarded frame count */
+	t_u32 qos_discarded_frm_cnt[8];
+	/** Qos mpdus Rx count */
+	t_u32 qos_mpdus_rx_cnt[8];
+	/** Qos retry rx count */
+	t_u32 qos_retries_rx_cnt[8];
+	/** CMAC ICV errors count */
+	t_u32 cmacicv_errors;
+	/** CMAC replays count */
+	t_u32 cmac_replays;
+	/** mgmt CCMP replays count */
+	t_u32 mgmt_ccmp_replays;
+	/** TKIP ICV errors count */
+	t_u32 tkipicv_errors;
+	/** TKIP replays count */
+	t_u32 tkip_replays;
+	/** CCMP decrypt errors count */
+	t_u32 ccmp_decrypt_errors;
+	/** CCMP replays count */
+	t_u32 ccmp_replays;
+	/** Tx amsdu count */
+	t_u32 tx_amsdu_cnt;
+	/** failed amsdu count */
+	t_u32 failed_amsdu_cnt;
+	/** retry amsdu count */
+	t_u32 retry_amsdu_cnt;
+	/** multi-retry amsdu count */
+	t_u32 multi_retry_amsdu_cnt;
+	/** Tx octets in amsdu count */
+	t_u64 tx_octets_in_amsdu_cnt;
+	/** amsdu ack failure count */
+	t_u32 amsdu_ack_failure_cnt;
+	/** Rx amsdu count */
+	t_u32 rx_amsdu_cnt;
+	/** Rx octets in amsdu count */
+	t_u64 rx_octets_in_amsdu_cnt;
+	/** Tx ampdu count */
+	t_u32 tx_ampdu_cnt;
+	/** tx mpdus in ampdu count */
+	t_u32 tx_mpdus_in_ampdu_cnt;
+	/** tx octets in ampdu count */
+	t_u64 tx_octets_in_ampdu_cnt;
+	/** ampdu Rx count */
+	t_u32 ampdu_rx_cnt;
+	/** mpdu in Rx ampdu count */
+	t_u32 mpdu_in_rx_ampdu_cnt;
+	/** Rx octets ampdu count */
+	t_u64 rx_octets_in_ampdu_cnt;
+	/** ampdu delimiter CRC error count */
+	t_u32 ampdu_delimiter_crc_error_cnt;
+    /** Rx Stuck Related Info*/
+    /** Rx Stuck Issue count */
+	t_u32 rx_stuck_issue_cnt[2];
+    /** Rx Stuck Recovery count */
+	t_u32 rx_stuck_recovery_cnt;
+    /** Rx Stuck TSF */
+	t_u64 rx_stuck_tsf[2];
+    /** Tx Watchdog Recovery Related Info */
+    /** Tx Watchdog Recovery count */
+	t_u32 tx_watchdog_recovery_cnt;
+    /** Tx Watchdog TSF */
+	t_u64 tx_watchdog_tsf[2];
+    /** Channel Switch Related Info */
+    /** Channel Switch Announcement Sent */
+	t_u32 channel_switch_ann_sent;
+    /** Channel Switch State */
+	t_u32 channel_switch_state;
+    /** Register Class */
+	t_u32 reg_class;
+    /** Channel Number */
+	t_u32 channel_number;
+    /** Channel Switch Mode */
+	t_u32 channel_switch_mode;
+    /** Reset Rx Mac Count */
+	t_u32 rx_reset_mac_recovery_cnt;
+    /** ISR2 Not Done Count*/
+	t_u32 rx_Isr2_NotDone_Cnt;
+    /** GDMA Abort Count */
+	t_u32 gdma_abort_cnt;
+    /** Rx Reset MAC Count */
+	t_u32 g_reset_rx_mac_cnt;
+	//Ownership error counters
+	/*Error Ownership error count */
+	t_u32 dwCtlErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwBcnErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwMgtErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwDatErrCnt;
+	/*BIGTK MME good count */
+	t_u32 bigtk_mmeGoodCnt;
+	/*BIGTK Replay error count */
+	t_u32 bigtk_replayErrCnt;
+	/*BIGTK MIC error count */
+	t_u32 bigtk_micErrCnt;
+	/*BIGTK MME not included count */
+	t_u32 bigtk_mmeNotFoundCnt;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+	/** tkip mic failures */
+	t_u32 tkip_mic_failures;
+	/** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+	/** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+	/** wep icv error count */
+	t_u32 wep_icv_error_count;
+	/** decrypt failure count */
+	t_u32 decrypt_failure_count;
+	/** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+	/** dot11 failed count */
+	t_u32 failed_count;
+	/** dot11 retry count */
+	t_u32 retry_count;
+	/** dot11 multi retry count */
+	t_u32 multi_retry_count;
+	/** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+	/** dot11 rts success count */
+	t_u32 rts_success_count;
+	/** dot11 rts failure count */
+	t_u32 rts_failure_count;
+	/** dot11 ack failure count */
+	t_u32 ack_failure_count;
+	/** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+	/** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+	/** dot11 fcs error count */
+	t_u32 fcs_error_count;
+	/** dot11 tx frame count */
+	t_u32 tx_frame_count;
+	/** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+	/** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK 0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK 0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK 0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK 0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK 0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK 0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK 0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK 0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK 0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK 0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK 0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK 0x00000fff
+#define MAX_PATH_NUM 3
+/** path A */
+#define PATH_A 0x01
+/** path B */
+#define PATH_B 0x02
+/** path AB */
+#define PATH_AB 0x03
+/** ALL the path */
+#define PATH_ALL 0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+	/** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+	/** RSSI */
+	/** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+	/** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+	/** RSSI of last data packet */
+	t_s16 data_rssi_last;
+	/** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+	/** SNR */
+	/** SNR of last beacon */
+	t_s16 bcn_snr_last;
+	/** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+	/** SNR of last data packet */
+	t_s16 data_snr_last;
+	/** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+	/** NF */
+	/** NF of last beacon */
+	t_s16 bcn_nf_last;
+	/** NF of beacon average */
+	t_s16 bcn_nf_avg;
+	/** NF of last data packet */
+	t_s16 data_nf_last;
+	/** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+	/** Firmware version */
+	t_u32 fw_ver;
+	/** Firmware Hotfix version */
+	t_u8 hotfix_version;
+	/** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+	/** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+	/** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+	/** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+	/** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+	/** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+	/** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+	/** length of hw he capability */
+	t_u8 hw_hecap_len;
+	/** 802.11ax HE capability */
+	t_u8 hw_he_cap[54];
+	/** length of hw 2.4G he capability */
+	t_u8 hw_2g_hecap_len;
+	/** 802.11ax 2.4G HE capability */
+	t_u8 hw_2g_he_cap[54];
+	/** 802.11ac device support for MIMO abstraction of MCSs */
+	t_u32 hw_dot_11ac_mcs_support;
+	/** User conf 802.11ac device support for MIMO abstraction of MCSs */
+	t_u32 usr_dot_11ac_mcs_support;
+	/** fw supported band */
+	t_u16 fw_bands;
+	/** region code */
+	t_u16 region_code;
+	/** force_reg */
+	t_u8 force_reg;
+	/** ECSA support */
+	t_u8 ecsa_enable;
+	/** Get log support */
+	t_u8 getlog_enable;
+	/** FW support for embedded supplicant */
+	t_u8 fw_supplicant_support;
+	/** ant info */
+	t_u8 antinfo;
+	/** max AP associated sta count supported by fw */
+	t_u8 max_ap_assoc_sta;
+	/** Bandwidth not support 80Mhz */
+	t_u8 prohibit_80mhz;
+	/** FW support beacon protection */
+	t_u8 fw_beacon_prot;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN 128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+	/** Selected version string */
+	t_u32 version_str_sel;
+	/** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+	/** Extended Capabilities value */
+	t_u8 rsvdBit87:1;	/* bit 87 */
+	t_u8 rsvdBit86:1;	/* bit 86 */
+	t_u8 rsvdBit85:1;	/* bit 85 */
+	t_u8 beacon_prot:1;	/* bit 84 */
+	t_u8 rsvdBit83:1;	/* bit 83 */
+	t_u8 rsvdBit82:1;	/* bit 82 */
+	t_u8 rsvdBit81:1;	/* bit 81 */
+	t_u8 rsvdBit80:1;	/* bit 80 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 TWTResp:1;		/* bit 78 */
+	t_u8 TWTReq:1;		/* bit 77 */
+	t_u8 rsvdBit76:1;	/* bit 76 */
+	t_u8 rsvdBit75:1;	/* bit 75 */
+	t_u8 rsvdBit74:1;	/* bit 74 */
+	t_u8 rsvdBit73:1;	/* bit 73 */
+	t_u8 FILS:1;		/* bit 72 */
+	t_u8 FTMI:1;		/* bit 71 */
+	t_u8 FTMR:1;		/* bit 70 */
+	t_u8 CAQ:1;		/* bit 69 */
+	t_u8 rsvdBit68:1;	/* bit 68 */
+	t_u8 NCC:1;		/* bit 67 */
+	t_u8 rsvdBit66:1;	/* bit 66 */
+	t_u8 chanSchedMgnt:1;	/* bit 65 */
+	t_u8 MaxAMSDU1:1;	/* bit 64 */
+	t_u8 MaxAMSDU0:1;	/* bit 63 */
+	t_u8 OperModeNtf:1;	/* bit 62 */
+	t_u8 TDLSWildBandwidth:1;	/* bit 61 */
+	t_u8 rsvdBit60:1;	/* bit 60 */
+	t_u8 rsvdBit59:1;	/* bit 59 */
+	t_u8 rsvdBit58:1;	/* bit 58 */
+	t_u8 rsvdBit57:1;	/* bit 57 */
+	t_u8 rsvdBit56:1;	/* bit 56 */
+	t_u8 rsvdBit55:1;	/* bit 55 */
+	t_u8 rsvdBit54:1;	/* bit 54 */
+	t_u8 rsvdBit53:1;	/* bit 53 */
+	t_u8 rsvdBit52:1;	/* bit 52 */
+	t_u8 rsvdBit51:1;	/* bit 51 */
+	t_u8 rsvdBit50:1;	/* bit 50 */
+	t_u8 rsvdBit49:1;	/* bit 49 */
+	t_u8 rsvdBit48:1;	/* bit 48 */
+	t_u8 rsvdBit47:1;	/* bit 47 */
+	t_u8 rsvdBit46:1;	/* bit 46 */
+	t_u8 rsvdBit45:1;	/* bit 45 */
+	t_u8 rsvdBit44:1;	/* bit 44 */
+	t_u8 rsvdBit43:1;	/* bit 43 */
+	t_u8 rsvdBit42:1;	/* bit 42 */
+	t_u8 rsvdBit41:1;	/* bit 41 */
+	t_u8 rsvdBit40:1;	/* bit 40 */
+	t_u8 TDLSChlSwitchProhib:1;	/* bit 39 */
+	t_u8 TDLSProhibited:1;	/* bit 38 */
+	t_u8 TDLSSupport:1;	/* bit 37 */
+	t_u8 MSGCF_Capa:1;	/* bit 36 */
+	t_u8 Reserved35:1;	/* bit 35 */
+	t_u8 SSPN_Interface:1;	/* bit 34 */
+	t_u8 EBR:1;		/* bit 33 */
+	t_u8 Qos_Map:1;		/* bit 32 */
+	t_u8 Interworking:1;	/* bit 31 */
+	t_u8 TDLSChannelSwitching:1;	/* bit 30 */
+	t_u8 TDLSPeerPSMSupport:1;	/* bit 29 */
+	t_u8 TDLSPeerUAPSDSupport:1;	/* bit 28 */
+	t_u8 UTC:1;		/* bit 27 */
+	t_u8 DMS:1;		/* bit 26 */
+	t_u8 SSID_List:1;	/* bit 25 */
+	t_u8 ChannelUsage:1;	/* bit 24 */
+	t_u8 TimingMeasurement:1;	/* bit 23 */
+	t_u8 MultipleBSSID:1;	/* bit 22 */
+	t_u8 AC_StationCount:1;	/* bit 21 */
+	t_u8 QoSTrafficCap:1;	/* bit 20 */
+	t_u8 BSS_Transition:1;	/* bit 19 */
+	t_u8 TIM_Broadcast:1;	/* bit 18 */
+	t_u8 WNM_Sleep:1;	/* bit 17 */
+	t_u8 TFS:1;		/* bit 16 */
+	t_u8 GeospatialLocation:1;	/* bit 15 */
+	t_u8 CivicLocation:1;	/* bit 14 */
+	t_u8 CollocatedIntf:1;	/* bit 13 */
+	t_u8 ProxyARPService:1;	/* bit 12 */
+	t_u8 FMS:1;		/* bit 11 */
+	t_u8 LocationTracking:1;	/* bit 10 */
+	t_u8 MulticastDiagnostics:1;	/* bit 9  */
+	t_u8 Diagnostics:1;	/* bit 8  */
+	t_u8 Event:1;		/* bit 7  */
+	t_u8 SPSMP_Support:1;	/* bit 6 */
+	t_u8 Reserved5:1;	/* bit 5 */
+	t_u8 PSMP_Capable:1;	/* bit 4 */
+	t_u8 RejectUnadmFrame:1;	/* bit 3 */
+	t_u8 ExtChanSwitching:1;	/* bit 2 */
+	t_u8 Reserved1:1;	/* bit 1 */
+	t_u8 BSS_CoexistSupport:1;	/* bit 0 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#else
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+	/** Extended Capabilities value */
+	t_u8 BSS_CoexistSupport:1;	/* bit 0 */
+	t_u8 Reserved1:1;	/* bit 1 */
+	t_u8 ExtChanSwitching:1;	/* bit 2 */
+	t_u8 RejectUnadmFrame:1;	/* bit 3 */
+	t_u8 PSMP_Capable:1;	/* bit 4 */
+	t_u8 Reserved5:1;	/* bit 5 */
+	t_u8 SPSMP_Support:1;	/* bit 6 */
+	t_u8 Event:1;		/* bit 7  */
+	t_u8 Diagnostics:1;	/* bit 8  */
+	t_u8 MulticastDiagnostics:1;	/* bit 9  */
+	t_u8 LocationTracking:1;	/* bit 10 */
+	t_u8 FMS:1;		/* bit 11 */
+	t_u8 ProxyARPService:1;	/* bit 12 */
+	t_u8 CollocatedIntf:1;	/* bit 13 */
+	t_u8 CivicLocation:1;	/* bit 14 */
+	t_u8 GeospatialLocation:1;	/* bit 15 */
+	t_u8 TFS:1;		/* bit 16 */
+	t_u8 WNM_Sleep:1;	/* bit 17 */
+	t_u8 TIM_Broadcast:1;	/* bit 18 */
+	t_u8 BSS_Transition:1;	/* bit 19 */
+	t_u8 QoSTrafficCap:1;	/* bit 20 */
+	t_u8 AC_StationCount:1;	/* bit 21 */
+	t_u8 MultipleBSSID:1;	/* bit 22 */
+	t_u8 TimingMeasurement:1;	/* bit 23 */
+	t_u8 ChannelUsage:1;	/* bit 24 */
+	t_u8 SSID_List:1;	/* bit 25 */
+	t_u8 DMS:1;		/* bit 26 */
+	t_u8 UTC:1;		/* bit 27 */
+	t_u8 TDLSPeerUAPSDSupport:1;	/* bit 28 */
+	t_u8 TDLSPeerPSMSupport:1;	/* bit 29 */
+	t_u8 TDLSChannelSwitching:1;	/* bit 30 */
+	t_u8 Interworking:1;	/* bit 31 */
+	t_u8 Qos_Map:1;		/* bit 32 */
+	t_u8 EBR:1;		/* bit 33 */
+	t_u8 SSPN_Interface:1;	/* bit 34 */
+	t_u8 Reserved35:1;	/* bit 35 */
+	t_u8 MSGCF_Capa:1;	/* bit 36 */
+	t_u8 TDLSSupport:1;	/* bit 37 */
+	t_u8 TDLSProhibited:1;	/* bit 38 */
+	t_u8 TDLSChlSwitchProhib:1;	/* bit 39 */
+	t_u8 rsvdBit40:1;	/* bit 40 */
+	t_u8 rsvdBit41:1;	/* bit 41 */
+	t_u8 rsvdBit42:1;	/* bit 42 */
+	t_u8 rsvdBit43:1;	/* bit 43 */
+	t_u8 rsvdBit44:1;	/* bit 44 */
+	t_u8 rsvdBit45:1;	/* bit 45 */
+	t_u8 rsvdBit46:1;	/* bit 46 */
+	t_u8 rsvdBit47:1;	/* bit 47 */
+	t_u8 rsvdBit48:1;	/* bit 48 */
+	t_u8 rsvdBit49:1;	/* bit 49 */
+	t_u8 rsvdBit50:1;	/* bit 50 */
+	t_u8 rsvdBit51:1;	/* bit 51 */
+	t_u8 rsvdBit52:1;	/* bit 52 */
+	t_u8 rsvdBit53:1;	/* bit 53 */
+	t_u8 rsvdBit54:1;	/* bit 54 */
+	t_u8 rsvdBit55:1;	/* bit 55 */
+	t_u8 rsvdBit56:1;	/* bit 56 */
+	t_u8 rsvdBit57:1;	/* bit 57 */
+	t_u8 rsvdBit58:1;	/* bit 58 */
+	t_u8 rsvdBit59:1;	/* bit 59 */
+	t_u8 rsvdBit60:1;	/* bit 60 */
+	t_u8 TDLSWildBandwidth:1;	/* bit 61 */
+	t_u8 OperModeNtf:1;	/* bit 62 */
+	t_u8 MaxAMSDU0:1;	/* bit 63 */
+	t_u8 MaxAMSDU1:1;	/* bit 64 */
+	t_u8 chanSchedMgnt:1;	/* bit 65 */
+	t_u8 rsvdBit66:1;	/* bit 66 */
+	t_u8 NCC:1;		/* bit 67 */
+	t_u8 rsvdBit68:1;	/* bit 68 */
+	t_u8 CAQ:1;		/* bit 69 */
+	t_u8 FTMR:1;		/* bit 70 */
+	t_u8 FTMI:1;		/* bit 71 */
+	t_u8 FILS:1;		/* bit 72 */
+	t_u8 rsvdBit73:1;	/* bit 73 */
+	t_u8 rsvdBit74:1;	/* bit 74 */
+	t_u8 rsvdBit75:1;	/* bit 75 */
+	t_u8 rsvdBit76:1;	/* bit 76 */
+	t_u8 TWTReq:1;		/* bit 77 */
+	t_u8 TWTResp:1;		/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit80:1;	/* bit 80 */
+	t_u8 rsvdBit81:1;	/* bit 81 */
+	t_u8 rsvdBit82:1;	/* bit 82 */
+	t_u8 rsvdBit83:1;	/* bit 83 */
+	t_u8 beacon_prot:1;	/* bit 84 */
+	t_u8 rsvdBit85:1;	/* bit 85 */
+	t_u8 rsvdBit86:1;	/* bit 86 */
+	t_u8 rsvdBit87:1;	/* bit 87 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+	/** BSS mode */
+	t_u32 bss_mode;
+	/** SSID */
+	mlan_802_11_ssid ssid;
+	/** Table index */
+	t_u32 scan_table_idx;
+	/** Channel */
+	t_u32 bss_chan;
+	/** Band */
+	t_u8 bss_band;
+	/** Region code */
+	t_u32 region_code;
+	/** Connection status */
+	t_u32 media_connected;
+	/** Radio on */
+	t_u32 radio_on;
+	/** Max power level in dBm */
+	t_s32 max_power_level;
+	/** Min power level in dBm */
+	t_s32 min_power_level;
+	/** Adhoc state */
+	t_u32 adhoc_state;
+	/** NF of last beacon */
+	t_s32 bcn_nf_last;
+	/** wep status */
+	t_u32 wep_status;
+	/** scan block status */
+	t_u8 scan_block;
+	/** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+	/** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+	/** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+	/** Capability Info */
+	t_u16 capability_info;
+	/** Beacon Interval */
+	t_u16 beacon_interval;
+	/** Listen Interval */
+	t_u16 listen_interval;
+	/** Association Id  */
+	t_u16 assoc_id;
+	/** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+	/** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+	/** Mobility Domain ID */
+	t_u16 mdid;
+	/** FT Capability policy */
+	t_u8 ft_cap;
+	/** 11h active */
+	t_bool is_11h_active;
+	/** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID 8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE 64
+
+/** rx_reorder_tbl */
+typedef struct {
+	/** TID */
+	t_u16 tid;
+	/** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+	/** Start window */
+	t_u32 start_win;
+	/** Window size */
+	t_u32 win_size;
+	/** amsdu flag */
+	t_u8 amsdu;
+	/** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+	/** TID */
+	t_u16 tid;
+	/** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	/** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM 10
+
+#ifdef SDIO
+/** sdio mp debug number */
+#define SDIO_MP_DBG_NUM 10
+#endif
+
+/** Maximum size of IEEE Information Elements */
+#define IEEE_MAX_IE_SIZE 256
+
+/** support up to 8 TDLS peer */
+#define MLAN_MAX_TDLS_PEER_SUPPORTED 8
+/** TDLS peer info */
+typedef struct _tdls_peer_info {
+	/** station mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** SNR */
+	t_s8 snr;
+	/** Noise Floor */
+	t_s8 nf;
+	/** Extended Capabilities IE */
+	t_u8 ext_cap[IEEE_MAX_IE_SIZE];
+	/** HT Capabilities IE */
+	t_u8 ht_cap[IEEE_MAX_IE_SIZE];
+	/** VHT Capabilities IE */
+	t_u8 vht_cap[IEEE_MAX_IE_SIZE];
+} tdls_peer_info;
+
+/** max ralist num */
+#define MLAN_MAX_RALIST_NUM 8
+/** ralist info */
+typedef struct _ralist_info {
+	/** RA list buffer */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	/** total packets in RA list */
+	t_u16 total_pkts;
+	/** tid num */
+	t_u8 tid;
+	/** tx_pause flag */
+	t_u8 tx_pause;
+} ralist_info, *pralist_info;
+
+/** mlan_debug_info data structure for MLAN_OID_GET_DEBUG_INFO */
+typedef struct _mlan_debug_info {
+	/* WMM AC_BK count */
+	t_u32 wmm_ac_bk;
+	/* WMM AC_BE count */
+	t_u32 wmm_ac_be;
+	/* WMM AC_VI count */
+	t_u32 wmm_ac_vi;
+	/* WMM AC_VO count */
+	t_u32 wmm_ac_vo;
+	/** Corresponds to max_tx_buf_size member of mlan_adapter*/
+	t_u32 max_tx_buf_size;
+	/** Corresponds to tx_buf_size member of mlan_adapter*/
+	t_u32 tx_buf_size;
+	/** Corresponds to curr_tx_buf_size member of mlan_adapter*/
+	t_u32 curr_tx_buf_size;
+	/** Tx table num */
+	t_u32 tx_tbl_num;
+	/** Tx ba stream table */
+	tx_ba_stream_tbl tx_tbl[MLAN_MAX_TX_BASTREAM_SUPPORTED];
+	/** Rx table num */
+	t_u32 rx_tbl_num;
+	/** Rx reorder table*/
+	rx_reorder_tbl rx_tbl[MLAN_MAX_RX_BASTREAM_SUPPORTED];
+	/** TDLS peer number */
+	t_u32 tdls_peer_num;
+	/** TDLS peer list*/
+	tdls_peer_info tdls_peer_list[MLAN_MAX_TDLS_PEER_SUPPORTED];
+	/** ralist num */
+	t_u32 ralist_num;
+	/** ralist info */
+	ralist_info ralist[MLAN_MAX_RALIST_NUM];
+	/** Corresponds to ps_mode member of mlan_adapter */
+	t_u16 ps_mode;
+	/** Corresponds to ps_state member of mlan_adapter */
+	t_u32 ps_state;
+#ifdef STA_SUPPORT
+	/** Corresponds to is_deep_sleep member of mlan_adapter */
+	t_u8 is_deep_sleep;
+#endif /** STA_SUPPORT */
+	/** Corresponds to pm_wakeup_card_req member of mlan_adapter */
+	t_u8 pm_wakeup_card_req;
+	/** Corresponds to pm_wakeup_fw_try member of mlan_adapter */
+	t_u32 pm_wakeup_fw_try;
+	/** time stamp when host try to wake up firmware */
+	t_u32 pm_wakeup_in_secs;
+	/** wake up timeout happened */
+	t_u32 pm_wakeup_timeout;
+	/** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+	/** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+	/** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+	/** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+	/** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+	/** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+	/** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+	/** bypass pkt count */
+	t_u32 bypass_pkt_count;
+	/** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+	/** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+	/** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+	/** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+	/** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+	/** rx pkts queued */
+	t_u32 rx_pkts_queued;
+	/** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+	/** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+	/** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+	/** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+#ifdef SDIO
+	/** Number of card to host command/event failures */
+	t_u32 num_cmdevt_card_to_host_failure;
+	/** Number of card to host Rx failures */
+	t_u32 num_rx_card_to_host_failure;
+	/** Number of interrupt read failures */
+	t_u32 num_int_read_failure;
+	/** Last interrupt status */
+	t_u32 last_int_status;
+	/** number of interrupt receive */
+	t_u32 num_of_irq;
+	/** flag for sdio rx aggr */
+	t_u8 sdio_rx_aggr;
+	/** FW update port number */
+	t_u32 mp_update[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX * 2];
+	/** Invalid port update count */
+	t_u32 mp_invalid_update;
+	/** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+	/** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last recv rd_bitmap */
+	t_u32 last_recv_rd_bitmap;
+    /** mp_data_port_mask */
+	t_u32 mp_data_port_mask;
+	/** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+	/** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+	/** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+	/** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** last mp_index */
+	t_u8 last_mp_index;
+	/** buffer for mp debug */
+	t_u8 *mpa_buf;
+	/** length info for mp buf size */
+	t_u32 mpa_buf_size;
+	/** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** mp aggr_pkt limit */
+	t_u8 mp_aggr_pkt_limit;
+#endif
+	/** Number of deauthentication events */
+	t_u32 num_event_deauth;
+	/** Number of disassosiation events */
+	t_u32 num_event_disassoc;
+	/** Number of link lost events */
+	t_u32 num_event_link_lost;
+	/** Number of deauthentication commands */
+	t_u32 num_cmd_deauth;
+	/** Number of association comamnd successes */
+	t_u32 num_cmd_assoc_success;
+	/** Number of association command failures */
+	t_u32 num_cmd_assoc_failure;
+	/** Number of consecutive association failures */
+	t_u32 num_cons_assoc_failure;
+
+	/** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+	/** Timeout command ID */
+	t_u16 timeout_cmd_id;
+	/** Timeout command action */
+	t_u16 timeout_cmd_act;
+	/** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+	/** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+	/** Last command index */
+	t_u16 last_cmd_index;
+	/** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+	/** Last command response index */
+	t_u16 last_cmd_resp_index;
+	/** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+	/** Last event index */
+	t_u16 last_event_index;
+	/** Number of no free command node */
+	t_u16 num_no_cmd_node;
+	/** pending command id */
+	t_u16 pending_cmd;
+	/** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+	/** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+	/** Corresponds to data_sent_cnt member of mlan_adapter */
+	t_u32 data_sent_cnt;
+	/** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+	/** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+	/** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+	/** Current available port for read */
+	t_u8 curr_rd_port;
+	/** Current available port for write */
+	t_u8 curr_wr_port;
+#ifdef PCIE
+	/** PCIE txbd read pointer */
+	t_u32 txbd_rdptr;
+	/** PCIE txbd write pointer */
+	t_u32 txbd_wrptr;
+	/** PCIE rxbd read pointer */
+	t_u32 rxbd_rdptr;
+	/** PCIE rxbd write pointer */
+	t_u32 rxbd_wrptr;
+	/** PCIE eventbd read pointer */
+	t_u32 eventbd_rdptr;
+	/** PCIE eventbd write pointer */
+	t_u32 eventbd_wrptr;
+	/** txrx_bd_size */
+	t_u16 txrx_bd_size;
+	/** txbd ring vbase */
+	t_u8 *txbd_ring_vbase;
+	/** txbd ring size */
+	t_u32 txbd_ring_size;
+	/** rxbd ring vbase */
+	t_u8 *rxbd_ring_vbase;
+	/** rxbd ring size */
+	t_u32 rxbd_ring_size;
+	/** evtbd ring vbase */
+	t_u8 *evtbd_ring_vbase;
+	/** evtbd ring size */
+	t_u32 evtbd_ring_size;
+#endif
+	/** Corresponds to cmdresp_received member of mlan_adapter */
+	t_u8 cmd_resp_received;
+	/** Corresponds to event_received member of mlan_adapter */
+	t_u8 event_received;
+	/**  pendig tx pkts */
+	t_u32 tx_pkts_queued;
+#ifdef UAP_SUPPORT
+	/**  pending bridge pkts */
+	t_u16 num_bridge_pkts;
+	/**  dropped pkts */
+	t_u32 num_drop_pkts;
+#endif
+	/** FW hang report */
+	t_u8 fw_hang_report;
+	/** mlan_adapter pointer */
+	t_void *mlan_adapter;
+	/** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+	/** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+	/** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+	/** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info_data {
+	/** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+	/** Power mgmt status */
+	t_u8 power_mgmt_status;
+	/** RSSI */
+	t_s8 rssi;
+	/** station bandmode */
+	t_u16 bandmode;
+	/** station stats */
+	sta_stats stats;
+	/** ie length */
+	t_u16 ie_len;
+} sta_info_data;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+	/** station count */
+	t_u16 sta_count;
+	/** station list */
+	sta_info_data info[MAX_NUM_CLIENTS];
+	/* ie_buf will be append at the end */
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+	/** Sub-command */
+	t_u32 sub_command;
+
+	/** Status information parameter */
+	union {
+		/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+		/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+		/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+		/** Statistics information for MLAN_OID_LINK_STATS*/
+		t_u8 link_statistic[1];
+		/** Firmware information for MLAN_OID_GET_FW_INFO */
+		mlan_fw_info fw_info;
+		/** Extended version information for MLAN_OID_GET_VER_EXT */
+		mlan_ver_ext ver_ext;
+		/** BSS information for MLAN_OID_GET_BSS_INFO */
+		mlan_bss_info bss_info;
+		/** Debug information for MLAN_OID_GET_DEBUG_INFO */
+		t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+		/** UAP Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_uap_stats ustats;
+		/** UAP station list for MLAN_OID_UAP_STA_LIST */
+		mlan_ds_sta_list sta_list;
+#endif
+	} param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+	MLAN_AUTH_MODE_OPEN = 0x00,
+	MLAN_AUTH_MODE_SHARED = 0x01,
+	MLAN_AUTH_MODE_FT = 0x02,
+	MLAN_AUTH_MODE_SAE = 0x03,
+	MLAN_AUTH_MODE_NETWORKEAP = 0x80,
+	MLAN_AUTH_MODE_AUTO = 0xFF,
+};
+
+/**Enumeration for AssocAgent authentication mode, sync from FW.*/
+typedef enum {
+	AssocAgentAuth_Open,
+	AssocAgentAuth_Shared,
+	AssocAgentAuth_FastBss,
+	AssocAgentAuth_FastBss_Skip,
+	AssocAgentAuth_Network_EAP,
+	AssocAgentAuth_Wpa3Sae = 6,
+	AssocAgentAuth_Auto,
+} AssocAgentAuthType_e;
+
+/** Enumeration for encryption mode */
+enum _mlan_encryption_mode {
+	MLAN_ENCRYPTION_MODE_NONE = 0,
+	MLAN_ENCRYPTION_MODE_WEP40 = 1,
+	MLAN_ENCRYPTION_MODE_TKIP = 2,
+	MLAN_ENCRYPTION_MODE_CCMP = 3,
+	MLAN_ENCRYPTION_MODE_WEP104 = 4,
+	MLAN_ENCRYPTION_MODE_GCMP = 5,
+	MLAN_ENCRYPTION_MODE_GCMP_256 = 6,
+	MLAN_ENCRYPTION_MODE_CCMP_256 = 7,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+	MLAN_PSK_PASSPHRASE = 1,
+	MLAN_PSK_PMK,
+	MLAN_PSK_CLEAR,
+	MLAN_PSK_QUERY,
+	MLAN_PSK_SAE_PASSWORD,
+};
+
+/** The bit to indicate the key is for unicast */
+#define MLAN_KEY_INDEX_UNICAST 0x40000000
+/** The key index to indicate default key */
+#define MLAN_KEY_INDEX_DEFAULT 0x000000ff
+/** Maximum key length */
+/* #define MLAN_MAX_KEY_LENGTH        32 */
+/** Minimum passphrase length */
+#define MLAN_MIN_PASSPHRASE_LENGTH 8
+/** Maximum passphrase length */
+#define MLAN_MAX_PASSPHRASE_LENGTH 63
+/** Minimum sae_password length */
+#define MLAN_MIN_SAE_PASSWORD_LENGTH 8
+/** Maximum sae_password length */
+#define MLAN_MAX_SAE_PASSWORD_LENGTH 255
+/** PMK length */
+#define MLAN_PMK_HEXSTR_LENGTH 64
+/* A few details needed for WEP (Wireless Equivalent Privacy) */
+/** 104 bits */
+#define MAX_WEP_KEY_SIZE 13
+/** 40 bits RC4 - WEP */
+#define MIN_WEP_KEY_SIZE 5
+/** packet number size */
+#define PN_SIZE 16
+/** max seq size of wpa/wpa2 key */
+#define SEQ_MAX_SIZE 8
+
+/** key flag for tx_seq */
+#define KEY_FLAG_TX_SEQ_VALID 0x00000001
+/** key flag for rx_seq */
+#define KEY_FLAG_RX_SEQ_VALID 0x00000002
+/** key flag for group key */
+#define KEY_FLAG_GROUP_KEY 0x00000004
+/** key flag for tx */
+#define KEY_FLAG_SET_TX_KEY 0x00000008
+/** key flag for mcast IGTK */
+#define KEY_FLAG_AES_MCAST_IGTK 0x00000010
+/** key flag for remove key */
+#define KEY_FLAG_REMOVE_KEY 0x80000000
+/** key flag for GCMP */
+#define KEY_FLAG_GCMP 0x00000020
+/** key flag for GCMP_256 */
+#define KEY_FLAG_GCMP_256 0x00000040
+/** key flag for ccmp 256 */
+#define KEY_FLAG_CCMP_256 0x00000080
+/** key flag for GMAC_128 */
+#define KEY_FLAG_GMAC_128 0x00000100
+/** key flag for GMAC_256 */
+#define KEY_FLAG_GMAC_256 0x00000200
+
+/** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+typedef struct _mlan_ds_encrypt_key {
+	/** Key disabled, all other fields will be
+	 *  ignore when this flag set to MTRUE
+	 */
+	t_u32 key_disable;
+	/** key removed flag, when this flag is set
+	 *  to MTRUE, only key_index will be check
+	 */
+	t_u32 key_remove;
+	/** Key index, used as current tx key index
+	 *  when is_current_wep_key is set to MTRUE
+	 */
+	t_u32 key_index;
+	/** Current Tx key flag */
+	t_u32 is_current_wep_key;
+	/** Key length */
+	t_u32 key_len;
+	/** Key */
+	t_u8 key_material[MLAN_MAX_KEY_LENGTH];
+	/** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** wapi key flag */
+	t_u32 is_wapi_key;
+	/** Initial packet number */
+	t_u8 pn[PN_SIZE];
+	/** key flags */
+	t_u32 key_flags;
+} mlan_ds_encrypt_key, *pmlan_ds_encrypt_key;
+
+/** Type definition of mlan_passphrase_t */
+typedef struct _mlan_passphrase_t {
+	/** Length of passphrase */
+	t_u32 passphrase_len;
+	/** Passphrase */
+	t_u8 passphrase[MLAN_MAX_PASSPHRASE_LENGTH];
+} mlan_passphrase_t;
+
+/** Type definition of mlan_sae_password_t */
+typedef struct _mlan_sae_password_t {
+	/** Length of SAE Password */
+	t_u32 sae_password_len;
+	/** SAE Password */
+	t_u8 sae_password[MLAN_MAX_SAE_PASSWORD_LENGTH];
+} mlan_sae_password_t;
+
+/** Type defnition of mlan_pmk_t */
+typedef struct _mlan_pmk_t {
+	/** PMK */
+	t_u8 pmk[MLAN_MAX_KEY_LENGTH];
+} mlan_pmk_t;
+
+/** Embedded supplicant RSN type: No RSN */
+#define RSN_TYPE_NO_RSN MBIT(0)
+/** Embedded supplicant RSN type: WPA */
+#define RSN_TYPE_WPA MBIT(3)
+/** Embedded supplicant RSN type: WPA-NONE */
+#define RSN_TYPE_WPANONE MBIT(4)
+/** Embedded supplicant RSN type: WPA2 */
+#define RSN_TYPE_WPA2 MBIT(5)
+/** Embedded supplicant RSN type: RFU */
+#define RSN_TYPE_VALID_BITS                                                    \
+	(RSN_TYPE_NO_RSN | RSN_TYPE_WPA | RSN_TYPE_WPANONE | RSN_TYPE_WPA2)
+
+/** Embedded supplicant cipher type: TKIP */
+#define EMBED_CIPHER_TKIP MBIT(2)
+/** Embedded supplicant cipher type: AES */
+#define EMBED_CIPHER_AES MBIT(3)
+/** Embedded supplicant cipher type: RFU */
+#define EMBED_CIPHER_VALID_BITS (EMBED_CIPHER_TKIP | EMBED_CIPHER_AES)
+
+/** Type definition of mlan_ds_passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */
+typedef struct _mlan_ds_passphrase {
+	/** SSID may be used */
+	mlan_802_11_ssid ssid;
+	/** BSSID may be used */
+	mlan_802_11_mac_addr bssid;
+	/** Flag for passphrase or pmk used */
+	t_u16 psk_type;
+	/** Passphrase or PMK */
+	union {
+		/** Passphrase */
+		mlan_passphrase_t passphrase;
+		/** SAE Password */
+		mlan_sae_password_t sae_password;
+		/** PMK */
+		mlan_pmk_t pmk;
+	} psk;
+} mlan_ds_passphrase, *pmlan_ds_passphrase;
+
+/** Type definition of mlan_ds_esupp_mode for MLAN_OID_SEC_CFG_ESUPP_MODE */
+typedef struct _mlan_ds_ewpa_mode {
+	/** RSN mode */
+	t_u32 rsn_mode;
+	/** Active pairwise cipher */
+	t_u32 act_paircipher;
+	/** Active pairwise cipher */
+	t_u32 act_groupcipher;
+} mlan_ds_esupp_mode, *pmlan_ds_esupp_mode;
+
+/** Type definition of mlan_ds_sec_cfg for MLAN_IOCTL_SEC_CFG */
+typedef struct _mlan_ds_sec_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Security configuration parameter */
+	union {
+		/** Authentication mode for MLAN_OID_SEC_CFG_AUTH_MODE */
+		t_u32 auth_mode;
+		/** Encryption mode for MLAN_OID_SEC_CFG_ENCRYPT_MODE */
+		t_u32 encrypt_mode;
+		/** WPA enabled flag for MLAN_OID_SEC_CFG_WPA_ENABLED */
+		t_u32 wpa_enabled;
+		/** WAPI enabled flag for MLAN_OID_SEC_CFG_WAPI_ENABLED */
+		t_u32 wapi_enabled;
+		/** Port Control enabled flag for MLAN_OID_SEC_CFG_PORT_CTRL */
+		t_u32 port_ctrl_enabled;
+		/** Encryption key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+		mlan_ds_encrypt_key encrypt_key;
+		/** Passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */
+		mlan_ds_passphrase passphrase;
+		/** Embedded supplicant WPA enabled flag for
+		 *  MLAN_OID_SEC_CFG_EWPA_ENABLED
+		 */
+		t_u32 ewpa_enabled;
+		/** Embedded supplicant mode for MLAN_OID_SEC_CFG_ESUPP_MODE */
+		mlan_ds_esupp_mode esupp_mode;
+#ifdef UAP_SUPPORT
+		t_u8 sta_mac[MLAN_MAC_ADDR_LENGTH];
+#endif
+	} param;
+} mlan_ds_sec_cfg, *pmlan_ds_sec_cfg;
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#define BIT_TLV_TYPE_CRYPTO_KEY (1 << 0)
+#define BIT_TLV_TYPE_CRYPTO_KEY_IV (1 << 1)
+#define BIT_TLV_TYPE_CRYPTO_KEY_PREFIX (1 << 2)
+#define BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK (1 << 3)
+
+/** Type definition of mlan_ds_sup_cfg */
+typedef struct _mlan_ds_sup_cfg {
+	/** Sub-command */
+	t_u8 sub_command;
+	/** output length */
+	t_u16 output_len;
+	/** number of data blks */
+	t_u16 data_blks_nr;
+	/** sub action code */
+	t_u8 sub_action_code;
+	/** skip bytes */
+	t_u16 skip_bytes;
+	/** iteration */
+	t_u32 iteration;
+	/** count */
+	t_u32 count;
+	/** pointer to output */
+	t_u8 *output;
+	/** key length  */
+	t_u16 key_len;
+	/** pointer to key */
+	t_u8 *key;
+	/** key iv length  */
+	t_u16 key_iv_len;
+	/** pointer to key iv */
+	t_u8 *key_iv;
+	/** key prefix length */
+	t_u16 key_prefix_len;
+	/** pointer to key prefix */
+	t_u8 *key_prefix;
+	/** pointer to data blk length array */
+	t_u32 *key_data_blk_len;
+	/** pointer to key data blk pointer array */
+	t_u8 **key_data_blk;
+	/** callback */
+	t_u8 call_back;
+} mlan_ds_sup_cfg, *pmlan_ds_sup_cfg;
+#endif
+
+/*-----------------------------------------------------------------*/
+/** Rate Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for rate type */
+enum _mlan_rate_type { MLAN_RATE_INDEX, MLAN_RATE_VALUE, MLAN_RATE_BITMAP };
+
+/** Enumeration for rate format */
+enum _mlan_rate_format {
+	MLAN_RATE_FORMAT_LG = 0,
+	MLAN_RATE_FORMAT_HT,
+	MLAN_RATE_FORMAT_VHT,
+	MLAN_RATE_FORMAT_HE,
+	MLAN_RATE_FORMAT_AUTO = 0xFF,
+};
+
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE 26
+
+/** Type definition of mlan_rate_cfg_t for MLAN_OID_RATE_CFG */
+typedef struct _mlan_rate_cfg_t {
+	/** Fixed rate: 0, auto rate: 1 */
+	t_u32 is_rate_auto;
+	/** Rate type. 0: index; 1: value; 2: bitmap */
+	t_u32 rate_type;
+	/** Rate/MCS index or rate value if fixed rate */
+	t_u32 rate;
+	/** Rate Bitmap */
+	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+	/** NSS */
+	t_u32 nss;
+	/* LG rate: 0, HT rate: 1, VHT rate: 2 */
+	t_u32 rate_format;
+	/** Rate Setting */
+	t_u16 rate_setting;
+} mlan_rate_cfg_t;
+
+/** HT channel bandwidth */
+typedef enum _mlan_ht_bw {
+	MLAN_HT_BW20,
+	MLAN_HT_BW40,
+	/** VHT channel bandwidth */
+	MLAN_VHT_BW80,
+	MLAN_VHT_BW160,
+} mlan_ht_bw;
+
+/** HT guard interval */
+typedef enum _mlan_ht_gi {
+	MLAN_HT_LGI,
+	MLAN_HT_SGI,
+} mlan_ht_gi;
+
+typedef enum _mlan_vht_stbc {
+	MLAN_VHT_STBC,
+	MLAN_VHT_NO_STBC,
+} mlan_vht_stbc;
+
+typedef enum _mlan_vht_ldpc {
+	MLAN_VHT_LDPC,
+	MLAN_VHT_NO_LDPC,
+} mlan_vht_ldpc;
+
+/** Band and BSS mode */
+typedef struct _mlan_band_data_rate {
+	/** Band configuration */
+	t_u8 config_bands;
+	/** BSS mode (Infra or IBSS) */
+	t_u8 bss_mode;
+} mlan_band_data_rate;
+
+/** Type definition of mlan_data_rate for MLAN_OID_GET_DATA_RATE */
+typedef struct _mlan_data_rate {
+	/** Tx data rate */
+	t_u32 tx_data_rate;
+	/** Rx data rate */
+	t_u32 rx_data_rate;
+
+	/** Tx channel bandwidth */
+	t_u32 tx_ht_bw;
+	/** Tx guard interval */
+	t_u32 tx_ht_gi;
+	/** Rx channel bandwidth */
+	t_u32 rx_ht_bw;
+	/** Rx guard interval */
+	t_u32 rx_ht_gi;
+	/** MCS index */
+	t_u32 tx_mcs_index;
+	t_u32 rx_mcs_index;
+	/** NSS */
+	t_u32 tx_nss;
+	t_u32 rx_nss;
+	/* LG rate: 0, HT rate: 1, VHT rate: 2 */
+	t_u32 tx_rate_format;
+	t_u32 rx_rate_format;
+} mlan_data_rate;
+
+/** Type definition of mlan_ds_rate for MLAN_IOCTL_RATE */
+typedef struct _mlan_ds_rate {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Rate configuration parameter */
+	union {
+		/** Rate configuration for MLAN_OID_RATE_CFG */
+		mlan_rate_cfg_t rate_cfg;
+		/** Data rate for MLAN_OID_GET_DATA_RATE */
+		mlan_data_rate data_rate;
+		/** Supported rates for MLAN_OID_SUPPORTED_RATES */
+		t_u8 rates[MLAN_SUPPORTED_RATES];
+		/** Band/BSS mode for getting supported rates */
+		mlan_band_data_rate rate_band_cfg;
+	} param;
+} mlan_ds_rate, *pmlan_ds_rate;
+
+/*-----------------------------------------------------------------*/
+/** Power Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** Type definition of mlan_power_cfg_t for MLAN_OID_POWER_CFG */
+typedef struct _mlan_power_cfg_t {
+	/** Is power auto */
+	t_u32 is_power_auto;
+	/** Power level in dBm */
+	t_s32 power_level;
+} mlan_power_cfg_t;
+
+/** max power table size */
+#define MAX_POWER_TABLE_SIZE 128
+#define TX_PWR_CFG_AUTO_CTRL_OFF 0xFF
+#define MAX_POWER_GROUP 64
+/** Type definition of mlan_power group info */
+typedef struct mlan_power_group {
+	/** rate format (LG: 0, HT: 1, VHT: 2, no auto ctrl: 0xFF) */
+	t_u32 rate_format;
+	/** bandwidth (LG: 20 MHz, HT: 20/40 MHz, VHT: 80/160/80+80 MHz) */
+	t_u8 bandwidth;
+	/** NSS */
+	t_u32 nss;
+	/** LG: first rate index, HT/VHT: first MCS */
+	t_u8 first_rate_ind;
+	/** LG: last rate index, HT/VHT: last MCS */
+	t_u8 last_rate_ind;
+	/** minmum tx power (dBm) */
+	t_s8 power_min;
+	/** maximum tx power (dBm) */
+	t_s8 power_max;
+	/** tx power step (dB) */
+	t_s8 power_step;
+} mlan_power_group;
+
+/** Type definition of mlan_power_cfg_ext for MLAN_OID_POWER_CFG_EXT */
+typedef struct _mlan_power_cfg_ext {
+	/** number of power_groups */
+	t_u32 num_pwr_grp;
+	/** array of power groups */
+	mlan_power_group power_group[MAX_POWER_GROUP];
+} mlan_power_cfg_ext;
+
+/** Type definition of mlan_ds_power_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_power_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Power configuration parameter */
+	union {
+		/** Power configuration for MLAN_OID_POWER_CFG */
+		mlan_power_cfg_t power_cfg;
+		/** Extended power configuration for MLAN_OID_POWER_CFG_EXT */
+		mlan_power_cfg_ext power_ext;
+		/** Low power mode for MLAN_OID_POWER_LOW_POWER_MODE */
+		t_u16 lpm;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_cfg;
+
+/** Type definition of mlan_ds_band_steer_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_band_steer_cfg {
+	/** Set/Get */
+	t_u8 action;
+	/** enable/disable band steering*/
+	t_u8 state;
+	/** Probe Response will be blocked to 2G channel for first
+	 * block_2g_prb_req probe requests*/
+	t_u8 block_2g_prb_req;
+	/** When band steering is enabled, limit the btm request sent to STA at
+	 * <max_btm_req_allowed>*/
+	t_u8 max_btm_req_allowed;
+} mlan_ds_band_steer_cfg, *pmlan_ds_band_steer_cfg;
+
+/** Type definition of mlan_ds_beacon_stuck_param_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_beacon_stuck_param_cfg {
+    /** subcmd */
+	t_u32 subcmd;
+    /** Set/Get */
+	t_u8 action;
+    /** No of beacon interval after which firmware will check if beacon Tx is going fine */
+	t_u8 beacon_stuck_detect_count;
+    /** Upon performing MAC reset, no of beacon interval after which firmware will check if recovery was successful */
+	t_u8 recovery_confirm_count;
+} mlan_ds_beacon_stuck_param_cfg, *pmlan_ds_beacon_stuck_param_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Power Management Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Host sleep config conditions : Cancel */
+#define HOST_SLEEP_CFG_CANCEL 0xffffffff
+
+/** Host sleep config condition: broadcast data */
+#define HOST_SLEEP_COND_BROADCAST_DATA MBIT(0)
+/** Host sleep config condition: unicast data */
+#define HOST_SLEEP_COND_UNICAST_DATA MBIT(1)
+/** Host sleep config condition: mac event */
+#define HOST_SLEEP_COND_MAC_EVENT MBIT(2)
+/** Host sleep config condition: multicast data */
+#define HOST_SLEEP_COND_MULTICAST_DATA MBIT(3)
+/** Host sleep config condition: IPV6 packet */
+#define HOST_SLEEP_COND_IPV6_PACKET MBIT(31)
+
+/** Host sleep config conditions: Default */
+#define HOST_SLEEP_DEF_COND                                                    \
+	(HOST_SLEEP_COND_BROADCAST_DATA | HOST_SLEEP_COND_UNICAST_DATA |       \
+	 HOST_SLEEP_COND_MAC_EVENT)
+
+/** Host sleep config GPIO : Default */
+#define HOST_SLEEP_DEF_GPIO 0xff
+/** Host sleep config gap : Default */
+#define HOST_SLEEP_DEF_GAP 200
+/** Host sleep config min wake holdoff */
+#define HOST_SLEEP_DEF_WAKE_HOLDOFF 0;
+/** Host sleep config inactivity timeout */
+#define HOST_SLEEP_DEF_INACTIVITY_TIMEOUT 10;
+
+/** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */
+typedef struct _mlan_ds_hs_cfg {
+	/** MTRUE to invoke the HostCmd, MFALSE otherwise */
+	t_u32 is_invoke_hostcmd;
+	/** Host sleep config condition */
+	/** Bit0: broadcast data
+	 *  Bit1: unicast data
+	 *  Bit2: mac event
+	 *  Bit3: multicast data
+	 */
+	t_u32 conditions;
+	/** GPIO pin or 0xff for interface */
+	t_u32 gpio;
+	/** Gap in milliseconds or or 0xff for special
+	 *  setting when GPIO is used to wakeup host
+	 */
+	t_u32 gap;
+	/** Host sleep wake interval */
+	t_u32 hs_wake_interval;
+	/** Parameter type for indication gpio*/
+	t_u8 param_type_ind;
+	/** GPIO pin for indication wakeup source */
+	t_u32 ind_gpio;
+	/** Level on ind_gpio pin for indication normal wakeup source */
+	t_u32 level;
+	/** Parameter type for extend hscfg*/
+	t_u8 param_type_ext;
+	/** Events that will be forced ignore*/
+	t_u32 event_force_ignore;
+	/** Events that will use extend gap to inform host*/
+	t_u32 event_use_ext_gap;
+	/** Ext gap*/
+	t_u8 ext_gap;
+	/** GPIO wave level for extend hscfg*/
+	t_u8 gpio_wave;
+} mlan_ds_hs_cfg, *pmlan_ds_hs_cfg;
+
+#define MAX_MGMT_FRAME_FILTER 2
+typedef struct _mlan_mgmt_frame_wakeup {
+	/** action - bitmap
+	 ** On matching rx'd pkt and filter during NON_HOSTSLEEP mode:
+	 **   Action[1]=0  Discard
+	 **   Action[1]=1  Allow
+	 ** Note that default action on non-match is "Allow".
+	 **
+	 ** On matching rx'd pkt and filter during HOSTSLEEP mode:
+	 **   Action[1:0]=00  Discard and Not Wake host
+	 **   Action[1:0]=01  Discard and Wake host
+	 **   Action[1:0]=10  Invalid
+	 ** Note that default action on non-match is "Discard and Not Wake
+	 *host".
+	 **/
+	t_u32 action;
+	/** Frame type(p2p, tdls...)
+	 ** type=0: invalid
+	 ** type=1: p2p
+	 ** type=others: reserved
+	 **/
+	t_u32 type;
+	/** Frame mask according to each type
+	 ** When type=1 for p2p, frame-mask have following define:
+	 **    Bit      Frame
+	 **     0       GO Negotiation Request
+	 **     1       GO Negotiation Response
+	 **     2       GO Negotiation Confirmation
+	 **     3       P2P Invitation Request
+	 **     4       P2P Invitation Response
+	 **     5       Device Discoverability Request
+	 **     6       Device Discoverability Response
+	 **     7       Provision Discovery Request
+	 **     8       Provision Discovery Response
+	 **     9       Notice of Absence
+	 **     10      P2P Presence Request
+	 **     11      P2P Presence Response
+	 **     12      GO Discoverability Request
+	 **     13-31   Reserved
+	 **
+	 ** When type=others, frame-mask is reserved.
+	 **/
+	t_u32 frame_mask;
+} mlan_mgmt_frame_wakeup, *pmlan_mgmt_frame_wakeup;
+
+/** Enable deep sleep mode */
+#define DEEP_SLEEP_ON 1
+/** Disable deep sleep mode */
+#define DEEP_SLEEP_OFF 0
+
+/** Default idle time in milliseconds for auto deep sleep */
+#define DEEP_SLEEP_IDLE_TIME 100
+
+typedef struct _mlan_ds_auto_ds {
+	/** auto ds mode, 0 - disable, 1 - enable */
+	t_u16 auto_ds;
+	/** auto ds idle time in milliseconds */
+	t_u16 idletime;
+} mlan_ds_auto_ds;
+
+/** Type definition of mlan_ds_inactivity_to
+ *  for MLAN_OID_PM_CFG_INACTIVITY_TO
+ */
+typedef struct _mlan_ds_inactivity_to {
+	/** Timeout unit in microsecond, 0 means 1000us (1ms) */
+	t_u32 timeout_unit;
+	/** Inactivity timeout for unicast data */
+	t_u32 unicast_timeout;
+	/** Inactivity timeout for multicast data */
+	t_u32 mcast_timeout;
+	/** Timeout for additional Rx traffic after Null PM1 packet exchange */
+	t_u32 ps_entry_timeout;
+} mlan_ds_inactivity_to, *pmlan_ds_inactivity_to;
+
+/** Minimum sleep period in milliseconds */
+#define MIN_SLEEP_PERIOD 10
+/** Maximum sleep period in milliseconds */
+#define MAX_SLEEP_PERIOD 60
+/** Special setting for UPSD certification tests */
+#define SLEEP_PERIOD_RESERVED_FF 0xFF
+
+/** PS null interval disable */
+#define PS_NULL_DISABLE (-1)
+
+/** Local listen interval disable */
+#define MRVDRV_LISTEN_INTERVAL_DISABLE (-1)
+/** Minimum listen interval */
+#define MRVDRV_MIN_LISTEN_INTERVAL 0
+
+/** Minimum multiple DTIM */
+#define MRVDRV_MIN_MULTIPLE_DTIM 0
+/** Maximum multiple DTIM */
+#define MRVDRV_MAX_MULTIPLE_DTIM 5
+/** Ignore multiple DTIM */
+#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
+/** Match listen interval to closest DTIM */
+#define MRVDRV_MATCH_CLOSEST_DTIM 0xfffd
+
+/** Minimum beacon miss timeout in milliseconds */
+#define MIN_BCN_MISS_TO 0
+/** Maximum beacon miss timeout in milliseconds */
+#define MAX_BCN_MISS_TO 50
+/** Disable beacon miss timeout */
+#define DISABLE_BCN_MISS_TO 65535
+
+/** Minimum delay to PS in milliseconds */
+#define MIN_DELAY_TO_PS 0
+/** Maximum delay to PS in milliseconds */
+#define MAX_DELAY_TO_PS 65535
+/** Delay to PS unchanged */
+#define DELAY_TO_PS_UNCHANGED (-1)
+/** Default delay to PS in milliseconds */
+#define DELAY_TO_PS_DEFAULT 1000
+
+/** PS mode: Unchanged */
+#define PS_MODE_UNCHANGED 0
+/** PS mode: Auto */
+#define PS_MODE_AUTO 1
+/** PS mode: Poll */
+#define PS_MODE_POLL 2
+/** PS mode: Null */
+#define PS_MODE_NULL 3
+
+/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
+typedef struct _mlan_ds_ps_cfg {
+	/** PS null interval in seconds */
+	t_u32 ps_null_interval;
+	/** Multiple DTIM interval */
+	t_u32 multiple_dtim_interval;
+	/** Listen interval */
+	t_u32 listen_interval;
+	/** Beacon miss timeout in milliseconds */
+	t_u32 bcn_miss_timeout;
+	/** Delay to PS in milliseconds */
+	t_s32 delay_to_ps;
+	/** PS mode */
+	t_u32 ps_mode;
+} mlan_ds_ps_cfg, *pmlan_ds_ps_cfg;
+
+/** Type definition of mlan_ds_sleep_params for MLAN_OID_PM_CFG_SLEEP_PARAMS */
+typedef struct _mlan_ds_sleep_params {
+	/** Error */
+	t_u32 error;
+	/** Offset in microseconds */
+	t_u32 offset;
+	/** Stable time in microseconds */
+	t_u32 stable_time;
+	/** Calibration control */
+	t_u32 cal_control;
+	/** External sleep clock */
+	t_u32 ext_sleep_clk;
+	/** Reserved */
+	t_u32 reserved;
+} mlan_ds_sleep_params, *pmlan_ds_sleep_params;
+
+/** sleep_param */
+typedef struct _ps_sleep_param {
+	/** control bitmap */
+	t_u32 ctrl_bitmap;
+	/** minimum sleep period (micro second) */
+	t_u32 min_sleep;
+	/** maximum sleep period (micro second) */
+	t_u32 max_sleep;
+} ps_sleep_param;
+
+/** inactivity sleep_param */
+typedef struct _inact_sleep_param {
+	/** inactivity timeout (micro second) */
+	t_u32 inactivity_to;
+	/** miniumu awake period (micro second) */
+	t_u32 min_awake;
+	/** maximum awake period (micro second) */
+	t_u32 max_awake;
+} inact_sleep_param;
+
+/** flag for ps mode */
+#define PS_FLAG_PS_MODE 1
+/** flag for sleep param */
+#define PS_FLAG_SLEEP_PARAM 2
+/** flag for inactivity sleep param */
+#define PS_FLAG_INACT_SLEEP_PARAM 4
+
+/** Enable Robust Coex mode */
+#define ROBUSTCOEX_GPIOCFG_ENABLE 1
+/** Disable Robust Coex mode */
+#define ROBUSTCOEX_GPIOCFG_DISABLE 0
+
+/** Disable power mode */
+#define PS_MODE_DISABLE 0
+/** Enable periodic dtim ps */
+#define PS_MODE_PERIODIC_DTIM 1
+/** Enable inactivity ps */
+#define PS_MODE_INACTIVITY 2
+/** FW wake up method interface */
+#define FW_WAKEUP_METHOD_INTERFACE 1
+/** FW wake up method gpio */
+#define FW_WAKEUP_METHOD_GPIO 2
+/** mlan_ds_ps_mgmt */
+typedef struct _mlan_ds_ps_mgmt {
+	/** flags for valid field */
+	t_u16 flags;
+	/** power mode */
+	t_u16 ps_mode;
+	/** sleep param */
+	ps_sleep_param sleep_param;
+	/** inactivity sleep param */
+	inact_sleep_param inact_param;
+} mlan_ds_ps_mgmt;
+
+/** mlan_ds_ps_info */
+typedef struct _mlan_ds_ps_info {
+	/** suspend allowed flag */
+	t_u32 is_suspend_allowed;
+} mlan_ds_ps_info;
+
+/** Type definition of mlan_ds_wakeup_reason for MLAN_OID_PM_HS_WAKEUP_REASON */
+typedef struct _mlan_ds_hs_wakeup_reason {
+	t_u16 hs_wakeup_reason;
+} mlan_ds_hs_wakeup_reason;
+
+/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
+typedef struct _mlan_ds_bcn_timeout {
+	/** Beacon miss timeout period window */
+	t_u16 bcn_miss_tmo_window;
+	/** Beacon miss timeout period */
+	t_u16 bcn_miss_tmo_period;
+	/** Beacon reacquire timeout period window */
+	t_u16 bcn_rq_tmo_window;
+	/** Beacon reacquire timeout period */
+	t_u16 bcn_rq_tmo_period;
+} mlan_ds_bcn_timeout, *pmlan_ds_bcn_timeout;
+
+/** Type definition of mlan_ds_pm_cfg for MLAN_IOCTL_PM_CFG */
+typedef struct _mlan_ds_pm_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Power management parameter */
+	union {
+		/** Power saving mode for MLAN_OID_PM_CFG_IEEE_PS */
+		t_u32 ps_mode;
+		/** Host Sleep configuration for MLAN_OID_PM_CFG_HS_CFG */
+		mlan_ds_hs_cfg hs_cfg;
+		/** Deep sleep mode for MLAN_OID_PM_CFG_DEEP_SLEEP */
+		mlan_ds_auto_ds auto_deep_sleep;
+		/** Inactivity timeout for MLAN_OID_PM_CFG_INACTIVITY_TO */
+		mlan_ds_inactivity_to inactivity_to;
+		/** Sleep period for MLAN_OID_PM_CFG_SLEEP_PD */
+		t_u32 sleep_period;
+		/** PS configuration parameters for MLAN_OID_PM_CFG_PS_CFG */
+		mlan_ds_ps_cfg ps_cfg;
+		/** PS configuration parameters for MLAN_OID_PM_CFG_SLEEP_PARAMS
+		 */
+		mlan_ds_sleep_params sleep_params;
+		/** PS configuration parameters for MLAN_OID_PM_CFG_PS_MODE */
+		mlan_ds_ps_mgmt ps_mgmt;
+		/** power info for MLAN_OID_PM_INFO */
+		mlan_ds_ps_info ps_info;
+		/** hs wakeup reason for MLAN_OID_PM_HS_WAKEUP_REASON */
+		mlan_ds_hs_wakeup_reason wakeup_reason;
+		/** config manamgement frame for hs wakeup */
+		mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+		/** Beacon timout parameters for MLAN_OID_PM_CFG_BCN_TIMEOUT */
+		mlan_ds_bcn_timeout bcn_timeout;
+	} param;
+} mlan_ds_pm_cfg, *pmlan_ds_pm_cfg;
+
+#ifdef RX_PACKET_COALESCE
+typedef struct {
+	mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+
+	t_u32 pkt_threshold; /** Packet threshold */
+	t_u16 delay; /** Timeout value in milliseconds */
+} wlan_ioctl_rx_pkt_coalesce_config_t;
+#endif
+
+/*-----------------------------------------------------------------*/
+/** WMM Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** WMM TSpec size */
+#define MLAN_WMM_TSPEC_SIZE 63
+/** WMM Add TS extra IE bytes */
+#define MLAN_WMM_ADDTS_EXTRA_IE_BYTES 256
+/** WMM statistics for packets hist bins */
+#define MLAN_WMM_STATS_PKTS_HIST_BINS 7
+/** Maximum number of AC QOS queues available */
+#define MLAN_WMM_MAX_AC_QUEUES 4
+
+/**
+ *  @brief IOCTL structure to send an ADDTS request and retrieve the response.
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    instigate an ADDTS management frame with an appropriate TSPEC IE as well
+ *    as any additional IEs appended in the ADDTS Action frame.
+ *
+ *  @sa woal_wmm_addts_req_ioctl
+ */
+typedef struct {
+	mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+
+	t_u32 timeout_ms; /**< Timeout value in milliseconds */
+	t_u8 ieee_status_code; /**< IEEE status code */
+
+	t_u32 ie_data_len; /**< Length of ie block in ie_data */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE /**< TSPEC to send in the ADDTS */
+		     + MLAN_WMM_ADDTS_EXTRA_IE_BYTES]; /**< Extra IE buf*/
+} wlan_ioctl_wmm_addts_req_t;
+
+/**
+ *  @brief IOCTL structure to send a DELTS request.
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    instigate an DELTS management frame with an appropriate TSPEC IE.
+ *
+ *  @sa woal_wmm_delts_req_ioctl
+ */
+typedef struct {
+	mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+	t_u8 ieee_reason_code; /**< IEEE reason code sent, unused for WMM */
+	t_u32 ie_data_len; /**< Length of ie block in ie_data */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE]; /**< TSPEC to send in the DELTS */
+} wlan_ioctl_wmm_delts_req_t;
+
+/**
+ *  @brief IOCTL structure to configure a specific AC Queue's parameters
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    get, set, or default the WMM AC queue parameters.
+ *
+ *  - msdu_lifetime_expiry is ignored if set to 0 on a set command
+ *
+ *  @sa woal_wmm_queue_config_ioctl
+ */
+typedef struct {
+	mlan_wmm_queue_config_action_e action; /**< Set, Get, or Default */
+	mlan_wmm_ac_e access_category; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+	t_u16 msdu_lifetime_expiry; /**< lifetime expiry in TUs */
+	t_u8 supported_rates[10]; /**< Not supported yet */
+} wlan_ioctl_wmm_queue_config_t;
+
+/**
+ *  @brief IOCTL structure to start, stop, and get statistics for a WMM AC
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    start or stop statistical collection for a given AC.  Also used to
+ *    retrieve and clear the collected stats on a given AC.
+ *
+ *  @sa woal_wmm_queue_stats_ioctl
+ */
+typedef struct {
+	/** Action of Queue Config : Start, Stop, or Get */
+	mlan_wmm_queue_stats_action_e action;
+	/** User Priority */
+	t_u8 user_priority;
+	/** Number of successful packets transmitted */
+	t_u16 pkt_count;
+	/** Packets lost; not included in pkt_count */
+	t_u16 pkt_loss;
+	/** Average Queue delay in microseconds */
+	t_u32 avg_queue_delay;
+	/** Average Transmission delay in microseconds */
+	t_u32 avg_tx_delay;
+	/** Calculated used time in units of 32 microseconds */
+	t_u16 used_time;
+	/** Calculated policed time in units of 32 microseconds */
+	t_u16 policed_time;
+	/** Queue Delay Histogram; number of packets per queue delay range
+	 *
+	 *  [0] -  0ms <= delay < 5ms
+	 *  [1] -  5ms <= delay < 10ms
+	 *  [2] - 10ms <= delay < 20ms
+	 *  [3] - 20ms <= delay < 30ms
+	 *  [4] - 30ms <= delay < 40ms
+	 *  [5] - 40ms <= delay < 50ms
+	 *  [6] - 50ms <= delay < msduLifetime (TUs)
+	 */
+	t_u16 delay_histogram[MLAN_WMM_STATS_PKTS_HIST_BINS];
+} wlan_ioctl_wmm_queue_stats_t,
+	/** Type definition of mlan_ds_wmm_queue_stats
+	 *  for MLAN_OID_WMM_CFG_QUEUE_STATS
+	 */
+mlan_ds_wmm_queue_stats, *pmlan_ds_wmm_queue_stats;
+
+/**
+ *  @brief IOCTL sub structure for a specific WMM AC Status
+ */
+typedef struct {
+	/** WMM Acm */
+	t_u8 wmm_acm;
+	/** Flow required flag */
+	t_u8 flow_required;
+	/** Flow created flag */
+	t_u8 flow_created;
+	/** Disabled flag */
+	t_u8 disabled;
+} wlan_ioctl_wmm_queue_status_ac_t;
+
+/**
+ *  @brief IOCTL structure to retrieve the WMM AC Queue status
+ *
+ *  IOCTL structure from the application layer to retrieve:
+ *     - ACM bit setting for the AC
+ *     - Firmware status (flow required, flow created, flow disabled)
+ *
+ *  @sa woal_wmm_queue_status_ioctl
+ */
+typedef struct {
+	/** WMM AC queue status */
+	wlan_ioctl_wmm_queue_status_ac_t ac_status[MLAN_WMM_MAX_AC_QUEUES];
+} wlan_ioctl_wmm_queue_status_t,
+	/** Type definition of mlan_ds_wmm_queue_status
+	 *  for MLAN_OID_WMM_CFG_QUEUE_STATUS
+	 */
+mlan_ds_wmm_queue_status, *pmlan_ds_wmm_queue_status;
+
+/** Type definition of mlan_ds_wmm_addts for MLAN_OID_WMM_CFG_ADDTS */
+typedef struct _mlan_ds_wmm_addts {
+	/** Result of ADDTS request */
+	mlan_cmd_result_e result;
+	/** Timeout value in milliseconds */
+	t_u32 timeout;
+	/** IEEE status code */
+	t_u32 status_code;
+	/** Dialog token */
+	t_u8 dialog_tok;
+	/** TSPEC data length */
+	t_u32 ie_data_len;
+	/** TSPEC to send in the ADDTS + buffering for any extra IEs */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE + MLAN_WMM_ADDTS_EXTRA_IE_BYTES];
+} mlan_ds_wmm_addts, *pmlan_ds_wmm_addts;
+
+/** Type definition of mlan_ds_wmm_delts for MLAN_OID_WMM_CFG_DELTS */
+typedef struct _mlan_ds_wmm_delts {
+	/** Result of DELTS request */
+	mlan_cmd_result_e result;
+	/** IEEE status code */
+	t_u32 status_code;
+	/** TSPEC data length */
+	t_u8 ie_data_len;
+	/** TSPEC to send in the DELTS */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE];
+} mlan_ds_wmm_delts, *pmlan_ds_wmm_delts;
+
+/** Type definition of mlan_ds_wmm_queue_config
+ *  for MLAN_OID_WMM_CFG_QUEUE_CONFIG
+ */
+typedef struct _mlan_ds_wmm_queue_config {
+	/** Action of Queue Config : Set, Get, or Default */
+	mlan_wmm_queue_config_action_e action;
+	/** WMM Access Category: WMM_AC_BK(0) to WMM_AC_VO(3) */
+	mlan_wmm_ac_e access_category;
+	/** Lifetime expiry in TUs */
+	t_u16 msdu_lifetime_expiry;
+	/** Reserve for future use */
+	t_u8 reserved[10];
+} mlan_ds_wmm_queue_config, *pmlan_ds_wmm_queue_config;
+
+/** Type definition of mlan_ds_wmm_cfg for MLAN_IOCTL_WMM_CFG */
+typedef struct _mlan_ds_wmm_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** WMM configuration parameter */
+	union {
+		/** WMM enable for MLAN_OID_WMM_CFG_ENABLE */
+		t_u32 wmm_enable;
+		/** QoS configuration for MLAN_OID_WMM_CFG_QOS */
+		t_u8 qos_cfg;
+		/** WMM add TS for MLAN_OID_WMM_CFG_ADDTS */
+		mlan_ds_wmm_addts addts;
+		/** WMM delete TS for MLAN_OID_WMM_CFG_DELTS */
+		mlan_ds_wmm_delts delts;
+		/** WMM queue configuration for MLAN_OID_WMM_CFG_QUEUE_CONFIG */
+		mlan_ds_wmm_queue_config q_cfg;
+		/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
+		 * WMM_AC_VO */
+		wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+		/** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATS */
+		mlan_ds_wmm_queue_stats q_stats;
+		/** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATUS */
+		mlan_ds_wmm_queue_status q_status;
+		/** WMM TS status for MLAN_OID_WMM_CFG_TS_STATUS */
+		mlan_ds_wmm_ts_status ts_status;
+	} param;
+} mlan_ds_wmm_cfg, *pmlan_ds_wmm_cfg;
+
+/*-----------------------------------------------------------------*/
+/** WPS Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for WPS session */
+enum _mlan_wps_status {
+	MLAN_WPS_CFG_SESSION_START = 1,
+	MLAN_WPS_CFG_SESSION_END = 0
+};
+
+/** Type definition of mlan_ds_wps_cfg for MLAN_IOCTL_WPS_CFG */
+typedef struct _mlan_ds_wps_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** WPS configuration parameter */
+	union {
+		/** WPS session for MLAN_OID_WPS_CFG_SESSION */
+		t_u32 wps_session;
+	} param;
+} mlan_ds_wps_cfg, *pmlan_ds_wps_cfg;
+
+/*-----------------------------------------------------------------*/
+/** 802.11n Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Maximum MCS */
+#define NUM_MCS_FIELD 16
+
+/** Supported stream modes */
+#define HT_STREAM_MODE_1X1 0x11
+#define HT_STREAM_MODE_2X2 0x22
+
+/* Both 2.4G and 5G band selected */
+#define BAND_SELECT_BOTH 0
+/* Band 2.4G selected */
+#define BAND_SELECT_BG 1
+/* Band 5G selected */
+#define BAND_SELECT_A 2
+
+/** Type definition of mlan_ds_11n_htcap_cfg for MLAN_OID_11N_HTCAP_CFG */
+typedef struct _mlan_ds_11n_htcap_cfg {
+	/** HT Capability information */
+	t_u32 htcap;
+	/** Band selection */
+	t_u32 misc_cfg;
+	/** Hardware HT cap information required */
+	t_u32 hw_cap_req;
+} mlan_ds_11n_htcap_cfg, *pmlan_ds_11n_htcap_cfg;
+
+/** Type definition of mlan_ds_11n_addba_param
+ * for MLAN_OID_11N_CFG_ADDBA_PARAM
+ */
+typedef struct _mlan_ds_11n_addba_param {
+	/** Timeout */
+	t_u32 timeout;
+	/** Buffer size for ADDBA request */
+	t_u32 txwinsize;
+	/** Buffer size for ADDBA response */
+	t_u32 rxwinsize;
+	/** amsdu for ADDBA request */
+	t_u8 txamsdu;
+	/** amsdu for ADDBA response */
+	t_u8 rxamsdu;
+} mlan_ds_11n_addba_param, *pmlan_ds_11n_addba_param;
+
+/** Type definition of mlan_ds_11n_tx_cfg for MLAN_OID_11N_CFG_TX */
+typedef struct _mlan_ds_11n_tx_cfg {
+	/** HTTxCap */
+	t_u16 httxcap;
+	/** HTTxInfo */
+	t_u16 httxinfo;
+	/** Band selection */
+	t_u32 misc_cfg;
+} mlan_ds_11n_tx_cfg, *pmlan_ds_11n_tx_cfg;
+
+/** BF Global Configuration */
+#define BF_GLOBAL_CONFIGURATION 0x00
+/** Performs NDP sounding for PEER specified */
+#define TRIGGER_SOUNDING_FOR_PEER 0x01
+/** TX BF interval for channel sounding */
+#define SET_GET_BF_PERIODICITY 0x02
+/** Tell FW not to perform any sounding for peer */
+#define TX_BF_FOR_PEER_ENBL 0x03
+/** TX BF SNR threshold for peer */
+#define SET_SNR_THR_PEER 0x04
+/** TX Sounding*/
+#define TX_SOUNDING_CFG 0x05
+
+/* Maximum number of peer MAC and status/SNR tuples */
+#define MAX_PEER_MAC_TUPLES 10
+
+/** Any new subcommand structure should be declare here */
+
+/** bf global cfg args */
+typedef struct _mlan_bf_global_cfg_args {
+	/** Global enable/disable bf */
+	t_u8 bf_enbl;
+	/** Global enable/disable sounding */
+	t_u8 sounding_enbl;
+	/** FB Type */
+	t_u8 fb_type;
+	/** SNR Threshold */
+	t_u8 snr_threshold;
+	/** Sounding interval in milliseconds */
+	t_u16 sounding_interval;
+	/** BF mode */
+	t_u8 bf_mode;
+	/** Reserved */
+	t_u8 reserved;
+} mlan_bf_global_cfg_args;
+
+/** trigger sounding args */
+typedef struct _mlan_trigger_sound_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Status */
+	t_u8 status;
+} mlan_trigger_sound_args;
+
+/** bf periodicity args */
+typedef struct _mlan_bf_periodicity_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Current Tx BF Interval in milliseconds */
+	t_u16 interval;
+	/** Status */
+	t_u8 status;
+} mlan_bf_periodicity_args;
+
+/** tx bf peer args */
+typedef struct _mlan_tx_bf_peer_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Reserved */
+	t_u16 reserved;
+	/** Enable/Disable Beamforming */
+	t_u8 bf_enbl;
+	/** Enable/Disable sounding */
+	t_u8 sounding_enbl;
+	/** FB Type */
+	t_u8 fb_type;
+} mlan_tx_bf_peer_args;
+
+/** SNR threshold args */
+typedef struct _mlan_snr_thr_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** SNR for peer */
+	t_u8 snr;
+} mlan_snr_thr_args;
+
+/** Type definition of mlan_ds_11n_tx_bf_cfg for MLAN_OID_11N_CFG_TX_BF_CFG */
+typedef struct _mlan_ds_11n_tx_bf_cfg {
+	/** BF Action */
+	t_u16 bf_action;
+	/** Action */
+	t_u16 action;
+	/** Number of peers */
+	t_u32 no_of_peers;
+	union {
+		mlan_bf_global_cfg_args bf_global_cfg;
+		mlan_trigger_sound_args bf_sound[MAX_PEER_MAC_TUPLES];
+		mlan_bf_periodicity_args bf_periodicity[MAX_PEER_MAC_TUPLES];
+		mlan_tx_bf_peer_args tx_bf_peer[MAX_PEER_MAC_TUPLES];
+		mlan_snr_thr_args bf_snr[MAX_PEER_MAC_TUPLES];
+	} body;
+} mlan_ds_11n_tx_bf_cfg, *pmlan_ds_11n_tx_bf_cfg;
+
+/** Type definition of mlan_ds_11n_amsdu_aggr_ctrl for
+ * MLAN_OID_11N_AMSDU_AGGR_CTRL*/
+typedef struct _mlan_ds_11n_amsdu_aggr_ctrl {
+	/** Enable/Disable */
+	t_u16 enable;
+	/** Current AMSDU size valid */
+	t_u16 curr_buf_size;
+} mlan_ds_11n_amsdu_aggr_ctrl, *pmlan_ds_11n_amsdu_aggr_ctrl;
+
+/** Type definition of mlan_ds_11n_aggr_prio_tbl
+ *  for MLAN_OID_11N_CFG_AGGR_PRIO_TBL
+ */
+typedef struct _mlan_ds_11n_aggr_prio_tbl {
+	/** ampdu priority table */
+	t_u8 ampdu[MAX_NUM_TID];
+	/** amsdu priority table */
+	t_u8 amsdu[MAX_NUM_TID];
+} mlan_ds_11n_aggr_prio_tbl, *pmlan_ds_11n_aggr_prio_tbl;
+
+/** DelBA All TIDs */
+#define DELBA_ALL_TIDS 0xff
+/** DelBA Tx */
+#define DELBA_TX MBIT(0)
+/** DelBA Rx */
+#define DELBA_RX MBIT(1)
+
+/** Type definition of mlan_ds_11n_delba for MLAN_OID_11N_CFG_DELBA */
+typedef struct _mlan_ds_11n_delba {
+	/** TID */
+	t_u8 tid;
+	/** Peer MAC address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Direction (Tx: bit 0, Rx: bit 1) */
+	t_u8 direction;
+} mlan_ds_11n_delba, *pmlan_ds_11n_delba;
+
+/** Type definition of mlan_ds_delba for MLAN_OID_11N_CFG_REJECT_ADDBA_REQ */
+typedef struct _mlan_ds_reject_addba_req {
+	/** Bit0    : host sleep activated
+	 *  Bit1    : auto reconnect enabled
+	 *  Others  : reserved
+	 */
+	t_u32 conditions;
+} mlan_ds_reject_addba_req, *pmlan_ds_reject_addba_req;
+
+/** Type definition of mlan_ds_ibss_ampdu_param */
+typedef struct _mlan_ds_ibss_ampdu_param {
+	/** ampdu priority table */
+	t_u8 ampdu[MAX_NUM_TID];
+	/** rx amdpdu setting */
+	t_u8 addba_reject[MAX_NUM_TID];
+} mlan_ds_ibss_ampdu_param, *pmlan_ds_ibss_ampdu_param;
+
+/** Type definition of mlan_ds_11n_cfg for MLAN_IOCTL_11N_CFG */
+typedef struct _mlan_ds_11n_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11n configuration parameter */
+	union {
+		/** Tx param for 11n for MLAN_OID_11N_CFG_TX */
+		mlan_ds_11n_tx_cfg tx_cfg;
+		/** Aggr priority table for MLAN_OID_11N_CFG_AGGR_PRIO_TBL */
+		mlan_ds_11n_aggr_prio_tbl aggr_prio_tbl;
+		/** Add BA param for MLAN_OID_11N_CFG_ADDBA_PARAM */
+		mlan_ds_11n_addba_param addba_param;
+		/** Add BA Reject paramters for MLAN_OID_11N_CFG_ADDBA_REJECT */
+		t_u8 addba_reject[MAX_NUM_TID];
+		/** Tx buf size for MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE */
+		t_u32 tx_buf_size;
+		/** HT cap info configuration for MLAN_OID_11N_HTCAP_CFG */
+		mlan_ds_11n_htcap_cfg htcap_cfg;
+		/** Tx param for 11n for MLAN_OID_11N_AMSDU_AGGR_CTRL */
+		mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+		/** Supported MCS Set field */
+		t_u8 supported_mcs_set[NUM_MCS_FIELD];
+		/** Transmit Beamforming Capabilities field */
+		t_u32 tx_bf_cap;
+		/** Transmit Beamforming configuration */
+		mlan_ds_11n_tx_bf_cfg tx_bf;
+		/** HT stream configuration */
+		t_u32 stream_cfg;
+		/** DelBA for MLAN_OID_11N_CFG_DELBA */
+		mlan_ds_11n_delba del_ba;
+		/** Reject Addba Req for MLAN_OID_11N_CFG_REJECT_ADDBA_REQ */
+		mlan_ds_reject_addba_req reject_addba_req;
+		/** Control coex RX window size configuration */
+		t_u32 coex_rx_winsize;
+		/** Control TX AMPDU configuration */
+		t_u32 txaggrctrl;
+		/** aggrprirotity table for MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM */
+		mlan_ds_ibss_ampdu_param ibss_ampdu;
+		/** Minimum BA Threshold for MLAN_OID_11N_CFG_MIN_BA_THRESHOLD
+		 */
+		t_u8 min_ba_threshold;
+	} param;
+} mlan_ds_11n_cfg, *pmlan_ds_11n_cfg;
+
+#define NUM_MCS_SUPP 20
+#define VHT_MCS_SET_LEN 8
+
+/** Type definition of mlan_ds_11ac_vhtcap_cfg for MLAN_OID_11AC_VHTCAP_CFG */
+typedef struct _mlan_ds_11ac_vhtcap_cfg {
+	/** HT Capability information */
+	t_u32 vhtcap;
+	/** Band selection */
+	t_u32 misc_cfg;
+	/** Hardware HT cap information required */
+	t_u32 hw_cap_req;
+} mlan_ds_11ac_vhtcap_cfg, *pmlan_ds_11ac_vhtcap_cfg;
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG_TX */
+typedef struct _mlan_ds_11ac_tx_cfg {
+	/** Band selection */
+	t_u8 band_cfg;
+	/** misc configuration */
+	t_u8 misc_cfg;
+	/** HTTxCap */
+	t_u16 vhttxcap;
+	/** HTTxInfo */
+	t_u16 vhttxinfo;
+} mlan_ds_11ac_tx_cfg, *pmlan_ds_11ac_tx_cfg;
+
+/** Tx */
+#define MLAN_RADIO_TX MBIT(0)
+/** Rx */
+#define MLAN_RADIO_RX MBIT(1)
+/** Tx & Rx */
+#define MLAN_RADIO_TXRX (MLAN_RADIO_TX | MLAN_RADIO_RX)
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG */
+typedef struct _mlan_ds_11ac_vht_cfg {
+	/** Band selection (1: 2.4G, 2: 5 G, 3: both 2.4G and 5G) */
+	t_u32 band;
+	/** TxRx (1: Tx, 2: Rx, 3: both Tx and Rx) */
+	t_u32 txrx;
+	/** BW CFG (0: 11N CFG, 1: vhtcap) */
+	t_u32 bwcfg;
+	/** VHT capabilities. */
+	t_u32 vht_cap_info;
+	/** VHT Tx mcs */
+	t_u32 vht_tx_mcs;
+	/** VHT Rx mcs */
+	t_u32 vht_rx_mcs;
+	/** VHT rx max rate */
+	t_u16 vht_rx_max_rate;
+	/** VHT max tx rate */
+	t_u16 vht_tx_max_rate;
+	/** Skip usr 11ac mcs cfg */
+	t_bool skip_usr_11ac_mcs_cfg;
+} mlan_ds_11ac_vht_cfg, *pmlan_ds_11ac_vht_cfg;
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG */
+typedef struct _mlan_ds_11ac_opermode_cfg {
+	/** channel width: 1-20MHz, 2-40MHz, 3-80MHz, 4-160MHz or 80+80MHz */
+	t_u8 bw;
+	/** Rx NSS */
+	t_u8 nss;
+} mlan_ds_11ac_opermode_cfg, *pmlan_ds_11ac_opermode_cfg;
+
+/** Type definition of mlan_ds_11ac_cfg for MLAN_IOCTL_11AC_CFG */
+typedef struct _mlan_ds_11ac_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11n configuration parameter */
+	union {
+		/** VHT configuration for MLAN_OID_11AC_VHT_CFG */
+		mlan_ds_11ac_vht_cfg vht_cfg;
+		/** Supported MCS Set field */
+		t_u8 supported_mcs_set[NUM_MCS_SUPP];
+		/** Oper mode configuration for MLAN_OID_11AC_OPERMODE_CFG */
+		mlan_ds_11ac_opermode_cfg opermode_cfg;
+	} param;
+} mlan_ds_11ac_cfg, *pmlan_ds_11ac_cfg;
+
+/** Type definition of mlan_ds_11ax_he_capa for MLAN_OID_11AX_HE_CFG */
+typedef MLAN_PACK_START struct _mlan_ds_11ax_he_capa {
+	/** tlv id of he capability */
+	t_u16 id;
+	/** length of the payload */
+	t_u16 len;
+	/** extension id */
+	t_u8 ext_id;
+	/** he mac capability info */
+	t_u8 he_mac_cap[6];
+	/** he phy capability info */
+	t_u8 he_phy_cap[11];
+	/** he txrx mcs support for 80MHz */
+	t_u8 he_txrx_mcs_support[4];
+	/** val for txrx mcs 160Mhz or 80+80, and PPE thresholds */
+	t_u8 val[28];
+} MLAN_PACK_END mlan_ds_11ax_he_capa, *pmlan_ds_11ax_he_capa;
+
+/** Type definition of mlan_ds_11ax_he_cfg for MLAN_OID_11AX_HE_CFG */
+typedef struct _mlan_ds_11ax_he_cfg {
+	/** band, BIT0:2.4G, BIT1:5G*/
+	t_u8 band;
+	/** mlan_ds_11ax_he_capa */
+	mlan_ds_11ax_he_capa he_cap;
+} mlan_ds_11ax_he_cfg, *pmlan_ds_11ax_he_cfg;
+/** Type definition of mlan_ds_11as_cfg for MLAN_IOCTL_11AX_CFG */
+typedef struct _mlan_ds_11ax_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11n configuration parameter */
+	union {
+		/** HE configuration for MLAN_OID_11AX_HE_CFG */
+		mlan_ds_11ax_he_cfg he_cfg;
+	} param;
+} mlan_ds_11ax_cfg, *pmlan_ds_11ax_cfg;
+
+#define MLAN_11AXCMD_CFG_ID_SR_OBSS_PD_OFFSET 1
+#define MLAN_11AXCMD_CFG_ID_SR_ENABLE 2
+#define MLAN_11AXCMD_CFG_ID_BEAM_CHANGE 3
+#define MLAN_11AXCMD_CFG_ID_HTC_ENABLE 4
+#define MLAN_11AXCMD_CFG_ID_TXOP_RTS 5
+#define MLAN_11AXCMD_CFG_ID_TX_OMI 6
+#define MLAN_11AXCMD_CFG_ID_OBSSNBRU_TOLTIME 7
+
+#define MLAN_11AXCMD_SR_SUBID 0x102
+#define MLAN_11AXCMD_BEAM_SUBID 0x103
+#define MLAN_11AXCMD_HTC_SUBID 0x104
+#define MLAN_11AXCMD_TXOMI_SUBID 0x105
+#define MLAN_11AXCMD_OBSS_TOLTIME_SUBID 0x106
+#define MLAN_11AXCMD_TXOPRTS_SUBID 0x108
+
+#define MLAN_11AX_TWT_SETUP_SUBID 0x114
+#define MLAN_11AX_TWT_TEARDOWN_SUBID 0x115
+
+#define MRVL_DOT11AX_ENABLE_SR_TLV_ID (PROPRIETARY_TLV_BASE_ID + 322)
+#define MRVL_DOT11AX_OBSS_PD_OFFSET_TLV_ID (PROPRIETARY_TLV_BASE_ID + 323)
+
+/** Type definition of mlan_11axcmdcfg_obss_pd_offset for MLAN_OID_11AX_CMD_CFG
+ */
+typedef struct MLAN_PACK_START _mlan_11axcmdcfg_obss_pd_offset {
+	/** <NON_SRG_OffSET, SRG_OFFSET> */
+	t_u8 offset[2];
+} MLAN_PACK_END mlan_11axcmdcfg_obss_pd_offset;
+
+/** Type definition of mlan_11axcmdcfg_sr_control for MLAN_OID_11AX_CMD_CFG */
+typedef struct MLAN_PACK_START _mlan_11axcmdcfg_sr_control {
+	/** 1 enable, 0 disable */
+	t_u8 control;
+} MLAN_PACK_END mlan_11axcmdcfg_sr_control;
+
+/** Type definition of mlan_ds_11ax_sr_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_11ax_sr_cmd {
+	/** type*/
+	t_u16 type;
+	/** length of TLV */
+	t_u16 len;
+	/** value */
+	union {
+		mlan_11axcmdcfg_obss_pd_offset obss_pd_offset;
+		mlan_11axcmdcfg_sr_control sr_control;
+	} param;
+} MLAN_PACK_END mlan_ds_11ax_sr_cmd, *pmlan_ds_11ax_sr_cmd;
+
+/** Type definition of mlan_ds_11ax_beam_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_beam_cmd {
+	/** command value: 1 is disable, 0 is enable*/
+	t_u8 value;
+} mlan_ds_11ax_beam_cmd, *pmlan_ds_11ax_beam_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_htc_cmd {
+	/** command value: 1 is enable, 0 is disable*/
+	t_u8 value;
+} mlan_ds_11ax_htc_cmd, *pmlan_ds_11ax_htc_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_txop_cmd {
+	/** Two byte rts threshold value of which only 10 bits, bit 0 to bit 9
+	 * are valid */
+	t_u16 rts_thres;
+} mlan_ds_11ax_txop_cmd, *pmlan_ds_11ax_txop_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_txomi_cmd {
+	/* 11ax spec 9.2.4.6a.2 OM Control 12 bits. Bit 0 to bit 11 */
+	t_u16 omi;
+} mlan_ds_11ax_txomi_cmd, *pmlan_ds_11ax_txomi_cmd;
+
+/** Type definition of mlan_ds_11ax_toltime_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_toltime_cmd {
+	/* OBSS Narrow Bandwidth RU Tolerance Time */
+	t_u32 tol_time;
+} mlan_ds_11ax_toltime_cmd, *pmlan_ds_11ax_toltime_cmd;
+
+/** Type definition of mlan_ds_11ax_cmd_cfg for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_cmd_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Sub-id */
+	t_u32 sub_id;
+	/** 802.11n configuration parameter */
+	union {
+		/** SR configuration for MLAN_11AXCMD_SR_SUBID */
+		mlan_ds_11ax_sr_cmd sr_cfg;
+		/** Beam configuration for MLAN_11AXCMD_BEAM_SUBID */
+		mlan_ds_11ax_beam_cmd beam_cfg;
+		/** HTC configuration for MLAN_11AXCMD_HTC_SUBID */
+		mlan_ds_11ax_htc_cmd htc_cfg;
+		/** txop RTS configuration for MLAN_11AXCMD_TXOPRTS_SUBID */
+		mlan_ds_11ax_txop_cmd txop_cfg;
+		/** tx omi configuration for MLAN_11AXCMD_TXOMI_SUBID */
+		mlan_ds_11ax_txomi_cmd txomi_cfg;
+		/** OBSS tolerance time configuration for
+		 * MLAN_11AXCMD_TOLTIME_SUBID */
+		mlan_ds_11ax_toltime_cmd toltime_cfg;
+	} param;
+} mlan_ds_11ax_cmd_cfg, *pmlan_ds_11ax_cmd_cfg;
+
+/** Type definition of mlan_ds_twt_setup for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twt_setup {
+	/** Implicit, 0: TWT session is explicit, 1: Session is implicit */
+	t_u8 implicit;
+	/** Announced, 0: Unannounced, 1: Announced TWT */
+	t_u8 announced;
+	/** Trigger Enabled, 0: Non-Trigger enabled, 1: Trigger enabled TWT */
+	t_u8 trigger_enabled;
+	/** TWT Information Disabled, 0: TWT info enabled, 1: TWT info disabled
+	 */
+	t_u8 twt_info_disabled;
+	/** Negotiation Type, 0: Future Individual TWT SP start time, 1: Next
+	 * Wake TBTT time */
+	t_u8 negotiation_type;
+	/** TWT Wakeup Duration, time after which the TWT requesting STA can
+	 * transition to doze state */
+	t_u8 twt_wakeup_duration;
+	/** Flow Identifier. Range: [0-7]*/
+	t_u8 flow_identifier;
+	/** Hard Constraint, 0: FW can tweak the TWT setup parameters if it is
+	 *rejected by AP.
+	 ** 1: Firmware should not tweak any parameters. */
+	t_u8 hard_constraint;
+	/** TWT Exponent, Range: [0-63] */
+	t_u8 twt_exponent;
+	/** TWT Mantissa Range: [0-sizeof(UINT16)] */
+	t_u16 twt_mantissa;
+    /** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
+	t_u8 twt_request;
+} MLAN_PACK_END mlan_ds_twt_setup, *pmlan_ds_twt_setup;
+
+/** Type definition of mlan_ds_twt_teardown for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twt_teardown {
+	/** TWT Flow Identifier. Range: [0-7] */
+	t_u8 flow_identifier;
+	/** Negotiation Type. 0: Future Individual TWT SP start time, 1: Next
+	 * Wake TBTT time */
+	t_u8 negotiation_type;
+	/** Tear down all TWT. 1: To teardown all TWT, 0 otherwise */
+	t_u8 teardown_all_twt;
+} MLAN_PACK_END mlan_ds_twt_teardown, *pmlan_ds_twt_teardown;
+
+/** Type definition of mlan_ds_twtcfg for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twtcfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Sub-id */
+	t_u32 sub_id;
+	/** TWT Setup/Teardown configuration parameter */
+	union {
+		/** TWT Setup config for Sub ID: MLAN_11AX_TWT_SETUP_SUBID */
+		mlan_ds_twt_setup twt_setup;
+		/** TWT Teardown config for Sub ID: MLAN_11AX_TWT_TEARDOWN_SUBID
+		 */
+		mlan_ds_twt_teardown twt_teardown;
+	} param;
+} MLAN_PACK_END mlan_ds_twtcfg, *pmlan_ds_twtcfg;
+
+/** Country code length */
+#define COUNTRY_CODE_LEN 3
+
+/*-----------------------------------------------------------------*/
+/** 802.11d Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Maximum subbands for 11d */
+#define MRVDRV_MAX_SUBBAND_802_11D 83
+
+/** Data structure for subband set */
+typedef struct _mlan_ds_subband_set_t {
+	/** First channel */
+	t_u8 first_chan;
+	/** Number of channels */
+	t_u8 no_of_chan;
+	/** Maximum Tx power in dBm */
+	t_u8 max_tx_pwr;
+} mlan_ds_subband_set_t;
+
+/** Domain regulatory information */
+typedef struct _mlan_ds_11d_domain_info {
+	/** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Band that channels in sub_band belong to */
+	t_u8 band;
+	/** No. of subband in below */
+	t_u8 no_of_sub_band;
+	/** Subband data to send/last sent */
+	mlan_ds_subband_set_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} mlan_ds_11d_domain_info;
+
+/** Type definition of mlan_ds_11d_cfg for MLAN_IOCTL_11D_CFG */
+typedef struct _mlan_ds_11d_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11d configuration parameter */
+	union {
+#ifdef STA_SUPPORT
+		/** Enable for MLAN_OID_11D_CFG_ENABLE */
+		t_u32 enable_11d;
+#endif				/* STA_SUPPORT */
+		/** Domain info for MLAN_OID_11D_DOMAIN_INFO_EXT */
+		mlan_ds_11d_domain_info domain_info;
+#ifdef UAP_SUPPORT
+		/** tlv data for MLAN_OID_11D_DOMAIN_INFO */
+		t_u8 domain_tlv[MAX_IE_SIZE];
+#endif				/* UAP_SUPPORT */
+	} param;
+} mlan_ds_11d_cfg, *pmlan_ds_11d_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Register Memory Access Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for CSU target device type */
+enum _mlan_csu_target_type {
+	MLAN_CSU_TARGET_CAU = 1,
+	MLAN_CSU_TARGET_PSU,
+};
+
+/** Enumeration for register type */
+enum _mlan_reg_type {
+	MLAN_REG_MAC = 1,
+	MLAN_REG_BBP,
+	MLAN_REG_RF,
+	MLAN_REG_CAU = 5,
+	MLAN_REG_PSU = 6,
+	MLAN_REG_BCA = 7,
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	MLAN_REG_MAC2 = 0x81,
+	MLAN_REG_BBP2 = 0x82,
+	MLAN_REG_RF2 = 0x83,
+	MLAN_REG_BCA2 = 0x87
+#endif
+};
+
+/** Type definition of mlan_ds_reg_rw for MLAN_OID_REG_RW */
+typedef struct _mlan_ds_reg_rw {
+	/** Register type */
+	t_u32 type;
+	/** Offset */
+	t_u32 offset;
+	/** Value */
+	t_u32 value;
+} mlan_ds_reg_rw;
+
+/** Maximum EEPROM data */
+#define MAX_EEPROM_DATA 256
+
+/** Type definition of mlan_ds_read_eeprom for MLAN_OID_EEPROM_RD */
+typedef struct _mlan_ds_read_eeprom {
+	/** Multiples of 4 */
+	t_u16 offset;
+	/** Number of bytes */
+	t_u16 byte_count;
+	/** Value */
+	t_u8 value[MAX_EEPROM_DATA];
+} mlan_ds_read_eeprom;
+
+/** Type definition of mlan_ds_mem_rw for MLAN_OID_MEM_RW */
+typedef struct _mlan_ds_mem_rw {
+	/** Address */
+	t_u32 addr;
+	/** Value */
+	t_u32 value;
+} mlan_ds_mem_rw;
+
+/** Type definition of mlan_ds_reg_mem for MLAN_IOCTL_REG_MEM */
+typedef struct _mlan_ds_reg_mem {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Register memory access parameter */
+	union {
+		/** Register access for MLAN_OID_REG_RW */
+		mlan_ds_reg_rw reg_rw;
+		/** EEPROM access for MLAN_OID_EEPROM_RD */
+		mlan_ds_read_eeprom rd_eeprom;
+		/** Memory access for MLAN_OID_MEM_RW */
+		mlan_ds_mem_rw mem_rw;
+	} param;
+} mlan_ds_reg_mem, *pmlan_ds_reg_mem;
+
+/*-----------------------------------------------------------------*/
+/** Multi-Radio Configuration Group */
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+/** 802.11h Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_DFS_TESTING */
+typedef struct _mlan_ds_11h_dfs_testing {
+	/** User-configured CAC period in milliseconds, 0 to use default */
+	t_u32 usr_cac_period_msec;
+	/** User-configured NOP period in seconds, 0 to use default */
+	t_u16 usr_nop_period_sec;
+	/** User-configured skip channel change, 0 to disable */
+	t_u8 usr_no_chan_change;
+	/** User-configured fixed channel to change to, 0 to use random channel
+	 */
+	t_u8 usr_fixed_new_chan;
+	/** User-configured cac restart */
+	t_u8 usr_cac_restart;
+} mlan_ds_11h_dfs_testing, *pmlan_ds_11h_dfs_testing;
+
+/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_CHAN_NOP_INFO */
+typedef struct _mlan_ds_11h_chan_nop_info {
+	/** current channel */
+	t_u8 curr_chan;
+	/** channel_width */
+	t_u8 chan_width;
+	/** flag for chan under nop */
+	t_bool chan_under_nop;
+	/** chan_ban_info for new channel */
+	chan_band_info new_chan;
+} mlan_ds_11h_chan_nop_info, *pmlan_ds_11h_chan_nop_info;
+
+typedef struct _mlan_ds_11h_chan_rep_req {
+	t_u16 startFreq;
+	Band_Config_t bandcfg;
+	t_u8 chanNum;
+	t_u32 millisec_dwell_time; /**< Channel dwell time in milliseconds */
+	t_u8 host_based;
+} mlan_ds_11h_chan_rep_req;
+
+typedef struct _mlan_ds_11h_dfs_w53_cfg {
+	/** dfs w53 cfg */
+	t_u8 dfs53cfg;
+} mlan_ds_11h_dfs_w53_cfg;
+
+/** Type definition of mlan_ds_11h_cfg for MLAN_IOCTL_11H_CFG */
+typedef struct _mlan_ds_11h_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	union {
+		/** Local power constraint for
+		 * MLAN_OID_11H_LOCAL_POWER_CONSTRAINT */
+		t_s8 usr_local_power_constraint;
+		/** User-configuation for MLAN_OID_11H_DFS_TESTING */
+		mlan_ds_11h_dfs_testing dfs_testing;
+		/** channel NOP information for MLAN_OID_11H_CHAN_NOP_INFO */
+		mlan_ds_11h_chan_nop_info ch_nop_info;
+		/** channel report req for MLAN_OID_11H_CHAN_REPORT_REQUEST */
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		/** channel switch count for MLAN_OID_11H_CHAN_SWITCH_COUNT*/
+		t_s8 cs_count;
+		mlan_ds_11h_dfs_w53_cfg dfs_w53_cfg;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER (3 * 1024)
+
+/** LDO Internal */
+#define LDO_INTERNAL 0
+/** LDO External */
+#define LDO_EXTERNAL 1
+
+/** Enumeration for IE type */
+enum _mlan_ie_type {
+	MLAN_IE_TYPE_GEN_IE = 0,
+#ifdef STA_SUPPORT
+	MLAN_IE_TYPE_ARP_FILTER,
+#endif /* STA_SUPPORT */
+};
+
+/** Type definition of mlan_ds_misc_gen_ie for MLAN_OID_MISC_GEN_IE */
+typedef struct _mlan_ds_misc_gen_ie {
+	/** IE type */
+	t_u32 type;
+	/** IE length */
+	t_u32 len;
+	/** IE buffer */
+	t_u8 ie_data[MAX_IE_SIZE];
+} mlan_ds_misc_gen_ie;
+
+#ifdef SDIO
+/** Type definition of mlan_ds_misc_sdio_mpa_ctrl
+ *  for MLAN_OID_MISC_SDIO_MPA_CTRL
+ */
+typedef struct _mlan_ds_misc_sdio_mpa_ctrl {
+	/** SDIO MP-A TX enable/disable */
+	t_u16 tx_enable;
+	/** SDIO MP-A RX enable/disable */
+	t_u16 rx_enable;
+	/** SDIO MP-A TX buf size */
+	t_u16 tx_buf_size;
+	/** SDIO MP-A RX buf size */
+	t_u16 rx_buf_size;
+	/** SDIO MP-A TX Max Ports */
+	t_u16 tx_max_ports;
+	/** SDIO MP-A RX Max Ports */
+	t_u16 rx_max_ports;
+} mlan_ds_misc_sdio_mpa_ctrl;
+#endif
+
+/** Type definition of mlan_ds_misc_cmd for MLAN_OID_MISC_HOST_CMD */
+typedef struct _mlan_ds_misc_cmd {
+	/** Command length */
+	t_u32 len;
+	/** Command buffer */
+	t_u8 cmd[MRVDRV_SIZE_OF_CMD_BUFFER];
+} mlan_ds_misc_cmd;
+
+/** Maximum number of system clocks */
+#define MLAN_MAX_CLK_NUM 16
+
+/** Clock type : Configurable */
+#define MLAN_CLK_CONFIGURABLE 0
+/** Clock type : Supported */
+#define MLAN_CLK_SUPPORTED 1
+
+/** Type definition of mlan_ds_misc_sys_clock for MLAN_OID_MISC_SYS_CLOCK */
+typedef struct _mlan_ds_misc_sys_clock {
+	/** Current system clock */
+	t_u16 cur_sys_clk;
+	/** Clock type */
+	t_u16 sys_clk_type;
+	/** Number of clocks */
+	t_u16 sys_clk_num;
+	/** System clocks */
+	t_u16 sys_clk[MLAN_MAX_CLK_NUM];
+} mlan_ds_misc_sys_clock;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+	MLAN_FUNC_INIT = 1,
+	MLAN_FUNC_SHUTDOWN,
+};
+
+/** Type definition of mlan_ds_misc_tx_datapause
+ * for MLAN_OID_MISC_TX_DATAPAUSE
+ */
+typedef struct _mlan_ds_misc_tx_datapause {
+	/** Tx data pause flag */
+	t_u16 tx_pause;
+	/** Max number of Tx buffers for all PS clients */
+	t_u16 tx_buf_cnt;
+} mlan_ds_misc_tx_datapause;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg
+ * for MLAN_OID_MISC_RX_ABORT_CFG
+ */
+typedef struct _mlan_ds_misc_rx_abort_cfg {
+	/** enable/disable rx abort */
+	t_u8 enable;
+	/** Rx weak RSSI pkt threshold */
+	t_s8 rssi_threshold;
+} mlan_ds_misc_rx_abort_cfg;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg_ext
+ * for MLAN_OID_MISC_RX_ABORT_CFG_EXT
+ */
+typedef struct _mlan_ds_misc_rx_abort_cfg_ext {
+	/** enable/disable dynamic rx abort */
+	t_u8 enable;
+	/** rssi margin */
+	t_s8 rssi_margin;
+	/** specify ceil rssi threshold */
+	t_s8 ceil_rssi_threshold;
+} mlan_ds_misc_rx_abort_cfg_ext;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg_ext
+ * for MLAN_OID_MISC_TX_AMDPU_PROT_MODE
+ */
+typedef struct _mlan_ds_misc_tx_ampdu_prot_mode {
+	/** set prot mode */
+	t_u16 mode;
+} mlan_ds_misc_tx_ampdu_prot_mode;
+
+/** Type definition of mlan_ds_misc_dot11mc_unassoc_ftm_cfg
+ * for MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG
+ */
+typedef struct _mlan_ds_misc_dot11mc_unassoc_ftm_cfg {
+	/** set the state */
+	t_u16 state;
+} mlan_ds_misc_dot11mc_unassoc_ftm_cfg;
+
+#define RATEADAPT_ALGO_LEGACY 0
+#define RATEADAPT_ALGO_SR 1
+
+/** Type definition of mlan_ds_misc_rate_adapt_cfg
+ * for MLAN_OID_MISC_RATE_ADAPT_CFG
+ */
+typedef struct _mlan_ds_misc_rate_adapt_cfg {
+	/** SR Rateadapt */
+	t_u8 sr_rateadapt;
+	/** set low threshold */
+	t_u8 ra_low_thresh;
+	/** set high threshold */
+	t_u8 ra_high_thresh;
+	/** set interval */
+	t_u16 ra_interval;
+} mlan_ds_misc_rate_adapt_cfg;
+
+/** Type definition of mlan_ds_misc_cck_desense_cfg
+ * for MLAN_OID_MISC_CCK_DESENSE_CFG
+ */
+typedef struct _mlan_ds_misc_cck_desense_cfg {
+	/** cck desense mode: 0:disable 1:normal 2:dynamic */
+	t_u16 mode;
+	/** specify rssi margin */
+	t_s8 margin;
+	/** specify ceil rssi threshold */
+	t_s8 ceil_thresh;
+	/** cck desense "on" interval count */
+	t_u8 num_on_intervals;
+	/** cck desense "off" interval count */
+	t_u8 num_off_intervals;
+} mlan_ds_misc_cck_desense_cfg;
+
+/** IP address length */
+#define IPADDR_LEN (16)
+/** Max number of ip */
+#define MAX_IPADDR (4)
+/** IP address type - NONE*/
+#define IPADDR_TYPE_NONE (0)
+/** IP address type - IPv4*/
+#define IPADDR_TYPE_IPV4 (1)
+/** IP operation remove */
+#define MLAN_IPADDR_OP_IP_REMOVE (0)
+/** IP operation ARP filter */
+#define MLAN_IPADDR_OP_ARP_FILTER MBIT(0)
+/** IP operation ARP response */
+#define MLAN_IPADDR_OP_AUTO_ARP_RESP MBIT(1)
+
+/** Type definition of mlan_ds_misc_ipaddr_cfg for MLAN_OID_MISC_IP_ADDR */
+typedef struct _mlan_ds_misc_ipaddr_cfg {
+	/** Operation code */
+	t_u32 op_code;
+	/** IP address type */
+	t_u32 ip_addr_type;
+	/** Number of IP */
+	t_u32 ip_addr_num;
+	/** IP address */
+	t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN];
+} mlan_ds_misc_ipaddr_cfg;
+
+/** Type definnition of mlan_ds_misc_ipv6_ra_offload for
+ * MLAN_OID_MISC_IPV6_RA_OFFLOAD*/
+typedef struct _mlan_ds_misc_ipv6_ra_offload {
+	/** 0: disable; 1: enable*/
+	t_u8 enable;
+	t_u8 ipv6_addr[16];
+} mlan_ds_misc_ipv6_ra_offload;
+
+/* MEF configuration disable */
+#define MEF_CFG_DISABLE 0
+/* MEF configuration Rx filter enable */
+#define MEF_CFG_RX_FILTER_ENABLE 1
+/* MEF configuration auto ARP response */
+#define MEF_CFG_AUTO_ARP_RESP 2
+/* MEF configuration host command */
+#define MEF_CFG_HOSTCMD 0xFFFF
+
+/** Type definition of mlan_ds_misc_mef_cfg for MLAN_OID_MISC_MEF_CFG */
+typedef struct _mlan_ds_misc_mef_cfg {
+	/** Sub-ID for operation */
+	t_u32 sub_id;
+	/** Parameter according to sub-ID */
+	union {
+		/** MEF command buffer for MEF_CFG_HOSTCMD */
+		mlan_ds_misc_cmd cmd_buf;
+	} param;
+} mlan_ds_misc_mef_cfg;
+
+/** Type definition of mlan_ds_misc_cfp_code for MLAN_OID_MISC_CFP_CODE */
+typedef struct _mlan_ds_misc_cfp_code {
+	/** CFP table code for 2.4GHz */
+	t_u32 cfp_code_bg;
+	/** CFP table code for 5GHz */
+	t_u32 cfp_code_a;
+} mlan_ds_misc_cfp_code;
+
+/** Type definition of mlan_ds_misc_arb_cfg
+ * for MLAN_OID_MISC_ARB_CFG
+ */
+typedef struct _mlan_ds_misc_arb_cfg {
+	/** arb mode 0-4 */
+	t_u32 arb_mode;
+} mlan_ds_misc_arb_cfg;
+
+/** Type definition of mlan_ds_misc_tp_state
+ *  for MLAN_OID_MISC_TP_STATE
+ */
+typedef struct _mlan_ds_misc_tp_state {
+	/** TP account mode 0-disable 1-enable */
+	t_u32 on;
+	/** Packet drop point */
+	t_u32 drop_point;
+} mlan_ds_misc_tp_state;
+
+/** Type definition of mlan_ds_misc_country_code
+ *  for MLAN_OID_MISC_COUNTRY_CODE
+ */
+typedef struct _mlan_ds_misc_country_code {
+	/** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+} mlan_ds_misc_country_code;
+
+/** action for set */
+#define SUBSCRIBE_EVT_ACT_BITWISE_SET 0x0002
+/** action for clear */
+#define SUBSCRIBE_EVT_ACT_BITWISE_CLR 0x0003
+/** BITMAP for subscribe event rssi low */
+#define SUBSCRIBE_EVT_RSSI_LOW MBIT(0)
+/** BITMAP for subscribe event snr low */
+#define SUBSCRIBE_EVT_SNR_LOW MBIT(1)
+/** BITMAP for subscribe event max fail */
+#define SUBSCRIBE_EVT_MAX_FAIL MBIT(2)
+/** BITMAP for subscribe event beacon missed */
+#define SUBSCRIBE_EVT_BEACON_MISSED MBIT(3)
+/** BITMAP for subscribe event rssi high */
+#define SUBSCRIBE_EVT_RSSI_HIGH MBIT(4)
+/** BITMAP for subscribe event snr high */
+#define SUBSCRIBE_EVT_SNR_HIGH MBIT(5)
+/** BITMAP for subscribe event data rssi low */
+#define SUBSCRIBE_EVT_DATA_RSSI_LOW MBIT(6)
+/** BITMAP for subscribe event data snr low */
+#define SUBSCRIBE_EVT_DATA_SNR_LOW MBIT(7)
+/** BITMAP for subscribe event data rssi high */
+#define SUBSCRIBE_EVT_DATA_RSSI_HIGH MBIT(8)
+/** BITMAP for subscribe event data snr high */
+#define SUBSCRIBE_EVT_DATA_SNR_HIGH MBIT(9)
+/** BITMAP for subscribe event link quality */
+#define SUBSCRIBE_EVT_LINK_QUALITY MBIT(10)
+/** BITMAP for subscribe event pre_beacon_lost */
+#define SUBSCRIBE_EVT_PRE_BEACON_LOST MBIT(11)
+/** default PRE_BEACON_MISS_COUNT */
+#define DEFAULT_PRE_BEACON_MISS 30
+
+/** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */
+typedef struct _mlan_ds_subscribe_evt {
+	/** evt action */
+	t_u16 evt_action;
+	/** bitmap for subscribe event */
+	t_u16 evt_bitmap;
+	/** Absolute value of RSSI threshold value (dBm) */
+	t_u8 low_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 * N -- report only happend > N consecutive times
+	 */
+	t_u8 low_rssi_freq;
+	/** SNR threshold value (dB) */
+	t_u8 low_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 low_snr_freq;
+	/** Failure count threshold */
+	t_u8 failure_count;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 failure_count_freq;
+	/** num of missed beacons */
+	t_u8 beacon_miss;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 beacon_miss_freq;
+	/** Absolute value of RSSI threshold value (dBm) */
+	t_u8 high_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 high_rssi_freq;
+	/** SNR threshold value (dB) */
+	t_u8 high_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 high_snr_freq;
+	/** Absolute value of data RSSI threshold value (dBm) */
+	t_u8 data_low_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_low_rssi_freq;
+	/** Absolute value of data SNR threshold value (dBm) */
+	t_u8 data_low_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_low_snr_freq;
+	/** Absolute value of data RSSI threshold value (dBm) */
+	t_u8 data_high_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_high_rssi_freq;
+	/** Absolute value of data SNR threshold value (dBm) */
+	t_u8 data_high_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_high_snr_freq;
+	/* Link SNR threshold (dB) */
+	t_u16 link_snr;
+	/* Link SNR frequency */
+	t_u16 link_snr_freq;
+	/* Second minimum rate value as per the rate table below */
+	t_u16 link_rate;
+	/* Second minimum rate frequency */
+	t_u16 link_rate_freq;
+	/* Tx latency value (us) */
+	t_u16 link_tx_latency;
+	/* Tx latency frequency */
+	t_u16 link_tx_lantency_freq;
+	/* Number of pre missed beacons */
+	t_u8 pre_beacon_miss;
+} mlan_ds_subscribe_evt;
+
+/** Max OTP user data length */
+#define MAX_OTP_USER_DATA_LEN 252
+
+/** Type definition of mlan_ds_misc_otp_user_data
+ * for MLAN_OID_MISC_OTP_USER_DATA
+ */
+typedef struct _mlan_ds_misc_otp_user_data {
+	/** Reserved */
+	t_u16 reserved;
+	/** OTP user data length */
+	t_u16 user_data_length;
+	/** User data buffer */
+	t_u8 user_data[MAX_OTP_USER_DATA_LEN];
+} mlan_ds_misc_otp_user_data;
+
+typedef struct _aggr_ctrl_cfg {
+	/** Enable */
+	t_u16 enable;
+	/** Aggregation alignment */
+	t_u16 aggr_align;
+	/** Aggregation max size */
+	t_u16 aggr_max_size;
+	/** Aggregation max packet number */
+	t_u16 aggr_max_num;
+	/** Aggrgation timeout, in microseconds */
+	t_u16 aggr_tmo;
+} aggr_ctrl_cfg;
+
+/** Type definition of mlan_ds_misc_aggr_ctrl
+ *  for MLAN_OID_MISC_AGGR_CTRL
+ */
+typedef struct _mlan_ds_misc_aggr_ctrl {
+	/** Tx aggregation control */
+	aggr_ctrl_cfg tx;
+} mlan_ds_misc_aggr_ctrl;
+
+#ifdef USB
+typedef struct _usb_aggr_ctrl_cfg {
+	/** Enable */
+	t_u16 enable;
+	/** Aggregation mode */
+	t_u16 aggr_mode;
+	/** Aggregation alignment */
+	t_u16 aggr_align;
+	/** Aggregation max packet/size */
+	t_u16 aggr_max;
+	/** Aggrgation timeout, in microseconds */
+	t_u16 aggr_tmo;
+} usb_aggr_ctrl_cfg;
+
+/** Type definition of mlan_ds_misc_usb_aggr_ctrl
+ *  for MLAN_OID_MISC_USB_AGGR_CTRL
+ */
+typedef struct _mlan_ds_misc_usb_aggr_ctrl {
+	/** Tx aggregation control */
+	usb_aggr_ctrl_cfg tx_aggr_ctrl;
+	/** Rx deaggregation control */
+	usb_aggr_ctrl_cfg rx_deaggr_ctrl;
+} mlan_ds_misc_usb_aggr_ctrl;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA 1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS 2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+	/** flags for NOA/OPP_PS */
+	t_u8 flags;
+	/** NoA enable/disable */
+	t_u8 noa_enable;
+	/** index */
+	t_u16 index;
+	/** NoA count */
+	t_u8 noa_count;
+	/** NoA duration */
+	t_u32 noa_duration;
+	/** NoA interval */
+	t_u32 noa_interval;
+	/** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+	/** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+/** Type definition of mlan_ds_gpio_tsf_latch */
+typedef struct _mlan_ds_gpio_tsf_latch {
+    /**clock sync Mode */
+	t_u8 clock_sync_mode;
+    /**clock sync Role */
+	t_u8 clock_sync_Role;
+    /**clock sync GPIO Pin Number */
+	t_u8 clock_sync_gpio_pin_number;
+    /**clock sync GPIO Level or Toggle */
+	t_u8 clock_sync_gpio_level_toggle;
+    /**clock sync GPIO Pulse Width */
+	t_u16 clock_sync_gpio_pulse_width;
+} mlan_ds_gpio_tsf_latch;
+
+/** Type definition of mlan_ds_tsf_info */
+typedef struct _mlan_ds_tsf_info {
+	/**get tsf info format */
+	t_u16 tsf_format;
+	/**tsf info */
+	t_u16 tsf_info;
+	/**tsf */
+	t_u64 tsf;
+	/**Positive or negative offset in microsecond from Beacon TSF to GPIO toggle TSF  */
+	t_s32 tsf_offset;
+} mlan_ds_tsf_info;
+
+#if defined(STA_SUPPORT)
+typedef struct _mlan_ds_misc_pmfcfg {
+	/** Management Frame Protection Capable */
+	t_u8 mfpc;
+	/** Management Frame Protection Required */
+	t_u8 mfpr;
+} mlan_ds_misc_pmfcfg;
+#endif
+
+#define MAX_SSID_NUM 16
+#define MAX_AP_LIST 8
+
+/**Action ID for TDLS disable link*/
+#define WLAN_TDLS_DISABLE_LINK 0x00
+/**Action ID for TDLS enable link*/
+#define WLAN_TDLS_ENABLE_LINK 0x01
+/**Action ID for TDLS create link*/
+#define WLAN_TDLS_CREATE_LINK 0x02
+/**Action ID for TDLS config link*/
+#define WLAN_TDLS_CONFIG_LINK 0x03
+/*reason code*/
+#define MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
+/** TDLS operation buffer */
+typedef struct _mlan_ds_misc_tdls_oper {
+	/** TDLS Action */
+	t_u16 tdls_action;
+	/** TDLS peer address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** peer capability */
+	t_u16 capability;
+	/** peer qos info */
+	t_u8 qos_info;
+	/** peer extend capability */
+	t_u8 *ext_capab;
+	/** extend capability len */
+	t_u8 ext_capab_len;
+	/** support rates */
+	t_u8 *supported_rates;
+	/** supported rates len */
+	t_u8 supported_rates_len;
+	/** peer ht_cap */
+	t_u8 *ht_capa;
+	/** peer vht capability */
+	t_u8 *vht_cap;
+} mlan_ds_misc_tdls_oper;
+
+/** flag for TDLS extcap */
+#define TDLS_IE_FLAGS_EXTCAP 0x0001
+/** flag for TDLS HTCAP */
+#define TDLS_IE_FLAGS_HTCAP 0x0002
+/** flag for TDLS HTINFO */
+#define TDLS_IE_FLAGS_HTINFO 0x0004
+/** flag for TDLS VHTCAP */
+#define TDLS_IE_FLAGS_VHTCAP 0x0008
+/** flag for TDLS VHTOPRAT */
+#define TDLS_IE_FLAGS_VHTOPRAT 0x0010
+/** flag for TDLS AID inof */
+#define TDLS_IE_FLAGS_AID 0x0020
+/** flag for TDLS Supported channels and regulatory class IE*/
+#define TDLS_IE_FLAGS_SUPP_CS_IE 0x0040
+/** flag for TDLS Qos info */
+#define TDLS_IE_FLAGS_QOS_INFO 0x0080
+/** flag for TDLS SETUP */
+#define TDLS_IE_FLAGS_SETUP 0x0100
+
+/** TDLS ie buffer */
+typedef struct _mlan_ds_misc_tdls_ies {
+	/** TDLS peer address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** flags for request IEs */
+	t_u16 flags;
+	/** Qos info */
+	t_u8 QosInfo;
+	/** Extended Capabilities IE */
+	t_u8 ext_cap[IEEE_MAX_IE_SIZE];
+	/** HT Capabilities IE */
+	t_u8 ht_cap[IEEE_MAX_IE_SIZE];
+	/** HT Information IE */
+	t_u8 ht_info[IEEE_MAX_IE_SIZE];
+	/** VHT Capabilities IE */
+	t_u8 vht_cap[IEEE_MAX_IE_SIZE];
+	/** VHT Operations IE */
+	t_u8 vht_oprat[IEEE_MAX_IE_SIZE];
+	/** aid Info */
+	t_u8 aid_info[IEEE_MAX_IE_SIZE];
+	/** supported channels */
+	t_u8 supp_chan[IEEE_MAX_IE_SIZE];
+	/** supported regulatory class */
+	t_u8 regulatory_class[IEEE_MAX_IE_SIZE];
+} mlan_ds_misc_tdls_ies;
+
+#ifdef RX_PACKET_COALESCE
+typedef struct _mlan_ds_misc_rx_packet_coalesce {
+	/** packet threshold */
+	t_u32 packet_threshold;
+	/** timeout value */
+	t_u16 delay;
+} mlan_ds_misc_rx_packet_coalesce;
+#endif
+
+typedef struct _mlan_ds_misc_dfs_repeater {
+	/** Set or Get */
+	t_u16 action;
+	/** 1 on or 0 off */
+	t_u16 mode;
+} mlan_ds_misc_dfs_repeater;
+
+#define WOWLAN_MAX_PATTERN_LEN 20
+#define WOWLAN_MAX_OFFSET_LEN 50
+#define MAX_NUM_FILTERS 10
+#define MEF_MODE_HOST_SLEEP (1 << 0)
+#define MEF_MODE_NON_HOST_SLEEP (1 << 1)
+#define MEF_ACTION_WAKE (1 << 0)
+#define MEF_ACTION_ALLOW (1 << 1)
+#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3
+#define MEF_AUTO_ARP 0x10
+#define MEF_AUTO_PING 0x20
+#define MEF_NS_RESP 0x40
+#define MEF_MAGIC_PKT 0x80
+#define CRITERIA_BROADCAST BIT(0)
+#define CRITERIA_UNICAST BIT(1)
+#define CRITERIA_MULTICAST BIT(3)
+
+#define MAX_NUM_ENTRIES 8
+#define MAX_NUM_BYTE_SEQ 6
+#define MAX_NUM_MASK_SEQ 6
+
+#define OPERAND_DNUM 1
+#define OPERAND_BYTE_SEQ 2
+
+#define MAX_OPERAND 0x40
+#define TYPE_BYTE_EQ (MAX_OPERAND + 1)
+#define TYPE_DNUM_EQ (MAX_OPERAND + 2)
+#define TYPE_BIT_EQ (MAX_OPERAND + 3)
+
+#define RPN_TYPE_AND (MAX_OPERAND + 4)
+#define RPN_TYPE_OR (MAX_OPERAND + 5)
+
+#define ICMP_OF_IP_PROTOCOL 0x01
+#define TCP_OF_IP_PROTOCOL 0x06
+#define UDP_OF_IP_PROTOCOL 0x11
+
+#define IPV4_PKT_OFFSET 20
+#define IP_PROTOCOL_OFFSET 31
+#define PORT_PROTOCOL_OFFSET 44
+
+#define FILLING_TYPE MBIT(0)
+#define FILLING_PATTERN MBIT(1)
+#define FILLING_OFFSET MBIT(2)
+#define FILLING_NUM_BYTES MBIT(3)
+#define FILLING_REPEAT MBIT(4)
+#define FILLING_BYTE_SEQ MBIT(5)
+#define FILLING_MASK_SEQ MBIT(6)
+
+/** Type definition of filter_item
+ *  Support three match methods:
+ *  <1>Byte comparison type=0x41
+ *  <2>Decimal comparison type=0x42
+ *  <3>Bit comparison type=0x43
+ */
+typedef struct _mef_filter_t {
+	/** flag*/
+	t_u32 fill_flag;
+	/** BYTE 0X41; Decimal 0X42; Bit 0x43*/
+	t_u16 type;
+	/** value*/
+	t_u32 pattern;
+	/** offset*/
+	t_u16 offset;
+	/** number of bytes*/
+	t_u16 num_bytes;
+	/** repeat*/
+	t_u16 repeat;
+	/** byte number*/
+	t_u8 num_byte_seq;
+	/** array*/
+	t_u8 byte_seq[MAX_NUM_BYTE_SEQ];
+	/** mask numbers*/
+	t_u8 num_mask_seq;
+	/** array*/
+	t_u8 mask_seq[MAX_NUM_MASK_SEQ];
+} mef_filter_t;
+
+typedef struct _mef_entry_t {
+	/** mode: bit0--hostsleep mode; bit1--non hostsleep mode */
+	t_u8 mode;
+	/** action: 0--discard and not wake host;
+		    1--discard and wake host;
+		    3--allow and wake host;*/
+	t_u8 action;
+	/** filter number */
+	t_u8 filter_num;
+	/** filter array*/
+	mef_filter_t filter_item[MAX_NUM_FILTERS];
+	/** rpn array*/
+	t_u8 rpn[MAX_NUM_FILTERS];
+} mef_entry_t;
+
+/** Type definition of mlan_ds_nvflt_mef_entry
+ *for MLAN_OID_MISC_MEF_FLT_CFG
+ */
+typedef struct _mlan_ds_misc_mef_flt_cfg {
+	/** Type of action*/
+	int mef_act_type;
+	/** Operation code*/
+	t_u32 op_code;
+	/** NV Filter Criteria*/
+	t_u32 criteria;
+	/** NV MEF entry*/
+	mef_entry_t mef_entry;
+} mlan_ds_misc_mef_flt_cfg;
+
+/** Enumeration for action type*/
+enum _mlan_act_mef_act_type {
+	MEF_ACT_ADD = 1,
+	MEF_ACT_ENABLE,
+	MEF_ACT_DISABLE,
+	MEF_ACT_CANCEL,
+	MEF_ACT_AUTOARP,
+	MEF_ACT_WOWLAN,
+	MEF_ACT_IPV6_NS,
+};
+
+typedef struct _mlan_ds_sensor_temp {
+	t_u32 temperature;
+} mlan_ds_sensor_temp;
+
+#define MLAN_KCK_LEN 16
+#define MLAN_KEK_LEN 16
+#define MLAN_REPLAY_CTR_LEN 8
+/** mlan_ds_misc_gtk_rekey_data */
+typedef struct _mlan_ds_misc_gtk_rekey_data {
+	/** key encryption key */
+	t_u8 kek[MLAN_KEK_LEN];
+	/** key confirmation key */
+	t_u8 kck[MLAN_KCK_LEN];
+	/** replay counter */
+	t_u8 replay_ctr[MLAN_REPLAY_CTR_LEN];
+} mlan_ds_misc_gtk_rekey_data;
+typedef struct _mlan_ds_bw_chan_oper {
+	/* bandwidth 20:20M 40:40M 80:80M */
+	t_u8 bandwidth;
+	/* channel number */
+	t_u8 channel;
+	/* Non-global operating class */
+	t_u8 oper_class;
+} mlan_ds_bw_chan_oper;
+
+typedef struct _mlan_ds_ind_rst_cfg {
+	/** Set or Get */
+	t_u16 action;
+	/** oob mode enable/ disable */
+	t_u8 ir_mode;
+	/** gpio pin */
+	t_u8 gpio_pin;
+} mlan_ds_ind_rst_cfg;
+
+#define MKEEP_ALIVE_IP_PKT_MAX 256
+typedef struct _mlan_ds_misc_keep_alive {
+	t_u8 mkeep_alive_id;
+	t_u8 enable;
+	/** enable/disable tcp reset*/
+	t_u8 reset;
+	/**True means saved in driver, false means not saved or download*/
+	t_u8 cached;
+	t_u32 send_interval;
+	t_u16 retry_interval;
+	t_u16 retry_count;
+	t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+	t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
+	t_u16 pkt_len;
+	t_u8 packet[MKEEP_ALIVE_IP_PKT_MAX];
+	/** Ethernet type */
+	t_u16 ether_type;
+} mlan_ds_misc_keep_alive, *pmlan_ds_misc_keep_alive;
+
+/** TX and RX histogram statistic parameters*/
+typedef MLAN_PACK_START struct _mlan_ds_misc_tx_rx_histogram {
+	/** Enable or disable get tx/rx histogram statistic */
+	t_u8 enable;
+	/** Choose to get TX, RX or both histogram statistic */
+	t_u16 action;
+	/** Size of Tx/Rx info */
+	t_u16 size;
+	/** Store Tx/Rx info */
+	t_u8 value[1];
+} MLAN_PACK_END mlan_ds_misc_tx_rx_histogram;
+
+typedef MLAN_PACK_START struct _mlan_ds_cw_mode_ctrl {
+	/** Mode of Operation 0: Disable 1: Tx Continuous Packet 2: Tx
+	 * Continuous Wave */
+	t_u8 mode;
+	/*channel */
+	t_u8 channel;
+	/* channel info */
+	t_u8 chanInfo;
+	/** Tx Power level in dBm */
+	t_u16 txPower;
+	/** Packet Length */
+	t_u16 pktLength;
+	/** bit rate Info */
+	t_u32 rateInfo;
+} MLAN_PACK_END mlan_ds_cw_mode_ctrl;
+
+#define RX_PKT_INFO MBIT(1)
+/** Struct for per-packet configuration */
+typedef struct _mlan_per_pkt_cfg {
+	/** Type ID*/
+	t_u16 type;
+	/** Length of payload*/
+	t_u16 len;
+	/**  Tx/Rx per-packet control */
+	t_u8 tx_rx_control;
+	/** Number of ethernet types in ether_type array */
+	t_u8 proto_type_num;
+	/** Array of ether_type for per-packet control */
+	t_u16 ether_type[];
+} mlan_per_pkt_cfg;
+
+/** Type definition of mlan_ds_misc_robustcoex_params for MLAN_IOCTL_MISC_CFG */
+typedef struct _mlan_ds_misc_robustcoex_params {
+	t_u16 method;
+	/** enable/disable robustcoex gpio cfg */
+	t_u8 enable;
+	/** Number of GPIO */
+	t_u8 gpio_num;
+	/** Polarity of GPIO */
+	t_u8 gpio_polarity;
+} mlan_ds_misc_robustcoex_params;
+
+#if defined(PCIE)
+typedef struct _mlan_ds_ssu_params {
+	t_u32 nskip;
+	t_u32 nsel;
+	t_u32 adcdownsample;
+	t_u32 mask_adc_pkt;
+	t_u32 out_16bits;
+	t_u32 spec_pwr_enable;
+	t_u32 rate_deduction;
+	t_u32 n_pkt_avg;
+} mlan_ds_ssu_params;
+#endif
+
+typedef MLAN_PACK_START struct _mlan_ds_hal_phy_cfg_params {
+	/** 11b pwr spectral density mask enable/disable */
+	t_u8 dot11b_psd_mask_cfg;
+	/** reserved fields for future hal/phy cfg use */
+	t_u8 reserved[7];
+} MLAN_PACK_END mlan_ds_hal_phy_cfg_params;
+
+#define MAX_NUM_MAC 2
+/** Type definition of mlan_ds_misc_mapping_policy */
+typedef struct _mlan_ds_misc_mapping_policy {
+	/** Enable/disable dynamic mapping */
+	t_u16 subcmd;
+	/** Mapping policy */
+	t_u8 mapping_policy;
+} mlan_ds_misc_mapping_policy, *pmlan_ds_misc_mapping_policy;
+
+typedef struct _dmcsChanStatus_t {
+	/** Channel number */
+	t_u8 channel;
+	/** Number of ap on this channel */
+	t_u8 ap_count;
+	/** Number of sta on this channel */
+	t_u8 sta_count;
+} dmcsChanStatus_t, *pdmcsChanStatus_t;
+
+typedef struct _dmcsStatus_t {
+	/** Radio ID */
+	t_u8 radio_id;
+	/** Running mode
+	** 0 - Idle
+	** 1 - DBC
+	** 2 - DRCS
+	*/
+	t_u8 running_mode;
+	/** Current channel status */
+	dmcsChanStatus_t chan_status[2];
+} dmcsStatus_t, *pdmcsStatus_t;
+
+/** Type definition of mlan_ds_misc_dmcs_status */
+typedef struct _mlan_ds_misc_dmcs_status {
+	t_u8 mapping_policy;
+	dmcsStatus_t radio_status[MAX_NUM_MAC];
+} mlan_ds_misc_dmcs_status, *pmlan_ds_misc_dmcs_status;
+
+/** Type definition of mlan_ds_misc_chan_trpc_cfg for
+ * MLAN_OID_MISC_GET_CHAN_TRPC_CFG */
+typedef struct _mlan_ds_misc_chan_trpc_cfg {
+	/** sub_band */
+	t_u16 sub_band;
+	/** length */
+	t_u16 length;
+	/** buf */
+	t_u8 trpc_buf[2048];
+} mlan_ds_misc_chan_trpc_cfg;
+
+#define MFG_CMD_SET_TEST_MODE   1
+#define MFG_CMD_UNSET_TEST_MODE 0
+#define MFG_CMD_TX_ANT          0x1004
+#define MFG_CMD_RX_ANT          0x1005
+#define MFG_CMD_TX_CONT         0x1009
+#define MFG_CMD_RF_CHAN         0x100A
+#define MFG_CMD_CLR_RX_ERR      0x1010
+#define MFG_CMD_TX_FRAME        0x1021
+#define MFG_CMD_RFPWR           0x1033
+#define MFG_CMD_RF_BAND_AG      0x1034
+#define MFG_CMD_RF_CHANNELBW    0x1044
+#define MFG_CMD_RADIO_MODE_CFG  0x1211
+#define MFG_CMD_CONFIG_MAC_HE_TB_TX 0x110A
+/** MFG CMD generic cfg */
+struct MLAN_PACK_START mfg_cmd_generic_cfg {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** value 1 */
+	t_u32 data1;
+	/** value 2 */
+	t_u32 data2;
+	/** value 3 */
+	t_u32 data3;
+} MLAN_PACK_END;
+
+/** MFG CMD Tx Frame 2 */
+struct MLAN_PACK_START mfg_cmd_tx_frame2 {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** enable */
+	t_u32 enable;
+	/** data_rate */
+	t_u32 data_rate;
+	/** frame pattern */
+	t_u32 frame_pattern;
+	/** frame length */
+	t_u32 frame_length;
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Adjust burst sifs */
+	t_u16 adjust_burst_sifs;
+	/** Burst sifs in us*/
+	t_u32 burst_sifs_in_us;
+	/** short preamble */
+	t_u32 short_preamble;
+	/** active sub channel */
+	t_u32 act_sub_ch;
+	/** short GI */
+	t_u32 short_gi;
+	/** Adv coding */
+	t_u32 adv_coding;
+	/** Tx beamforming */
+	t_u32 tx_bf;
+	/** HT Greenfield Mode*/
+	t_u32 gf_mode;
+	/** STBC */
+	t_u32 stbc;
+	/** power id */
+	t_u32 rsvd[2];
+    /** NumPkt */
+	t_u32 NumPkt;
+    /** MaxPE */
+	t_u32 MaxPE;
+    /** BeamChange */
+	t_u32 BeamChange;
+    /** Dcm */
+	t_u32 Dcm;
+    /** Doppler */
+	t_u32 Doppler;
+    /** MidP */
+	t_u32 MidP;
+    /** QNum */
+	t_u32 QNum;
+
+} MLAN_PACK_END;
+
+/* MFG CMD Tx Continuous */
+struct MLAN_PACK_START mfg_cmd_tx_cont {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** enable Tx*/
+	t_u32 enable_tx;
+	/** Continuous Wave mode */
+	t_u32 cw_mode;
+	/** payload pattern */
+	t_u32 payload_pattern;
+	/** CS Mode */
+	t_u32 cs_mode;
+	/** active sub channel */
+	t_u32 act_sub_ch;
+	/** Tx rate */
+	t_u32 tx_rate;
+	/** power id */
+	t_u32 rsvd;
+} MLAN_PACK_END;
+
+struct MLAN_PACK_START mfg_Cmd_HE_TBTx_t {
+    /** MFG command code */
+	t_u32 mfg_cmd;
+    /** Action */
+	t_u16 action;
+    /** Device ID */
+	t_u16 device_id;
+    /** MFG Error code */
+	t_u32 error;
+    /** Enable Tx */
+	t_u16 enable;
+    /** Q num */
+	t_u16 qnum;
+    /** AID */
+	t_u16 aid;
+    /** AXQ Mu Timer */
+	t_u16 axq_mu_timer;
+    /** Tx Power */
+	t_u16 tx_power;
+} MLAN_PACK_END;
+
+typedef struct _mlan_ds_misc_chnrgpwr_cfg {
+	/** length */
+	t_u16 length;
+	/** chnrgpwr buf */
+	t_u8 chnrgpwr_buf[2048];
+} mlan_ds_misc_chnrgpwr_cfg;
+
+/** dfs chan list for MLAN_OID_MISC_CFP_TABLE */
+typedef struct _mlan_ds_misc_cfp_tbl {
+	/** band */
+	t_u8 band;
+	/** num chan */
+	t_u8 num_chan;
+	/** cfp table */
+	chan_freq_power_t cfp_tbl[];
+} mlan_ds_misc_cfp_tbl;
+
+/** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */
+typedef struct _mlan_ds_misc_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Miscellaneous configuration parameter */
+	union {
+		/** Generic IE for MLAN_OID_MISC_GEN_IE */
+		mlan_ds_misc_gen_ie gen_ie;
+		/** Region code for MLAN_OID_MISC_REGION */
+		t_u32 region_code;
+#ifdef SDIO
+		/** SDIO MP-A Ctrl command for MLAN_OID_MISC_SDIO_MPA_CTRL */
+		mlan_ds_misc_sdio_mpa_ctrl mpa_ctrl;
+#endif
+		/** Hostcmd for MLAN_OID_MISC_HOST_CMD */
+		mlan_ds_misc_cmd hostcmd;
+		/** System clock for MLAN_OID_MISC_SYS_CLOCK */
+		mlan_ds_misc_sys_clock sys_clock;
+		/** WWS set/get for MLAN_OID_MISC_WWS */
+		t_u32 wws_cfg;
+		/** Get associate response for MLAN_OID_MISC_ASSOC_RSP */
+		mlan_ds_misc_assoc_rsp assoc_resp;
+		/** Function init/shutdown for MLAN_OID_MISC_INIT_SHUTDOWN */
+		t_u32 func_init_shutdown;
+		/** Custom IE for MLAN_OID_MISC_CUSTOM_IE */
+		mlan_ds_misc_custom_ie cust_ie;
+		t_u16 tdls_idle_time;
+		/** Config dynamic bandwidth*/
+		t_u16 dyn_bw;
+		/** TDLS configuration for MLAN_OID_MISC_TDLS_CONFIG */
+		mlan_ds_misc_tdls_config tdls_config;
+		/** TDLS operation for MLAN_OID_MISC_TDLS_OPER */
+		mlan_ds_misc_tdls_oper tdls_oper;
+		/** TDLS ies for  MLAN_OID_MISC_GET_TDLS_IES */
+		mlan_ds_misc_tdls_ies tdls_ies;
+		/**tdls cs off channel*/
+		t_u8 tdls_cs_channel;
+		/** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+		mlan_ds_misc_tx_datapause tx_datapause;
+		/** IP address configuration */
+		mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+		/** IPv6 Router Advertisement offload configuration */
+		mlan_ds_misc_ipv6_ra_offload ipv6_ra_offload;
+		/** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+		t_u32 mac_ctrl;
+		/** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+		mlan_ds_misc_mef_cfg mef_cfg;
+		/** CFP code for MLAN_OID_MISC_CFP_CODE */
+		mlan_ds_misc_cfp_code cfp_code;
+		/** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+		mlan_ds_misc_country_code country_code;
+		/** Thermal reading for MLAN_OID_MISC_THERMAL */
+		t_u32 thermal;
+		/** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+		t_u32 mgmt_subtype_mask;
+		/** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+		mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+		/** Driver debug bit masks */
+		t_u32 drvdbg;
+#endif
+		/** Hotspot config param set */
+		t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+		ExtCap_t ext_cap;
+#endif
+		mlan_ds_misc_otp_user_data otp_user_data;
+#ifdef USB
+		/** USB aggregation parameters for MLAN_OID_MISC_USB_AGGR_CTRL
+		 */
+		mlan_ds_misc_usb_aggr_ctrl usb_aggr_params;
+#endif
+		mlan_ds_misc_aggr_ctrl aggr_params;
+		/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_gpio_tsf_latch gpio_tsf_latch_config;
+		mlan_ds_tsf_info tsf_info;
+		mlan_ds_coalesce_cfg coalesce_cfg;
+		t_u8 low_pwr_mode;
+		/** MEF-FLT-CONFIG for MLAN_OID_MISC_NV_FLT_CFG */
+		mlan_ds_misc_mef_flt_cfg mef_flt_cfg;
+		mlan_ds_misc_dfs_repeater dfs_repeater;
+#ifdef RX_PACKET_COALESCE
+		mlan_ds_misc_rx_packet_coalesce rx_coalesce;
+#endif
+		/** FW reload flag */
+		t_u8 fw_reload;
+		mlan_ds_sensor_temp sensor_temp;
+		/** GTK rekey data */
+		mlan_ds_misc_gtk_rekey_data gtk_rekey;
+		mlan_ds_bw_chan_oper bw_chan_oper;
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+		t_u64 misc_tsf;
+		mlan_ds_custom_reg_domain custom_reg_domain;
+		mlan_ds_misc_keep_alive keep_alive;
+		mlan_ds_misc_tx_rx_histogram tx_rx_histogram;
+		mlan_ds_cw_mode_ctrl cwmode;
+		/**  Tx/Rx per-packet control */
+		t_u8 txrx_pkt_ctrl;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+#if defined(PCIE)
+		mlan_ds_ssu_params ssu_params;
+#endif
+		/** boot sleep enable or disable */
+		t_u16 boot_sleep;
+		/** Mapping Policy */
+		mlan_ds_misc_mapping_policy dmcs_policy;
+		mlan_ds_misc_dmcs_status dmcs_status;
+		mlan_ds_misc_rx_abort_cfg rx_abort_cfg;
+		mlan_ds_misc_rx_abort_cfg_ext rx_abort_cfg_ext;
+		mlan_ds_misc_tx_ampdu_prot_mode tx_ampdu_prot_mode;
+		mlan_ds_misc_rate_adapt_cfg rate_adapt_cfg;
+		mlan_ds_misc_cck_desense_cfg cck_desense_cfg;
+		mlan_ds_misc_chan_trpc_cfg trpc_cfg;
+		mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+
+		mlan_ds_band_steer_cfg band_steer_cfg;
+		mlan_ds_beacon_stuck_param_cfg beacon_stuck_cfg;
+		struct mfg_cmd_generic_cfg mfg_generic_cfg;
+		struct mfg_cmd_tx_cont mfg_tx_cont;
+		struct mfg_cmd_tx_frame2 mfg_tx_frame2;
+		struct mfg_Cmd_HE_TBTx_t mfg_he_power;
+		mlan_ds_misc_arb_cfg arb_cfg;
+		mlan_ds_misc_cfp_tbl cfp;
+		t_u8 range_ext_mode;
+		mlan_ds_misc_dot11mc_unassoc_ftm_cfg dot11mc_unassoc_ftm_cfg;
+		mlan_ds_misc_tp_state tp_state;
+		mlan_ds_hal_phy_cfg_params hal_phy_cfg_params;
+#ifdef UAP_SUPPORT
+		t_u8 wacp_mode;
+#endif
+	} param;
+} mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
+
+/** Hotspot status enable */
+#define HOTSPOT_ENABLED MBIT(0)
+/** Hotspot status disable */
+#define HOTSPOT_DISABLED MFALSE
+/** Keep Hotspot2.0 compatible in mwu and wpa_supplicant */
+#define HOTSPOT_BY_SUPPLICANT MBIT(1)
+
+/** Reason codes */
+#define MLAN_REASON_UNSPECIFIED 1
+#define MLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define MLAN_REASON_DEAUTH_LEAVING 3
+#define MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define MLAN_REASON_DISASSOC_AP_BUSY 5
+#define MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA 6
+#define MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA 7
+#define MLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+#endif /* !_MLAN_IOCTL_H_ */
diff --git a/wlan_sd8987/mlan/mlan_join.c b/wlan_sd8987/mlan/mlan_join.c
new file mode 100755
index 0000000..e2cde9d
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_join.c
@@ -0,0 +1,2688 @@
+/** @file mlan_join.c
+ *
+ *  @brief Functions implementing wlan infrastructure and adhoc join routines
+ *
+ *  IOCTL handlers as well as command preparation and response routines
+ *  for sending adhoc start, adhoc join, and association commands
+ *  to the firmware.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/30/2008: initial version
+******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+/********************************************************
+			Local Constants
+********************************************************/
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief Append a generic IE as a pass through TLV to a TLV buffer.
+ *
+ *  This function is called from the network join command prep. routine.
+ *    If the IE buffer has been setup by the application, this routine appends
+ *    the buffer as a pass through TLV type to the request.
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param ppbuffer pointer to command buffer pointer
+ *
+ *  @return         bytes added to the buffer
+ */
+static int
+wlan_cmd_append_generic_ie(mlan_private *priv, t_u8 **ppbuffer)
+{
+	int ret_len = 0;
+	MrvlIEtypesHeader_t ie_header;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	/*
+	 * If there is a generic ie buffer setup, append it to the return
+	 *   parameter buffer pointer.
+	 */
+	if (priv->gen_ie_buf_len) {
+		PRINTM(MINFO, "append generic IE %d to %p\n",
+		       priv->gen_ie_buf_len, *ppbuffer);
+
+		/* Wrap the generic IE buffer with a pass through TLV type */
+		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+		ie_header.len = wlan_cpu_to_le16(priv->gen_ie_buf_len);
+		memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+			   sizeof(ie_header), sizeof(ie_header));
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += sizeof(ie_header);
+		ret_len += sizeof(ie_header);
+
+		/* Copy the generic IE buffer to the output buffer, advance
+		 * pointer */
+		memcpy_ext(priv->adapter, *ppbuffer, priv->gen_ie_buf,
+			   priv->gen_ie_buf_len, priv->gen_ie_buf_len);
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += priv->gen_ie_buf_len;
+		ret_len += priv->gen_ie_buf_len;
+
+		/* Reset the generic IE buffer */
+		priv->gen_ie_buf_len = 0;
+	}
+
+	/* return the length appended to the buffer */
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief Append  IE as a pass through TLV to a TLV buffer.
+ *
+ *  This routine appends IE as a pass through TLV type to the request.
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param ie       A pointer to IE buffer
+ *  @param ppbuffer pointer to command buffer pointer
+ *
+ *  @return         bytes added to the buffer
+ */
+static int
+wlan_cmd_append_pass_through_ie(mlan_private *priv,
+				IEEEtypes_Generic_t *ie, t_u8 **ppbuffer)
+{
+	int ret_len = 0;
+	MrvlIEtypesHeader_t ie_header;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (ie->ieee_hdr.len) {
+		PRINTM(MINFO, "append generic IE %d to %p\n", ie->ieee_hdr.len,
+		       *ppbuffer);
+
+		/* Wrap the generic IE buffer with a pass through TLV type */
+		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
+		ie_header.len = wlan_cpu_to_le16(ie->ieee_hdr.len +
+						 sizeof(IEEEtypes_Header_t));
+		memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+			   sizeof(ie_header), sizeof(ie_header));
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += sizeof(ie_header);
+		ret_len += sizeof(ie_header);
+
+		/* Copy the generic IE buffer to the output buffer, advance
+		 * pointer */
+		memcpy_ext(priv->adapter, *ppbuffer, ie,
+			   ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
+			   ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
+		ret_len += ie->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
+	}
+	/* return the length appended to the buffer */
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief Append TSF tracking info from the scan table for the target AP
+ *
+ *  This function is called from the network join command prep. routine.
+ *     The TSF table TSF sent to the firmware contains two TSF values:
+ *        - the TSF of the target AP from its previous beacon/probe response
+ *        - the TSF timestamp of our local MAC at the time we observed the
+ *          beacon/probe response.
+ *
+ *     The firmware uses the timestamp values to set an initial TSF value
+ *        in the MAC for the new association after a reassociation attempt.
+ *
+ *    @param pmpriv     A pointer to mlan_private structure
+ *    @param ppbuffer   A pointer to command buffer pointer
+ *    @param pbss_desc  A pointer to the BSS Descriptor from the scan table of
+ *                      the AP we are trying to join
+ *
+ *    @return         bytes added to the buffer
+ */
+static int
+wlan_cmd_append_tsf_tlv(mlan_private *pmriv, t_u8 **ppbuffer,
+			BSSDescriptor_t *pbss_desc)
+{
+	MrvlIEtypes_TsfTimestamp_t tsf_tlv;
+	t_u64 tsf_val;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	memset(pmriv->adapter, &tsf_tlv, 0x00,
+	       sizeof(MrvlIEtypes_TsfTimestamp_t));
+
+	tsf_tlv.header.type = wlan_cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
+	tsf_tlv.header.len = wlan_cpu_to_le16(2 * sizeof(tsf_val));
+
+	memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_tlv, sizeof(tsf_tlv.header),
+		   sizeof(tsf_tlv.header));
+	*ppbuffer += sizeof(tsf_tlv.header);
+
+	/* TSF timestamp from the firmware TSF when the bcn/prb rsp was received
+	 */
+	tsf_val = wlan_cpu_to_le64(pbss_desc->network_tsf);
+	memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val),
+		   sizeof(tsf_val));
+	*ppbuffer += sizeof(tsf_val);
+
+	memcpy_ext(pmriv->adapter, &tsf_val, pbss_desc->time_stamp,
+		   sizeof(pbss_desc->time_stamp), sizeof(tsf_val));
+
+	PRINTM(MINFO, "ASSOC: TSF offset calc: %016llx - %016llx\n", tsf_val,
+	       pbss_desc->network_tsf);
+
+	memcpy_ext(pmriv->adapter, *ppbuffer, &tsf_val, sizeof(tsf_val),
+		   sizeof(tsf_val));
+	*ppbuffer += sizeof(tsf_val);
+
+	LEAVE();
+	return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
+}
+
+/**
+ *  @brief This function finds out the common rates between rate1 and rate2.
+ *
+ *  It will fill common rates in rate1 as output if found.
+ *
+ *  NOTE: Setting the MSB of the basic rates needs to be taken
+ *   care of, either before or after calling this function
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param rate1       the buffer which keeps input and output
+ *  @param rate1_size  the size of rate1 buffer
+ *  @param rate2       the buffer which keeps rate2
+ *  @param rate2_size  the size of rate2 buffer.
+ *
+ *  @return            MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_get_common_rates(mlan_private *pmpriv,
+		      t_u8 *rate1, t_u32 rate1_size,
+		      t_u8 *rate2, t_u32 rate2_size)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	t_u8 *ptr = rate1;
+	t_u8 *tmp = MNULL;
+	t_u32 i, j;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle, rate1_size,
+			       MLAN_MEM_DEF, &tmp);
+	if (ret != MLAN_STATUS_SUCCESS || !tmp) {
+		PRINTM(MERROR, "Failed to allocate buffer\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memcpy_ext(pmpriv->adapter, tmp, rate1, rate1_size, rate1_size);
+	memset(pmpriv->adapter, rate1, 0, rate1_size);
+
+	for (i = 0; rate2[i] && i < rate2_size; i++) {
+		for (j = 0; tmp[j] && j < rate1_size; j++) {
+			/* Check common rate, excluding the bit
+			 * for basic rate */
+			if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
+				*rate1++ = tmp[j];
+				break;
+			}
+		}
+	}
+
+	HEXDUMP("rate1 (AP) Rates", tmp, rate1_size);
+	HEXDUMP("rate2 (Card) Rates", rate2, rate2_size);
+	HEXDUMP("Common Rates", ptr, rate1 - ptr);
+	PRINTM(MINFO, "Tx DataRate is set to 0x%X\n", pmpriv->data_rate);
+
+	if (!pmpriv->is_data_rate_auto) {
+		while (*ptr) {
+			if ((*ptr & 0x7f) == pmpriv->data_rate) {
+				ret = MLAN_STATUS_SUCCESS;
+				goto done;
+			}
+			ptr++;
+		}
+		PRINTM(MMSG,
+		       "Previously set fixed data rate %#x is not "
+		       "compatible with the network\n", pmpriv->data_rate);
+
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	if (tmp)
+		pcb->moal_mfree(pmpriv->adapter->pmoal_handle, tmp);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Create the intersection of the rates supported by a target BSS and
+ *         our pmadapter settings for use in an assoc/join command.
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pbss_desc        BSS Descriptor whose rates are used in the setup
+ *  @param pout_rates       Output: Octet array of rates common between the BSS
+ *                          and the pmadapter supported rates settings
+ *  @param pout_rates_size  Output: Number of rates/octets set in pout_rates
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_setup_rates_from_bssdesc(mlan_private *pmpriv,
+			      BSSDescriptor_t *pbss_desc,
+			      t_u8 *pout_rates, t_u32 *pout_rates_size)
+{
+	t_u8 card_rates[WLAN_SUPPORTED_RATES];
+	t_u32 card_rates_size = 0;
+	ENTER();
+	/* Copy AP supported rates */
+	memcpy_ext(pmpriv->adapter, pout_rates, pbss_desc->supported_rates,
+		   WLAN_SUPPORTED_RATES, WLAN_SUPPORTED_RATES);
+
+	if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
+	     pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
+	    (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
+		/* Special Case: For Japan, 11G rates on CH14 are not allowed */
+		card_rates_size =
+			wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
+						 BAND_B, card_rates);
+	} else {
+		/* Get the STA supported rates */
+		card_rates_size =
+			wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
+						 pmpriv->config_bands,
+						 card_rates);
+	}
+	/* Get the common rates between AP and STA supported rates */
+	if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES,
+				  card_rates, card_rates_size)) {
+		*pout_rates_size = 0;
+		PRINTM(MERROR, "wlan_get_common_rates failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	*pout_rates_size =
+		MIN(wlan_strlen((char *)pout_rates), WLAN_SUPPORTED_RATES);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Update the scan entry TSF timestamps to reflect a new association
+ *
+ *  @param pmpriv        A pointer to mlan_private structure
+ *  @param pnew_bss_desc A pointer to the newly associated AP's scan table entry
+ *
+ *  @return              N/A
+ */
+static t_void
+wlan_update_tsf_timestamps(mlan_private *pmpriv, BSSDescriptor_t *pnew_bss_desc)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 table_idx;
+	t_u64 new_tsf_base;
+	t_s64 tsf_delta;
+
+	ENTER();
+
+	memcpy_ext(pmpriv->adapter, &new_tsf_base, pnew_bss_desc->time_stamp,
+		   sizeof(pnew_bss_desc->time_stamp), sizeof(new_tsf_base));
+
+	tsf_delta = new_tsf_base - pnew_bss_desc->network_tsf;
+
+	PRINTM(MINFO, "TSF: Update TSF timestamps, 0x%016llx -> 0x%016llx\n",
+	       pnew_bss_desc->network_tsf, new_tsf_base);
+
+	for (table_idx = 0; table_idx < pmadapter->num_in_scan_table;
+	     table_idx++) {
+		pmadapter->pscan_table[table_idx].network_tsf += tsf_delta;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Append a wapi IE
+ *
+ *  This function is called from the network join command prep. routine.
+ *    If the IE buffer has been setup by the application, this routine appends
+ *    the buffer as a wapi TLV type to the request.
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param ppbuffer pointer to command buffer pointer
+ *
+ *  @return         bytes added to the buffer
+ */
+static int
+wlan_cmd_append_wapi_ie(mlan_private *priv, t_u8 **ppbuffer)
+{
+	int retlen = 0;
+	MrvlIEtypesHeader_t ie_header;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	/*
+	 * If there is a wapi ie buffer setup, append it to the return
+	 *   parameter buffer pointer.
+	 */
+	if (priv->wapi_ie_len) {
+		PRINTM(MCMND, "append wapi ie %d to %p\n", priv->wapi_ie_len,
+		       *ppbuffer);
+
+		/* Wrap the generic IE buffer with a pass through TLV type */
+		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+		ie_header.len = wlan_cpu_to_le16(priv->wapi_ie_len);
+		memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+			   sizeof(ie_header), sizeof(ie_header));
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += sizeof(ie_header);
+		retlen += sizeof(ie_header);
+
+		/* Copy the wapi IE buffer to the output buffer, advance pointer
+		 */
+		memcpy_ext(priv->adapter, *ppbuffer, priv->wapi_ie,
+			   priv->wapi_ie_len, priv->wapi_ie_len);
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += priv->wapi_ie_len;
+		retlen += priv->wapi_ie_len;
+	}
+	/* return the length appended to the buffer */
+	LEAVE();
+	return retlen;
+}
+
+/**
+ *  @brief Append a osen IE
+ *
+ *  This function is called from the network join command prep. routine.
+ *    If the IE buffer has been setup by the application, this routine appends
+ *    the buffer as a osen TLV type to the request.
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param ppbuffer pointer to command buffer pointer
+ *
+ *  @return         bytes added to the buffer
+ */
+static int
+wlan_cmd_append_osen_ie(mlan_private *priv, t_u8 **ppbuffer)
+{
+	int retlen = 0;
+	MrvlIEtypesHeader_t ie_header;
+
+	ENTER();
+
+	/* Null Checks */
+	if (ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+	if (*ppbuffer == MNULL) {
+		LEAVE();
+		return 0;
+	}
+
+	/*
+	 * If there is a osen ie buffer setup, append it to the return
+	 *   parameter buffer pointer.
+	 */
+	if (priv->osen_ie_len) {
+		PRINTM(MCMND, "append osen ie %d to %p\n", priv->osen_ie_len,
+		       *ppbuffer);
+
+		/* Wrap the generic IE buffer with a pass through TLV type */
+		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_VENDOR_SPECIFIC_IE);
+		ie_header.len = wlan_cpu_to_le16(priv->osen_ie[1]);
+		memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
+			   sizeof(ie_header), sizeof(ie_header));
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += sizeof(ie_header);
+		retlen += sizeof(ie_header);
+
+		/* Copy the osen IE buffer to the output buffer, advance pointer
+		 */
+		memcpy_ext(priv->adapter, *ppbuffer, &priv->osen_ie[2],
+			   priv->osen_ie[1], priv->osen_ie[1]);
+
+		/* Increment the return size and the return buffer pointer param
+		 */
+		*ppbuffer += priv->osen_ie[1];
+		retlen += priv->osen_ie[1];
+	}
+	/* return the length appended to the buffer */
+	LEAVE();
+	return retlen;
+}
+
+/**
+ *  @brief This function get the rsn_cap from RSN ie buffer.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param data         A pointer to rsn_ie data after IE header
+ *  @param return       rsn_cap
+ */
+static t_u16
+wlan_get_rsn_cap(t_u8 *data)
+{
+	t_u16 rsn_cap = 0;
+	t_u16 *ptr;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	/* rsn_cap = data + 2 bytes version + 4 bytes
+	 * group_cipher_suite + 2 bytes pairwise_cipher_count +
+	 * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
+	 * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
+	 */
+	ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8));
+	pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
+	ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8) +
+			sizeof(t_u16) +
+			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
+	akm_suite_count = wlan_le16_to_cpu(*ptr);
+	ptr = (t_u16 *)(data + sizeof(t_u16) + 4 * sizeof(t_u8) +
+			sizeof(t_u16) +
+			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+			sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
+	rsn_cap = wlan_le16_to_cpu(*ptr);
+	PRINTM(MCMND, "rsn_cap=0x%x\n", rsn_cap);
+	return rsn_cap;
+}
+
+/**
+ *  @brief This function check if we should enable 11w
+ *
+ *  @param pmpriv       	A pointer to mlan_private structure
+ *
+ *  @param BSSDescriptor_t      A pointer to BSSDescriptor_t data structure
+ *  @param return       	MTRUE/MFALSE
+ */
+static t_u8
+wlan_use_mfp(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc)
+{
+	t_u16 ap_rsn_cap = 0;
+	t_u16 sta_rsn_cap = 0;
+	t_u8 ap_mfpc, ap_mfpr;
+	t_u8 sta_mfpc, sta_mfpr;
+
+	if (pmpriv->wpa_ie[0] != RSN_IE)
+		return 0;
+	sta_rsn_cap = wlan_get_rsn_cap(pmpriv->wpa_ie + 2);
+	if (!pbss_desc->prsn_ie)
+		return 0;
+	ap_rsn_cap = wlan_get_rsn_cap(pbss_desc->prsn_ie->data);
+	ap_mfpc = ((ap_rsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+	ap_mfpr = ((ap_rsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+	sta_mfpc = ((sta_rsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+	sta_mfpr = ((sta_rsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+	if (!ap_mfpc && !ap_mfpr)
+		return MFALSE;
+	if (!sta_mfpc && !sta_mfpr)
+		return MFALSE;
+	return MTRUE;
+}
+
+/********************************************************
+				Global Functions
+********************************************************/
+
+/**
+ *  @brief This function updates RSN IE in the association request.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param ptlv_rsn_ie       A pointer to rsn_ie TLV
+ */
+static int
+wlan_update_rsn_ie(mlan_private *pmpriv, MrvlIEtypes_RsnParamSet_t *ptlv_rsn_ie)
+{
+	t_u16 *prsn_cap;
+	t_u16 *ptr;
+	t_u16 *akm_suite_count_ptr;
+	t_u16 pmf_mask = 0x00;
+	t_u8 *temp;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	t_u16 temp_akm_suite_count = 0;
+	int found = 0;
+	t_u8 sha_256_oui[4] = { 0x00, 0x0f, 0xac, 0x06 };
+	t_u8 sae_oui[4] = { 0x00, 0x0f, 0xac, 0x08 };
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	int ap_mfpc = 0, ap_mfpr = 0, ret = MLAN_STATUS_SUCCESS;
+
+	pmf_mask = (((pmpriv->pmfcfg.mfpc << MFPC_BIT) |
+		     (pmpriv->pmfcfg.mfpr << MFPR_BIT)) | (~PMF_MASK));
+	/* prsn_cap = prsn_ie->rsn_ie + 2 bytes version + 4 bytes
+	 * group_cipher_suite + 2 bytes pairwise_cipher_count +
+	 * pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes
+	 * akm_suite_count + akm_suite_count * AKM_SUITE_LEN
+	 */
+	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8));
+	pairwise_cipher_count = wlan_le16_to_cpu(*ptr);
+	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
+			sizeof(t_u16) +
+			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN);
+	temp_akm_suite_count = wlan_le16_to_cpu(*ptr);
+	akm_suite_count = wlan_le16_to_cpu(*ptr);
+	/* Save pointer to akm_suite_count in RSN IE to update it later */
+	akm_suite_count_ptr = ptr;
+	temp = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
+		sizeof(t_u16) +
+		pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+		sizeof(t_u16);
+	/* ptr now points to the 1st AKM suite */
+	if (temp_akm_suite_count > 1) {
+		while (temp_akm_suite_count) {
+			if (pmpriv->sec_info.authentication_mode ==
+			    MLAN_AUTH_MODE_SAE) {
+				if (!memcmp(pmadapter, temp, sae_oui,
+					    AKM_SUITE_LEN)) {
+					found = 1;
+					break;
+				}
+			} else if (!memcmp(pmadapter, temp, sha_256_oui,
+					   AKM_SUITE_LEN)) {
+				found = 1;
+				break;
+			}
+			temp += AKM_SUITE_LEN;
+			temp_akm_suite_count--;
+		}
+		if (found) {
+			/* Copy SHA256 as AKM suite */
+			memcpy_ext(pmadapter,
+				   ptlv_rsn_ie->rsn_ie +
+				   (sizeof(t_u16) + 4 * sizeof(t_u8) +
+				    sizeof(t_u16) +
+				    pairwise_cipher_count *
+				    PAIRWISE_CIPHER_SUITE_LEN +
+				    sizeof(t_u16)),
+				   temp, AKM_SUITE_LEN, AKM_SUITE_LEN);
+			/* Shift remaining bytes of RSN IE after this */
+			memmove(pmadapter,
+				ptlv_rsn_ie->rsn_ie +
+				(sizeof(t_u16) + 4 * sizeof(t_u8) +
+				 sizeof(t_u16) +
+				 pairwise_cipher_count *
+				 PAIRWISE_CIPHER_SUITE_LEN +
+				 sizeof(t_u16) + AKM_SUITE_LEN),
+				ptlv_rsn_ie->rsn_ie +
+				(sizeof(t_u16) + 4 * sizeof(t_u8) +
+				 sizeof(t_u16) +
+				 pairwise_cipher_count *
+				 PAIRWISE_CIPHER_SUITE_LEN +
+				 sizeof(t_u16) +
+				 akm_suite_count * AKM_SUITE_LEN),
+				ptlv_rsn_ie->header.len -
+				(sizeof(t_u16) + 4 * sizeof(t_u8) +
+				 sizeof(t_u16) +
+				 pairwise_cipher_count *
+				 PAIRWISE_CIPHER_SUITE_LEN +
+				 sizeof(t_u16) +
+				 akm_suite_count * AKM_SUITE_LEN));
+			ptlv_rsn_ie->header.len =
+				ptlv_rsn_ie->header.len -
+				(akm_suite_count - 1) * AKM_SUITE_LEN;
+			/* Update akm suite count */
+			akm_suite_count = 1;
+			*akm_suite_count_ptr = akm_suite_count;
+		}
+	}
+	ptr = (t_u16 *)(ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) +
+			sizeof(t_u16) +
+			pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN +
+			sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN);
+	prsn_cap = ptr;
+
+	ap_mfpc = ((*prsn_cap & (0x1 << MFPC_BIT)) == (0x1 << MFPC_BIT));
+	ap_mfpr = ((*prsn_cap & (0x1 << MFPR_BIT)) == (0x1 << MFPR_BIT));
+
+	if ((!ap_mfpc && !ap_mfpr && pmpriv->pmfcfg.mfpr) ||
+	    ((!ap_mfpc) && ap_mfpr) ||
+	    (ap_mfpc && ap_mfpr && (!pmpriv->pmfcfg.mfpc))) {
+		PRINTM(MERROR,
+		       "Mismatch in PMF config of STA and AP, can't associate to AP\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if ((pmpriv->pmfcfg.mfpr && pmpriv->pmfcfg.mfpc) || pmpriv->pmfcfg.mfpc) {
+		*prsn_cap |= PMF_MASK;
+		*prsn_cap &= pmf_mask;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief This function is to find FT AKM in RSN.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @param rsn_ie       A pointer to rsn_ie
+ *
+ */
+t_u8
+wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie)
+{
+	t_u8 *temp;
+	t_u16 count;
+	t_u16 pairwise_cipher_count = 0;
+	t_u16 akm_suite_count = 0;
+	t_u8 found = 0;
+	t_u8 rsn_ft_1x_oui[4] = { 0x00, 0x0f, 0xac, 0x03 };
+	t_u8 rsn_ft_psk_oui[4] = { 0x00, 0x0f, 0xac, 0x04 };
+	t_u8 rsn_ft_sae_oui[4] = { 0x00, 0x0f, 0xac, 0x09 };
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (!rsn_ie)
+		goto done;
+
+	if (rsn_ie[0] != RSN_IE)
+		goto done;
+
+	/*  2 bytes header + 2 bytes version + 4 bytes group_cipher_suite +
+	 *  2 bytes pairwise_cipher_count + pairwise_cipher_count *
+	 * PAIRWISE_CIPHER_SUITE_LEN (4) + 2 bytes akm_suite_count +
+	 * akm_suite_count * AKM_SUITE_LEN (4)
+	 */
+	count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8));
+	pairwise_cipher_count = wlan_le16_to_cpu(count);
+	count = *(t_u16 *)(rsn_ie + 2 + 2 + 4 * sizeof(t_u8) + sizeof(t_u16) +
+			   pairwise_cipher_count * 4);
+	akm_suite_count = wlan_le16_to_cpu(count);
+	temp = (t_u8 *)(rsn_ie + 2 + sizeof(t_u16) + 4 * sizeof(t_u8) +
+			sizeof(t_u16) + pairwise_cipher_count * 4 +
+			sizeof(t_u16));
+
+	while (akm_suite_count) {
+		if (!memcmp(pmadapter, temp, rsn_ft_1x_oui,
+			    sizeof(rsn_ft_1x_oui)) ||
+		    !memcmp(pmadapter, temp, rsn_ft_psk_oui,
+			    sizeof(rsn_ft_psk_oui)) ||
+		    !memcmp(pmadapter, temp, rsn_ft_sae_oui,
+			    sizeof(rsn_ft_sae_oui))) {
+			found = 1;
+			break;
+		}
+		temp += 4;
+		akm_suite_count--;
+	}
+
+done:
+	LEAVE();
+	return found;
+}
+
+/**
+ *  @brief This function is to find specific IE.
+ *
+ *  @param ie           A pointer to ie buffer
+ *  @param ie_len    Length of ie buffer
+ *  @param ie_type  Type of ie that wants to be found in ie buffer
+ *
+ *  @return     MFALSE if not found; MTURE if found
+ */
+static t_u8
+wlan_find_ie(t_u8 *ie, t_u8 ie_len, t_u8 ie_type)
+{
+	IEEEtypes_Header_t *pheader = MNULL;
+	t_u8 *pos = MNULL;
+	t_s8 ret_len;
+	t_u8 ret = MFALSE;
+
+	ENTER();
+
+	pos = (t_u8 *)ie;
+	ret_len = ie_len;
+	while (ret_len >= 2) {
+		pheader = (IEEEtypes_Header_t *)pos;
+		if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) > ret_len) {
+			PRINTM(MMSG, "invalid IE length = %d left len %d\n",
+			       pheader->len, ret_len);
+			break;
+		}
+		if (pheader->element_id == ie_type) {
+			ret = MTRUE;
+			break;
+		}
+		ret_len -= pheader->len + sizeof(IEEEtypes_Header_t);
+		pos += pheader->len + sizeof(IEEEtypes_Header_t);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of association.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer cast of BSSDescriptor_t from the
+ *                        scan table to assoc
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_associate(mlan_private *pmpriv,
+			  HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_ASSOCIATE *passo = &cmd->params.associate;
+	BSSDescriptor_t *pbss_desc;
+	MrvlIEtypes_SsIdParamSet_t *pssid_tlv;
+	MrvlIEtypes_PhyParamSet_t *pphy_tlv;
+	MrvlIEtypes_SsParamSet_t *pss_tlv;
+	MrvlIEtypes_RatesParamSet_t *prates_tlv;
+	MrvlIEtypes_AuthType_t *pauth_tlv = MNULL;
+	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv = MNULL;
+	MrvlIEtypes_SecurityCfg_t *psecurity_cfg_ie = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+	WLAN_802_11_RATES rates;
+	t_u32 rates_size;
+	t_u16 tmp_cap;
+	t_u8 *pos;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	void *rsn_wpa_ie_tmp = MNULL;
+#endif
+	t_u8 ft_akm = 0;
+	t_u8 oper_class;
+	t_u8 oper_class_flag = MFALSE;
+	MrvlIEtypes_HostMlme_t *host_mlme_tlv = MNULL;
+	MrvlIEtypes_PrevBssid_t *prev_bssid_tlv = MNULL;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+
+	ENTER();
+
+	pbss_desc = (BSSDescriptor_t *)pdata_buf;
+	pos = (t_u8 *)passo;
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
+
+	/* Save so we know which BSS Desc to use in the response handler */
+	pmpriv->pattempted_bss_desc = pbss_desc;
+	/* clear assoc_rsp_size */
+	pmpriv->assoc_rsp_size = 0;
+
+	memcpy_ext(pmadapter, passo->peer_sta_addr, pbss_desc->mac_address,
+		   sizeof(pbss_desc->mac_address),
+		   sizeof(passo->peer_sta_addr));
+	pos += sizeof(passo->peer_sta_addr);
+
+	/* Set the listen interval */
+	passo->listen_interval = wlan_cpu_to_le16(pmpriv->listen_interval);
+	/* Set the beacon period */
+	passo->beacon_period = wlan_cpu_to_le16(pbss_desc->beacon_period);
+
+	pos += sizeof(passo->cap_info);
+	pos += sizeof(passo->listen_interval);
+	pos += sizeof(passo->beacon_period);
+	pos += sizeof(passo->dtim_period);
+
+	pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)pos;
+	pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+	pssid_tlv->header.len = (t_u16)pbss_desc->ssid.ssid_len;
+	memcpy_ext(pmadapter, pssid_tlv->ssid, pbss_desc->ssid.ssid,
+		   pssid_tlv->header.len, pssid_tlv->header.len);
+	pos += sizeof(pssid_tlv->header) + pssid_tlv->header.len;
+	pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
+
+	pphy_tlv = (MrvlIEtypes_PhyParamSet_t *)pos;
+	pphy_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
+	pphy_tlv->header.len = sizeof(pphy_tlv->fh_ds.ds_param_set);
+	memcpy_ext(pmadapter, &pphy_tlv->fh_ds.ds_param_set,
+		   &pbss_desc->phy_param_set.ds_param_set.current_chan,
+		   sizeof(pphy_tlv->fh_ds.ds_param_set),
+		   sizeof(pphy_tlv->fh_ds.ds_param_set));
+	pos += sizeof(pphy_tlv->header) + pphy_tlv->header.len;
+	pphy_tlv->header.len = wlan_cpu_to_le16(pphy_tlv->header.len);
+
+	pss_tlv = (MrvlIEtypes_SsParamSet_t *)pos;
+	pss_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CF);
+	pss_tlv->header.len = sizeof(pss_tlv->cf_ibss.cf_param_set);
+	pos += sizeof(pss_tlv->header) + pss_tlv->header.len;
+	pss_tlv->header.len = wlan_cpu_to_le16(pss_tlv->header.len);
+
+	/* Get the common rates supported between the driver and the BSS Desc */
+	if (wlan_setup_rates_from_bssdesc(pmpriv, pbss_desc, rates,
+					  &rates_size)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Save the data rates into Current BSS state structure */
+	pmpriv->curr_bss_params.num_of_rates = rates_size;
+	memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates, rates,
+		   rates_size, WLAN_SUPPORTED_RATES);
+
+	/* Setup the Rates TLV in the association command */
+	prates_tlv = (MrvlIEtypes_RatesParamSet_t *)pos;
+	prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+	prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
+	memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
+	pos += sizeof(prates_tlv->header) + rates_size;
+	PRINTM(MINFO, "ASSOC_CMD: Rates size = %d\n", rates_size);
+
+	/* Add the Authentication type to be used for Auth frames if needed */
+	if ((pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)
+		) {
+		pauth_tlv = (MrvlIEtypes_AuthType_t *)pos;
+		pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+		pauth_tlv->header.len = sizeof(pauth_tlv->auth_type);
+		if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
+		    (pmpriv->sec_info.authentication_mode ==
+		     MLAN_AUTH_MODE_NETWORKEAP))
+			pauth_tlv->auth_type = wlan_cpu_to_le16((t_u16)pmpriv->
+								sec_info.
+								authentication_mode);
+		else if (pmpriv->sec_info.authentication_mode ==
+			 MLAN_AUTH_MODE_FT)
+			pauth_tlv->auth_type =
+				wlan_cpu_to_le16(AssocAgentAuth_FastBss_Skip);
+		else if (pmpriv->sec_info.authentication_mode ==
+			 MLAN_AUTH_MODE_SAE)
+			pauth_tlv->auth_type =
+				wlan_cpu_to_le16(AssocAgentAuth_Wpa3Sae);
+		else
+			pauth_tlv->auth_type =
+				wlan_cpu_to_le16(MLAN_AUTH_MODE_OPEN);
+		pos += sizeof(pauth_tlv->header) + pauth_tlv->header.len;
+		pauth_tlv->header.len = wlan_cpu_to_le16(pauth_tlv->header.len);
+	}
+
+	if ((pauth_tlv != MNULL) &&
+	    (pauth_tlv->auth_type ==
+	     wlan_cpu_to_le16(AssocAgentAuth_Wpa3Sae))) {
+		if (pbss_desc->prsnx_ie && pbss_desc->prsnx_ie->ieee_hdr.len &&
+		    (pbss_desc->prsnx_ie->data[0] & (0x1 << SAE_H2E_BIT))) {
+			MrvlIEtypes_SAE_PWE_Mode_t *psae_pwe_mode_tlv;
+
+			/* Setup the sae pwe derivation mode TLV in the association command */
+			psae_pwe_mode_tlv = (MrvlIEtypes_SAE_PWE_Mode_t *) pos;
+			psae_pwe_mode_tlv->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_WPA3_SAE_PWE_DERIVATION_MODE);
+			psae_pwe_mode_tlv->header.len =
+				sizeof(psae_pwe_mode_tlv->pwe);
+			psae_pwe_mode_tlv->pwe[0] =
+				pbss_desc->prsnx_ie->data[0];
+			pos += sizeof(psae_pwe_mode_tlv->header) +
+				sizeof(psae_pwe_mode_tlv->pwe);
+		}
+	}
+
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter) &&
+	    (pbss_desc->bss_band & pmpriv->config_bands) &&
+	    !(ISSUPP_11NENABLED(pmadapter->fw_cap_info) &&
+	      (!pbss_desc->disable_11n) &&
+	      (pmpriv->config_bands & BAND_GN
+	       || pmpriv->config_bands & BAND_AN) && (pbss_desc->pht_cap))) {
+		/* Append a channel TLV for the channel the attempted AP was
+		 * found on */
+		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+		       sizeof(ChanScanParamSet_t));
+		pchan_tlv->chan_scan_param[0].chan_number =
+			(pbss_desc->phy_param_set.ds_param_set.current_chan);
+		PRINTM(MINFO, "Assoc: TLV Chan = %d\n",
+		       pchan_tlv->chan_scan_param[0].chan_number);
+
+		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+		PRINTM(MINFO, "Assoc: TLV Bandcfg = %x\n",
+		       pchan_tlv->chan_scan_param[0].bandcfg);
+		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+	}
+	if (!pmpriv->wps.session_enable) {
+		if ((pmpriv->sec_info.wpa_enabled ||
+		     pmpriv->sec_info.wpa2_enabled)) {
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			/* WPA_IE or RSN_IE */
+			prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+			prsn_ie_tlv->header.type =
+				prsn_ie_tlv->header.type & 0x00FF;
+			prsn_ie_tlv->header.type =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+			prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+			prsn_ie_tlv->header.len =
+				prsn_ie_tlv->header.len & 0x00FF;
+			if (prsn_ie_tlv->header.len <=
+			    (sizeof(pmpriv->wpa_ie) - 2))
+				memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+					   &pmpriv->wpa_ie[2],
+					   prsn_ie_tlv->header.len,
+					   prsn_ie_tlv->header.len);
+			else {
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			HEXDUMP("ASSOC_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
+				sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len);
+			pos += sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len;
+			prsn_ie_tlv->header.len =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+	    /** parse rsn ie to find whether ft akm is used*/
+			ft_akm = wlan_ft_akm_is_used(pmpriv, pmpriv->wpa_ie);
+			/* Append PMF Configuration coming from cfg80211 layer */
+			psecurity_cfg_ie = (MrvlIEtypes_SecurityCfg_t *) pos;
+			psecurity_cfg_ie->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_SECURITY_CFG);
+
+			pmpriv->curr_bss_params.use_mfp =
+				wlan_use_mfp(pmpriv, pbss_desc);
+			PRINTM(MCMND, "use_mfp=%d\n",
+			       pmpriv->curr_bss_params.use_mfp);
+
+			if (!pmpriv->curr_bss_params.use_mfp)
+				psecurity_cfg_ie->use_mfp = MFALSE;
+			else
+				psecurity_cfg_ie->use_mfp = MTRUE;
+			psecurity_cfg_ie->header.len = sizeof(t_u8);
+			pos += sizeof(psecurity_cfg_ie->header)
+				+ psecurity_cfg_ie->header.len;
+		}
+#ifdef DRV_EMBEDDED_SUPPLICANT
+		else if (supplicantIsEnabled(pmpriv->psapriv)) {
+			supplicantClrEncryptKey(pmpriv->psapriv);
+
+			if (pbss_desc->prsn_ie)
+				rsn_wpa_ie_tmp = pbss_desc->prsn_ie;
+			else if (pbss_desc->pwpa_ie)
+				rsn_wpa_ie_tmp = pbss_desc->pwpa_ie;
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			pos += supplicantFormatRsnWpaTlv(pmpriv->psapriv,
+							 rsn_wpa_ie_tmp,
+							 prsn_ie_tlv);
+		}
+#endif
+		else if (pmpriv->sec_info.ewpa_enabled) {
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			if (pbss_desc->pwpa_ie) {
+				prsn_ie_tlv->header.type =
+					(t_u16)(*(pbss_desc->pwpa_ie))
+					.vend_hdr.element_id;
+				prsn_ie_tlv->header.type =
+					prsn_ie_tlv->header.type & 0x00FF;
+				prsn_ie_tlv->header.type =
+					wlan_cpu_to_le16(prsn_ie_tlv->header.
+							 type);
+				prsn_ie_tlv->header.len =
+					(t_u16)(*(pbss_desc->pwpa_ie))
+					.vend_hdr.len;
+				prsn_ie_tlv->header.len =
+					prsn_ie_tlv->header.len & 0x00FF;
+				if (prsn_ie_tlv->header.len <=
+				    (sizeof(pmpriv->wpa_ie))) {
+					memcpy_ext(pmadapter,
+						   prsn_ie_tlv->rsn_ie,
+						   &((*(pbss_desc->pwpa_ie))
+						     .vend_hdr.oui[0]),
+						   prsn_ie_tlv->header.len,
+						   prsn_ie_tlv->header.len);
+				} else {
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+
+				HEXDUMP("ASSOC_CMD: RSN IE",
+					(t_u8 *)prsn_ie_tlv,
+					sizeof(prsn_ie_tlv->header) +
+					prsn_ie_tlv->header.len);
+				pos += sizeof(prsn_ie_tlv->header) +
+					prsn_ie_tlv->header.len;
+				prsn_ie_tlv->header.len =
+					wlan_cpu_to_le16(prsn_ie_tlv->header.
+							 len);
+			}
+			if (pbss_desc->prsn_ie) {
+				prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+				prsn_ie_tlv->header.type =
+					(t_u16)(*(pbss_desc->prsn_ie))
+					.ieee_hdr.element_id;
+				prsn_ie_tlv->header.type =
+					prsn_ie_tlv->header.type & 0x00FF;
+				prsn_ie_tlv->header.type =
+					wlan_cpu_to_le16(prsn_ie_tlv->header.
+							 type);
+				prsn_ie_tlv->header.len =
+					(t_u16)(*(pbss_desc->prsn_ie))
+					.ieee_hdr.len;
+				prsn_ie_tlv->header.len =
+					prsn_ie_tlv->header.len & 0x00FF;
+				if (prsn_ie_tlv->header.len <=
+				    (sizeof(pmpriv->wpa_ie))) {
+					memcpy_ext(pmadapter,
+						   prsn_ie_tlv->rsn_ie,
+						   &((*(pbss_desc->prsn_ie))
+						     .data[0]),
+						   prsn_ie_tlv->header.len,
+						   prsn_ie_tlv->header.len);
+					ret = wlan_update_rsn_ie(pmpriv,
+								 prsn_ie_tlv);
+					if (ret != MLAN_STATUS_SUCCESS) {
+						goto done;
+					}
+				} else {
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+
+				HEXDUMP("ASSOC_CMD: RSN IE",
+					(t_u8 *)prsn_ie_tlv,
+					sizeof(prsn_ie_tlv->header) +
+					prsn_ie_tlv->header.len);
+				pos += sizeof(prsn_ie_tlv->header) +
+					prsn_ie_tlv->header.len;
+				prsn_ie_tlv->header.len =
+					wlan_cpu_to_le16(prsn_ie_tlv->header.
+							 len);
+			}
+		}
+	}
+
+	if (ISSUPP_11NENABLED(pmadapter->fw_cap_info) &&
+	    (!pbss_desc->disable_11n) &&
+	    wlan_11n_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+		wlan_cmd_append_11n_tlv(pmpriv, pbss_desc, &pos);
+	else if ((pmpriv->hotspot_cfg & HOTSPOT_ENABLED) &&
+		 !(pmpriv->hotspot_cfg & HOTSPOT_BY_SUPPLICANT))
+		wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, &pos);
+	if (pmpriv->adapter->ecsa_enable) {
+		oper_class_flag =
+			wlan_find_ie(pmpriv->gen_ie_buf, pmpriv->gen_ie_buf_len,
+				     REGULATORY_CLASS);
+		if (!oper_class_flag) {
+			if (MLAN_STATUS_SUCCESS ==
+			    wlan_get_curr_oper_class(pmpriv,
+						     pbss_desc->phy_param_set.
+						     ds_param_set.current_chan,
+						     pbss_desc->curr_bandwidth,
+						     &oper_class))
+				wlan_add_supported_oper_class_ie(pmpriv, &pos,
+								 oper_class);
+		}
+	}
+	if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) &&
+	    (!pbss_desc->disable_11n) &&
+	    wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+		wlan_cmd_append_11ac_tlv(pmpriv, pbss_desc, &pos);
+
+	if ((IS_FW_SUPPORT_11AX(pmadapter)) && (!pbss_desc->disable_11n) &&
+	    wlan_11ax_bandconfig_allowed(pmpriv, pbss_desc->bss_band))
+		wlan_cmd_append_11ax_tlv(pmpriv, pbss_desc, &pos);
+
+	wlan_wmm_process_association_req(pmpriv, &pos, &pbss_desc->wmm_ie,
+					 pbss_desc->pht_cap);
+	if (pmpriv->sec_info.wapi_enabled && pmpriv->wapi_ie_len)
+		wlan_cmd_append_wapi_ie(pmpriv, &pos);
+
+	if (pmpriv->sec_info.osen_enabled && pmpriv->osen_ie_len)
+		wlan_cmd_append_osen_ie(pmpriv, &pos);
+
+	wlan_cmd_append_generic_ie(pmpriv, &pos);
+
+	if (ft_akm && pbss_desc->pmd_ie)
+		wlan_cmd_append_pass_through_ie(pmpriv,
+						(IEEEtypes_Generic_t *)
+						pbss_desc->pmd_ie, &pos);
+	wlan_cmd_append_tsf_tlv(pmpriv, &pos, pbss_desc);
+
+	if (pmpriv->curr_bss_params.host_mlme) {
+		host_mlme_tlv = (MrvlIEtypes_HostMlme_t *) pos;
+		host_mlme_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_HOST_MLME);
+		host_mlme_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(host_mlme_tlv->host_mlme));
+		host_mlme_tlv->host_mlme = MTRUE;
+		pos += sizeof(host_mlme_tlv->header) +
+			host_mlme_tlv->header.len;
+	}
+	if (memcmp(pmadapter, &pmpriv->curr_bss_params.prev_bssid, zero_mac,
+		   MLAN_MAC_ADDR_LENGTH)) {
+		prev_bssid_tlv = (MrvlIEtypes_PrevBssid_t *) pos;
+		prev_bssid_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_PREV_BSSID);
+		prev_bssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
+		memcpy_ext(pmadapter, prev_bssid_tlv->prev_bssid,
+			   &pmpriv->curr_bss_params.prev_bssid,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		PRINTM(MCMND, "ASSOCIATE: PREV_BSSID = " MACSTR "\n",
+		       MAC2STR(pmpriv->curr_bss_params.prev_bssid));
+		pos += sizeof(prev_bssid_tlv->header) + MLAN_MAC_ADDR_LENGTH;
+	}
+
+	if (wlan_11d_create_dnld_countryinfo(pmpriv, (t_u8)pbss_desc->bss_band)) {
+		PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (wlan_11d_parse_dnld_countryinfo(pmpriv,
+					    pmpriv->pattempted_bss_desc)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/*
+	 * Call 11h join API after capability bits are set so adhoc/infra 11h
+	 * behavior can be properly triggered.  pos modified if data is appended
+	 */
+	wlan_11h_process_join(pmpriv, &pos, &passo->cap_info,
+			      (t_u8)pbss_desc->bss_band,
+			      pbss_desc->phy_param_set.ds_param_set.
+			      current_chan, &pbss_desc->wlan_11h_bss_info);
+
+	cmd->size = wlan_cpu_to_le16((t_u16)(pos - (t_u8 *)passo) + S_DS_GEN);
+
+	/* Set the Capability info at last */
+	memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+		   sizeof(passo->cap_info), sizeof(tmp_cap));
+
+	if (pmpriv->config_bands == BAND_B)
+		SHORT_SLOT_TIME_DISABLED(tmp_cap);
+
+	tmp_cap &= CAPINFO_MASK;
+	PRINTM(MINFO, "ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap,
+	       CAPINFO_MASK);
+	tmp_cap = wlan_cpu_to_le16(tmp_cap);
+	memcpy_ext(pmadapter, &passo->cap_info, &tmp_cap, sizeof(tmp_cap),
+		   sizeof(passo->cap_info));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Association firmware command response handler
+ *
+ *   The response buffer for the association command has the following
+ *      memory layout.
+ *
+ *   For cases where an association response was not received (indicated
+ *      by the CapInfo and AId field):
+ *
+ *     .------------------------------------------------------------.
+ *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
+ *     .------------------------------------------------------------.
+ *     |  cap_info/Error Return(t_u16):                             |
+ *     |           0xFFFF(-1): Internal error for association       |
+ *     |           0xFFFE(-2): Authentication unhandled message     |
+ *     |           0xFFFD(-3): Authentication refused               |
+ *     |           0xFFFC(-4): Timeout waiting for AP response      |
+ *     |           0xFFFB(-5): Internal error for authentication    |
+ *     .------------------------------------------------------------.
+ *     |  status_code(t_u16):                                       |
+ *     |        If cap_info is -1:                                  |
+ *     |           An internal firmware failure prevented the       |
+ *     |           command from being processed. The status code    |
+ *     |           is 6 if associate response parameter invlaid,    |
+ *     |           1 otherwise.                                     |
+ *     |                                                            |
+ *     |        If cap_info is -2:                                  |
+ *     |           An authentication frame was received but was     |
+ *     |           not handled by the firmware. IEEE Status code    |
+ *     |           for the failure is returned.                     |
+ *     |                                                            |
+ *     |        If cap_info is -3:                                  |
+ *     |           An authentication frame was received and the     |
+ *     |           status_code is the IEEE Status reported in the   |
+ *     |           response.                                        |
+ *     |                                                            |
+ *     |        If cap_info is -4:                                  |
+ *     |           (1) Association response timeout                 |
+ *     |           (2) Authentication response timeout              |
+ *     |                                                            |
+ *     |        If cap_info is -5:                                  |
+ *     |           An internal firmware failure prevented the       |
+ *     |           command from being processed. The status code    |
+ *     |           is 6 if authentication parameter invlaid,        |
+ *     |           1 otherwise.                                     |
+ *     .------------------------------------------------------------.
+ *     |  a_id(t_u16): 0xFFFF                                       |
+ *     .------------------------------------------------------------.
+ *
+ *
+ *   For cases where an association response was received, the IEEE
+ *     standard association response frame is returned:
+ *
+ *     .------------------------------------------------------------.
+ *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
+ *     .------------------------------------------------------------.
+ *     |  cap_info(t_u16): IEEE Capability                          |
+ *     .------------------------------------------------------------.
+ *     |  status_code(t_u16): IEEE Status Code                      |
+ *     .------------------------------------------------------------.
+ *     |  a_id(t_u16): IEEE Association ID                          |
+ *     .------------------------------------------------------------.
+ *     |  IEEE IEs(variable): Any received IEs comprising the       |
+ *     |                      remaining portion of a received       |
+ *     |                      association response frame.           |
+ *     .------------------------------------------------------------.
+ *
+ *  For simplistic handling, the status_code field can be used to determine
+ *    an association success (0) or failure (non-zero).
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11_associate(mlan_private *pmpriv,
+			  HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	IEEEtypes_AssocRsp_t *passoc_rsp;
+	BSSDescriptor_t *pbss_desc;
+	t_u8 enable_data = MTRUE;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	t_u8 cur_mac[MLAN_MAC_ADDR_LENGTH];
+	t_u8 media_connected = pmpriv->media_connected;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	assoc_logger_data *assoc_succ;
+	mlan_ds_bss *bss;
+	IEEEtypes_MgmtHdr_t *hdr;
+
+	ENTER();
+
+	if (pmpriv->curr_bss_params.host_mlme) {
+		hdr = (IEEEtypes_MgmtHdr_t *)&resp->params;
+		if (!memcmp(pmpriv->adapter, hdr->BssId,
+			    pmpriv->pattempted_bss_desc->mac_address,
+			    MLAN_MAC_ADDR_LENGTH))
+			passoc_rsp =
+				(IEEEtypes_AssocRsp_t *)((t_u8 *)(&resp->params)
+							 +
+							 sizeof
+							 (IEEEtypes_MgmtHdr_t));
+		else
+			passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
+	} else
+
+		passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params;
+	passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code);
+	if (pmpriv->media_connected == MTRUE)
+		memcpy_ext(pmpriv->adapter, cur_mac,
+			   pmpriv->curr_bss_params.bss_descriptor.mac_address,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+	HEXDUMP("ASSOC_RESP:", (t_u8 *)&resp->params, (resp->size - S_DS_GEN));
+
+	pmpriv->assoc_rsp_size =
+		MIN(resp->size - S_DS_GEN, sizeof(pmpriv->assoc_rsp_buf));
+
+	memcpy_ext(pmpriv->adapter, pmpriv->assoc_rsp_buf, &resp->params,
+		   pmpriv->assoc_rsp_size, pmpriv->assoc_rsp_size);
+
+	if (pioctl_req != MNULL) {
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		bss->param.ssid_bssid.assoc_rsp.assoc_resp_len =
+			pmpriv->assoc_rsp_size;
+		memcpy_ext(pmpriv->adapter,
+			   bss->param.ssid_bssid.assoc_rsp.assoc_resp_buf,
+			   pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
+			   ASSOC_RSP_BUF_SIZE);
+	}
+	if (passoc_rsp->status_code) {
+		if (pmpriv->media_connected == MTRUE) {
+			if (pmpriv->port_ctrl_mode == MTRUE)
+				pmpriv->port_open = pmpriv->prior_port_status;
+			if (!memcmp(pmpriv->adapter, cur_mac,
+				    pmpriv->pattempted_bss_desc->mac_address,
+				    MLAN_MAC_ADDR_LENGTH))
+				wlan_reset_connect_state(pmpriv, MTRUE);
+			else
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT,
+						MNULL);
+		} else
+			wlan_reset_connect_state(pmpriv, MTRUE);
+		pmpriv->adapter->dbg.num_cmd_assoc_failure++;
+		pmpriv->adapter->dbg.num_cons_assoc_failure++;
+		PRINTM(MERROR,
+		       "ASSOC_RESP: Association Failed, "
+		       "status code = %d, error = 0x%x, a_id = 0x%x\n",
+		       passoc_rsp->status_code,
+		       wlan_le16_to_cpu(*(t_u16 *)&passoc_rsp->capability),
+		       wlan_le16_to_cpu(passoc_rsp->a_id));
+		memset(pmadapter, event_buf, 0, sizeof(event_buf));
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER;
+		pevent->event_len = sizeof(passoc_rsp->status_code);
+		memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+			   &passoc_rsp->status_code, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER,
+				pevent);
+
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Send a Media Connected event, according to the Spec */
+	pmpriv->media_connected = MTRUE;
+	pmpriv->adapter->pps_uapsd_mode = MFALSE;
+	pmpriv->adapter->tx_lock_flag = MFALSE;
+	pmpriv->adapter->delay_null_pkt = MFALSE;
+
+	/* Set the attempted BSSID Index to current */
+	pbss_desc = pmpriv->pattempted_bss_desc;
+
+	PRINTM(MCMND, "ASSOC_RESP: %-32s (a_id = 0x%x)\n", pbss_desc->ssid.ssid,
+	       wlan_le16_to_cpu(passoc_rsp->a_id));
+	/* Restore default extended capabilities */
+	memcpy_ext(pmpriv->adapter, &pmpriv->ext_cap, &pmpriv->def_ext_cap,
+		   sizeof(pmpriv->ext_cap), sizeof(pmpriv->ext_cap));
+	/* Make a copy of current BSSID descriptor */
+	memcpy_ext(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+		   pbss_desc, sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
+	/* Update curr_bss_params */
+	pmpriv->curr_bss_params.bss_descriptor.channel =
+		pbss_desc->phy_param_set.ds_param_set.current_chan;
+
+	pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
+
+	/* Store current channel for further reference.
+	 * This would save one extra call to get current
+	 * channel when disconnect/bw_ch event is raised.
+	 */
+	pmpriv->adapter->dfsr_channel =
+		pmpriv->curr_bss_params.bss_descriptor.channel;
+
+	/*
+	 * Adjust the timestamps in the scan table to be relative to the newly
+	 * associated AP's TSF
+	 */
+	wlan_update_tsf_timestamps(pmpriv, pbss_desc);
+
+	if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE)
+		pmpriv->curr_bss_params.wmm_enabled = MTRUE;
+	else
+		pmpriv->curr_bss_params.wmm_enabled = MFALSE;
+
+	if ((pmpriv->wmm_required ||
+	     (pbss_desc->pht_cap &&
+	      (pbss_desc->pht_cap->ieee_hdr.element_id == HT_CAPABILITY))) &&
+	    pmpriv->curr_bss_params.wmm_enabled)
+		pmpriv->wmm_enabled = MTRUE;
+	else
+		pmpriv->wmm_enabled = MFALSE;
+
+	pmpriv->curr_bss_params.wmm_uapsd_enabled = MFALSE;
+
+	if (pmpriv->wmm_enabled == MTRUE)
+		pmpriv->curr_bss_params.wmm_uapsd_enabled =
+			pbss_desc->wmm_ie.qos_info.qos_uapsd;
+
+	PRINTM(MINFO, "ASSOC_RESP: curr_pkt_filter is 0x%x\n",
+	       pmpriv->curr_pkt_filter);
+	if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled)
+		pmpriv->wpa_is_gtk_set = MFALSE;
+	if (pmpriv->wmm_enabled)
+		/* Don't re-enable carrier until we get the WMM_GET_STATUS event
+		 */
+		enable_data = MFALSE;
+	else
+		/* Since WMM is not enabled, setup the queues with the defaults
+		 */
+		wlan_wmm_setup_queues(pmpriv);
+
+	if (enable_data)
+		PRINTM(MINFO, "Post association, re-enabling data flow\n");
+
+	/* Reset SNR/NF/RSSI values */
+	pmpriv->data_rssi_last = 0;
+	pmpriv->data_nf_last = 0;
+	pmpriv->data_rssi_avg = 0;
+	pmpriv->data_nf_avg = 0;
+	pmpriv->bcn_rssi_last = 0;
+	pmpriv->bcn_nf_last = 0;
+	pmpriv->bcn_rssi_avg = 0;
+	pmpriv->bcn_nf_avg = 0;
+	pmpriv->rxpd_rate = 0;
+	pmpriv->rxpd_rate_info = 0;
+	/* Reset mib statistics */
+	pmpriv->amsdu_rx_cnt = 0;
+	pmpriv->amsdu_tx_cnt = 0;
+	pmpriv->msdu_in_rx_amsdu_cnt = 0;
+	pmpriv->msdu_in_tx_amsdu_cnt = 0;
+	if (pbss_desc->pvht_cap && pbss_desc->pht_cap) {
+		if (GET_VHTCAP_MAXMPDULEN
+		    (pbss_desc->pvht_cap->vht_cap.vht_cap_info) == 2)
+			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_12K;
+		else if (GET_VHTCAP_MAXMPDULEN
+			 (pbss_desc->pvht_cap->vht_cap.vht_cap_info) == 1)
+			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+		else
+			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+	} else if (pbss_desc->pht_cap) {
+		if (GETHT_MAXAMSDU(pbss_desc->pht_cap->ht_cap.ht_cap_info))
+			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+		else
+			pmpriv->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+	}
+
+	wlan_save_curr_bcn(pmpriv);
+
+	pmpriv->adapter->dbg.num_cmd_assoc_success++;
+	pmpriv->adapter->dbg.num_cons_assoc_failure = 0;
+	PRINTM(MINFO, "ASSOC_RESP: Associated\n");
+	pevent->bss_index = pmpriv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
+	pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+	memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		   (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		   MLAN_MAC_ADDR_LENGTH, pevent->event_len);
+
+	/* Add the ra_list here for infra mode as there will be only 1 ra always
+	 */
+	if (media_connected) {
+		/** replace ralist's mac address with new mac address */
+		if (0 ==
+		    wlan_ralist_update(pmpriv, cur_mac,
+				       pmpriv->curr_bss_params.bss_descriptor.
+				       mac_address))
+			wlan_ralist_add(pmpriv,
+					pmpriv->curr_bss_params.bss_descriptor.
+					mac_address);
+		wlan_11n_cleanup_reorder_tbl(pmpriv);
+		wlan_11n_deleteall_txbastream_tbl(pmpriv);
+
+	} else
+		wlan_ralist_add(pmpriv,
+				pmpriv->curr_bss_params.bss_descriptor.
+				mac_address);
+
+	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
+
+	/* Send OBSS scan param to the application if available */
+	wlan_2040_coex_event(pmpriv);
+	wlan_coex_ampdu_rxwinsize(pmpriv->adapter);
+
+	if (!pmpriv->sec_info.wpa_enabled && !pmpriv->sec_info.wpa2_enabled
+	    && !pmpriv->sec_info.ewpa_enabled
+	    && !pmpriv->sec_info.wapi_enabled
+	    && !pmpriv->wps.session_enable && !pmpriv->sec_info.osen_enabled
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	    && !supplicantIsEnabled(pmpriv->psapriv)
+#endif
+		) {
+		/* We are in Open/WEP mode, open port immediately */
+		if (pmpriv->port_ctrl_mode == MTRUE) {
+			pmpriv->port_open = MTRUE;
+			PRINTM(MINFO, "ASSOC_RESP: port_status = OPEN\n");
+		}
+	}
+	if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled
+	    || pmpriv->sec_info.ewpa_enabled
+	    || pmpriv->sec_info.wapi_enabled
+	    || pmpriv->wps.session_enable || pmpriv->sec_info.osen_enabled
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	    || (supplicantIsEnabled(pmpriv->psapriv))
+#endif
+		)
+		pmpriv->adapter->scan_block = MTRUE;
+
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	supplicantInitSession(pmpriv->psapriv,
+			      (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
+			      ssid.ssid,
+			      pmpriv->curr_bss_params.bss_descriptor.ssid.
+			      ssid_len,
+			      (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
+			      mac_address, (t_u8 *)&pmpriv->curr_addr);
+#endif
+
+	pevent = (mlan_event *)event_buf;
+	memset(pmadapter, event_buf, 0, sizeof(event_buf));
+	pevent->bss_index = pmpriv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER;
+	pevent->event_len = sizeof(assoc_logger_data);
+	assoc_succ = (assoc_logger_data *) pevent->event_buf;
+	memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->bssid,
+		   pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+	memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->oui,
+		   pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH / 2,
+		   MLAN_MAC_ADDR_LENGTH / 2);
+	memcpy_ext(pmpriv->adapter, (t_u8 *)assoc_succ->ssid,
+		   pbss_desc->ssid.ssid, pbss_desc->ssid.ssid_len,
+		   MLAN_MAX_SSID_LENGTH);
+	assoc_succ->rssi = pbss_desc->rssi;
+	assoc_succ->channel = pbss_desc->channel;
+	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER, pevent);
+
+done:
+	/* Need to indicate IOCTL complete */
+	if (pioctl_req != MNULL) {
+		if (ret != MLAN_STATUS_SUCCESS) {
+			if (passoc_rsp->status_code)
+				pioctl_req->status_code =
+					(wlan_le16_to_cpu
+					 (*(t_u16 *)&passoc_rsp->capability)
+					 << 16) + passoc_rsp->status_code;
+			else
+				pioctl_req->status_code =
+					MLAN_ERROR_CMD_ASSOC_FAIL;
+		} else {
+			pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of ad_hoc_start.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer cast of mlan_802_11_ssid structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_ad_hoc_start(mlan_private *pmpriv,
+			     HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_AD_HOC_START *padhoc_start = &cmd->params.adhoc_start;
+	BSSDescriptor_t *pbss_desc;
+	t_u32 cmd_append_size = 0;
+	t_u32 i;
+	t_u16 tmp_cap;
+	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+
+	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
+	/* wpa ie for WPA_NONE AES */
+	const t_u8 wpa_ie[24] = { 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01,
+		0x01, 0x00, 0x00, 0x50, 0xf2, 0x04,
+		0x01, 0x00, 0x00, 0x50, 0xf2, 0x00,
+		0x01, 0x00, 0x00, 0x50, 0xf2, 0x00
+	};
+	t_s32 append_size_11h = 0;
+	t_u8 *pos =
+		(t_u8 *)padhoc_start + sizeof(HostCmd_DS_802_11_AD_HOC_START);
+
+	ENTER();
+
+	if (!pmadapter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
+
+	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+	pmpriv->pattempted_bss_desc = pbss_desc;
+
+	/*
+	 * Fill in the parameters for 2 data structures:
+	 *   1. HostCmd_DS_802_11_AD_HOC_START command
+	 *   2. pbss_desc
+	 * Driver will fill up SSID, bss_mode,IBSS param, Physical Param,
+	 * probe delay, and Cap info.
+	 * Firmware will fill up beacon period, Basic rates
+	 * and operational rates.
+	 */
+
+	memset(pmadapter, padhoc_start->ssid, 0, MLAN_MAX_SSID_LENGTH);
+
+	memcpy_ext(pmadapter, padhoc_start->ssid,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len,
+		   MLAN_MAX_SSID_LENGTH);
+
+	PRINTM(MINFO, "ADHOC_S_CMD: SSID = %s\n", padhoc_start->ssid);
+
+	memset(pmadapter, pbss_desc->ssid.ssid, 0, MLAN_MAX_SSID_LENGTH);
+	memcpy_ext(pmadapter, pbss_desc->ssid.ssid,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid,
+		   ((mlan_802_11_ssid *)pdata_buf)->ssid_len,
+		   MLAN_MAX_SSID_LENGTH);
+
+	pbss_desc->ssid.ssid_len =
+		MIN(MLAN_MAX_SSID_LENGTH,
+		    ((mlan_802_11_ssid *)pdata_buf)->ssid_len);
+
+	/* Set the BSS mode */
+	padhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
+	pbss_desc->bss_mode = MLAN_BSS_MODE_IBSS;
+	padhoc_start->beacon_period = wlan_cpu_to_le16(pmpriv->beacon_period);
+	pbss_desc->beacon_period = pmpriv->beacon_period;
+
+	/* Set Physical param set */
+/** Parameter IE Id */
+#define DS_PARA_IE_ID 3
+/** Parameter IE length */
+#define DS_PARA_IE_LEN 1
+
+	padhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
+	padhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
+
+	if (!wlan_get_cfp_by_band_and_channel
+	    (pmadapter, pmadapter->adhoc_start_band,
+	     (t_u16)pmpriv->adhoc_channel, pmadapter->region_channel)) {
+		chan_freq_power_t *cfp;
+		cfp = wlan_get_cfp_by_band_and_channel(pmadapter,
+						       pmadapter->
+						       adhoc_start_band,
+						       FIRST_VALID_CHANNEL,
+						       pmadapter->
+						       region_channel);
+		if (cfp)
+			pmpriv->adhoc_channel = (t_u8)cfp->channel;
+	}
+
+	MASSERT(pmpriv->adhoc_channel);
+
+	PRINTM(MINFO, "ADHOC_S_CMD: Creating ADHOC on Channel %d\n",
+	       pmpriv->adhoc_channel);
+
+	pmpriv->curr_bss_params.bss_descriptor.channel = pmpriv->adhoc_channel;
+	pmpriv->curr_bss_params.band = pmadapter->adhoc_start_band;
+
+	pbss_desc->channel = pmpriv->adhoc_channel;
+	padhoc_start->phy_param_set.ds_param_set.current_chan =
+		pmpriv->adhoc_channel;
+
+	memcpy_ext(pmadapter, &pbss_desc->phy_param_set,
+		   &padhoc_start->phy_param_set,
+		   sizeof(IEEEtypes_PhyParamSet_t),
+		   sizeof(IEEEtypes_PhyParamSet_t));
+
+	pbss_desc->network_type_use = Wlan802_11DS;
+
+	/* Set IBSS param set */
+/** IBSS parameter IE Id */
+#define IBSS_PARA_IE_ID 6
+/** IBSS parameter IE length */
+#define IBSS_PARA_IE_LEN 2
+
+	padhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
+	padhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
+	padhoc_start->ss_param_set.ibss_param_set.atim_window =
+		wlan_cpu_to_le16(pmpriv->atim_window);
+	pbss_desc->atim_window = pmpriv->atim_window;
+	memcpy_ext(pmadapter, &pbss_desc->ss_param_set,
+		   &padhoc_start->ss_param_set, sizeof(IEEEtypes_SsParamSet_t),
+		   sizeof(IEEEtypes_SsParamSet_t));
+
+	/* Set Capability info */
+	padhoc_start->cap.ess = 0;
+	padhoc_start->cap.ibss = 1;
+	pbss_desc->cap_info.ibss = 1;
+
+	/* Set up privacy in pbss_desc */
+	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled
+	    || pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
+/** Ad-Hoc capability privacy on */
+#define AD_HOC_CAP_PRIVACY_ON 1
+		PRINTM(MINFO, "ADHOC_S_CMD: wep_status set, Privacy to WEP\n");
+		pbss_desc->privacy = Wlan802_11PrivFilter8021xWEP;
+		padhoc_start->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
+	} else {
+		PRINTM(MWARN, "ADHOC_S_CMD: wep_status NOT set, Setting "
+		       "Privacy to ACCEPT ALL\n");
+		pbss_desc->privacy = Wlan802_11PrivFilterAcceptAll;
+	}
+
+	memset(pmadapter, padhoc_start->DataRate, 0,
+	       sizeof(padhoc_start->DataRate));
+
+	if ((pmpriv->adapter->region_code == COUNTRY_CODE_JP_40 ||
+	     pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
+	    (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) {
+		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, BAND_B,
+					   padhoc_start->DataRate);
+	} else {
+		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
+					   pmadapter->adhoc_start_band,
+					   padhoc_start->DataRate);
+	}
+
+	if ((pmadapter->adhoc_start_band & BAND_G) &&
+	    (pmpriv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       &pmpriv->curr_pkt_filter);
+
+		if (ret) {
+			PRINTM(MERROR,
+			       "ADHOC_S_CMD: G Protection config failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/* Find the last non zero */
+	for (i = 0;
+	     i < sizeof(padhoc_start->DataRate) && padhoc_start->DataRate[i];
+	     i++)
+		/* XXX Do not delete no-operation line */
+		;
+
+	pmpriv->curr_bss_params.num_of_rates = i;
+
+	/* Copy the ad-hoc creating rates into Current BSS rate structure */
+	memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates,
+		   &padhoc_start->DataRate,
+		   pmpriv->curr_bss_params.num_of_rates, WLAN_SUPPORTED_RATES);
+
+	PRINTM(MINFO, "ADHOC_S_CMD: Rates=%02x %02x %02x %02x\n",
+	       padhoc_start->DataRate[0], padhoc_start->DataRate[1],
+	       padhoc_start->DataRate[2], padhoc_start->DataRate[3]);
+
+	PRINTM(MINFO, "ADHOC_S_CMD: AD HOC Start command is ready\n");
+
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
+		/* Append a channel TLV */
+		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+		       sizeof(ChanScanParamSet_t));
+		pchan_tlv->chan_scan_param[0].chan_number =
+			(t_u8)pmpriv->curr_bss_params.bss_descriptor.channel;
+
+		PRINTM(MINFO, "ADHOC_S_CMD: TLV Chan = %d\n",
+		       pchan_tlv->chan_scan_param[0].chan_number);
+
+		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type(pmpriv->curr_bss_params.band);
+		PRINTM(MINFO, "ADHOC_S_CMD: TLV Bandcfg = %x\n",
+		       pchan_tlv->chan_scan_param[0].bandcfg);
+		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+		cmd_append_size +=
+			sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+	}
+
+	if (wlan_11d_create_dnld_countryinfo(pmpriv,
+					     pmpriv->curr_bss_params.band)) {
+		PRINTM(MERROR, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/*
+	 * Call 11h start API to add any 11h flags/elements as TLV parameters
+	 */
+	append_size_11h =
+		wlan_11h_process_start(pmpriv, &pos, &padhoc_start->cap,
+				       pmpriv->adhoc_channel,
+				       &pbss_desc->wlan_11h_bss_info);
+	if (append_size_11h >= 0)
+		cmd_append_size += append_size_11h;
+	else {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (pmpriv->sec_info.ewpa_enabled) {
+		memcpy_ext(pmadapter, pmpriv->wpa_ie, wpa_ie, sizeof(wpa_ie),
+			   sizeof(pmpriv->wpa_ie));
+		pmpriv->wpa_ie_len = sizeof(wpa_ie);
+	}
+
+	if (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled) {
+		prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+		prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+		/* WPA_IE or RSN_IE */
+		prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
+		prsn_ie_tlv->header.type =
+			wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+		prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+		prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
+		if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
+			memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+				   &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len,
+				   prsn_ie_tlv->header.len);
+		else {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		DBG_HEXDUMP(MCMD_D, "ADHOC_S_CMD: RSN IE", (t_u8 *)prsn_ie_tlv,
+			    sizeof(prsn_ie_tlv->header) +
+			    prsn_ie_tlv->header.len);
+		pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+		cmd_append_size +=
+			sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+		prsn_ie_tlv->header.len =
+			wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+	}
+
+	cmd->size = (t_u16)wlan_cpu_to_le16((t_u16)
+					    (sizeof
+					     (HostCmd_DS_802_11_AD_HOC_START) +
+					     S_DS_GEN + cmd_append_size));
+
+	memcpy_ext(pmadapter, &tmp_cap, &padhoc_start->cap, sizeof(t_u16),
+		   sizeof(tmp_cap));
+
+	if (pmadapter->adhoc_start_band == BAND_B)
+		SHORT_SLOT_TIME_DISABLED(tmp_cap);
+	else
+		SHORT_SLOT_TIME_ENABLED(tmp_cap);
+
+	tmp_cap = wlan_cpu_to_le16(tmp_cap);
+	memcpy_ext(pmadapter, &padhoc_start->cap, &tmp_cap, sizeof(t_u16),
+		   sizeof(padhoc_start->cap));
+
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of ad_hoc_join.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    Void cast of BSSDescriptor_t from the
+ *                        scan table to join
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_802_11_ad_hoc_join(mlan_private *pmpriv,
+			    HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_AD_HOC_JOIN *padhoc_join = &cmd->params.adhoc_join;
+	BSSDescriptor_t *pbss_desc = (BSSDescriptor_t *)pdata_buf;
+	MrvlIEtypes_ChanListParamSet_t *pchan_tlv;
+	MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv;
+	t_u32 cmd_append_size = 0;
+	t_u16 tmp_cap;
+	t_u32 i, rates_size = 0;
+	t_u32 curr_pkt_filter;
+	t_u8 *pos = (t_u8 *)padhoc_join + sizeof(HostCmd_DS_802_11_AD_HOC_JOIN);
+
+	ENTER();
+
+/** Use G protection */
+#define USE_G_PROTECTION 0x02
+	if (pbss_desc->erp_flags & USE_G_PROTECTION) {
+		curr_pkt_filter = pmpriv->curr_pkt_filter |
+			HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
+
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       &curr_pkt_filter);
+		if (ret) {
+			PRINTM(MERROR,
+			       "ADHOC_J_CMD: G Protection config failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	pmpriv->pattempted_bss_desc = pbss_desc;
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
+
+	padhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
+
+	padhoc_join->bss_descriptor.beacon_period =
+		wlan_cpu_to_le16(pbss_desc->beacon_period);
+
+	memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.bssid,
+		   &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+
+	memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.ssid,
+		   &pbss_desc->ssid.ssid, pbss_desc->ssid.ssid_len,
+		   MLAN_MAX_SSID_LENGTH);
+
+	memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.phy_param_set,
+		   &pbss_desc->phy_param_set, sizeof(IEEEtypes_PhyParamSet_t),
+		   sizeof(IEEEtypes_PhyParamSet_t));
+
+	padhoc_join->bss_descriptor.phy_param_set.fh_param_set.dwell_time =
+		wlan_cpu_to_le16(padhoc_join->bss_descriptor.phy_param_set.
+				 fh_param_set.dwell_time);
+
+	memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.ss_param_set,
+		   &pbss_desc->ss_param_set, sizeof(IEEEtypes_SsParamSet_t),
+		   sizeof(IEEEtypes_SsParamSet_t));
+	padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window = 0;
+	padhoc_join->bss_descriptor.ss_param_set.ibss_param_set.atim_window =
+		wlan_cpu_to_le16(padhoc_join->bss_descriptor.ss_param_set.
+				 ibss_param_set.atim_window);
+
+	memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info,
+		   sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+
+	tmp_cap &= CAPINFO_MASK;
+
+	PRINTM(MINFO, "ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", tmp_cap,
+	       CAPINFO_MASK);
+	memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+		   sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+
+	/* Information on BSSID descriptor passed to FW */
+	PRINTM(MINFO, "ADHOC_J_CMD: BSSID = " MACSTR ", SSID = %s\n",
+	       MAC2STR(padhoc_join->bss_descriptor.bssid),
+	       padhoc_join->bss_descriptor.ssid);
+
+	for (i = 0; i < WLAN_SUPPORTED_RATES && pbss_desc->supported_rates[i];
+	     i++)
+		/* XXX Do not delete no-operation line */
+		;
+	rates_size = i;
+
+	/* Copy Data Rates from the Rates recorded in scan response */
+	memset(pmadapter, padhoc_join->bss_descriptor.data_rates, 0,
+	       sizeof(padhoc_join->bss_descriptor.data_rates));
+	memcpy_ext(pmadapter, padhoc_join->bss_descriptor.data_rates,
+		   pbss_desc->supported_rates, rates_size,
+		   WLAN_SUPPORTED_RATES);
+
+	HEXDUMP("Adapted Rates:", padhoc_join->bss_descriptor.data_rates,
+		rates_size);
+
+	/* Copy the adhoc join rates into Current BSS state structure */
+	pmpriv->curr_bss_params.num_of_rates = rates_size;
+	memcpy_ext(pmadapter, &pmpriv->curr_bss_params.data_rates,
+		   pbss_desc->supported_rates, rates_size,
+		   WLAN_SUPPORTED_RATES);
+
+	/* Copy the channel information */
+	pmpriv->curr_bss_params.bss_descriptor.channel = pbss_desc->channel;
+	pmpriv->curr_bss_params.band = (t_u8)pbss_desc->bss_band;
+
+	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled
+	    || pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.ewpa_enabled)
+		padhoc_join->bss_descriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
+
+	if (IS_SUPPORT_MULTI_BANDS(pmadapter)) {
+		/* Append a channel TLV */
+		pchan_tlv = (MrvlIEtypes_ChanListParamSet_t *)pos;
+		pchan_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		pchan_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t));
+
+		memset(pmadapter, pchan_tlv->chan_scan_param, 0x00,
+		       sizeof(ChanScanParamSet_t));
+		pchan_tlv->chan_scan_param[0].chan_number =
+			(pbss_desc->phy_param_set.ds_param_set.current_chan);
+		PRINTM(MINFO, "ADHOC_J_CMD: TLV Chan = %d\n",
+		       pchan_tlv->chan_scan_param[0].chan_number);
+
+		pchan_tlv->chan_scan_param[0].bandcfg.chanBand =
+			wlan_band_to_radio_type((t_u8)pbss_desc->bss_band);
+
+		PRINTM(MINFO, "ADHOC_J_CMD: TLV Bandcfg = %x\n",
+		       pchan_tlv->chan_scan_param[0].bandcfg);
+		pos += sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+		cmd_append_size +=
+			sizeof(pchan_tlv->header) + sizeof(ChanScanParamSet_t);
+	}
+
+	if (wlan_11d_create_dnld_countryinfo(pmpriv, (t_u8)pbss_desc->bss_band)) {
+		PRINTM(MERROR, "Dnld_countryinfo_11d failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (wlan_11d_parse_dnld_countryinfo(pmpriv,
+					    pmpriv->pattempted_bss_desc)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/*
+	 * Call 11h join API after capability bits are set so
+	 *   adhoc/infra 11h behavior can be properly triggered.
+	 *   pos modified if data is appended
+	 */
+	cmd_append_size +=
+		wlan_11h_process_join(pmpriv, &pos,
+				      &padhoc_join->bss_descriptor.cap,
+				      (t_u8)pbss_desc->bss_band,
+				      pbss_desc->channel,
+				      &pbss_desc->wlan_11h_bss_info);
+
+	if (pmpriv->sec_info.wpa_enabled) {
+		prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+		/* WPA_IE or RSN_IE */
+		prsn_ie_tlv->header.type = (t_u16)pmpriv->wpa_ie[0];
+		prsn_ie_tlv->header.type = prsn_ie_tlv->header.type & 0x00FF;
+		prsn_ie_tlv->header.type =
+			wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+		prsn_ie_tlv->header.len = (t_u16)pmpriv->wpa_ie[1];
+		prsn_ie_tlv->header.len = prsn_ie_tlv->header.len & 0x00FF;
+		if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie) - 2))
+			memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+				   &pmpriv->wpa_ie[2], prsn_ie_tlv->header.len,
+				   prsn_ie_tlv->header.len);
+		else {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
+			sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len);
+		pos += sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+		cmd_append_size +=
+			sizeof(prsn_ie_tlv->header) + prsn_ie_tlv->header.len;
+		prsn_ie_tlv->header.len =
+			wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+	} else if (pmpriv->sec_info.ewpa_enabled) {
+		prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+		if (pbss_desc->pwpa_ie) {
+			prsn_ie_tlv->header.type =
+				(t_u16)(*(pbss_desc->pwpa_ie))
+				.vend_hdr.element_id;
+			prsn_ie_tlv->header.type =
+				prsn_ie_tlv->header.type & 0x00FF;
+			prsn_ie_tlv->header.type =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+			prsn_ie_tlv->header.len =
+				(t_u16)(*(pbss_desc->pwpa_ie)).vend_hdr.len;
+			prsn_ie_tlv->header.len =
+				prsn_ie_tlv->header.len & 0x00FF;
+			if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie))) {
+				memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+					   &((*(pbss_desc->pwpa_ie))
+					     .vend_hdr.oui[0]),
+					   prsn_ie_tlv->header.len,
+					   prsn_ie_tlv->header.len);
+			} else {
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+
+			HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
+				sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len);
+			pos += sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len;
+			cmd_append_size += sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len;
+			prsn_ie_tlv->header.len =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+		}
+		if (pbss_desc->prsn_ie) {
+			prsn_ie_tlv = (MrvlIEtypes_RsnParamSet_t *)pos;
+			prsn_ie_tlv->header.type =
+				(t_u16)(*(pbss_desc->prsn_ie))
+				.ieee_hdr.element_id;
+			prsn_ie_tlv->header.type =
+				prsn_ie_tlv->header.type & 0x00FF;
+			prsn_ie_tlv->header.type =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.type);
+			prsn_ie_tlv->header.len =
+				(t_u16)(*(pbss_desc->prsn_ie)).ieee_hdr.len;
+			prsn_ie_tlv->header.len =
+				prsn_ie_tlv->header.len & 0x00FF;
+			if (prsn_ie_tlv->header.len <= (sizeof(pmpriv->wpa_ie))) {
+				memcpy_ext(pmadapter, prsn_ie_tlv->rsn_ie,
+					   &((*(pbss_desc->prsn_ie)).data[0]),
+					   prsn_ie_tlv->header.len,
+					   prsn_ie_tlv->header.len);
+			} else {
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+
+			HEXDUMP("ADHOC_JOIN: RSN IE", (t_u8 *)prsn_ie_tlv,
+				sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len);
+			pos += sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len;
+			cmd_append_size += sizeof(prsn_ie_tlv->header) +
+				prsn_ie_tlv->header.len;
+			prsn_ie_tlv->header.len =
+				wlan_cpu_to_le16(prsn_ie_tlv->header.len);
+		}
+	}
+
+	cmd->size = (t_u16)wlan_cpu_to_le16((t_u16)
+					    (sizeof
+					     (HostCmd_DS_802_11_AD_HOC_JOIN) +
+					     S_DS_GEN + cmd_append_size));
+
+	memcpy_ext(pmadapter, &tmp_cap, &padhoc_join->bss_descriptor.cap,
+		   sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+	tmp_cap = wlan_cpu_to_le16(tmp_cap);
+
+	memcpy_ext(pmadapter, &padhoc_join->bss_descriptor.cap, &tmp_cap,
+		   sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of ad_hoc_start and
+ *          ad_hoc_join
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11_ad_hoc(mlan_private *pmpriv,
+		       HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	HostCmd_DS_802_11_AD_HOC_START_RESULT *padhoc_start_result =
+		&resp->params.adhoc_start_result;
+	HostCmd_DS_802_11_AD_HOC_JOIN_RESULT *padhoc_join_result =
+		&resp->params.adhoc_join_result;
+	BSSDescriptor_t *pbss_desc;
+	t_u16 command = resp->command;
+	t_u8 result = 0;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	int ie_len = 0;
+	IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+
+	ENTER();
+
+	pmpriv->wmm_enabled = MFALSE;
+	if (command == HostCmd_CMD_802_11_AD_HOC_START) {
+		result = padhoc_start_result->result;
+		ie_len = resp->size -
+			(sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
+			 S_DS_GEN);
+		pwmm_param_ie =
+			(IEEEtypes_WmmParameter_t
+			 *)((t_u8 *)resp +
+			    (sizeof(HostCmd_DS_802_11_AD_HOC_START_RESULT) +
+			     S_DS_GEN));
+	} else {
+		result = padhoc_join_result->result;
+		ie_len = resp->size -
+			(sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
+			 S_DS_GEN);
+		pwmm_param_ie =
+			(IEEEtypes_WmmParameter_t
+			 *)((t_u8 *)resp +
+			    (sizeof(HostCmd_DS_802_11_AD_HOC_JOIN_RESULT) +
+			     S_DS_GEN));
+	}
+
+	pbss_desc = pmpriv->pattempted_bss_desc;
+
+	/*
+	 * Join result code 0 --> SUCCESS
+	 */
+	if (result) {
+		PRINTM(MERROR, "ADHOC_RESP Failed 0x%x\n", result);
+		if (pmpriv->media_connected == MTRUE)
+			wlan_reset_connect_state(pmpriv, MTRUE);
+		if (pmpriv->adhoc_state == ADHOC_STARTING)
+			pmpriv->adhoc_state = ADHOC_IDLE;
+
+		memset(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor,
+		       0x00, sizeof(BSSDescriptor_t));
+
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Send a Media Connected event, according to the Spec */
+	pmpriv->media_connected = MTRUE;
+
+	if (command == HostCmd_CMD_802_11_AD_HOC_START) {
+		PRINTM(MINFO, "ADHOC_S_RESP  %s\n", pbss_desc->ssid.ssid);
+
+		/* Update the created network descriptor with the new BSSID */
+		memcpy_ext(pmpriv->adapter, pbss_desc->mac_address,
+			   padhoc_start_result->bssid, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+
+		pmpriv->adhoc_state = ADHOC_STARTED;
+		if (pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS)
+			wlan_11h_radar_detected_callback((t_void *)pmpriv);
+	} else {
+		/*
+		 * Now the join cmd should be successful.
+		 * If BSSID has changed use SSID to compare instead of BSSID
+		 */
+		PRINTM(MINFO, "ADHOC_J_RESP  %s\n", pbss_desc->ssid.ssid);
+
+		/*
+		 * Make a copy of current BSSID descriptor, only needed
+		 * for join since the current descriptor is already
+		 * being used for adhoc start
+		 */
+		memcpy_ext(pmpriv->adapter,
+			   &pmpriv->curr_bss_params.bss_descriptor, pbss_desc,
+			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
+		pmpriv->adhoc_state = ADHOC_JOINED;
+	}
+
+	/** process wmm ie */
+	if (ie_len >= (int)sizeof(IEEEtypes_VendorHeader_t)) {
+		if ((pwmm_param_ie->vend_hdr.element_id ==
+		     VENDOR_SPECIFIC_221) &&
+		    !memcmp(pmadapter, pwmm_param_ie->vend_hdr.oui, wmm_oui,
+			    sizeof(wmm_oui)) &&
+		    (pwmm_param_ie->vend_hdr.len + 2 == ie_len)) {
+			DBG_HEXDUMP(MCMD_D, "WMM Param", (t_u8 *)pwmm_param_ie,
+				    ie_len);
+			memcpy_ext(pmpriv->adapter,
+				   (t_u8 *)&pmpriv->curr_bss_params.
+				   bss_descriptor.wmm_ie, pwmm_param_ie,
+				   (pwmm_param_ie->vend_hdr.len + 2),
+				   sizeof(IEEEtypes_WmmParameter_t));
+			pmpriv->wmm_enabled = MTRUE;
+			wlan_wmm_setup_queue_priorities(pmpriv, pwmm_param_ie);
+			wlan_wmm_setup_ac_downgrade(pmpriv);
+		}
+	}
+	/* Since WMM is not enabled, setup the queues with the defaults */
+	if (!pmpriv->wmm_enabled)
+		wlan_wmm_setup_queues(pmpriv);
+
+	PRINTM(MINFO, "ADHOC_RESP: Channel = %d\n", pmpriv->adhoc_channel);
+	PRINTM(MINFO, "ADHOC_RESP: BSSID = " MACSTR "\n",
+	       MAC2STR(pmpriv->curr_bss_params.bss_descriptor.mac_address));
+
+	pevent->bss_index = pmpriv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED;
+	pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+	memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		   (t_u8 *)pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent);
+	wlan_save_curr_bcn(pmpriv);
+
+done:
+	/* Need to indicate IOCTL complete */
+	if (pioctl_req != MNULL) {
+		if (ret != MLAN_STATUS_SUCCESS)
+			pioctl_req->status_code = MLAN_ERROR_CMD_ASSOC_FAIL;
+		else
+			pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Associated to a specific BSS discovered in a scan
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param pbss_desc     A pointer to the BSS descriptor to associate with.
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_associate(mlan_private *pmpriv, t_void *pioctl_buf,
+	       BSSDescriptor_t *pbss_desc)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 current_bssid[MLAN_MAC_ADDR_LENGTH];
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	ENTER();
+
+	/* Return error if the pmadapter or table entry
+	 *  is not marked as infra */
+	if ((pmpriv->bss_mode != MLAN_BSS_MODE_INFRA) ||
+	    (pbss_desc->bss_mode != MLAN_BSS_MODE_INFRA)) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memcpy_ext(pmpriv->adapter, &current_bssid,
+		   &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		   sizeof(current_bssid), sizeof(current_bssid));
+
+	/* Clear any past association response stored for application retrieval
+	 */
+	pmpriv->assoc_rsp_size = 0;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ASSOCIATE,
+			       HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Start an Adhoc Network
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param padhoc_ssid  The ssid of the Adhoc Network
+ *
+ *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
+ */
+mlan_status
+wlan_adhoc_start(mlan_private *pmpriv, t_void *pioctl_buf,
+		 mlan_802_11_ssid *padhoc_ssid)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
+	t_u8 radar = MFALSE;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	ENTER();
+
+	/*
+	 * If the report indicates no measurement was done, leave the default
+	 * return value alone.
+	 */
+	if (!pmeas_state->meas_rpt_returned.rpt.basic.map.unmeasured) {
+		radar = pmeas_state->meas_rpt_returned.rpt.basic.map.radar ?
+			MTRUE : MFALSE;
+	}
+
+	if (radar) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		LEAVE();
+		return ret;
+	}
+
+	PRINTM(MINFO, "Adhoc Channel = %d\n", pmpriv->adhoc_channel);
+	PRINTM(MINFO, "curr_bss_params.channel = %d\n",
+	       pmpriv->curr_bss_params.bss_descriptor.channel);
+	PRINTM(MINFO, "curr_bss_params.band = %d\n",
+	       pmpriv->curr_bss_params.band);
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_AD_HOC_START,
+			       HostCmd_ACT_GEN_SET, 0, pioctl_buf, padhoc_ssid);
+#if defined(STA_SUPPORT)
+	if (ret == MLAN_STATUS_SUCCESS)
+		memcpy_ext(pmpriv->adapter, &pmpriv->adhoc_last_start_ssid,
+			   padhoc_ssid, sizeof(mlan_802_11_ssid),
+			   sizeof(mlan_802_11_ssid));
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Join an adhoc network found in a previous scan
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param pbss_desc     A pointer to the BSS descriptor found in a previous
+ * scan to attempt to join
+ *
+ *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
+ */
+mlan_status
+wlan_adhoc_join(mlan_private *pmpriv, t_void *pioctl_buf,
+		BSSDescriptor_t *pbss_desc)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	ENTER();
+
+	PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid =%s\n",
+	       pmpriv->curr_bss_params.bss_descriptor.ssid.ssid);
+	PRINTM(MINFO, "wlan_adhoc_join: CurBss.ssid_len =%u\n",
+	       pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+	PRINTM(MINFO, "wlan_adhoc_join: ssid =%s\n", pbss_desc->ssid.ssid);
+	PRINTM(MINFO, "wlan_adhoc_join: ssid len =%u\n",
+	       pbss_desc->ssid.ssid_len);
+
+	/* Check if the requested SSID is already joined */
+	if (pmpriv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
+	    !wlan_ssid_cmp(pmadapter, &pbss_desc->ssid,
+			   &pmpriv->curr_bss_params.bss_descriptor.ssid) &&
+	    (pmpriv->curr_bss_params.bss_descriptor.bss_mode ==
+	     MLAN_BSS_MODE_IBSS)) {
+		PRINTM(MINFO,
+		       "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
+		       "not attempting to re-join\n");
+
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	PRINTM(MINFO, "curr_bss_params.channel = %d\n",
+	       pmpriv->curr_bss_params.bss_descriptor.channel);
+	PRINTM(MINFO, "curr_bss_params.band = %d\n",
+	       pmpriv->curr_bss_params.band);
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_AD_HOC_JOIN,
+			       HostCmd_ACT_GEN_SET, 0, pioctl_buf, pbss_desc);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Send Deauthentication Request or Stop the AdHoc network depending on
+ * mode
+ *
+ *  @param pmpriv    A pointer to mlan_private structure
+ *  @param pioctl_req A pointer to mlan_ioctl_req structure
+ *  @param deauth_param A pointer to mlan_deauth_param structure
+ *
+ *  @return          MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail,
+ * MLAN_STATUS_PENDING--pending
+ */
+mlan_status
+wlan_disconnect(mlan_private *pmpriv,
+		mlan_ioctl_req *pioctl_req, mlan_deauth_param *deauth_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_deauth_param local_param = {.mac_addr = {0, 0, 0, 0, 0, 0},
+	.reason_code = DEF_DEAUTH_REASON_CODE
+	};
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+
+	if (deauth_param)
+		memcpy_ext(pmpriv->adapter, &local_param, deauth_param,
+			   sizeof(*deauth_param), sizeof(local_param));
+	if (pmpriv->media_connected == MTRUE) {
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+			if (!deauth_param ||
+			    !memcmp(pmpriv->adapter, deauth_param->mac_addr,
+				    zero_mac, sizeof(zero_mac)))
+				memcpy_ext(pmpriv->adapter,
+					   local_param.mac_addr,
+					   (t_u8 *)&pmpriv->curr_bss_params.
+					   bss_descriptor.mac_address,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+#ifdef WIFI_DIRECT_SUPPORT
+			if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				ret = wlan_prepare_cmd(pmpriv,
+						       HostCmd_CMD_802_11_DISASSOCIATE,
+						       HostCmd_ACT_GEN_SET, 0,
+						       (t_void *)pioctl_req,
+						       &local_param);
+			else
+#endif
+				ret = wlan_prepare_cmd(pmpriv,
+						       HostCmd_CMD_802_11_DEAUTHENTICATE,
+						       HostCmd_ACT_GEN_SET, 0,
+						       (t_void *)pioctl_req,
+						       &local_param);
+
+			if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
+				ret = MLAN_STATUS_PENDING;
+
+		} else if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_AD_HOC_STOP,
+					       HostCmd_ACT_GEN_SET, 0,
+					       (t_void *)pioctl_req, MNULL);
+
+			if (ret == MLAN_STATUS_SUCCESS && pioctl_req)
+				ret = MLAN_STATUS_PENDING;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Convert band to radio type used in channel TLV
+ *
+ *  @param band     Band enumeration to convert to a channel TLV radio type
+ *
+ *  @return         Radio type designator for use in a channel TLV
+ */
+t_u8
+wlan_band_to_radio_type(t_u8 band)
+{
+	t_u8 ret_radio_type;
+
+	ENTER();
+
+	switch (band) {
+	case BAND_A:
+	case BAND_AN:
+	case BAND_A | BAND_AN:
+	case BAND_A | BAND_AN | BAND_AAC:
+		ret_radio_type = BAND_5GHZ;
+		break;
+	case BAND_B:
+	case BAND_G:
+	case BAND_B | BAND_G:
+	default:
+		ret_radio_type = BAND_2GHZ;
+		break;
+	}
+
+	LEAVE();
+	return ret_radio_type;
+}
diff --git a/wlan_sd8987/mlan/mlan_join.h b/wlan_sd8987/mlan/mlan_join.h
new file mode 100755
index 0000000..44d9e84
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_join.h
@@ -0,0 +1,42 @@
+/** @file mlan_join.h
+ *
+ *  @brief This file defines the interface for the WLAN infrastructure
+ *  and adhoc join routines.
+ *
+ *  Driver interface functions and type declarations for the join module
+ *  implemented in mlan_join.c.  Process all start/join requests for
+ *  both adhoc and infrastructure networks
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_JOIN_H_
+#define _MLAN_JOIN_H_
+
+/** Size of buffer allocated to store the association response from firmware */
+#define MRVDRV_ASSOC_RSP_BUF_SIZE 500
+
+/** Size of buffer allocated to store IEs passed to firmware in the assoc req */
+#define MRVDRV_GENIE_BUF_SIZE 256
+
+#endif /* _MLAN_JOIN_H_ */
diff --git a/wlan_sd8987/mlan/mlan_main.h b/wlan_sd8987/mlan/mlan_main.h
new file mode 100755
index 0000000..f399852
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_main.h
@@ -0,0 +1,4423 @@
+/** @file mlan_main.h
+ *
+ *  @brief This file defines the private and adapter data
+ *  structures and declares global function prototypes used
+ *  in MLAN module.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_MAIN_H_
+#define _MLAN_MAIN_H_
+
+#ifdef DEBUG_LEVEL1
+extern t_void (*print_callback) (t_pvoid pmoal_handle, t_u32 level,
+				 char *pformat, IN ...);
+
+extern mlan_status (*get_sys_time_callback) (t_void *pmoal_handle,
+					     t_u32 *psec, t_u32 *pusec);
+
+extern t_u32 mlan_drvdbg;
+
+#ifdef DEBUG_LEVEL2
+#define PRINTM_MINFO(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MINFO) && (print_callback))                 \
+			print_callback(MNULL, MINFO, msg);                     \
+	} while (0)
+#define PRINTM_MWARN(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MWARN) && (print_callback))                 \
+			print_callback(MNULL, MWARN, msg);                     \
+	} while (0)
+#define PRINTM_MENTRY(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MENTRY) && (print_callback))                \
+			print_callback(MNULL, MENTRY, msg);                    \
+	} while (0)
+#define PRINTM_GET_SYS_TIME(level, psec, pusec)                                \
+	do {                                                                   \
+		if ((level & mlan_drvdbg) && (get_sys_time_callback))          \
+			get_sys_time_callback(MNULL, psec, pusec);             \
+	} while (0)
+
+/** Hexdump for level-2 debugging */
+#define HEXDUMP(x, y, z)                                                       \
+	do {                                                                   \
+		if ((mlan_drvdbg & (MHEX_DUMP | MINFO)) && (print_callback))   \
+			print_callback(MNULL, MHEX_DUMP | MINFO, x, y, z);     \
+	} while (0)
+
+#else
+
+#define PRINTM_MINFO(msg...)                                                   \
+	do {                                                                   \
+	} while (0)
+#define PRINTM_MWARN(msg...)                                                   \
+	do {                                                                   \
+	} while (0)
+#define PRINTM_MENTRY(msg...)                                                  \
+	do {                                                                   \
+	} while (0)
+
+#define PRINTM_GET_SYS_TIME(level, psec, pusec)                                \
+	do {                                                                   \
+		if ((level & mlan_drvdbg) && (get_sys_time_callback) &&        \
+		    (level != MINFO) && (level != MWARN))                      \
+			get_sys_time_callback(MNULL, psec, pusec);             \
+	} while (0)
+
+/** Hexdump for debugging */
+#define HEXDUMP(x, y, z)                                                       \
+	do {                                                                   \
+	} while (0)
+
+#endif /* DEBUG_LEVEL2 */
+
+#define PRINTM_MFW_D(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MFW_D) && (print_callback))                 \
+			print_callback(MNULL, MFW_D, msg);                     \
+	} while (0)
+#define PRINTM_MCMD_D(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MCMD_D) && (print_callback))                \
+			print_callback(MNULL, MCMD_D, msg);                    \
+	} while (0)
+#define PRINTM_MDAT_D(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MDAT_D) && (print_callback))                \
+			print_callback(MNULL, MDAT_D, msg);                    \
+	} while (0)
+#define PRINTM_MIF_D(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MIF_D) && (print_callback))                 \
+			print_callback(MNULL, MIF_D, msg);                     \
+	} while (0)
+
+#define PRINTM_MIOCTL(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MIOCTL) && (print_callback))                \
+			print_callback(MNULL, MIOCTL, msg);                    \
+	} while (0)
+#define PRINTM_MINTR(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MINTR) && (print_callback))                 \
+			print_callback(MNULL, MINTR, msg);                     \
+	} while (0)
+#define PRINTM_MEVENT(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MEVENT) && (print_callback))                \
+			print_callback(MNULL, MEVENT, msg);                    \
+	} while (0)
+#define PRINTM_MCMND(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MCMND) && (print_callback))                 \
+			print_callback(MNULL, MCMND, msg);                     \
+	} while (0)
+#define PRINTM_MDATA(msg...)                                                   \
+	do {                                                                   \
+		if ((mlan_drvdbg & MDATA) && (print_callback))                 \
+			print_callback(MNULL, MDATA, msg);                     \
+	} while (0)
+#define PRINTM_MERROR(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MERROR) && (print_callback))                \
+			print_callback(MNULL, MERROR, msg);                    \
+	} while (0)
+#define PRINTM_MFATAL(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MFATAL) && (print_callback))                \
+			print_callback(MNULL, MFATAL, msg);                    \
+	} while (0)
+#define PRINTM_MMSG(msg...)                                                    \
+	do {                                                                   \
+		if ((mlan_drvdbg & MMSG) && (print_callback))                  \
+			print_callback(MNULL, MMSG, msg);                      \
+	} while (0)
+
+#define PRINTM(level, msg...) PRINTM_##level((char *)msg)
+
+/** Log debug message */
+#ifdef __GNUC__
+#define PRINTM_NETINTF(level, pmpriv)                                          \
+	do {                                                                   \
+		if ((mlan_drvdbg & level) && pmpriv &&                         \
+		    pmpriv->adapter->callbacks.moal_print_netintf)             \
+			pmpriv->adapter->callbacks.moal_print_netintf(         \
+				pmpriv->adapter->pmoal_handle,                 \
+				pmpriv->bss_index, level);                     \
+	} while (0)
+#endif /* __GNUC__ */
+
+/** Max hex dump data length */
+#define MAX_DATA_DUMP_LEN 64
+
+/** Debug hexdump for level-1 debugging */
+#define DBG_HEXDUMP(level, x, y, z)                                            \
+	do {                                                                   \
+		if ((mlan_drvdbg & level) && print_callback)                   \
+			print_callback(MNULL, MHEX_DUMP | level, x, y, z);     \
+	} while (0)
+
+#else /* DEBUG_LEVEL1 */
+
+#define PRINTM(level, msg...)                                                  \
+	do {                                                                   \
+	} while (0)
+
+#define PRINTM_NETINTF(level, pmpriv)                                          \
+	do {                                                                   \
+	} while (0)
+
+/** Debug hexdump for level-1 debugging */
+#define DBG_HEXDUMP(level, x, y, z)                                            \
+	do {                                                                   \
+	} while (0)
+
+/** Hexdump for debugging */
+#define HEXDUMP(x, y, z)                                                       \
+	do {                                                                   \
+	} while (0)
+
+#define PRINTM_GET_SYS_TIME(level, psec, pusec)                                \
+	do {                                                                   \
+	} while (0)
+
+#endif /* DEBUG_LEVEL1 */
+
+/* Reason Code 3: STA is leaving (or has left) IBSS or ESS */
+#define DEF_DEAUTH_REASON_CODE (0x3)
+
+/** Log entry point for debugging */
+#define ENTER()                                                                \
+	do {                                                                   \
+		PRINTM(MENTRY, "Enter: %s\n", __func__);                       \
+	} while (0)
+
+/** Log exit point for debugging */
+#define LEAVE()                                                                \
+	do {                                                                   \
+		PRINTM(MENTRY, "Leave: %s\n", __func__);                       \
+	} while (0)
+
+/** Find minimum */
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/** Find maximum */
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifdef memset
+#undef memset
+#endif
+/** Memset routine */
+#define memset(adapter, s, c, len)                                             \
+	(adapter->callbacks.moal_memset(adapter->pmoal_handle, s, c, len))
+
+#ifdef memmove
+#undef memmove
+#endif
+/** Memmove routine */
+#define memmove(adapter, dest, src, len)                                       \
+	(adapter->callbacks.moal_memmove(adapter->pmoal_handle, dest, src, len))
+
+#ifdef memcpy
+#undef memcpy
+#endif
+/** Memcpy routine */
+#define memcpy(adapter, to, from, len)                                         \
+	(adapter->callbacks.moal_memcpy(adapter->pmoal_handle, to, from, len))
+/* memcpy_ext rountine */
+#define memcpy_ext(adapter, to, from, len, size)                               \
+	(adapter->callbacks.moal_memcpy_ext(adapter->pmoal_handle, to, from,   \
+					    len, size))
+
+#ifdef memcmp
+#undef memcmp
+#endif
+/** Memcmp routine */
+#define memcmp(adapter, s1, s2, len)                                           \
+	(adapter->callbacks.moal_memcmp(adapter->pmoal_handle, s1, s2, len))
+
+/** Find number of elements */
+#ifndef NELEMENTS
+#define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+/** SWAP: swap t_u8 */
+#define SWAP_U8(a, b)                                                          \
+	{                                                                      \
+		t_u8 t;                                                        \
+		t = a;                                                         \
+		a = b;                                                         \
+		b = t;                                                         \
+	}
+
+/** SWAP: swap t_u8 */
+#define SWAP_U16(a, b)                                                         \
+	{                                                                      \
+		t_u16 t;                                                       \
+		t = a;                                                         \
+		a = b;                                                         \
+		b = t;                                                         \
+	}
+
+/** 16 bits byte swap */
+#define swap_byte_16(x)                                                        \
+	((t_u16)((((t_u16)(x)&0x00ffU) << 8) | (((t_u16)(x)&0xff00U) >> 8)))
+
+/** 32 bits byte swap */
+#define swap_byte_32(x)                                                        \
+	((t_u32)((((t_u32)(x)&0x000000ffUL) << 24) |                           \
+		 (((t_u32)(x)&0x0000ff00UL) << 8) |                            \
+		 (((t_u32)(x)&0x00ff0000UL) >> 8) |                            \
+		 (((t_u32)(x)&0xff000000UL) >> 24)))
+
+/** 64 bits byte swap */
+#define swap_byte_64(x)                                                        \
+	((t_u64)((t_u64)(((t_u64)(x)&0x00000000000000ffULL) << 56) |           \
+		 (t_u64)(((t_u64)(x)&0x000000000000ff00ULL) << 40) |           \
+		 (t_u64)(((t_u64)(x)&0x0000000000ff0000ULL) << 24) |           \
+		 (t_u64)(((t_u64)(x)&0x00000000ff000000ULL) << 8) |            \
+		 (t_u64)(((t_u64)(x)&0x000000ff00000000ULL) >> 8) |            \
+		 (t_u64)(((t_u64)(x)&0x0000ff0000000000ULL) >> 24) |           \
+		 (t_u64)(((t_u64)(x)&0x00ff000000000000ULL) >> 40) |           \
+		 (t_u64)(((t_u64)(x)&0xff00000000000000ULL) >> 56)))
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) x
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) x
+/** Convert n/w to host */
+#define mlan_ntohs(x) x
+/** Convert host to n/w */
+#define mlan_htons(x) x
+/** Convert from 16 bit little endian format to CPU format */
+#define wlan_le16_to_cpu(x) swap_byte_16(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define wlan_le32_to_cpu(x) swap_byte_32(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define wlan_le64_to_cpu(x) swap_byte_64(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define wlan_cpu_to_le16(x) swap_byte_16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define wlan_cpu_to_le32(x) swap_byte_32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define wlan_cpu_to_le64(x) swap_byte_64(x)
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x)                                                 \
+	{                                                                      \
+		(x)->tx_pkt_length = wlan_cpu_to_le16((x)->tx_pkt_length);     \
+		(x)->tx_pkt_offset = wlan_cpu_to_le16((x)->tx_pkt_offset);     \
+		(x)->tx_pkt_type = wlan_cpu_to_le16((x)->tx_pkt_type);         \
+		(x)->tx_control = wlan_cpu_to_le32((x)->tx_control);           \
+		(x)->tx_control_1 = wlan_cpu_to_le32((x)->tx_control_1);       \
+	}
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x)                                                 \
+	{                                                                      \
+		(x)->rx_pkt_length = wlan_le16_to_cpu((x)->rx_pkt_length);     \
+		(x)->rx_pkt_offset = wlan_le16_to_cpu((x)->rx_pkt_offset);     \
+		(x)->rx_pkt_type = wlan_le16_to_cpu((x)->rx_pkt_type);         \
+		(x)->seq_num = wlan_le16_to_cpu((x)->seq_num);                 \
+		(x)->rx_info = wlan_le32_to_cpu((x)->rx_info);                 \
+
+}
+
+#else
+/** Convert ulong n/w to host */
+#define mlan_ntohl(x) swap_byte_32(x)
+/** Convert host ulong to n/w */
+#define mlan_htonl(x) swap_byte_32(x)
+/** Convert n/w to host */
+#define mlan_ntohs(x) swap_byte_16(x)
+/** Convert host to n/w */
+#define mlan_htons(x) swap_byte_16(x)
+/** Do nothing */
+#define wlan_le16_to_cpu(x) x
+/** Do nothing */
+#define wlan_le32_to_cpu(x) x
+/** Do nothing */
+#define wlan_le64_to_cpu(x) x
+/** Do nothing */
+#define wlan_cpu_to_le16(x) x
+/** Do nothing */
+#define wlan_cpu_to_le32(x) x
+/** Do nothing */
+#define wlan_cpu_to_le64(x) x
+
+/** Convert TxPD to little endian format from CPU format */
+#define endian_convert_TxPD(x)                                                 \
+	do {                                                                   \
+	} while (0)
+/** Convert RxPD from little endian format to CPU format */
+#define endian_convert_RxPD(x)                                                 \
+	do {                                                                   \
+	} while (0)
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** Global moal_assert_callback */
+extern t_void (*assert_callback) (t_void *pmoal_handle, t_u32 cond);
+
+/** Assertion */
+#define MASSERT(cond)                                                          \
+	do {                                                                   \
+		if (!(cond)) {                                                 \
+			PRINTM(MFATAL, "ASSERT: %s: %i\n", __func__,           \
+			       __LINE__);                                      \
+			if (assert_callback) {                                 \
+				assert_callback(MNULL, (t_ptr)(cond));         \
+			} else {                                               \
+				do {                                           \
+				} while (1);                                   \
+			}                                                      \
+		}                                                              \
+	} while (0)
+
+/** Maximum event buffer size */
+#define MAX_EVENT_SIZE (3 * 1024)
+
+#ifdef STA_SUPPORT
+/** Maximum buffer size for ARP filter */
+#define ARP_FILTER_MAX_BUF_SIZE 68
+#endif /* STA_SUPPORT */
+
+/** 60 seconds */
+#define MRVDRV_TIMER_60S 60000
+/** 10 seconds */
+#define MRVDRV_TIMER_10S 10000
+/** 5 seconds */
+#define MRVDRV_TIMER_5S 5000
+/** 3 seconds */
+#define MRVDRV_TIMER_3S 3000
+/** 1 second */
+#define MRVDRV_TIMER_1S 1000
+
+/** Maximum size of multicast list */
+#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
+/** Maximum size of channel */
+#define MRVDRV_MAX_CHANNEL_SIZE 14
+/** Maximum length of SSID */
+#define MRVDRV_MAX_SSID_LENGTH 32
+/** WEP list macros & data structures */
+/** Size of key buffer in bytes */
+#define MRVL_KEY_BUFFER_SIZE_IN_BYTE 16
+/** Maximum length of WPA key */
+#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32
+
+/** Default listen interval */
+#define MLAN_DEFAULT_LISTEN_INTERVAL 20
+
+/** Maximum number of region codes */
+#define MRVDRV_MAX_REGION_CODE 9
+
+/** Maximum number of CFP codes for BG */
+#define MRVDRV_MAX_CFP_CODE_BG 0
+/** Maximum number of CFP codes for A */
+#define MRVDRV_MAX_CFP_CODE_A 5
+
+/** high rx pending packets */
+#define HIGH_RX_PENDING 1000
+/** low rx pending packets */
+#define LOW_RX_PENDING 800
+
+/** Default region code */
+#define MRVDRV_DEFAULT_REGION_CODE 0x10
+/** Default country code */
+#define MRVDRV_DEFAULT_COUNTRY_CODE "US"
+
+/** Japan country code */
+#define COUNTRY_CODE_JP_40 0x40
+/** Japan special country code */
+#define COUNTRY_CODE_JP_FF 0xFF
+
+/** Default factor for calculating beacon average */
+#define DEFAULT_BCN_AVG_FACTOR 8
+/** Default factor for calculating data average */
+#define DEFAULT_DATA_AVG_FACTOR 8
+
+/** The first valid channel for use */
+#define FIRST_VALID_CHANNEL 0xff
+/** Default Ad-Hoc channel */
+#define DEFAULT_AD_HOC_CHANNEL 6
+/** Default Ad-Hoc channel A */
+#define DEFAULT_AD_HOC_CHANNEL_A 36
+
+/** Number of WEP keys */
+#define MRVL_NUM_WEP_KEY (4)
+
+/** Default multiple DTIM */
+#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1
+
+/** Default beacon missing timeout */
+#define DEFAULT_BCN_MISS_TIMEOUT 10
+
+/** Maximum buffer space for beacons retrieved from scan responses */
+#define MAX_SCAN_BEACON_BUFFER 102400
+/** Default buffer space for beacons retrieved from scan responses */
+#define DEFAULT_SCAN_BEACON_BUFFER 4096
+
+/**
+ * @brief Buffer pad space for newly allocated beacons/probe responses
+ *
+ * Beacons are typically 6 bytes longer than an equivalent probe response.
+ *  For each scan response stored, allocate an extra byte pad at the end to
+ *  allow easy expansion to store a beacon in the same memory a probe response
+ *  previously contained
+ */
+#define SCAN_BEACON_ENTRY_PAD 6
+
+/** Scan time specified in the channel TLV
+ *  for each channel for passive scans
+ */
+#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for active scans
+ */
+#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 200
+
+/** Scan time specified in the channel TLV
+ *  for each channel for specific scans
+ */
+#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME 110
+
+/**
+ * Max total scan time in milliseconds
+ * The total scan time should be less than scan command timeout value (20s)
+ */
+#define MRVDRV_MAX_TOTAL_SCAN_TIME (MRVDRV_TIMER_10S * 2 - MRVDRV_TIMER_1S)
+
+/** Offset for GTK as it has version to skip past for GTK */
+#define RSN_GTK_OUI_OFFSET 2
+
+/** If OUI is not found */
+#define MLAN_OUI_NOT_PRESENT 0
+/** If OUI is found */
+#define MLAN_OUI_PRESENT 1
+
+/** Is cmd_resp, event or data packet received? */
+#define IS_CARD_RX_RCVD(adapter)                                               \
+	(adapter->cmd_resp_received || adapter->event_received ||              \
+	 adapter->data_received)
+#ifdef USB
+/** Type length */
+#define MLAN_TYPE_LEN 4
+/** Type Command */
+#define MLAN_USB_TYPE_CMD 0xF00DFACE
+/** Type VDLL */
+#define MLAN_USB_TYPE_VDLL 0xF00DC0DE
+/** Type Data */
+#define MLAN_USB_TYPE_DATA 0xBEADC0DE
+/** Type Event */
+#define MLAN_USB_TYPE_EVENT 0xBEEFFACE
+#endif /* USB */
+/** Type command */
+#define MLAN_TYPE_CMD 1
+/** Type data */
+#define MLAN_TYPE_DATA 0
+/** Type event */
+#define MLAN_TYPE_EVENT 3
+/** Type vdll */
+#define MLAN_TYPE_VDLL 4
+#ifdef SDIO
+/** Type single port aggr data */
+#define MLAN_TYPE_SPA_DATA 10
+/** OFFSET of 512 block number */
+#define OFFSET_OF_BLOCK_NUMBER 15
+/** OFFSET of SDIO Header */
+#define OFFSET_OF_SDIO_HEADER 28
+/** sdio max rx size for cmd53, 255 * 256, reserve 1 block for DMA alignment */
+#define SDIO_CMD53_MAX_SIZE 65280
+#define MAX_SUPPORT_AMSDU_SIZE 4096
+/** Maximum numbfer of registers to read for multiple port */
+#if defined(SD8887) || defined(SD8997) || defined(SD8977) || defined(SD8987) || defined(SD9098) || defined(SD9097) || defined(SD8978) || defined(SD9177)
+#define MAX_MP_REGS 196
+#else
+/* upto 0xB7 */
+#define MAX_MP_REGS 184
+#endif
+/** Maximum port */
+#define MAX_PORT 32
+/** Maximum port 16 */
+#define MAX_PORT_16	(16)
+
+/** max MP REGS */
+#define MAX_MP_REGS_MAX (196)
+
+/** Multi port TX aggregation buffer size */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (65280)	/* 64K - 256 */
+
+/** Multi port RX aggregation buffer size */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (65280)	/* 64K - 256 */
+
+#endif /* SDIO */
+
+/** Minimum BA threshold */
+#define MIN_BA_THRESHOLD 16
+
+/** High threshold at which to start drop packets */
+#define RX_HIGH_THRESHOLD 1024
+/** Low threshold to allow Rx BA */
+#define RX_LOW_THRESHOLD 128
+
+#define MFG_CMD_SET_TEST_MODE   1
+#define MFG_CMD_UNSET_TEST_MODE 0
+#define MFG_CMD_TX_ANT          0x1004
+#define MFG_CMD_RX_ANT          0x1005
+#define MFG_CMD_TX_CONT         0x1009
+#define MFG_CMD_RF_CHAN         0x100A
+#define MFG_CMD_CLR_RX_ERR      0x1010
+#define MFG_CMD_TX_FRAME        0x1021
+#define MFG_CMD_RF_BAND_AG      0x1034
+#define MFG_CMD_RF_CHANNELBW    0x1044
+#define MFG_CMD_RADIO_MODE_CFG  0x1211
+#define MFG_CMD_CONFIG_MAC_HE_TB_TX 0x110A
+
+/** Debug command number */
+#define DBG_CMD_NUM 10
+
+/** Info for debug purpose */
+typedef struct _wlan_dbg {
+	/** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+	/** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+	/** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+	/** Number of card to host command/event failures */
+	t_u32 num_cmdevt_card_to_host_failure;
+	/** Number of card to host Rx failures */
+	t_u32 num_rx_card_to_host_failure;
+	/** Number of interrupt read failures */
+	t_u32 num_int_read_failure;
+	/** Last interrupt status */
+	t_u32 last_int_status;
+	/** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+	/** Number of deauthentication events */
+	t_u32 num_event_deauth;
+	/** Number of disassosiation events */
+	t_u32 num_event_disassoc;
+	/** Number of link lost events */
+	t_u32 num_event_link_lost;
+	/** Number of deauthentication commands */
+	t_u32 num_cmd_deauth;
+	/** Number of association comamnd successes */
+	t_u32 num_cmd_assoc_success;
+	/** Number of association command failures */
+	t_u32 num_cmd_assoc_failure;
+	/** Number of consecutive association command failures */
+	t_u32 num_cons_assoc_failure;
+
+	/** Timeout command ID */
+	t_u16 timeout_cmd_id;
+	/** Timeout command action */
+	t_u16 timeout_cmd_act;
+	/** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+	/** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+	/** Last command index */
+	t_u16 last_cmd_index;
+	/** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+	/** Last command response index */
+	t_u16 last_cmd_resp_index;
+	/** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+	/** Last event index */
+	t_u16 last_event_index;
+	/** Number of no free command node */
+	t_u16 num_no_cmd_node;
+} wlan_dbg;
+
+/** Hardware status codes */
+typedef enum _WLAN_HARDWARE_STATUS {
+	WlanHardwareStatusReady,
+	WlanHardwareStatusGetHwSpec,
+	WlanHardwareStatusGetHwSpecdone,
+	WlanHardwareStatusInitializing,
+	WlanHardwareStatusInitdone,
+	WlanHardwareStatusReset,
+	WlanHardwareStatusClosing,
+	WlanHardwareStatusNotReady
+} WLAN_HARDWARE_STATUS;
+
+/** WLAN_802_11_POWER_MODE */
+typedef enum _WLAN_802_11_POWER_MODE {
+	Wlan802_11PowerModeCAM,
+	Wlan802_11PowerModePSP
+} WLAN_802_11_POWER_MODE;
+
+/** tx param */
+typedef struct _mlan_tx_param {
+	/** next packet length */
+	t_u32 next_pkt_len;
+} mlan_tx_param;
+
+/** PS_STATE */
+typedef enum _PS_STATE {
+	PS_STATE_AWAKE,
+	PS_STATE_PRE_SLEEP,
+	PS_STATE_SLEEP_CFM,
+	PS_STATE_SLEEP
+} PS_STATE;
+
+/** Minimum flush timer for win size of 1 is 50 ms */
+#define MIN_FLUSH_TIMER_MS 50
+/** Minimum flush timer for win size of 1 is 15 ms */
+#define MIN_FLUSH_TIMER_15_MS 15
+
+/** Tx BA stream table */
+typedef struct _TxBAStreamTbl TxBAStreamTbl;
+
+/** Add BA parameter data structure */
+typedef struct {
+	/** Window size for initiator */
+	t_u32 tx_win_size;
+	/** Window size for receiver */
+	t_u32 rx_win_size;
+	/** Block ack timeout */
+	t_u32 timeout;
+	/** amsdu support for ADDBA request */
+	t_u8 tx_amsdu;
+	/** amsdu support for ADDBA response */
+	t_u8 rx_amsdu;
+} add_ba_param_t;
+
+/** Tx aggregation data structure */
+typedef struct _txAggr_t {
+	/** AMPDU user */
+	t_u8 ampdu_user;
+	/** AMPDU AP */
+	t_u8 ampdu_ap;
+	/** AMSDU */
+	t_u8 amsdu;
+} tx_aggr_t;
+
+/** del ba threshold */
+#define DEL_BA_THRESHOLD 10
+/** BA stream status */
+typedef enum _baStatus_e {
+	BA_STREAM_NOT_SETUP = 0,
+	BA_STREAM_SETUP_INPROGRESS,
+	BA_STREAM_SETUP_COMPLETE
+} baStatus_e;
+
+/** RA list table */
+typedef struct _raListTbl raListTbl, *praListTbl;
+
+/** RA list table */
+struct _raListTbl {
+	/** Pointer to previous node */
+	raListTbl *pprev;
+	/** Pointer to next node */
+	raListTbl *pnext;
+	/** Buffer list head */
+	mlan_list_head buf_head;
+	/** RA list buffer */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	/** total packets in RA list */
+	t_u16 total_pkts;
+	/** packets received */
+	t_u16 packet_count;
+	/** packet count threshold to setup BA */
+	t_u8 ba_packet_threshold;
+	/** is 11n enabled */
+	t_u8 is_11n_enabled;
+	/** max amsdu size */
+	t_u16 max_amsdu;
+	/** BA stream status */
+	baStatus_e ba_status;
+	/** del ba count */
+	t_u8 del_ba_count;
+	/** amsdu in ampdu flag */
+	t_u8 amsdu_in_ampdu;
+	/** tdls flag */
+	t_u8 is_tdls_link;
+	/** tx_pause flag */
+	t_u8 tx_pause;
+};
+
+/** TID table */
+typedef struct _tidTbl {
+	/** RA list head */
+	mlan_list_head ra_list;
+	/** Current RA list */
+	raListTbl *ra_list_curr;
+} tid_tbl_t;
+
+/** Highest priority setting for a packet (uses voice AC) */
+#define WMM_HIGHEST_PRIORITY 7
+/** Highest priority TID  */
+#define HIGH_PRIO_TID 7
+/** Lowest priority TID  */
+#define LOW_PRIO_TID 0
+/** No packet priority (< lowest) */
+#define NO_PKT_PRIO_TID -1
+
+/** Max driver packet delay in msec */
+#define WMM_DRV_DELAY_MAX 510
+
+/** Struct of WMM DESC */
+typedef struct _wmm_desc {
+	/** TID table */
+	tid_tbl_t tid_tbl_ptr[MAX_NUM_TID];
+	/** Packets out */
+	t_u32 packets_out[MAX_NUM_TID];
+	/** Packets queued */
+	t_u32 pkts_queued[MAX_NUM_TID];
+	/** Packets paused */
+	t_u32 pkts_paused[MAX_NUM_TID];
+	/** Spin lock to protect ra_list */
+	t_void *ra_list_spinlock;
+
+	/** AC status */
+	WmmAcStatus_t ac_status[MAX_AC_QUEUES];
+	/** AC downgraded values */
+	mlan_wmm_ac_e ac_down_graded_vals[MAX_AC_QUEUES];
+
+	/** Max driver packet delay sent to the firmware for expiry eval */
+	t_u32 drv_pkt_delay_max;
+
+	/** WMM queue priority table */
+	t_u8 queue_priority[MAX_AC_QUEUES];
+	/** User priority packet transmission control */
+	t_u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1];	/* UP: 0 to 7 */
+
+	/** Number of transmit packets queued */
+	mlan_scalar tx_pkts_queued;
+	/** Tracks highest priority with a packet queued */
+	mlan_scalar highest_queued_prio;
+} wmm_desc_t;
+
+/** Security structure */
+typedef struct _wlan_802_11_security_t {
+	/** WPA enabled flag */
+	t_u8 wpa_enabled;
+	/** E-Supplicant enabled flag */
+	t_u8 ewpa_enabled;
+	/** WPA2 enabled flag */
+	t_u8 wpa2_enabled;
+	/** WAPI enabled flag */
+	t_u8 wapi_enabled;
+	/** WAPI key on flag */
+	t_u8 wapi_key_on;
+	/** WEP status */
+	WLAN_802_11_WEP_STATUS wep_status;
+	/** Authentication mode */
+	t_u32 authentication_mode;
+	/** Encryption mode */
+	t_u32 encryption_mode;
+	/** Hotspot OSEN enabled */
+	t_u8 osen_enabled;
+} wlan_802_11_security_t;
+
+/** Current Basic Service Set State Structure */
+typedef struct {
+	/** BSS descriptor */
+	BSSDescriptor_t bss_descriptor;
+	/** WMM enable? */
+	t_u8 wmm_enabled;
+	/** Uapsd enable?*/
+	t_u8 wmm_uapsd_enabled;
+	/** Band */
+	t_u8 band;
+	/** Number of rates supported */
+	t_u32 num_of_rates;
+	/** Supported rates*/
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+	/** Host MLME flag*/
+	t_u8 host_mlme;
+	mlan_802_11_mac_addr prev_bssid;
+	t_u8 use_mfp;
+} current_bss_params_t;
+
+/** Sleep_params */
+typedef struct _sleep_params_t {
+	/** Sleep parameter error */
+	t_u16 sp_error;
+	/** Sleep parameter offset */
+	t_u16 sp_offset;
+	/** Sleep parameter stable time */
+	t_u16 sp_stable_time;
+	/** Sleep parameter calibration control */
+	t_u8 sp_cal_control;
+	/** Sleep parameter external sleep clock */
+	t_u8 sp_ext_sleep_clk;
+	/** Sleep parameter reserved */
+	t_u16 sp_reserved;
+} sleep_params_t;
+
+/** Sleep_period */
+typedef struct sleep_period_t {
+	/** Sleep period */
+	t_u16 period;
+	/** Reserved */
+	t_u16 reserved;
+} sleep_period_t;
+
+/** mrvl_wep_key_t */
+typedef struct _mrvl_wep_key_t {
+	/** Length */
+	t_u32 length;
+	/** WEP key index */
+	t_u32 key_index;
+	/** WEP key length */
+	t_u32 key_length;
+	/** WEP keys */
+	t_u8 key_material[MRVL_KEY_BUFFER_SIZE_IN_BYTE];
+} mrvl_wep_key_t;
+
+/** Maximum number of region channel */
+#define MAX_REGION_CHANNEL_NUM 2
+
+/** Region-band mapping table */
+typedef struct _region_chan_t {
+	/** TRUE if this entry is valid */
+	t_u8 valid;
+	/** Region code for US, Japan ... */
+	t_u8 region;
+	/** Band B/G/A, used for BAND_CONFIG cmd */
+	t_u8 band;
+	/** Actual No. of elements in the array below */
+	t_u8 num_cfp;
+	/** chan-freq-txpower mapping table */
+	chan_freq_power_t *pcfp;
+} region_chan_t;
+
+/** State of 11d */
+typedef enum _state_11d_t {
+	DISABLE_11D = 0,
+	ENABLE_11D = 1,
+} state_11d_t;
+
+#define DEFAULT_11D_STATE DISABLE_11D
+
+/** Domain regulatory information */
+typedef struct _wlan_802_11d_domain_reg {
+	/** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** band that channels in sub_band belong to */
+	t_u8 band;
+	/** No. of subband in below */
+	t_u8 no_of_sub_band;
+	/** Subband data to send/last sent */
+	IEEEtypes_SubbandSet_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} wlan_802_11d_domain_reg_t;
+
+/** Data for state machine */
+typedef struct _wlan_802_11d_state {
+	/** True for enabling 11D */
+	state_11d_t enable_11d;
+	/** True for user enabling 11D */
+	state_11d_t user_enable_11d;
+} wlan_802_11d_state_t;
+
+/** 802.11h State information kept in the 'mlan_private' driver structure */
+typedef struct {
+	/** Indicate 11h is enabled from host */
+	t_bool is_11h_host;
+	/** Indicates whether 11h is enabled in the driver */
+	t_bool is_11h_enabled;
+	/** Indicates whether 11h is active in the firmware */
+	t_bool is_11h_active;
+	/** Master device using automatic channel select */
+	t_bool adhoc_auto_sel_chan;
+	/** Set when driver receives a STOP TX event from fw */
+	t_bool tx_disabled;
+	/** Channel that ChanSwAnn was received for, non-zero = active */
+	t_u8 dfs_slave_csa_chan;
+	/** Expiry for above variable, seconds in system time */
+	t_u32 dfs_slave_csa_expire_at_sec;
+} wlan_11h_interface_state_t;
+
+#if defined(UAP_SUPPORT)
+/** UAP get info callback state kept in the 'mlan_private' driver structure */
+typedef struct {
+	/** UAP internal callback after wlan_uap_get_channel */
+	/**  (parameter is really pointer to mlan_private)   */
+	mlan_status (*get_chan_callback) (t_void *);
+	/** current ioctl_req (to be completed in callback) */
+	pmlan_ioctl_req pioctl_req_curr;
+	/** band config from MrvlIEtypes_channel_band_t */
+	Band_Config_t bandcfg;
+	/** channel from MrvlIEtypes_channel_band_t */
+	t_u8 channel;
+	/** beacon period (in msec) from MrvlIEtypes_beacon_period_t */
+	t_u16 beacon_period;
+	/** dtim period (no unit) from MrvlIEtypes_dtim_period_t */
+	t_u8 dtim_period;
+} wlan_uap_get_info_cb_t;
+#endif
+
+/** Data structure for WPS information */
+typedef struct {
+	/** WPS IE */
+	IEEEtypes_VendorSpecific_t wps_ie;
+	/** Session enable flag */
+	t_u8 session_enable;
+} wps_t;
+
+/** mlan_operations data structure */
+typedef struct _mlan_operations {
+	/** cmd init handler */
+	mlan_status (*init_cmd) (t_void *priv, t_u8 first_bss);
+	/** ioctl handler */
+	mlan_status (*ioctl) (t_void *adapter, pmlan_ioctl_req pioctl_req);
+	/** cmd handler */
+	mlan_status (*prepare_cmd) (t_void *priv, t_u16 cmd_no,
+				    t_u16 cmd_action, t_u32 cmd_oid,
+				    t_void *pioctl_buf, t_void *pdata_buf,
+				    t_void *pcmd_buf);
+	/** cmdresp handler */
+	mlan_status (*process_cmdresp) (t_void *priv, t_u16 cmdresp_no,
+					t_void *pcmd_buf, t_void *pioctl);
+	/** rx handler */
+	mlan_status (*process_rx_packet) (t_void *adapter, pmlan_buffer pmbuf);
+	/** event handler */
+	mlan_status (*process_event) (t_void *priv);
+	/** txpd handler */
+	t_void *(*process_txpd) (t_void *priv, pmlan_buffer pmbuf);
+	/** BSS role */
+	mlan_bss_role bss_role;
+} mlan_operations, *pmlan_operations;
+
+/** Private structure for MLAN */
+typedef struct _mlan_private {
+	/** Pointer to mlan_adapter */
+	struct _mlan_adapter *adapter;
+	/** BSS index */
+	t_u8 bss_index;
+	/** BSS type */
+	t_u8 bss_type;
+	/** BSS role */
+	t_u8 bss_role;
+	/** BSS virtual flag */
+	t_u8 bss_virtual;
+	/** BSS Priority */
+	t_u8 bss_priority;
+	/** BSS number */
+	t_u8 bss_num;
+	/** Frame type */
+	t_u8 frame_type;
+	/** MAC address information */
+	t_u8 curr_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Media connection status */
+	t_bool media_connected;
+
+	/** Current packet filter */
+	t_u32 curr_pkt_filter;
+	/** Infrastructure mode */
+	t_u32 bss_mode;
+
+	/** Tx packet control */
+	t_u32 pkt_tx_ctrl;
+
+	/** Tx power level */
+	t_s16 tx_power_level;
+	/** Maximum Tx power level */
+	t_s8 max_tx_power_level;
+	/** Minimum Tx power level */
+	t_s8 min_tx_power_level;
+	/** Tx rate */
+	t_u8 tx_rate;
+	t_u8 tx_rate_info;
+	/*HE tx tone mode and DCM info */
+	t_u8 ext_tx_rate_info;
+	/*HE rx tone mode and DCM info */
+	t_u8 rxpd_rx_info;
+	/** rxpd_htinfo */
+	t_u8 rxpd_rate_info;
+	/** max amsdu size */
+	t_u16 max_amsdu;
+	/** amsdu disable flag */
+	t_u8 amsdu_disable;
+	/** 802.11n Device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11n_dev_cap_bg;
+	/** 802.11n Device Capabilities for 5GHz */
+	t_u32 usr_dot_11n_dev_cap_a;
+	/** MIMO abstraction of MCSs supported by device */
+	t_u8 usr_dev_mcs_support;
+#ifdef UAP_SUPPORT
+	/** UAP 11n flag */
+	t_u8 is_11n_enabled;
+#endif				/* UAP_SUPPORT */
+	/** UAP 11ac flag */
+	t_u8 is_11ac_enabled;
+	/** UAP 11ax flag */
+	t_u8 is_11ax_enabled;
+	/** tx vht_info */
+	t_u8 tx_vhtinfo;
+	/** rxpd_vhtinfo */
+	t_u8 rxpd_vhtinfo;
+	/** 802.11ac Device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+	/** 802.11ac Device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+	/** MIMO abstraction of MCSs supported by device */
+	t_u32 usr_dot_11ac_mcs_support;
+	/** user dot 11ac_BW */
+	t_u8 usr_dot_11ac_bw;
+	/** user dot 11ac_opermode_BW */
+	t_u8 usr_dot_11ac_opermode_bw;
+	/** user dot 11ac_opermode_nss */
+	t_u8 usr_dot_11ac_opermode_nss;
+	/** length of hw he capability */
+	t_u8 user_hecap_len;
+	/** user configured 802.11ax HE capability */
+	t_u8 user_he_cap[54];
+	/** length of hw he capability */
+	t_u8 user_2g_hecap_len;
+	/** user configured 802.11ax HE capability */
+	t_u8 user_2g_he_cap[54];
+	/**  dropped pkts */
+	t_u32 num_drop_pkts;
+#ifdef UAP_SUPPORT
+	/** packet forward control */
+	t_u8 pkt_fwd;
+#endif
+	/** TX beamforming capability */
+	t_u32 tx_bf_cap;
+	/** Rx PD rate */
+	t_u8 rxpd_rate;
+	/** Bitmap rates */
+	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+	/** Data rate */
+	t_u32 data_rate;
+	/** Automatic data rate flag */
+	t_u8 is_data_rate_auto;
+	/** Factor for calculating beacon average */
+	t_u16 bcn_avg_factor;
+	/** Factor for calculating data average */
+	t_u16 data_avg_factor;
+	/** SNR */
+	t_s8 snr;
+	/** Noise Floor */
+	t_s8 nf;
+	/** Last data RSSI */
+	t_s16 data_rssi_last;
+	/** Last data Noise Floor */
+	t_s16 data_nf_last;
+	/** Average data RSSI */
+	t_s16 data_rssi_avg;
+	/** Averag data Noise Floor */
+	t_s16 data_nf_avg;
+	/** Last beacon RSSI */
+	t_s16 bcn_rssi_last;
+	/** Last beacon Noise Floor */
+	t_s16 bcn_nf_last;
+	/** Average beacon RSSI */
+	t_s16 bcn_rssi_avg;
+	/** Average beacon Noise Floor */
+	t_s16 bcn_nf_avg;
+	/** Attempted BSS descriptor */
+	BSSDescriptor_t *pattempted_bss_desc;
+
+	/** GTK rekey data*/
+	mlan_ds_misc_gtk_rekey_data gtk_rekey;
+
+	/** Current SSID/BSSID related parameters*/
+	current_bss_params_t curr_bss_params;
+	/** current channel flags */
+	t_u32 curr_chan_flags;
+	/** User selected bands */
+	t_u16 config_bands;
+
+	/** Beacon period */
+	t_u16 beacon_period;
+	/** Listen interval */
+	t_u16 listen_interval;
+	/** ATIM window */
+	t_u16 atim_window;
+
+	/** AdHoc channel */
+	t_u8 adhoc_channel;
+	/** AdHoc link sensed flag */
+	t_u8 adhoc_is_link_sensed;
+	/** AdHoc operating state */
+	t_u8 adhoc_state;
+#if defined(STA_SUPPORT)
+	/** AdHoc operating state backup */
+	t_u8 adhoc_state_prev;
+	/** AdHoc previous ssid used for Start */
+	mlan_802_11_ssid adhoc_last_start_ssid;
+#endif
+	/** FSM variable for 11d support */
+	wlan_802_11d_state_t state_11d;
+	/** FSM variable for 11h support */
+	wlan_11h_interface_state_t intf_state_11h;
+#ifdef UAP_SUPPORT
+	/** Whether UAP interface has started */
+	t_bool uap_bss_started;
+	/** Whether UAP interface start from hostapd */
+	t_bool uap_host_based;
+	/**UAP operating channel*/
+	t_u8 uap_channel;
+	/** state variable for UAP Get Info callback */
+	wlan_uap_get_info_cb_t uap_state_chan_cb;
+#endif				/* UAP_SUPPORT */
+
+	/** Security related */
+	/** Encryption parameter */
+	wlan_802_11_security_t sec_info;
+	/** WEP keys */
+	mrvl_wep_key_t wep_key[MRVL_NUM_WEP_KEY];
+	/** Current WEP key index */
+	t_u16 wep_key_curr_index;
+	/** EWPA query 0: disable, 1: enable */
+	t_u8 ewpa_query;
+	/** Encryption Key*/
+	t_u8 wpa_ie[256];
+	/** WPA IE length */
+	t_u8 wpa_ie_len;
+	/** GTK set flag */
+	t_u8 wpa_is_gtk_set;
+	/** AES key material */
+	mlan_ds_encrypt_key aes_key;
+#if defined(STA_SUPPORT)
+	/* Mgmt Frame Protection config */
+	mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+	/** WAPI IE */
+	t_u8 wapi_ie[256];
+	/** WAPI IE length */
+	t_u8 wapi_ie_len;
+	/** OSEN IE */
+	t_u8 osen_ie[256];
+	/** OSEN IE length */
+	t_u8 osen_ie_len;
+	/** Pointer to the station table */
+	mlan_list_head sta_list;
+	/** tdls pending queue */
+	mlan_list_head tdls_pending_txq;
+	t_u16 tdls_idle_time;
+
+	/** MGMT IE */
+	custom_ie mgmt_ie[MAX_MGMT_IE_INDEX];
+	/** mgmt frame passthru mask */
+	t_u32 mgmt_frame_passthru_mask;
+	/** WMM required */
+	t_u8 wmm_required;
+	/** WMM enabled */
+	t_u8 wmm_enabled;
+	/** WMM qos info */
+	t_u8 wmm_qosinfo;
+	/** saved WMM qos info */
+	t_u8 saved_wmm_qosinfo;
+	/**host tdls uapsd support*/
+	t_u8 host_tdls_uapsd_support;
+	/**host tdls channel switch support*/
+	t_u8 host_tdls_cs_support;
+	/**supported channel IE len*/
+	t_u8 chan_supp_len;
+	/**save channel support IE*/
+	t_u8 chan_supp[MAX_IE_SIZE];
+	/**supported regulatory classl IE len*/
+	t_u8 supp_regulatory_class_len;
+	/**save support channel regulatory class IE*/
+	t_u8 supp_regulatory_class[MAX_IE_SIZE];
+	/**tdls cs off channel*/
+	t_u8 tdls_cs_channel;
+	/** WMM related variable*/
+	wmm_desc_t wmm;
+
+	/** Pointer to the Transmit BA stream table*/
+	mlan_list_head tx_ba_stream_tbl_ptr;
+	/** Pointer to the priorities for AMSDU/AMPDU table*/
+	tx_aggr_t aggr_prio_tbl[MAX_NUM_TID];
+	/** Pointer to the priorities for AMSDU/AMPDU table*/
+	t_u8 addba_reject[MAX_NUM_TID];
+	/** Pointer to the priorities for AMSDU/AMPDU table*/
+	t_u8 ibss_ampdu[MAX_NUM_TID];
+	/** Pointer to the priorities for AMSDU/AMPDU table*/
+	t_u8 ibss_addba_reject[MAX_NUM_TID];
+	/** Struct to store ADDBA parameters */
+	add_ba_param_t add_ba_param;
+	/**  user rx_win_size */
+	t_u32 user_rxwinsize;
+	/** last rx_seq */
+	t_u16 rx_seq[MAX_NUM_TID];
+	/** Pointer to the Receive Reordering table*/
+	mlan_list_head rx_reorder_tbl_ptr;
+	/** Lock for Rx packets */
+	t_void *rx_pkt_lock;
+
+#ifdef STA_SUPPORT
+	/** Buffer to store the association response for application retrieval
+	 */
+	t_u8 assoc_rsp_buf[MRVDRV_ASSOC_RSP_BUF_SIZE];
+	/** Length of the data stored in assoc_rsp_buf */
+	t_u32 assoc_rsp_size;
+
+	/** Generic IEEE IEs passed from the application to be inserted into the
+	 *    association request to firmware
+	 */
+	t_u8 gen_ie_buf[MRVDRV_GENIE_BUF_SIZE];
+	/** Length of the data stored in gen_ie_buf */
+	t_u8 gen_ie_buf_len;
+
+	/** disconnect reason code*/
+	t_u16 disconnect_reason_code;
+	t_u8 *pcurr_bcn_buf;
+	t_u32 curr_bcn_size;
+	t_void *curr_bcn_buf_lock;
+
+	/** WPS */
+	wps_t wps;
+#endif				/* STA_SUPPORT */
+
+	/** function table */
+	mlan_operations ops;
+	/** tx pause flag */
+	t_u8 tx_pause;
+	/** Port Control mode */
+	t_u8 port_ctrl_mode;
+
+	/** Port open flag */
+	t_u8 port_open;
+
+	/** Port open flag state at time of association attempt */
+	t_u8 prior_port_status;
+	/** Bypass TX queue */
+	mlan_list_head bypass_txq;
+	/** IP address operation */
+	t_u32 op_code;
+	/** IP address */
+	t_u8 ip_addr[IPADDR_LEN];
+	t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+	ExtCap_t ext_cap;
+	ExtCap_t def_ext_cap;
+#endif
+	/** interface header len */
+	t_u8 intf_hr_len;
+#ifdef USB
+	/** USB data port */
+	t_u32 port;
+#endif
+	/** Control TX AMPDU on infra link */
+	t_u8 txaggrctrl;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	t_void *psapriv;
+#endif
+	/** rx per packet info */
+	t_u8 rx_pkt_info;
+	/** received amsdu count*/
+	t_u32 amsdu_rx_cnt;
+	/** received msdu count in amsdu*/
+	t_u32 msdu_in_rx_amsdu_cnt;
+	/** tx amsdu count*/
+	t_u32 amsdu_tx_cnt;
+	/** tx msdu count in amsdu*/
+	t_u32 msdu_in_tx_amsdu_cnt;
+} mlan_private, *pmlan_private;
+
+typedef struct _assoc_logger {
+	/** vendor specific */
+	t_u8 oui[3];
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+	t_s32 rssi;
+	t_u32 channel;
+} assoc_logger_data;
+
+/** Tx BA stream table */
+struct _TxBAStreamTbl {
+	/** TxBAStreamTbl previous node */
+	TxBAStreamTbl *pprev;
+	/** TxBAStreamTbl next node */
+	TxBAStreamTbl *pnext;
+	/** TID */
+	int tid;
+	/** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	/** BA stream status */
+	baStatus_e ba_status;
+	t_u8 amsdu;
+};
+
+/** RX reorder table */
+typedef struct _RxReorderTbl RxReorderTbl;
+
+typedef struct {
+	/** Timer for flushing */
+	t_void *timer;
+	/** Timer set flag */
+	t_u8 timer_is_set;
+	/** RxReorderTbl ptr */
+	RxReorderTbl *ptr;
+	/** Priv pointer */
+	mlan_private *priv;
+} reorder_tmr_cnxt_t;
+
+/** RX reorder table */
+struct _RxReorderTbl {
+	/** RxReorderTbl previous node */
+	RxReorderTbl *pprev;
+	/** RxReorderTbl next node */
+	RxReorderTbl *pnext;
+	/** TID */
+	int tid;
+	/** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+	/** Start window */
+	int start_win;
+	/** last_seq */
+	int last_seq;
+	/** Window size */
+	int win_size;
+	/** Pointer to pointer to RxReorderTbl */
+	t_void **rx_reorder_ptr;
+	/** Timer context */
+	reorder_tmr_cnxt_t timer_context;
+	/** BA stream status */
+	baStatus_e ba_status;
+	t_u8 amsdu;
+	/** no packet drop flag for rx_reorder_tbl */
+	t_u8 force_no_drop;
+	/** flag for check start win */
+	t_u8 check_start_win;
+	/** pkt receive after BA setup */
+	t_u8 pkt_count;
+	/** flush data flag */
+	t_u8 flush_data;
+};
+
+/** BSS priority node */
+typedef struct _mlan_bssprio_node mlan_bssprio_node;
+
+/** BSS priority node */
+struct _mlan_bssprio_node {
+	/** Pointer to previous node */
+	mlan_bssprio_node *pprev;
+	/** Pointer to next node */
+	mlan_bssprio_node *pnext;
+	/** Pointer to priv */
+	pmlan_private priv;
+};
+
+/** BSS priority table */
+typedef struct _mlan_bssprio_tbl mlan_bssprio_tbl;
+
+/** BSS priority table */
+struct _mlan_bssprio_tbl {
+	/** BSS priority list head */
+	mlan_list_head bssprio_head;
+	/** Current priority node */
+	mlan_bssprio_node *bssprio_cur;
+};
+
+/** cmd_ctrl_node */
+typedef struct _cmd_ctrl_node cmd_ctrl_node;
+
+/** _cmd_ctrl_node */
+struct _cmd_ctrl_node {
+	/** Pointer to previous node */
+	cmd_ctrl_node *pprev;
+	/** Pointer to next node */
+	cmd_ctrl_node *pnext;
+	/** Pointer to priv */
+	pmlan_private priv;
+	/** Command number */
+	t_u32 cmd_no;
+	/** Command flag */
+	t_u32 cmd_flag;
+	/** Pointer to mlan_buffer */
+	mlan_buffer *cmdbuf;
+	/** Pointer to mlan_buffer */
+	mlan_buffer *respbuf;
+	/** Command parameter */
+	t_void *pdata_buf;
+	/** Pointer to mlan_ioctl_req if command is from IOCTL */
+	t_void *pioctl_buf;
+#if defined(PCIE) || defined(SDIO)
+	/** pre_allocated mlan_buffer for cmd */
+	mlan_buffer *pmbuf;
+#endif
+};
+
+/** default tdls wmm qosinfo */
+#define DEFAULT_TDLS_WMM_QOS_INFO 15
+/** default tdls sleep period */
+#define DEFAULT_TDLS_SLEEP_PERIOD 30
+
+/** TDLS status */
+typedef enum _tdlsStatus_e {
+	TDLS_NOT_SETUP = 0,
+	TDLS_SETUP_INPROGRESS,
+	TDLS_SETUP_COMPLETE,
+	TDLS_SETUP_FAILURE,
+	TDLS_TEAR_DOWN,
+	TDLS_SWITCHING_CHANNEL,
+	TDLS_IN_BASE_CHANNEL,
+	TDLS_IN_OFF_CHANNEL,
+} tdlsStatus_e;
+/** station node */
+typedef struct _sta_node sta_node, *psta_node;
+
+/** station node*/
+struct _sta_node {
+	/** previous node */
+	sta_node *pprev;
+	/** next node */
+	sta_node *pnext;
+	/** station mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** wmm flag */
+	t_u8 is_wmm_enabled;
+	/** 11n flag */
+	t_u8 is_11n_enabled;
+	/** AMPDU STA */
+	t_u8 ampdu_sta[MAX_NUM_TID];
+	/** last rx_seq */
+	t_u16 rx_seq[MAX_NUM_TID];
+	/** max amsdu size */
+	t_u16 max_amsdu;
+	/** HT cap */
+	IEEEtypes_HTCap_t HTcap;
+	/** 11ac flag */
+	t_u8 is_11ac_enabled;
+	/** UAP 11ax flag */
+	t_u8 is_11ax_enabled;
+	IEEEtypes_HECap_t he_cap;
+	/** SNR */
+	t_s8 snr;
+	/** Noise Floor */
+	t_s8 nf;
+	/** peer capability */
+	t_u16 capability;
+	/** tdls status */
+	tdlsStatus_e status;
+	/** flag for host based tdls */
+	t_u8 external_tdls;
+	/** peer support rates */
+	t_u8 support_rate[32];
+	/** rate size */
+	t_u8 rate_len;
+	/*Qos capability info */
+	t_u8 qos_info;
+	/** HT info in TDLS setup confirm*/
+	IEEEtypes_HTInfo_t HTInfo;
+	/** peer BSSCO_20_40*/
+	IEEEtypes_2040BSSCo_t BSSCO_20_40;
+	/*Extended capability */
+	IEEEtypes_ExtCap_t ExtCap;
+	/*RSN IE */
+	IEEEtypes_Generic_t rsn_ie;
+	/**Link ID*/
+	IEEEtypes_LinkIDElement_t link_ie;
+	/** AID info */
+	IEEEtypes_AID_t aid_info;
+	/** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t vht_cap;
+	/** VHT Operations IE */
+	IEEEtypes_VHTOprat_t vht_oprat;
+	/** wapi key on off flag */
+	t_u8 wapi_key_on;
+	/** tx pause status */
+	t_u8 tx_pause;
+	/** station band mode */
+	t_u16 bandmode;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	t_void *cm_connectioninfo;
+#endif
+	sta_stats stats;
+};
+
+/** 802.11h State information kept in the 'mlan_adapter' driver structure */
+typedef struct {
+	/** Min TX Power capability sent to FW for 11h use and fw power control
+	 */
+	t_s8 min_tx_power_capability;
+	/** Max TX Power capability sent to FW for 11h use and fw power control
+	 */
+	t_s8 max_tx_power_capability;
+	/** User provisioned local power constraint sent in association requests
+	 */
+	t_s8 usr_def_power_constraint;
+	/** Received CHANNEL_SWITCH_ANN event */
+	t_bool recvd_chanswann_event;
+	/** Indicates an interface wants to enable master radar detection */
+	t_bool master_radar_det_enable_pending;
+	/** Indicates an interface wants to enable slave radar detection */
+	t_bool slave_radar_det_enable_pending;
+	/** Indicates whether master radar detection active in the firmware */
+	t_bool is_master_radar_det_active;
+	/** Indicates whether slave radar detection active in the firmware */
+	t_bool is_slave_radar_det_active;
+	/** Quiet IE */
+	IEEEtypes_Quiet_t quiet_ie;
+} wlan_11h_device_state_t;
+
+/** Enumeration for DFS Timestamp represents field */
+enum _dfs_timestamp_repr_e {
+	/** Ignore entry */
+	DFS_TS_REPR_NOT_IN_USE = 0,
+	/** NOP (Non-Occupancy Period) start time */
+	DFS_TS_REPR_NOP_START = 1,
+	/** CAC (Channel Availability Check) completion time */
+	DFS_TS_REPR_CAC_COMPLETION
+};
+
+/** DFS Timestamp type used for marking NOP/CAC events */
+typedef struct _wlan_dfs_timestamp_t wlan_dfs_timestamp_t;
+
+/** DFS Timestamp type used for marking NOP/CAC events */
+struct _wlan_dfs_timestamp_t {
+	/** Pointer to previous node */
+	wlan_dfs_timestamp_t *pprev;
+	/** Pointer to next node */
+	wlan_dfs_timestamp_t *pnext;
+	/** WLAN Channel number */
+	t_u8 channel;
+	/** What this timestamp represents */
+	t_u8 represents;
+	/** reserved field */
+	t_u16 reserved;
+	/** timestamp - seconds */
+	t_u32 ts_sec;
+	/** timestamp - microseconds */
+	t_u32 ts_usec;
+};
+
+/** DFS State information kept in the 'mlan_adapter' driver structure */
+typedef struct {
+	/** Indicates whether DFS channel check is occurring in firmware */
+	t_bool dfs_check_pending;
+	/** Indicates whether DFS channel check found radar */
+	t_bool dfs_radar_found;
+	/** Channel radar is being checked on.  BAND_A is assumed. */
+	t_u8 dfs_check_channel;
+	/** point to the priv which start the DFS check */
+	t_void *dfs_check_priv;
+	/** Timestamp when we got last report,
+	 * to determine if data is old or not.
+	 */
+	t_u32 dfs_report_time_sec;
+	/** List for holding dfs_timestamps for NOP/CAC events */
+	mlan_list_head dfs_ts_head;
+} wlan_dfs_device_state_t;
+
+/** Enumeration for mlan_ds_11h_radar_det_hndlg stages */
+enum _mlan_ds_11h_rdh_stages {
+	RDH_OFF = 0,
+	RDH_CHK_INTFS = 1,
+	RDH_STOP_TRAFFIC,
+	RDH_GET_INFO_CHANNEL,
+	RDH_GET_INFO_BEACON_DTIM,
+	RDH_SET_CUSTOM_IE,
+	RDH_REM_CUSTOM_IE,
+	RDH_STOP_INTFS,
+	RDH_SET_NEW_CHANNEL,
+	RDH_RESTART_INTFS,
+	RDH_RESTART_TRAFFIC
+};
+
+/** State info for Radar Detected Handling kept in 'mlan_adapter' */
+typedef struct {
+	/** Stage (of Operation) */
+	t_u8 stage;
+	/** Number of interfaces to handle */
+	t_u8 priv_list_count;
+	/** Index of interface in process (used by some stages) */
+	t_u8 priv_curr_idx;
+	/** Current Channel (to leave) */
+	t_u8 curr_channel;
+	/** New Channel (to switch to) */
+	t_u8 new_channel;
+	/** UAP band_config */
+	Band_Config_t uap_band_cfg;
+	/** BEACON*DTIM period (in msec; max of STA/UAP) */
+	t_u16 max_bcn_dtim_ms;
+	/** tx block flag */
+	t_u8 tx_block;
+	/** List of interfaces to handle */
+	mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+} wlan_radar_det_hndlg_state_t;
+
+/** DFS/RDH testing exception settings kept in 'mlan_adapter' */
+typedef struct {
+	/** user-configured CAC period (in msec) */
+	t_u32 user_cac_period_msec;
+	/** user-configured NOP period (in sec) */
+	t_u16 user_nop_period_sec;
+	/** user-configured skip channel change on radar */
+	t_bool no_channel_change_on_radar;
+	/** user-configured new channel to change to on radar */
+	t_u8 fixed_new_channel_on_radar;
+	/** user-configured cac restart */
+	t_u8 cac_restart;
+	/**  cac channel */
+	t_u8 chan;
+	/** band cfg */
+	Band_Config_t bandcfg;
+	/** cac time */
+	t_u32 millisec_dwell_time;
+} wlan_dfs_testing_settings_t;
+
+/**
+ * @brief Driver measurement state held in 'mlan_adapter' structure
+ *
+ *  Used to record a measurement request that the driver is pending on
+ *    the result (received measurement report).
+ */
+typedef struct {
+	/**
+	 * Dialog token of a pending measurement request/report.  Used to
+	 *   block execution while waiting for the specific dialog token
+	 */
+	t_u8 meas_rpt_pend_on;
+
+	/**
+	 * Measurement report received from the firmware that we were pending on
+	 */
+	HostCmd_DS_MEASUREMENT_REPORT meas_rpt_returned;
+
+} wlan_meas_state_t;
+
+#ifdef SDIO
+/**
+ *  @brief Link buffer into aggregate head buffer
+ *
+ *  @param pmbuf_aggr	Pointer to aggregation buffer
+ *  @param pmbuf		Pointer to buffer to copy
+ */
+static inline t_void
+wlan_link_buf_to_aggr(pmlan_buffer pmbuf_aggr, pmlan_buffer pmbuf)
+{
+	/* link new buf at end of list */
+	pmbuf->pnext = pmbuf_aggr;
+	pmbuf->pprev = pmbuf_aggr->pprev;
+	pmbuf->pparent = pmbuf_aggr;
+	pmbuf_aggr->pprev->pnext = pmbuf;
+	pmbuf_aggr->pprev = pmbuf;
+	pmbuf_aggr->use_count++;
+}
+
+/** data structure for SDIO MPA TX */
+typedef struct _sdio_mpa_tx {
+	/** allocated buf for tx aggreation */
+	t_u8 *head_ptr;
+	/** multiport tx aggregation buffer pointer */
+	t_u8 *buf;
+	/** multiport tx aggregation buffer length */
+	t_u32 buf_len;
+	/** multiport tx aggregation packet count */
+	t_u32 pkt_cnt;
+	/** multiport tx aggregation ports */
+	t_u32 ports;
+	/** multiport tx aggregation starting port */
+	t_u16 start_port;
+	/** multiport tx aggregation enable/disable flag */
+	t_u8 enabled;
+	/** multiport tx aggregation buffer size */
+	t_u32 buf_size;
+	/** multiport tx aggregation pkt aggr limit */
+	t_u32 pkt_aggr_limit;
+	/** multiport write info */
+	t_u16 mp_wr_info[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** multiport rx aggregation mbuf array */
+	pmlan_buffer mbuf_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+} sdio_mpa_tx;
+
+/** data structure for SDIO MPA RX */
+typedef struct _sdio_mpa_rx {
+	/** allocated buf for rx aggreation */
+	t_u8 *head_ptr;
+	/** multiport rx aggregation buffer pointer */
+	t_u8 *buf;
+	/** multiport rx aggregation buffer length */
+	t_u32 buf_len;
+	/** multiport rx aggregation packet count */
+	t_u32 pkt_cnt;
+	/** multiport rx aggregation ports */
+	t_u32 ports;
+	/** multiport rx aggregation starting port */
+	t_u16 start_port;
+
+	/** multiport rx aggregation mbuf array */
+	pmlan_buffer mbuf_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** multiport rx aggregation pkt len array */
+	t_u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+
+	/** multiport rx aggregation enable/disable flag */
+	t_u8 enabled;
+	/** multiport rx aggregation buffer size */
+	t_u32 buf_size;
+	/** multiport rx aggregation pkt aggr limit */
+	t_u32 pkt_aggr_limit;
+} sdio_mpa_rx;
+#endif
+
+#ifdef USB
+/** data structure for USB Rx Deaggregation */
+typedef struct _usb_rx_deaggr_params {
+	/** Rx aggregation control */
+	usb_aggr_ctrl_cfg aggr_ctrl;
+} usb_rx_deaggr_params;
+
+#define MAX_USB_TX_PORT_NUM 1
+/** data structure for USB Tx Aggregation */
+typedef struct _usb_tx_aggr_params {
+	/** Tx aggregation control */
+	usb_aggr_ctrl_cfg aggr_ctrl;
+	/** allocated pmbuf for tx aggreation */
+	pmlan_buffer pmbuf_aggr;
+	/** packet len used in pmbuf_aggr */
+	t_u32 aggr_len;
+	/** usb_tx_aggr timer */
+	t_void *paggr_hold_timer;
+	/** usb_tx_aggr timer set flag */
+	t_u8 aggr_hold_timer_is_set;
+	/** Timeout duration in milliseconds to wait for aggregation */
+	t_u32 hold_timeout_msec;
+	/** lock for transmission */
+	t_void *paggr_lock;
+	/** port for data transmission */
+	t_u32 port;
+	/** pointer to moal_adatper structure */
+	t_void *phandle;
+} usb_tx_aggr_params, *pusb_tx_aggr_params;
+#endif
+
+/** Type definition of mef_entry*/
+typedef struct _mef_cfg_data {
+	/** criteria*/
+	t_u32 criteria;
+	/** entry num*/
+	t_u16 entry_num;
+	/** entry pointer*/
+	mef_entry_t *pentry;
+} mef_cfg_data;
+
+/** Type definition of mef_entry*/
+typedef struct _mef_entry {
+	/** Flag for auto arp entry*/
+	int enable_autoarp_entry;
+	/** Num for wowlan entry*/
+	int num_wowlan_entry;
+	/** Num for IPv6 neighbor solicitation message offload */
+	int num_ipv6_ns_offload;
+
+	/** criteria*/
+	t_u32 criteria;
+	/** MEF CFG Array to store etted_entry_bitmap;
+	 *  Caution: 0-3 is for NVIDIA WHITE/BLACK list entries
+	 *  Caution: 4   is for NVIDIA ping entry
+	 *  Caution: 5   is for Auto Arp Entry
+	 *  Caution: 6   is for wowlan Entry
+	 *  Caution: 7   is for IPv6 Neighbor Solicitation offload Entry
+	 */
+	mef_entry_t entry[MAX_NUM_ENTRIES];
+} mef_entry;
+
+/** vdll_dnld_ctrl structure */
+typedef struct _vdll_dnld_ctrl {
+	/**  pending  VDLL block */
+	t_u8 *pending_block;
+	/* pending VDLL block len */
+	t_u16 pending_block_len;
+	/** memory for VDLL fw image */
+	t_u8 *vdll_mem;
+	/**  VDLL fw image len */
+	t_u32 vdll_len;
+#if defined(SDIO) || defined(PCIE)
+	/** mlan_buffer for VDLL download */
+	mlan_buffer *cmd_buf;
+#endif
+} vdll_dnld_ctrl, *pvdll_dnld_ctrl;
+
+/** mlan_init_para structure */
+typedef struct _mlan_init_para {
+#ifdef MFG_CMD_SUPPORT
+	/** MFG mode */
+	t_u32 mfg_mode;
+#endif
+#ifdef SDIO
+	/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+	/** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+	/** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+	/** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#endif
+	/** Auto deep sleep */
+	t_u32 auto_ds;
+	/** IEEE PS mode */
+	t_u32 ps_mode;
+	/** Max Tx buffer size */
+	t_u32 max_tx_buf;
+	/** 802.11d configuration */
+	t_u32 cfg_11d;
+	/** 802.11H DFS Master Radar Detect */
+	t_u32 dfs_master_radar_det_en;
+	/** 802.11H DFS Slave Radar Detect */
+	t_u32 dfs_slave_radar_det_en;
+	/** dev cap mask */
+	t_u32 dev_cap_mask;
+	/** oob independent reset mode */
+	t_u32 indrstcfg;
+	/** passive to active scan */
+	t_u8 passive_to_active_scan;
+	/** uap max sta */
+	t_u8 uap_max_sta;
+	/** dfs w53 cfg */
+	t_u8 dfs53cfg;
+#ifdef PCIE
+    /** adma ring size */
+	t_u16 ring_size;
+#endif
+	t_u8 ext_scan;
+} mlan_init_para, *pmlan_init_para;
+
+#ifdef SDIO
+typedef struct _mlan_sdio_card_reg {
+	t_u8 start_rd_port;
+	t_u8 start_wr_port;
+	t_u8 base_0_reg;
+	t_u8 base_1_reg;
+	t_u8 poll_reg;
+	t_u8 host_int_enable;
+	t_u8 host_int_status;
+	t_u8 status_reg_0;
+	t_u8 status_reg_1;
+	t_u8 sdio_int_mask;
+	t_u32 data_port_mask;
+	t_u8 max_mp_regs;
+	t_u8 rd_bitmap_l;
+	t_u8 rd_bitmap_u;
+	t_u8 rd_bitmap_1l;
+	t_u8 rd_bitmap_1u;
+	t_u8 wr_bitmap_l;
+	t_u8 wr_bitmap_u;
+	t_u8 wr_bitmap_1l;
+	t_u8 wr_bitmap_1u;
+	t_u8 rd_len_p0_l;
+	t_u8 rd_len_p0_u;
+	t_u8 card_config_2_1_reg;
+	t_u8 cmd_config_0;
+	t_u8 cmd_config_1;
+	t_u8 cmd_config_2;
+	t_u8 cmd_config_3;
+	t_u8 cmd_rd_len_0;
+	t_u8 cmd_rd_len_1;
+	t_u8 cmd_rd_len_2;
+	t_u8 cmd_rd_len_3;
+	t_u8 io_port_0_reg;
+	t_u8 io_port_1_reg;
+	t_u8 io_port_2_reg;
+	t_u8 host_int_rsr_reg;
+	t_u8 host_int_mask_reg;
+	t_u8 host_int_status_reg;
+	t_u8 host_restart_reg;
+	t_u8 card_to_host_event_reg;
+	t_u8 host_interrupt_mask_reg;
+	t_u8 card_interrupt_status_reg;
+	t_u8 card_interrupt_rsr_reg;
+	t_u8 card_revision_reg;
+	t_u8 card_ocr_0_reg;
+	t_u8 card_ocr_1_reg;
+	t_u8 card_ocr_3_reg;
+	t_u8 card_config_reg;
+	t_u8 card_misc_cfg_reg;
+	t_u8 debug_0_reg;
+	t_u8 debug_1_reg;
+	t_u8 debug_2_reg;
+	t_u8 debug_3_reg;
+	t_u32 fw_reset_reg;
+	t_u8 fw_reset_val;
+	t_u8 fw_dnld_offset_0_reg;
+	t_u8 fw_dnld_offset_1_reg;
+	t_u8 fw_dnld_offset_2_reg;
+	t_u8 fw_dnld_offset_3_reg;
+	t_u8 fw_dnld_status_0_reg;
+	t_u8 fw_dnld_status_1_reg;
+	t_u8 winner_check_reg;
+} mlan_sdio_card_reg, *pmlan_sdio_card_reg;
+
+typedef struct _mlan_sdio_card {
+	const mlan_sdio_card_reg *reg;
+    /** maximum ports */
+	t_u8 max_ports;
+    /** mp aggregation packet limit */
+	t_u8 mp_aggr_pkt_limit;
+    /** sdio new mode support */
+	t_bool supports_sdio_new_mode;
+    /** max tx aggr buf size */
+	t_u32 mp_tx_aggr_buf_size;
+    /** max rx aggr buf size */
+	t_u32 mp_rx_aggr_buf_size;
+    /** IO port */
+	t_u32 ioport;
+	/** number of interrupt receive */
+	t_u32 num_of_irq;
+	/** max SDIO single port tx size */
+	t_u16 max_sp_tx_size;
+	/** max SDIO single port rx size */
+	t_u16 max_sp_rx_size;
+	/** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+	/** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+	/** SDIO end port from txbufcfg */
+	t_u16 mp_end_port;
+	/** SDIO port mask calculated based on txbufcfg end port */
+	t_u32 mp_data_port_mask;
+	/** Current available port for read */
+	t_u8 curr_rd_port;
+	/** Current available port for write */
+	t_u8 curr_wr_port;
+	/** FW update port number */
+	t_u32 mp_update[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX * 2];
+	/** Invalid port update count */
+	t_u32 mp_invalid_update;
+	/** Array to store values of SDIO multiple port group registers */
+	t_u8 *mp_regs;
+	/** allocated buf to read SDIO multiple port group registers */
+	t_u8 *mp_regs_buf;
+	/** buffer to handle receive packet */
+	t_u8 *rx_buf;
+	/** allocated buf for receive */
+	t_u8 *rx_buffer;
+	/* see blk_queue_max_segment_size */
+	t_u32 max_seg_size;
+	/* see blk_queue_max_segments */
+	t_u16 max_segs;
+
+	/** data structure for SDIO MPA TX */
+	sdio_mpa_tx mpa_tx;
+	/** packet number for tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+	/** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last wr_bitmap from FW */
+	t_u32 last_recv_wr_bitmap;
+	/** last wr_bitmap from FW */
+	t_u32 last_recv_rd_bitmap;
+	/** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+	/** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last length for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+	/** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+
+	/** buffer for mp debug */
+	t_u8 *mpa_buf;
+	/** length info for mp buf size */
+	t_u32 mpa_buf_size;
+
+	/** last mp_index */
+	t_u8 last_mp_index;
+
+	/** data structure for SDIO MPA RX */
+	sdio_mpa_rx mpa_rx;
+	/** packet number for tx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+
+	/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+	/** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+
+	/** flag for sdio rx aggr */
+	t_bool sdio_rx_aggr_enable;
+	/** fw rx block size */
+	t_u16 sdio_rx_block_size;
+} mlan_sdio_card, *pmlan_sdio_card;
+#endif
+
+#ifdef PCIE
+#define MAX_TXRX_BD         32
+#define ADMA_MAX_TXRX_BD    512
+#define ADMA_DEF_TXRX_BD    128
+/** 128 entry will mapping to 7*/
+#define TXRX_DEF_NUM_DESC 7
+/** 8 entry will mapping to 3 */
+#define EVT_NUM_DESC 3
+#define MLAN_MAX_TXRX_BD    MAX(ADMA_MAX_TXRX_BD, MAX_TXRX_BD)
+/** 8 Event buffer ring */
+#define MLAN_MAX_EVT_BD 0x08
+typedef struct _mlan_pcie_card_reg {
+	/* TX buffer description rd pointer */
+	t_u32 reg_txbd_rdptr;
+	/* TX buffer description wr pointer */
+	t_u32 reg_txbd_wrptr;
+	/* RX buffer description rd pointer */
+	t_u32 reg_rxbd_rdptr;
+	/* RX buffer description wr pointer */
+	t_u32 reg_rxbd_wrptr;
+	/** evtbd rdptr register */
+	t_u32 reg_evtbd_rdptr;
+	/** evtbd wrptr register */
+	t_u32 reg_evtbd_wrptr;
+	/** host int mask register */
+	t_u16 reg_host_int_mask;
+	/** host int status mask register*/
+	t_u16 reg_host_int_status_mask;
+	/** host int status register */
+	t_u16 reg_host_int_status;
+	/** host int status clr selection */
+	t_u32 reg_host_int_clr_sel;
+	/** cpu int event register */
+	t_u16 reg_cpu_int_event;
+	/** ip revision register */
+	t_u16 reg_ip_rev;
+	/** revision id register */
+	t_u32 reg_rev_id;
+	/** driver ready register */
+	t_u16 reg_drv_ready;
+	/** cpu int status register */
+	t_u16 reg_cpu_int_status;
+	/** scratch 0 register */
+	t_u16 reg_scratch_0;
+	/** scratch 1 register */
+	t_u16 reg_scratch_1;
+	/** scratch 2 register */
+	t_u16 reg_scratch_2;
+	/** scratch 3 register */
+	t_u16 reg_scratch_3;
+	/** scratch 6 register */
+	t_u16 reg_scratch_6;
+	/** scratch 7 register */
+	t_u16 reg_scratch_7;
+	/** host interrupt mask*/
+	t_u32 host_intr_mask;
+	/** data send interrupt for host*/
+	t_u32 host_intr_dnld_done;
+	/** Data receive interrupt for host */
+	t_u32 host_intr_upld_rdy;
+	/** Command sent interrupt for host */
+	t_u32 host_intr_cmd_done;
+	/** Event ready interrupt for host */
+	t_u32 host_intr_event_rdy;
+	t_u32 host_intr_cmd_dnld;
+	/* TX/RX buffer description mask */
+	t_u32 txrx_rw_ptr_mask;
+	/* TX/RX buffer description wrap mask */
+	t_u32 txrx_rw_ptr_wrap_mask;
+	/* TX/RX buffer description indication */
+	t_u32 txrx_rw_ptr_rollover_ind;
+	/** ADMA feature */
+	t_u8 use_adma;
+	/** write to clear interrupt status flag */
+	t_u8 msi_int_wr_clr;
+} mlan_pcie_card_reg, *pmlan_pcie_card_reg;
+
+typedef struct _mlan_pcie_card {
+	const mlan_pcie_card_reg *reg;
+	/** PCIE interrupt modes 0: Legacy, 1: MSI, 2:MSI-X */
+	t_u32 pcie_int_mode;
+	/** PCIE function number */
+	t_u8 func_num;
+	/** pending num of tx ring buffer in firmware */
+	t_u8 txbd_pending;
+	/** Write pointer for TXBD ring */
+	t_u32 txbd_wrptr;
+	/** Shadow copy of TXBD read pointer */
+	t_u32 txbd_rdptr;
+	/** TXBD ring size */
+	t_u32 txbd_ring_size;
+	/** Lock for protecting the TX ring */
+	t_void *tx_ring_lock;
+	/** Virtual base address of txbd_ring */
+	t_u8 *txbd_ring_vbase;
+	/** Physical base address of txbd_ring */
+	t_u64 txbd_ring_pbase;
+	/** Ring of buffer descriptors for TX */
+	t_void *txbd_ring[MLAN_MAX_TXRX_BD];
+	/** A list of mlan_buffer objects used for data tx */
+	mlan_buffer *tx_buf_list[MLAN_MAX_TXRX_BD];
+	/** Flush indicator for txbd_ring */
+	t_bool txbd_flush;
+	/** txrx data dma ring size */
+	t_u16 txrx_bd_size;
+    /** txrx num desc */
+	t_u16 txrx_num_desc;
+
+	/** Shadow copy of RXBD write pointer */
+	t_u32 rxbd_wrptr;
+	/** RxBD read pointer */
+	t_u32 rxbd_rdptr;
+	/** RXBD ring size */
+	t_u32 rxbd_ring_size;
+	/** A spinlock for rxbd_ring */
+	t_void *rx_ring_lock;
+	/** Virtual base address of rxbd_ring */
+	t_u8 *rxbd_ring_vbase;
+	/** Physical base address of rxbd_ring */
+	t_u64 rxbd_ring_pbase;
+	/** Ring of buffer descriptors for RX */
+	t_void *rxbd_ring[MLAN_MAX_TXRX_BD];
+	/** A list of mlan_buffer objects used for data rx */
+	mlan_buffer *rx_buf_list[MLAN_MAX_TXRX_BD];
+
+	/** Shadow copy of cmdrsp/evt write pointer */
+	t_u32 evtbd_wrptr;
+	/** Read pointer for cmdrsp/evt ring */
+	t_u32 evtbd_rdptr;
+	/** Size of the cmdrsp/evt ring */
+	t_u32 evtbd_ring_size;
+	/** Virtual base address of evtbd_bd_ring */
+	t_u8 *evtbd_ring_vbase;
+	/** Physical base address of evtbd_bd_ring */
+	t_u64 evtbd_ring_pbase;
+	/** Ring of buffer descriptors for EVENT */
+	t_void *evtbd_ring[MLAN_MAX_EVT_BD];
+	/** A list of mlan_buffer objects used for EVENT */
+	mlan_buffer *evt_buf_list[MLAN_MAX_EVT_BD];
+
+	/** Command buffer */
+	mlan_buffer *cmd_buf;
+	/** Command response buffer */
+	mlan_buffer *cmdrsp_buf;
+	/** Command buffer */
+	mlan_buffer *vdll_cmd_buf;
+	/** last tx_pkt_size  */
+	t_u32 last_tx_pkt_size[MLAN_MAX_TXRX_BD];
+} mlan_pcie_card, *pmlan_pcie_card;
+#endif
+
+#ifdef USB
+typedef struct _mlan_usb_card {
+	/** data structure for USB Rx Deaggregation */
+	usb_rx_deaggr_params usb_rx_deaggr;
+	/** data structure for USB Tx Aggregation */
+	usb_tx_aggr_params usb_tx_aggr[MAX_USB_TX_PORT_NUM];
+	/** USB sggregation supported by FW */
+	t_u8 fw_usb_aggr;
+
+} mlan_usb_card, *pmlan_usb_card;
+
+#endif
+
+typedef struct _mlan_card_info {
+	/** Max Tx buffer size */
+	t_u32 max_tx_buf_size;
+    /** support V14_FW_API */
+	t_u8 v14_fw_api;
+	/** support V16_FW_API */
+	t_u8 v16_fw_api;
+	/** support V17_FW_API */
+	t_u8 v17_fw_api;
+	/** suppress PS handshake */
+	t_u8 supp_ps_handshake;
+	/** DEFAULT_11N_TX_BF_CAP */
+	t_u32 default_11n_tx_bf_cap;
+} mlan_card_info, *pmlan_card_info;
+
+typedef struct _mlan_adapter mlan_adapter, *pmlan_adapter;
+
+/**Adapter_operations data structure*/
+typedef struct _adapter_operations {
+	/**firmware download handler*/
+	mlan_status (*dnld_fw) (pmlan_adapter pmadapter, pmlan_fw_image pmfw);
+	/**interrupt handler*/
+	mlan_status (*interrupt) (t_u16 msg_id, pmlan_adapter pmadapter);
+	/**INT process handler*/
+	mlan_status (*process_int_status) (pmlan_adapter pmadapter);
+	/**host to card handler*/
+	mlan_status (*host_to_card) (pmlan_private pmpriv, t_u8 type,
+				     mlan_buffer *pmbuf,
+				     mlan_tx_param *tx_param);
+	/*wakeup card */
+	mlan_status (*wakeup_card) (pmlan_adapter pmadapter, t_u8 timeout);
+	/*reset the PM setting of card */
+	mlan_status (*reset_card) (pmlan_adapter adapter);
+	/** Handle event/cmd complete*/
+	mlan_status (*event_complete) (mlan_adapter *pmlan_adapter,
+				       pmlan_buffer pmbuf, mlan_status status);
+	/** Handle complete receiving data */
+	mlan_status (*data_complete) (mlan_adapter *pmlan_adapter,
+				      pmlan_buffer pmbuf, mlan_status status);
+	/** Handle command response complete */
+	mlan_status (*cmdrsp_complete) (mlan_adapter *pmlan_adapter,
+					pmlan_buffer pmbuf, mlan_status status);
+	/** Handle rx packet */
+	mlan_status (*handle_rx_packet) (mlan_adapter *pmadapter,
+					 pmlan_buffer pmbuf);
+	/** handle dump interface specific info */
+	mlan_status (*debug_dump) (mlan_adapter *pmadapter);
+	/** disable host interrupt */
+	mlan_status (*disable_host_int) (mlan_adapter *pmadapter);
+	/** enable host interrupt */
+	mlan_status (*enable_host_int) (mlan_adapter *pmadapter);
+	/**Interface header length*/
+	t_u32 intf_header_len;
+} mlan_adapter_operations;
+
+/** Adapter data structure for MLAN */
+typedef struct _mlan_adapter {
+	/** MOAL handle structure */
+	t_void *pmoal_handle;
+	/** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+	/** Private pointer */
+	pmlan_private priv[MLAN_MAX_BSS_NUM];
+	/** Total number of Priv number */
+	t_u8 priv_num;
+	/** Priority table for bss */
+	mlan_bssprio_tbl bssprio_tbl[MLAN_MAX_BSS_NUM];
+	/** Callback table */
+	mlan_callbacks callbacks;
+	/** Init parameters */
+	mlan_init_para init_para;
+	/** mlan_lock for init/shutdown */
+	t_void *pmlan_lock;
+	/** main_proc_lock for main_process */
+	t_void *pmain_proc_lock;
+	/** mlan_processing */
+	t_u32 mlan_processing;
+	/** main_process_cnt */
+	t_u32 main_process_cnt;
+	/** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+	/** rx_proc_lock for main_rx_process */
+	t_void *prx_proc_lock;
+	/** more_rx_task_flag */
+	t_u32 more_rx_task_flag;
+	/** rx work enable flag */
+	t_u8 rx_work_flag;
+	/* number of rx pkts queued */
+	t_u16 rx_pkts_queued;
+	/** more task flag */
+	t_u32 more_task_flag;
+	/** delay task flag */
+	t_u32 delay_task_flag;
+	/** Max tx buf size */
+	t_u16 max_tx_buf_size;
+	/** Tx buf size */
+	t_u16 tx_buf_size;
+	/** current tx buf size in fw */
+	t_u16 curr_tx_buf_size;
+	/** flush data flag */
+	t_u8 flush_data;
+	/** STATUS variables */
+	WLAN_HARDWARE_STATUS hw_status;
+	/** PnP SUPPORT */
+	t_u8 surprise_removed;
+	/** FW hang report */
+	t_u8 fw_hang_report;
+
+	/** ECSA support */
+	t_u8 ecsa_enable;
+
+	/** Get log support */
+	t_u8 getlog_enable;
+
+	/** Radio on flag */
+	t_u16 radio_on;
+
+	/** Firmware release number */
+	t_u32 fw_release_number;
+	/** firmware version */
+	t_u8 fw_ver;
+	/** firmware minor version */
+	t_u8 fw_min_ver;
+	/** firmare hotfix version */
+	t_u8 fw_hotfix_ver;
+	/** uap firmware version */
+	t_u8 uap_fw_ver;
+	/** mac address retrun from get_hw_spec */
+	t_u8 permanent_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Number of antenna used */
+	t_u16 number_of_antenna;
+	/** antenna info */
+	t_u8 antinfo;
+	/** Firmware capability information */
+	t_u32 fw_cap_info;
+	/** Extended firmware capability information */
+	t_u32 fw_cap_ext;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	/** High byte for 5G, low byte for 2G, like 0x2211 0x22 for 5G, 0x11 for
+	 * 2G */
+	t_u16 user_htstream;
+#endif
+	/** vdll ctrl */
+	vdll_dnld_ctrl vdll_ctrl;
+#if defined(SDIO) || defined(PCIE)
+	/** pint_lock for interrupt handling */
+	t_void *pint_lock;
+	/** Interrupt status */
+	t_u32 ireg;
+#endif
+	/** card type */
+	t_u16 card_type;
+	/** card rev */
+	t_u8 card_rev;
+	const mlan_card_info *pcard_info;
+#ifdef SDIO
+	pmlan_sdio_card pcard_sd;
+#endif
+#ifdef PCIE
+	pmlan_pcie_card pcard_pcie;
+#endif
+#ifdef USB
+	pmlan_usb_card pcard_usb;
+#endif
+
+	/** Event cause */
+	t_u32 event_cause;
+	/** Event buffer */
+	pmlan_buffer pmlan_buffer_event;
+	/** Upload length */
+	t_u32 upld_len;
+	/** Upload buffer*/
+	t_u8 upld_buf[WLAN_UPLD_SIZE];
+	/** Data sent:
+	 *       TRUE - Data is sent to fw, no Tx Done received
+	 *       FALSE - Tx done received for previous Tx
+	 */
+	t_u8 data_sent;
+	/** Data sent cnt */
+	t_u32 data_sent_cnt;
+	/** CMD sent:
+	 *       TRUE - CMD is sent to fw, no CMD Done received
+	 *       FALSE - CMD done received for previous CMD
+	 */
+	t_u8 cmd_sent;
+	/** CMD Response received:
+	 *       TRUE - CMD is response is received from fw, and yet to process
+	 *       FALSE - No cmd response to process
+	 */
+	t_u8 cmd_resp_received;
+	/** Event received:
+	 *       TRUE - Event received from fw, and yet to process
+	 *       FALSE - No events to process
+	 */
+	t_u8 event_received;
+
+	/** Data received:
+	 *       TRUE - Data received from fw
+	 *       FALSE - No Data received
+	 */
+	t_u8 data_received;
+
+	/** Command-related variables */
+	/** Command sequence number */
+	t_u16 seq_num;
+	/** Command controller nodes */
+	cmd_ctrl_node *cmd_pool;
+	/** Current Command */
+	cmd_ctrl_node *curr_cmd;
+	/** mlan_lock for command */
+	t_void *pmlan_cmd_lock;
+	/** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+	/** Last init fw command id */
+	t_u16 last_init_cmd;
+	/** Command timer */
+	t_void *pmlan_cmd_timer;
+	/** Command timer set flag */
+	t_u8 cmd_timer_is_set;
+	/** time stamp for command dnld */
+	t_u32 dnld_cmd_in_secs;
+
+	/** Command Queues */
+	/** Free command buffers */
+	mlan_list_head cmd_free_q;
+	/** Pending command buffers */
+	mlan_list_head cmd_pending_q;
+	/** Command queue for scanning */
+	mlan_list_head scan_pending_q;
+	/** ioctl pending queue */
+	mlan_list_head ioctl_pending_q;
+	/** pending_ioctl flag */
+	t_u8 pending_ioctl;
+	pmlan_private pending_disconnect_priv;
+	/** mlan_processing */
+	t_u32 scan_processing;
+	/** ext_scan enh support flag */
+	t_u8 ext_scan_enh;
+	/** scan type: 0 legacy, 1: enhance scan*/
+	t_u8 ext_scan_type;
+	/** ext scan timeout */
+	t_u8 ext_scan_timeout;
+	/** coex scan flag */
+	t_u8 coex_scan;
+	/** coex min scan time */
+	t_u8 coex_min_scan_time;
+	/** coex max scan time */
+	t_u8 coex_max_scan_time;
+	/** coex win size flag */
+	t_u8 coex_win_size;
+	/** coex amdpdu tx win size */
+	t_u8 coex_tx_win_size;
+	/** coex ampdu rx win size */
+	t_u8 coex_rx_win_size;
+	/** Region code */
+	t_u16 region_code;
+	/** Region Channel data */
+	region_chan_t region_channel[MAX_REGION_CHANNEL_NUM];
+	/** CFP table code for 2.4GHz */
+	t_u8 cfp_code_bg;
+	/** CFP table code for 5GHz */
+	t_u8 cfp_code_a;
+	wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+	/** Minimum BA Threshold */
+	t_u8 min_ba_threshold;
+#ifdef STA_SUPPORT
+	/** Universal Channel data */
+	region_chan_t universal_channel[MAX_REGION_CHANNEL_NUM];
+	/** Parsed region channel */
+	parsed_region_chan_11d_t parsed_region_chan;
+#endif				/* STA_SUPPORT */
+	/** 11D and Domain Regulatory Data */
+	wlan_802_11d_domain_reg_t domain_reg;
+	/** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** FSM variable for 11h support */
+	wlan_11h_device_state_t state_11h;
+	/** FSM variable for DFS support */
+	wlan_dfs_device_state_t state_dfs;
+	/** FSM variable for RDH support */
+	wlan_radar_det_hndlg_state_t state_rdh;
+	/** variable to configure dfs channel switch count */
+	t_s8 dfs_cs_count;
+	/** User configured settings for DFS testing */
+	wlan_dfs_testing_settings_t dfs_test_params;
+	/**  dfs w53 cfg */
+	t_u8 dfs53cfg;
+	/** FSM variable for MEAS support */
+	wlan_meas_state_t state_meas;
+	/** Scan table */
+	BSSDescriptor_t *pscan_table;
+	/** scan age in secs */
+	t_u32 age_in_secs;
+	/** Active scan for hidden ssid triggered */
+	t_u8 active_scan_triggered;
+	/** channel statstics */
+	ChanStatistics_t *pchan_stats;
+	/** Number of records in the chan_stats */
+	t_u32 num_in_chan_stats;
+	/** index of chan stats */
+	t_u32 idx_chan_stats;
+	t_u8 bgscan_reported;
+
+	/** Number of records in the scan table */
+	t_u32 num_in_scan_table;
+	/** Scan probes */
+	t_u16 scan_probes;
+
+	/** Scan type */
+	t_u8 scan_type;
+	/** Scan mode */
+	t_u32 scan_mode;
+	/** Specific scan time */
+	t_u16 specific_scan_time;
+	/** Active scan time */
+	t_u16 active_scan_time;
+	/** Passive scan time */
+	t_u16 passive_scan_time;
+	/** Passive scan to active scan */
+	t_u8 passive_to_active_scan;
+	/** scan channel gap time */
+	t_u16 scan_chan_gap;
+	/** Scan block flag */
+	t_u8 scan_block;
+	/** Extended scan or legacy scan */
+	t_u8 ext_scan;
+	t_u32 bcn_buf_size;
+	/** Beacon buffer */
+	t_u8 *bcn_buf;
+	/** Pointer to valid beacon buffer end */
+	t_u8 *pbcn_buf_end;
+	/** allocate fixed scan beacon buffer size*/
+	t_u32 fixed_beacon_buffer;
+
+	/** F/W supported bands */
+	t_u16 fw_bands;
+	/** User selected band to start adhoc network */
+	t_u16 adhoc_start_band;
+	/** User selected bands */
+	t_u16 config_bands;
+	/** Pointer to channel list last sent to the firmware for scanning */
+	ChanScanParamSet_t *pscan_channels;
+
+	/** Tx lock flag */
+	t_u8 tx_lock_flag;
+	/** Rx lock flag */
+	t_u8 rx_lock_flag;
+	/** main lock flag */
+	t_u8 main_lock_flag;
+#ifdef USB
+	/** Tx CMD endpoint address */
+	t_u8 tx_cmd_ep;
+	/** Rx CMD/EVT endpoint address */
+	t_u8 rx_cmd_ep;
+	/** Rx data endpoint address */
+	t_u8 rx_data_ep;
+	/** Tx data endpoint address */
+	t_u8 tx_data_ep;
+#endif
+
+	/** sleep_params_t */
+	sleep_params_t sleep_params;
+	/** sleep_period_t (Enhanced Power Save) */
+	sleep_period_t sleep_period;
+	/** saved sleep_period_t (Enhanced Power Save) */
+	sleep_period_t saved_sleep_period;
+
+	/** Power Save mode */
+	/**
+	 * Wlan802_11PowerModeCAM = disable
+	 * Wlan802_11PowerModePSP = enable
+	 */
+	t_u16 ps_mode;
+	/** Power Save state */
+	t_u32 ps_state;
+	/** Need to wakeup flag */
+	t_u8 need_to_wakeup;
+	/** keep_wakeup */
+	t_u8 keep_wakeup;
+
+	/** Multiple DTIM */
+	t_u16 multiple_dtim;
+	/** Local listen interval */
+	t_u16 local_listen_interval;
+	/** Null packet interval */
+	t_u16 null_pkt_interval;
+
+	/** IEEE ps inactivity timout value */
+	t_u16 inact_tmo;
+	/** Power save confirm sleep command buffer */
+	pmlan_buffer psleep_cfm;
+	/** Beacon miss timeout */
+	t_u16 bcn_miss_time_out;
+
+	/** Deep Sleep flag */
+	t_u8 is_deep_sleep;
+	/** Idle time */
+	t_u16 idle_time;
+	/** Auto Deep Sleep enabled at init time */
+	t_u8 init_auto_ds;
+
+	/** delay null pkt flag */
+	t_u8 delay_null_pkt;
+	/** Delay to PS in milliseconds */
+	t_u16 delay_to_ps;
+	/** Enhanced PS mode */
+	t_u16 enhanced_ps_mode;
+	/** Device wakeup required flag */
+	t_u8 pm_wakeup_card_req;
+
+	/** Gen NULL pkg */
+	t_u16 gen_null_pkt;
+
+	/** PPS/UAPSD mode flag */
+	t_u16 pps_uapsd_mode;
+	/** Number of wakeup tries */
+	t_u32 pm_wakeup_fw_try;
+	/** time stamp when host try to wake up firmware */
+	t_u32 pm_wakeup_in_secs;
+	/** Card wakeup timer */
+	t_void *pwakeup_fw_timer;
+	/** Card wakeup timer */
+	t_u8 wakeup_fw_timer_is_set;
+	/** Number of wake up timeouts */
+	t_u32 pm_wakeup_timeout;
+
+	/** Host Sleep configured flag */
+	t_u8 is_hs_configured;
+	/** Host Sleep configuration */
+	hs_config_param hs_cfg;
+	/** Host Sleep activated flag */
+	t_u8 hs_activated;
+	/** mef_flt_cfg_mef configuration */
+	mef_entry entry_cfg;
+	/** Event body */
+	t_u8 event_body[MAX_EVENT_SIZE];
+	/** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+	/** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+#ifdef STA_SUPPORT
+	/** Adhoc Secondary Channel Bandwidth */
+	t_u8 chan_bandwidth;
+#endif				/* STA_SUPPORT */
+
+	/** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+	/** 802.11ac device support for MIMO abstraction of MCSs */
+	t_u32 hw_dot_11ac_mcs_support;
+	/** length of hw he capability */
+	t_u8 hw_hecap_len;
+	/** 802.11ax HE capability */
+	t_u8 hw_he_cap[54];
+	/** length of hw 2.4G he capability */
+	t_u8 hw_2g_hecap_len;
+	/** 802.11ax 2.4G HE capability */
+	t_u8 hw_2g_he_cap[54];
+	/** max mgmt IE index in device */
+	t_u16 max_mgmt_ie_index;
+	/** Head of Rx data queue */
+	mlan_list_head rx_data_queue;
+#ifdef MFG_CMD_SUPPORT
+	t_u32 mfg_mode;
+#endif
+	/** Debug */
+	wlan_dbg dbg;
+
+	/** RX pending for forwarding packets */
+	mlan_scalar pending_bridge_pkts;
+
+#ifdef STA_SUPPORT
+	/** ARP filter buffer */
+	t_u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];
+	/** ARP filter buffer size */
+	t_u32 arp_filter_size;
+#endif				/* STA_SUPPORT */
+	/** Minimum delay between HsActive and HostWake (in msec) */
+	t_u16 min_wake_holdoff;
+	/** Host sleep wake interval(in msec) */
+	t_u32 hs_wake_interval;
+	/** Host sleep inactivity timeout (in msec) */
+	t_u32 hs_inactivity_timeout;
+	/** Parameter type for indication gpio*/
+	t_u8 param_type_ind;
+	/** GPIO pin for indication wakeup source */
+	t_u32 ind_gpio;
+	/** Level on ind_gpio pin for indication normal wakeup source */
+	t_u32 level;
+	/** Parameter type for extend hscfg*/
+	t_u8 param_type_ext;
+	/** Events that will be forced ignore */
+	t_u32 event_force_ignore;
+	/** Events that will use extend gap to inform host*/
+	t_u32 event_use_ext_gap;
+	/** Extend gap*/
+	t_u8 ext_gap;
+	/** GPIO wave level for extend hscfg */
+	t_u8 gpio_wave;
+	/** Dynamic MIMO-SISO switch for hscfg*/
+	t_u8 hs_mimo_switch;
+	/** management frame wakeup filter config */
+	mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+	/** Bypass TX queue pkt count  */
+	t_u32 bypass_pkt_count;
+#ifdef STA_SUPPORT
+	/** warm-reset IOCTL request buffer pointer */
+	pmlan_ioctl_req pwarm_reset_ioctl_req;
+#endif
+	/** SCAN IOCTL request buffer pointer */
+	pmlan_ioctl_req pscan_ioctl_req;
+	/** DPD data pointer */
+	t_u8 *pdpd_data;
+	/** DPD data length  */
+	t_u32 dpd_data_len;
+	/** region txpowerlimit cfg data buf pointer */
+	t_u8 *ptxpwr_data;
+	/** region txpowerlimit cfg data len */
+	t_u32 txpwr_data_len;
+	/** Cal data pointer */
+	t_u8 *pcal_data;
+	/** Cal data length  */
+	t_u32 cal_data_len;
+	/** tdls status */
+	/* TDLS_NOT_SETUP|TDLS_SWITCHING_CHANNEL|TDLS_IN_BASE_CHANNEL|TDLS_IN_SWITCH_CHANNEL */
+	tdlsStatus_e tdls_status;
+	/** Feature control bitmask */
+	t_u32 feature_control;
+
+	/** Control coex RX window size configuration */
+	t_u8 coex_rx_winsize;
+	t_bool dfs_repeater;
+	t_u32 dfsr_channel;
+	t_u8 chanrpt_param_bandcfg;
+#if defined(PCIE)
+	mlan_buffer *ssu_buf;
+#endif
+	/** maximum sta connection */
+	t_u8 max_sta_conn;
+	otp_region_info_t *otp_region;
+	chan_freq_power_t *cfp_otp_bg;
+	t_u8 *tx_power_table_bg;
+	t_u32 tx_power_table_bg_size;
+	t_u8 tx_power_table_bg_rows;
+	t_u8 tx_power_table_bg_cols;
+	chan_freq_power_t *cfp_otp_a;
+	t_u8 *tx_power_table_a;
+	t_u32 tx_power_table_a_size;
+	t_u8 tx_power_table_a_rows;
+	t_u8 tx_power_table_a_cols;
+	/**mlan adapter operations*/
+	mlan_adapter_operations ops;
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	/** authenticator_priv */
+	pmlan_private authenticator_priv;
+#endif
+	/** TP accounting mode 1-enable 0-disable */
+	t_u32 tp_state_on;
+	/** Packet drop point */
+	t_u32 tp_state_drop_point;
+} mlan_adapter, *pmlan_adapter;
+
+/** Check if stream 2X2 enabled */
+#define IS_STREAM_2X2(x) ((x)&FEATURE_CTRL_STREAM_2X2)
+/** Check if DFS support enabled */
+#define IS_DFS_SUPPORT(x) ((x)&FEATURE_CTRL_DFS_SUPPORT)
+#ifdef USB
+/** Check if winner check & not wait for FW ready event */
+#define IS_USB_NEW_INIT(x) ((x)&FEATURE_CTRL_USB_NEW_INIT)
+#endif
+
+/** Ethernet packet type for EAPOL */
+#define MLAN_ETHER_PKT_TYPE_EAPOL (0x888E)
+#define MLAN_ETHER_PKT_TYPE_ARP (0x0806)
+/** Ethernet packet type for WAPI */
+#define MLAN_ETHER_PKT_TYPE_WAPI (0x88B4)
+/** Ethernet packet type offset */
+#define MLAN_ETHER_PKT_TYPE_OFFSET (12)
+
+mlan_status wlan_init_lock_list(pmlan_adapter pmadapter);
+mlan_status wlan_init_priv_lock_list(pmlan_adapter pmadapter, t_u8 start_index);
+t_void wlan_free_lock_list(pmlan_adapter pmadapter);
+mlan_status wlan_init_timer(pmlan_adapter pmadapter);
+t_void wlan_free_timer(pmlan_adapter pmadapter);
+
+/* Function prototype */
+/** Initialize firmware */
+mlan_status wlan_init_fw(pmlan_adapter pmadapter);
+
+/** get hw spec complete */
+mlan_status wlan_get_hw_spec_complete(pmlan_adapter pmadapter);
+
+/** Initialize firmware complete */
+mlan_status wlan_init_fw_complete(pmlan_adapter pmadapter);
+
+/** Shutdown firmware complete */
+mlan_status wlan_shutdown_fw_complete(pmlan_adapter pmadapter);
+
+/** Receive event */
+mlan_status wlan_recv_event(pmlan_private priv, mlan_event_id event_id,
+			    t_void *pmevent);
+
+/** Initialize mlan_adapter structure */
+t_void wlan_init_adapter(pmlan_adapter pmadapter);
+
+/** Initialize mlan_private structure */
+mlan_status wlan_init_priv(pmlan_private priv);
+#ifdef USB
+/** get pcie device from card type */
+mlan_status wlan_get_usb_device(pmlan_adapter pmadapter);
+#endif
+mlan_status wlan_download_vdll_block(mlan_adapter *pmadapter, t_u8 *block,
+				     t_u16 block_len);
+mlan_status wlan_process_vdll_event(pmlan_private pmpriv, pmlan_buffer pevent);
+/** Process event */
+mlan_status wlan_process_event(pmlan_adapter pmadapter);
+
+/** Prepare command */
+mlan_status wlan_prepare_cmd(pmlan_private priv, t_u16 cmd_no,
+			     t_u16 cmd_action, t_u32 cmd_oid,
+			     t_void *pioctl_buf, t_void *pdata_buf);
+
+/** cmd timeout handler */
+t_void wlan_cmd_timeout_func(t_void *function_context);
+
+/**
+ *  @brief check if Tx pending
+ *
+ *  @param pmadapter	Pointer to mlan_adapter
+ *  @return  MTRUE/MFALSE;
+ */
+static inline t_u8
+wlan_is_tx_pending(mlan_adapter *pmadapter)
+{
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type) &&
+	    pmadapter->pcard_pcie->txbd_pending)
+		return MTRUE;
+#endif
+	return MFALSE;
+}
+
+/** process host cmd */
+mlan_status wlan_misc_ioctl_host_cmd(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req);
+/** process init/shutdown cmd*/
+mlan_status wlan_misc_ioctl_init_shutdown(pmlan_adapter pmadapter,
+					  pmlan_ioctl_req pioctl_req);
+/** process debug info */
+mlan_status wlan_get_info_debug_info(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req);
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+extern pmlan_operations mlan_ops[];
+/** Set/Get BSS role */
+mlan_status wlan_bss_ioctl_bss_role(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req);
+#endif
+
+#if defined(PCIE)
+mlan_status wlan_misc_ssu(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_hal_phy_cfg(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_set_ewpa_mode(mlan_private *priv, pmlan_ds_passphrase psec_pp);
+mlan_status wlan_find_bss(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req);
+
+/* block main process */
+void mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block);
+/* block rx process */
+void mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block);
+/** check pending command */
+int wlan_check_pending_cmd(mlan_adapter *pmadapter);
+/** Allocate memory for adapter structure members */
+mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter);
+/** Free adapter */
+t_void wlan_free_adapter(pmlan_adapter pmadapter);
+/** Free priv */
+t_void wlan_free_priv(mlan_private *pmpriv);
+/** Allocate command buffer */
+mlan_status wlan_alloc_cmd_buffer(mlan_adapter *pmadapter);
+/** Free command buffer */
+mlan_status wlan_free_cmd_buffer(mlan_adapter *pmadapter);
+/** Request command lock */
+t_void wlan_request_cmd_lock(mlan_adapter *pmadapter);
+/** Release command lock */
+t_void wlan_release_cmd_lock(mlan_adapter *pmadapter);
+#ifdef STA_SUPPORT
+/** Flush the scan pending queue */
+t_void wlan_flush_scan_queue(pmlan_adapter pmadapter);
+t_void wlan_move_cmd_to_cmd_pending_q(pmlan_adapter pmadapter);
+mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+#endif
+/**Cancel pending command */
+t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter, t_u8 flag);
+/**Cancel pending ioctl */
+t_void wlan_cancel_pending_ioctl(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req);
+/**Cancel bss pending ioctl */
+t_void wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index);
+
+/** Insert command to free queue */
+t_void wlan_insert_cmd_to_free_q(mlan_adapter *pmadapter,
+				 cmd_ctrl_node *pcmd_node);
+
+/** Insert command to pending queue */
+t_void wlan_insert_cmd_to_pending_q(mlan_adapter *pmadapter,
+				    cmd_ctrl_node *pcmd_node, t_u32 addtail);
+
+/** Execute next command */
+mlan_status wlan_exec_next_cmd(mlan_adapter *pmadapter);
+/** Proecess command response */
+mlan_status wlan_process_cmdresp(mlan_adapter *pmadapter);
+/** Handle received packet, has extra handling for aggregate packets */
+mlan_status wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+/** Process transmission */
+mlan_status wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf,
+			    mlan_tx_param *tx_param);
+/** Transmit a null data packet */
+mlan_status wlan_send_null_packet(pmlan_private priv, t_u8 flags);
+
+#ifdef SDIO
+mlan_status wlan_alloc_sdio_mpa_buffers(mlan_adapter *pmadapter,
+					t_u32 mpa_tx_buf_size,
+					t_u32 mpa_rx_buf_size);
+
+mlan_status wlan_free_sdio_mpa_buffers(mlan_adapter *pmadapter);
+#endif
+
+/** Process write data complete */
+mlan_status wlan_write_data_complete(pmlan_adapter pmlan_adapter,
+				     pmlan_buffer pmbuf, mlan_status status);
+
+#ifdef USB
+mlan_status wlan_usb_deaggr_rx_pkt(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+
+/**
+ *  @brief  This function resets USB Tx Aggregation buffers
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *
+ *  @return 	N/A
+ */
+static INLINE t_void
+wlan_reset_usb_tx_aggr(pmlan_adapter pmadapter)
+{
+	t_s32 i = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+		pcb->moal_spin_lock(pmadapter->pmoal_handle,
+				    pmadapter->pcard_usb->usb_tx_aggr[i].
+				    paggr_lock);
+		if (pmadapter->pcard_usb->usb_tx_aggr[i].aggr_hold_timer_is_set) {
+			pcb->moal_stop_timer(pmadapter->pmoal_handle,
+					     pmadapter->pcard_usb->
+					     usb_tx_aggr[i]
+					     .paggr_hold_timer);
+			pmadapter->pcard_usb->usb_tx_aggr[i]
+				.aggr_hold_timer_is_set = MFALSE;
+		}
+		if (pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable &&
+		    pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr != MNULL) {
+			wlan_write_data_complete(pmadapter, pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr, MLAN_STATUS_FAILURE);	/* did not get sent */
+			pmadapter->pcard_usb->usb_tx_aggr[i].pmbuf_aggr = MNULL;
+			pmadapter->pcard_usb->usb_tx_aggr[i].aggr_len = 0;
+		}
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pcard_usb->usb_tx_aggr[i].
+				      paggr_lock);
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief  This function get usb_tx_aggr_params
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param port		    port for TX
+ *
+ *  @return	            A pointer to usb_tx_aggr_params
+ */
+static INLINE usb_tx_aggr_params *
+wlan_get_usb_tx_aggr_params(pmlan_adapter pmadapter, t_u32 port)
+{
+	int i;
+	ENTER();
+	for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+		if (pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable &&
+		    pmadapter->pcard_usb->usb_tx_aggr[i].port == port)
+			return &pmadapter->pcard_usb->usb_tx_aggr[i];
+	}
+	LEAVE();
+	return MNULL;
+}
+
+t_void wlan_usb_tx_aggr_timeout_func(t_void *function_context);
+mlan_status wlan_usb_host_to_card_aggr(pmlan_adapter pmadapter,
+				       pmlan_buffer pmbuf,
+				       mlan_tx_param *tx_param,
+				       usb_tx_aggr_params *aggr_params);
+#endif
+
+/** Process receive packet complete */
+mlan_status wlan_recv_packet_complete(pmlan_adapter pmadapter,
+				      pmlan_buffer pmbuf, mlan_status status);
+/** Clean Tx Rx queues */
+t_void wlan_clean_txrx(pmlan_private priv);
+
+t_void wlan_add_buf_bypass_txqueue(mlan_adapter *pmadapter, pmlan_buffer pmbuf);
+t_void wlan_process_bypass_tx(mlan_adapter *pmadapter);
+t_void wlan_cleanup_bypass_txq(pmlan_private priv);
+t_u8 wlan_bypass_tx_list_empty(mlan_adapter *pmadapter);
+
+/** Check if this is the last packet */
+t_u8 wlan_check_last_packet_indication(pmlan_private priv);
+
+#define MOAL_ALLOC_MLAN_BUFFER (0)
+#define MOAL_MALLOC_BUFFER (1)
+
+#ifdef PCIE
+/* This defines the direction arg to the DMA mapping routines. */
+#define PCI_DMA_BIDIRECTIONAL 0
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#define PCI_DMA_NONE 3
+#endif
+
+/** function to allocate a mlan_buffer */
+pmlan_buffer wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len,
+				    t_u32 head_room, t_u32 malloc_flag);
+/** function to free a mlan_buffer */
+t_void wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf);
+
+/** command resp handler for version ext */
+mlan_status wlan_ret_ver_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf);
+
+/** command resp handler for rx mgmt forward registration */
+mlan_status wlan_ret_rx_mgmt_ind(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+/** Check Power Save condition */
+t_void wlan_check_ps_cond(mlan_adapter *pmadapter);
+
+/** handle command for enhanced power save mode */
+mlan_status wlan_cmd_enh_power_mode(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *cmd,
+				    t_u16 cmd_action, t_u16 ps_bitmap,
+				    t_void *pdata_buf);
+/** handle command resp for enhanced power save mode */
+mlan_status wlan_ret_enh_power_mode(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *resp,
+				    mlan_ioctl_req *pioctl_buf);
+
+/** handle commnand for cfg data */
+mlan_status wlan_cmd_cfg_data(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action,
+			      t_u32 cmd_oid, t_void *pdata_buf);
+/** handle command resp for cfg data */
+mlan_status wlan_ret_cfg_data(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp, t_void *pioctl_buf);
+
+/** Process sleep confirm command response */
+void wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter, t_u8 *pbuf,
+				     t_u32 len);
+
+/** Perform hs related activities on receving the power up interrupt */
+void wlan_process_hs_config(pmlan_adapter pmadapter);
+
+t_void wlan_wakeup_card_timeout_func(void *function_context);
+
+mlan_status wlan_process_802dot11_mgmt_pkt(mlan_private *priv, t_u8 *payload,
+					   t_u32 payload_len, RxPD *prx_pd);
+
+mlan_status wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_remain_chan_cfg(pmlan_adapter pmadapter,
+					     pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_remain_on_channel(pmlan_private pmpriv,
+				       HostCmd_DS_COMMAND *cmd,
+				       t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_remain_on_channel(pmlan_private pmpriv,
+				       HostCmd_DS_COMMAND *resp,
+				       mlan_ioctl_req *pioctl_buf);
+
+#ifdef WIFI_DIRECT_SUPPORT
+mlan_status wlan_bss_ioctl_wifi_direct_mode(pmlan_adapter pmadapter,
+					    pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_wifi_direct_mode(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *cmd,
+				      t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_wifi_direct_mode(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_p2p_params_config(pmlan_private pmpriv,
+				       HostCmd_DS_COMMAND *cmd,
+				       t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_p2p_params_config(pmlan_private pmpriv,
+				       HostCmd_DS_COMMAND *resp,
+				       mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_p2p_config(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req);
+#endif
+mlan_status wlan_cmd_gpio_tsf_latch(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *cmd,
+				    t_u16 cmd_action,
+				    mlan_ioctl_req *pioctl_buf,
+				    t_void *pdata_buf);
+mlan_status wlan_ret_gpio_tsf_latch(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *resp,
+				    mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_gpio_tsf_latch_config(pmlan_adapter pmadapter,
+					    pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_get_tsf_info(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req);
+/** get ralist info */
+int wlan_get_ralist_info(mlan_private *priv, pralist_info buf);
+/** dump ralist */
+void wlan_dump_ralist(mlan_private *priv);
+
+/** get pm info */
+mlan_status wlan_get_pm_info(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_bss_ioctl_bss_remove(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_mimo_switch_cfg(pmlan_adapter pmadapter,
+					     pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
+					HostCmd_DS_COMMAND *cmd,
+					t_void *pdata_buf);
+
+mlan_status wlan_misc_per_pkt_cfg(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_config_mgmt_filter(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_hs_wakeup_reason(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *cmd,
+				      t_void *pdata_buf);
+
+mlan_status wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_get_tx_rx_histogram(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_tx_rx_pkt_stats(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *cmd,
+				     pmlan_ioctl_req pioctl_buf,
+				     t_void *pdata_buf);
+mlan_status wlan_ret_tx_rx_pkt_stats(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *resp,
+				     mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_radio_ioctl_radio_ctl(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_tx_rate_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *cmd,
+				 t_u16 cmd_action, t_void *pdata_buf,
+				 mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_tx_rate_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_cfg(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req);
+mlan_status wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_rate_ioctl_get_data_rate(pmlan_adapter pmadapter,
+					  pmlan_ioctl_req pioctl_req);
+
+t_void wlan_host_sleep_activated_event(pmlan_private priv, t_u8 activated);
+/** Handles the command response of hs_cfg */
+mlan_status wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,
+				   HostCmd_DS_COMMAND *resp,
+				   mlan_ioctl_req *pioctl_buf);
+/** Sends HS_WAKEUP event to applications */
+t_void wlan_host_sleep_wakeup_event(pmlan_private priv);
+
+/** Prepares command of robustcoex */
+mlan_status wlan_cmd_robustcoex(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				t_u16 *pdata_buf);
+/** Set Robustcoex gpiocfg */
+mlan_status wlan_misc_robustcoex(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req);
+
+/** Set mapping policy/get DMCS status */
+mlan_status wlan_misc_dmcs_config(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req);
+/** Prepares command of DMCS config */
+mlan_status wlan_cmd_dmcs_config(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *cmd,
+				 t_u16 cmd_action, t_void *pdata_buf);
+/** Handles command response of DMCS config */
+mlan_status wlan_ret_dmcs_config(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+#if defined(PCIE)
+mlan_status wlan_cmd_ssu(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+			 t_u16 cmd_action, t_u16 *pdata_buf);
+#endif
+
+/** send get hw spec command to firmware */
+mlan_status wlan_adapter_get_hw_spec(pmlan_adapter pmadapter);
+/** send adapter specific init cmd to firmware */
+mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter);
+/** get/set bandcfg */
+mlan_status wlan_radio_ioctl_band_cfg(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status wlan_cmd_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+					 HostCmd_DS_COMMAND *cmd,
+					 t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
+					 const HostCmd_DS_COMMAND *resp,
+					 mlan_ioctl_req *pioctl_buf);
+#endif
+
+#ifdef STA_SUPPORT
+/** warm reset */
+mlan_status wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req);
+/** Process received packet */
+mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+/** ioctl handler for station mode */
+mlan_status wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+/** cmd handler for station mode */
+mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
+				     t_u16 cmd_action, t_u32 cmd_oid,
+				     t_void *pioctl_buf,
+				     t_void *pdata_buf, t_void *pcmd_buf);
+
+/** cmdresp handler for station mode */
+mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+					 t_void *pcmd_buf, t_void *pioctl);
+
+/** rx handler for station mode */
+mlan_status wlan_ops_sta_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf);
+
+/** event handler for station mode */
+mlan_status wlan_ops_sta_process_event(t_void *priv);
+
+/** fill txpd for station mode */
+t_void *wlan_ops_sta_process_txpd(t_void *priv, pmlan_buffer pmbuf);
+
+/** send init cmd to firmware for station mode */
+mlan_status wlan_ops_sta_init_cmd(t_void *priv, t_u8 first_bss);
+
+/** Flush the scan table */
+mlan_status wlan_flush_scan_table(pmlan_adapter pmadapter);
+
+/** Scan for networks */
+mlan_status wlan_scan_networks(mlan_private *pmpriv, t_void *pioctl_buf,
+			       wlan_user_scan_cfg *puser_scan_in);
+
+/** Scan for specific SSID */
+mlan_status wlan_scan_specific_ssid(mlan_private *pmpriv,
+				    t_void *pioctl_buf,
+				    mlan_802_11_ssid *preq_ssid);
+
+/** Scan command handler */
+mlan_status wlan_cmd_802_11_scan(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf);
+
+/** Handler for scan command response */
+mlan_status wlan_ret_802_11_scan(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp, t_void *pioctl_buf);
+
+/** Extended scan command handler */
+mlan_status wlan_cmd_802_11_scan_ext(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *pcmd,
+				     t_void *pdata_buf);
+/** Handler for extended scan command response */
+mlan_status wlan_ret_802_11_scan_ext(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *resp,
+				     t_void *pioctl_buf);
+/** Handler event for extended scan report */
+mlan_status wlan_handle_event_ext_scan_report(mlan_private *pmpriv,
+					      mlan_buffer *pmbuf);
+mlan_status wlan_handle_event_ext_scan_status(mlan_private *pmpriv,
+					      mlan_buffer *pmbuf);
+
+/** check network compatibility */
+t_s32 wlan_is_network_compatible(mlan_private *pmpriv, t_u32 index, t_u32 mode);
+
+/** Find an SSID in a list */
+t_s32 wlan_find_ssid_in_list(pmlan_private pmpriv, mlan_802_11_ssid *ssid,
+			     t_u8 *bssid, t_u32 mode);
+
+/** Find a BSSID in a list */
+t_s32 wlan_find_bssid_in_list(mlan_private *pmpriv, t_u8 *bssid, t_u32 mode);
+
+/** Find best network */
+mlan_status wlan_find_best_network(mlan_private *pmpriv,
+				   mlan_ssid_bssid *preq_ssid_bssid);
+
+/** Compare two SSIDs */
+t_s32 wlan_ssid_cmp(pmlan_adapter pmadapter, mlan_802_11_ssid *ssid1,
+		    mlan_802_11_ssid *ssid2);
+
+/** Associate */
+mlan_status wlan_associate(mlan_private *pmpriv, IN t_void *pioctl_buf,
+			   IN BSSDescriptor_t *pBSSDesc);
+
+/** Associate command handler */
+mlan_status wlan_cmd_802_11_associate(mlan_private *pmpriv,
+				      HostCmd_DS_COMMAND *cmd,
+				      t_void *pdata_buf);
+
+/** Handler for association command response */
+mlan_status wlan_ret_802_11_associate(mlan_private *pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      t_void *pioctl_buf);
+
+/** Reset connected state */
+t_void wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect);
+
+t_void wlan_2040_coex_event(pmlan_private pmpriv);
+
+/** convert band to radio type */
+t_u8 wlan_band_to_radio_type(t_u8 band);
+/** convert radio_type to band */
+t_u8 radio_type_to_band(t_u8 chanBand);
+
+/** Disconnect */
+mlan_status wlan_disconnect(mlan_private *pmpriv,
+			    mlan_ioctl_req *pioctl_req,
+			    mlan_deauth_param *deauth_param);
+
+/** Ad-Hoc start */
+mlan_status wlan_adhoc_start(mlan_private *pmpriv, t_void *pioctl_buf,
+			     mlan_802_11_ssid *padhoc_ssid);
+
+/** Ad-Hoc join */
+mlan_status wlan_adhoc_join(mlan_private *pmpriv, t_void *pioctl_buf,
+			    BSSDescriptor_t *pBSSDesc);
+
+/** Ad-Hoc start command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_start(mlan_private *pmpriv,
+					 HostCmd_DS_COMMAND *cmd,
+					 t_void *pdata_buf);
+
+/** Ad-Hoc command handler */
+mlan_status wlan_cmd_802_11_ad_hoc_join(mlan_private *pmpriv,
+					HostCmd_DS_COMMAND *cmd,
+					t_void *pdata_buf);
+
+/** Handler for Ad-Hoc commands */
+mlan_status wlan_ret_802_11_ad_hoc(mlan_private *pmpriv,
+				   HostCmd_DS_COMMAND *resp,
+				   t_void *pioctl_buf);
+
+/** Handler for bgscan query commands */
+mlan_status wlan_cmd_802_11_bg_scan_query(mlan_private *pmpriv,
+					  HostCmd_DS_COMMAND *pcmd,
+					  t_void *pdata_buf);
+/** Handler for bgscan config command */
+mlan_status wlan_cmd_bgscan_config(mlan_private *pmpriv,
+				   HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf);
+/** Hander for bgscan config command response */
+mlan_status wlan_ret_bgscan_config(mlan_private *pmpriv,
+				   HostCmd_DS_COMMAND *resp,
+				   mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_802_11_bgscan_query(mlan_private *pmpriv,
+					 HostCmd_DS_COMMAND *resp,
+					 mlan_ioctl_req *pioctl_buf);
+
+/** Get Channel-Frequency-Power by band and channel */
+chan_freq_power_t *wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,
+						    t_u8 band, t_u16 channel,
+						    region_chan_t
+						    *region_channel);
+/** Find Channel-Frequency-Power by band and channel */
+chan_freq_power_t *wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
+						     t_u8 band, t_u16 channel);
+/** Find Channel-Frequency-Power by band and frequency */
+chan_freq_power_t *wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter,
+						  t_u8 band, t_u32 freq);
+/** Get Tx power of channel from Channel-Frequency-Power */
+t_u8 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel);
+/** find frequency from band and channel */
+t_u32 wlan_find_freq_from_band_chan(t_u8, t_u8);
+
+/*  Save a beacon buffer of the current bss descriptor */
+t_void wlan_save_curr_bcn(mlan_private *pmpriv);
+/*  Free a beacon buffer of the current bss descriptor */
+t_void wlan_free_curr_bcn(mlan_private *pmpriv);
+
+#endif /* STA_SUPPORT */
+
+/* Rate related functions */
+t_u8 wlan_convert_v14_tx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info);
+t_u8 wlan_convert_v14_rx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info);
+/** Convert index into data rate */
+t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
+			      t_u8 rate_info, t_u8 ext_rate_info);
+/** Get active data rates */
+t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
+				 t_u16 config_bands, WLAN_802_11_RATES rates);
+/** Get supported data rates */
+t_u32 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
+			       t_u16 config_bands, WLAN_802_11_RATES rates);
+/** Convert data rate to index */
+t_u8 wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate);
+/** Check if rate is auto */
+t_u8 wlan_is_rate_auto(mlan_private *pmpriv);
+/** Get rate index */
+int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rateBitmap, int size);
+mlan_status wlan_cmd_rxabortcfg(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				t_void *pdata_buf);
+mlan_status wlan_ret_rxabortcfg(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *resp,
+				mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_rxabortcfg_ext(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *cmd,
+				    t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_rxabortcfg_ext(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *resp,
+				    mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv,
+					HostCmd_DS_COMMAND *cmd,
+					t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_tx_ampdu_prot_mode(pmlan_private pmpriv,
+					HostCmd_DS_COMMAND *resp,
+					mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+					     HostCmd_DS_COMMAND *cmd,
+					     t_u16 cmd_action,
+					     t_void *pdata_buf);
+mlan_status wlan_ret_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
+					     HostCmd_DS_COMMAND *resp,
+					     mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_hal_phy_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *cmd,
+				 t_u16 cmd_action, t_u16 *pdata_buf);
+mlan_status wlan_ret_hal_phy_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_rate_adapt_cfg(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *cmd,
+				    t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_rate_adapt_cfg(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *resp,
+				    mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *cmd,
+				     t_u16 cmd_action, t_void *pdata_buf);
+
+mlan_status wlan_ret_cck_desense_cfg(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *resp,
+				     mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_arb_cfg(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+			     t_void *pdata_buf);
+mlan_status wlan_ret_arb_cfg(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_rxabortcfg(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_rxabortcfg_ext(pmlan_adapter pmadapter,
+					   pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tx_ampdu_prot_mode(pmlan_adapter pmadapter,
+					       pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmlan_adapter pmadapter,
+						    pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_rate_adapt_cfg(pmlan_adapter pmadapter,
+					   pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_cck_desense_cfg(pmlan_adapter pmadapter,
+					    pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mfg(pmlan_private pmpriv, pHostCmd_DS_COMMAND cmd,
+			 t_u16 cmd_action, t_pvoid pdata_buf);
+mlan_status wlan_ret_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+			 mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req);
+/* CFP related functions */
+/** Region code index table */
+extern t_u16 region_code_index[MRVDRV_MAX_REGION_CODE];
+/** The table to keep CFP code for BG */
+extern t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG];
+/** The table to keep CFP code for A */
+extern t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A];
+
+/** Set region table */
+mlan_status wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u8 band);
+/** Get radar detection requirements*/
+t_bool wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl);
+/** check if scan type is passive for b/g band*/
+t_bool wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl);
+/** check if channel is NO_IR (passive) */
+t_bool wlan_is_chan_passive(mlan_private *priv, t_u8 band, t_u8 chan);
+/** check if channel is disabled */
+t_bool wlan_is_chan_disabled(mlan_private *priv, t_u8 band, t_u8 chan);
+/** check if channel is blacklisted */
+t_bool wlan_is_chan_blacklisted(mlan_private *priv, t_u8 band, t_u8 chan);
+/** set blacklist setting for a channel */
+t_bool wlan_set_chan_blacklist(mlan_private *priv, t_u8 band, t_u8 chan,
+			       t_bool bl);
+
+/* 802.11D related functions */
+/** Initialize 11D */
+t_void wlan_11d_priv_init(mlan_private *pmpriv);
+/** Initialize 11D */
+t_void wlan_11d_init(mlan_adapter *pmadapter);
+/** Enable 11D */
+mlan_status wlan_11d_enable(mlan_private *pmpriv, t_void *pioctl_buf,
+			    state_11d_t flag);
+/** Get if 11D is enabled */
+t_bool wlan_11d_is_enabled(mlan_private *pmpriv);
+/** Get if FW 11D is enabled */
+t_bool wlan_fw_11d_is_enabled(mlan_private *pmpriv);
+/** Get if priv is station */
+t_bool wlan_is_station(mlan_private *pmpriv);
+/** Command handler for 11D country info */
+mlan_status wlan_cmd_802_11d_domain_info(mlan_private *pmpriv,
+					 HostCmd_DS_COMMAND *pcmd,
+					 t_u16 cmd_action);
+/** Handler for 11D country info command response */
+mlan_status wlan_ret_802_11d_domain_info(mlan_private *pmpriv,
+					 HostCmd_DS_COMMAND *resp);
+/** Convert channel to frequency */
+t_u32 wlan_11d_chan_2_freq(pmlan_adapter pmadapter, t_u8 chan, t_u8 band);
+#ifdef STA_SUPPORT
+/** Set 11D universal table */
+mlan_status wlan_11d_set_universaltable(mlan_private *pmpriv, t_u8 band);
+/** Clear 11D region table */
+mlan_status wlan_11d_clear_parsedtable(mlan_private *pmpriv);
+/** Create 11D country information for downloading */
+mlan_status wlan_11d_create_dnld_countryinfo(mlan_private *pmpriv, t_u8 band);
+/** Get scan type from 11D info */
+t_u8 wlan_11d_get_scan_type(pmlan_adapter pmadapter, t_u8 band, t_u8 chan,
+			    parsed_region_chan_11d_t *parsed_region_chan);
+/** Parse 11D country info */
+mlan_status wlan_11d_parse_dnld_countryinfo(mlan_private *pmpriv,
+					    BSSDescriptor_t *pBSSDesc);
+/** Prepare 11D domain information for download */
+mlan_status wlan_11d_prepare_dnld_domain_info_cmd(mlan_private *pmpriv);
+/** Parse 11D country information into domain info */
+mlan_status wlan_11d_parse_domain_info(pmlan_adapter pmadapter,
+				       IEEEtypes_CountryInfoFullSet_t
+				       *country_info, t_u8 band,
+				       parsed_region_chan_11d_t
+				       *parsed_region_chan);
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Handle 11D domain information from UAP */
+mlan_status wlan_11d_handle_uap_domain_info(mlan_private *pmpriv, t_u8 band,
+					    t_u8 *domain_tlv,
+					    t_void *pioctl_buf);
+#endif
+/** Configure 11D domain info command */
+mlan_status wlan_11d_cfg_domain_info(pmlan_adapter pmadapter,
+				     mlan_ioctl_req *pioctl_req);
+
+/** This function converts region string to CFP table code */
+mlan_status wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,
+					       t_u8 *country_code,
+					       t_u8 *cfp_bg, t_u8 *cfp_a);
+
+/** This function finds if given country code is in EU table */
+t_bool wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code);
+
+/** check if station list is empty */
+t_u8 wlan_is_station_list_empty(mlan_private *priv);
+/** get station node */
+sta_node *wlan_get_station_entry(mlan_private *priv, t_u8 *mac);
+/** delete station list */
+t_void wlan_delete_station_list(pmlan_private priv);
+/** delete station entry */
+t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac);
+/** add station entry */
+sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac);
+/** process uap rx packet */
+
+void wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
+			       sta_node *sta_ptr);
+/** find specific ie */
+t_u8 *wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
+			   IEEEtypes_ElementId_e id, t_u8 ext_id);
+t_u8 wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len);
+
+/**
+ *  @brief This function checks whether a station TDLS link is enabled or not
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param mac      station mac address
+ *  @return
+ * TDLS_NOT_SETUP/TDLS_SETUP_INPROGRESS/TDLS_SETUP_COMPLETE/TDLS_SETUP_FAILURE/TDLS_TEAR_DOWN
+ */
+static INLINE tdlsStatus_e
+wlan_get_tdls_link_status(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		return sta_ptr->status;
+	return TDLS_NOT_SETUP;
+}
+
+/**
+ *  @brief This function checks if TDLS link is in channel switching
+ *
+ *  @param status     tdls link status
+ *  @return         MTRUE/MFALSE
+ */
+static INLINE int
+wlan_is_tdls_link_chan_switching(tdlsStatus_e status)
+{
+	return (status == TDLS_SWITCHING_CHANNEL) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function checks if send command to firmware is allowed
+ *
+ *  @param status     tdls link status
+ *  @return         MTRUE/MFALSE
+ */
+static INLINE int
+wlan_is_send_cmd_allowed(tdlsStatus_e status)
+{
+	int ret = MTRUE;
+	switch (status) {
+	case TDLS_SWITCHING_CHANNEL:
+	case TDLS_IN_OFF_CHANNEL:
+		ret = MFALSE;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function checks if TDLS link is setup
+ *
+ *  @param status     tdls link status
+ *  @return         MTRUE/MFALSE
+ */
+static INLINE int
+wlan_is_tdls_link_setup(tdlsStatus_e status)
+{
+	int ret = MFALSE;
+	switch (status) {
+	case TDLS_SWITCHING_CHANNEL:
+	case TDLS_IN_OFF_CHANNEL:
+	case TDLS_IN_BASE_CHANNEL:
+	case TDLS_SETUP_COMPLETE:
+		ret = MTRUE;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function checks tx_pause flag for peer
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ra       Address of the receiver STA
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE int
+wlan_is_tx_pause(mlan_private *priv, t_u8 *ra)
+{
+	sta_node *sta_ptr = MNULL;
+	sta_ptr = wlan_get_station_entry(priv, ra);
+	if (sta_ptr)
+		return sta_ptr->tx_pause;
+	return MFALSE;
+}
+
+t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause);
+
+#ifdef UAP_SUPPORT
+mlan_status wlan_process_uap_rx_packet(mlan_private *priv, pmlan_buffer pmbuf);
+t_void wlan_drop_tx_pkts(pmlan_private priv);
+#endif /* UAP_SUPPORT */
+
+#ifdef UAP_SUPPORT
+/* process the recevied packet and bridge the packet */
+mlan_status wlan_uap_recv_packet(mlan_private *priv, pmlan_buffer pmbuf);
+#endif /* UAP_SUPPORT */
+
+mlan_status wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
+					   pmlan_ioctl_req pioctl_req,
+					   t_bool send_ioctl);
+
+mlan_status wlan_cmd_get_hw_spec(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *pcmd);
+mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp, t_void *pioctl_buf);
+#ifdef SDIO
+mlan_status wlan_cmd_sdio_rx_aggr_cfg(HostCmd_DS_COMMAND *pcmd,
+				      t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_sdio_rx_aggr_cfg(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp);
+#endif
+
+mlan_status wlan_misc_ioctl_mac_control(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_mac_control(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *pcmd,
+				 t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_mac_control(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_cw_mode_ctrl(pmlan_private pmpriv,
+				  HostCmd_DS_COMMAND *cmd,
+				  t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_cw_mode_ctrl(pmlan_private pmpriv,
+				  HostCmd_DS_COMMAND *resp,
+				  mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_radio_control(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *cmd,
+					  t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_802_11_radio_control(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_rf_antenna(pmlan_private pmpriv,
+				       HostCmd_DS_COMMAND *cmd,
+				       t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,
+				       HostCmd_DS_COMMAND *resp,
+				       mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter, t_u16 type,
+				HostCmd_DS_COMMAND *resp,
+				mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_mem_access(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *resp,
+				mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_read_eeprom(pmlan_adapter pmadapter,
+					   pmlan_ioctl_req pioctl_req);
+mlan_status wlan_reg_mem_ioctl_mem_rw(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_reg_access(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				t_void *pdata_buf);
+mlan_status wlan_cmd_mem_access(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				t_void *pdata_buf);
+mlan_status wlan_cmd_802_11_mac_address(pmlan_private pmpriv,
+					HostCmd_DS_COMMAND *cmd,
+					t_u16 cmd_action);
+mlan_status wlan_ret_802_11_mac_address(pmlan_private pmpriv,
+					HostCmd_DS_COMMAND *resp,
+					mlan_ioctl_req *pioctl_buf);
+
+int wlan_get_tdls_list(mlan_private *priv, tdls_peer_info *buf);
+t_void wlan_hold_tdls_packets(pmlan_private priv, t_u8 *mac);
+t_void wlan_restore_tdls_packets(pmlan_private priv, t_u8 *mac,
+				 tdlsStatus_e status);
+t_void wlan_update_non_tdls_ralist(mlan_private *priv, t_u8 *mac,
+				   t_u8 tx_pause);
+mlan_status wlan_misc_ioctl_tdls_config(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req);
+void wlan_11n_send_delba_to_peer(mlan_private *priv, t_u8 *ra);
+void wlan_process_tdls_action_frame(pmlan_private priv, t_u8 *pbuf, t_u32 len);
+mlan_status wlan_misc_ioctl_tdls_oper(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_tdls_get_ies(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+mlan_status wlan_misc_ioctl_tdls_idle_time(pmlan_adapter pmadapter,
+					   pmlan_ioctl_req pioctl_req);
+
+t_void wlan_tdls_config(pmlan_private pmpriv, t_u8 enable);
+mlan_status wlan_misc_ioctl_tdls_cs_channel(pmlan_adapter pmadapter,
+					    pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_get_info_ver_ext(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ioctl_link_statistic(mlan_private *pmpriv,
+				      pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_802_11_link_statistic(pmlan_private pmpriv,
+					   HostCmd_DS_COMMAND *cmd,
+					   t_u16 cmd_action,
+					   mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_ret_get_link_statistic(pmlan_private pmpriv,
+					HostCmd_DS_COMMAND *resp,
+					mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req);
+
+#ifdef DEBUG_LEVEL1
+mlan_status wlan_set_drvdbg(pmlan_adapter pmadapter,
+			    pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_hotspot_cfg(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req);
+
+#ifdef STA_SUPPORT
+mlan_status wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req);
+
+t_u32 wlan_is_ext_capa_support(mlan_private *pmpriv);
+#endif
+
+#ifdef STA_SUPPORT
+void wlan_add_ext_capa_info_ie(mlan_private *pmpriv,
+			       BSSDescriptor_t *pbss_desc, t_u8 **pptlv_out);
+#endif
+
+mlan_status wlan_cmd_boot_sleep(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				t_void *pdata_buf);
+
+mlan_status wlan_ret_boot_sleep(pmlan_private pmpriv,
+				HostCmd_DS_COMMAND *resp,
+				mlan_ioctl_req *pioctl_buf);
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+mlan_status wlan_cmd_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+			    t_u16 cmd_action, t_u16 *pdata_buf);
+
+mlan_status wlan_ret_crypto(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf);
+#endif
+
+#define BW_20MHZ 0
+#define BW_40MHZ 1
+#define BW_80MHZ 2
+#define BW_160MHZ 3
+int wlan_add_supported_oper_class_ie(mlan_private *pmpriv,
+				     t_u8 **pptlv_out, t_u8 curr_oper_class);
+mlan_status wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel,
+				     t_u8 bw, t_u8 *oper_class);
+mlan_status wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
+					    t_u8 oper_class);
+mlan_status wlan_misc_ioctl_operclass_validation(pmlan_adapter pmadapter,
+						 mlan_ioctl_req *pioctl_req);
+mlan_status wlan_misc_ioctl_oper_class(pmlan_adapter pmadapter,
+				       mlan_ioctl_req *pioctl_req);
+
+t_u16 wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info);
+t_u8 wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd);
+
+mlan_status wlan_misc_otp_user_data(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req);
+
+#ifdef USB
+extern mlan_adapter_operations mlan_usb_ops;
+
+mlan_status wlan_misc_ioctl_usb_aggr_ctrl(pmlan_adapter pmadapter,
+					  pmlan_ioctl_req pioctl_req);
+#endif
+
+mlan_status wlan_misc_ioctl_aggr_ctrl(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_packet_aggr_ctrl(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *cmd,
+				      t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_packet_aggr_ctrl(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_ioctl_txcontrol(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_region(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req);
+
+#ifdef RX_PACKET_COALESCE
+mlan_status
+
+wlan_misc_ioctl_rx_pkt_coalesce_config(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req);
+#endif
+
+void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
+					  pmlan_buffer pevent);
+
+mlan_status wlan_misc_ioctl_dfs_repeater_cfg(pmlan_adapter pmadapter,
+					     pmlan_ioctl_req pioctl_req);
+
+t_bool wlan_check_interface_active(mlan_adapter *pmadapter);
+
+mlan_status wlan_misc_ioctl_coalesce_cfg(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_low_pwr_mode(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_pmic_configure(pmlan_adapter pmadapter,
+					   pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_cwmode_ctrl(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_set_mef_entry(mlan_private *pmpriv,
+			       pmlan_adapter pmadapter, mef_cfg_data * pmef);
+mlan_status wlan_process_mef_cfg_cmd(mlan_private *pmpriv,
+				     pmlan_adapter pmadapter);
+mlan_status wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_ind_rst_cfg(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND *cmd,
+				 t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_ind_rst_cfg(pmlan_private pmpriv,
+				 HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_802_11_supplicant_pmk(pmlan_private pmpriv,
+					   HostCmd_DS_COMMAND *cmd,
+					   t_u16 cmd_action, t_void *pdata_buf);
+
+mlan_status wlan_ret_802_11_supplicant_pmk(pmlan_private pmpriv,
+					   HostCmd_DS_COMMAND *resp,
+					   mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_sec_ioctl_passphrase(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req);
+void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left);
+
+void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter);
+
+mlan_status wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_get_cfp_table(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req);
+mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+			     t_u16 cmd_action);
+mlan_status wlan_ret_get_tsf(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf);
+
+t_u8 wlan_ft_akm_is_used(mlan_private *pmpriv, t_u8 *rsn_ie);
+
+mlan_status wlan_get_rgchnpwr_cfg(pmlan_adapter pmadapter,
+				  mlan_ioctl_req *pioctl_req);
+mlan_status wlan_get_chan_trpc_cfg(pmlan_adapter pmadapter,
+				   mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_get_chan_trpc_config(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *cmd,
+					  t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_get_chan_trpc_config(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_ps_inactivity_timeout(pmlan_private pmpriv,
+					   HostCmd_DS_COMMAND *cmd,
+					   t_u16 cmd_action, t_void *pdata_buf);
+
+t_u8 wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv,
+				     t_u16 IeeeMacRate, t_u8 *dst_mac);
+t_u8 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate);
+
+t_u8 wlan_get_center_freq_idx(mlan_private *pmpriv, t_u16 band,
+			      t_u32 pri_chan, t_u8 chan_bw);
+
+mlan_status wlan_ret_chan_region_cfg(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *resp,
+				     mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_misc_ioctl_fw_dump_event(pmlan_adapter pmadapter,
+					  mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_fw_dump_event(pmlan_private pmpriv,
+				   HostCmd_DS_COMMAND *cmd,
+				   t_u16 cmd_action, t_void *pdata_buf);
+
+mlan_status wlan_misc_bootsleep(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_misc_ioctl_dyn_bw(pmlan_adapter pmadapter,
+				   mlan_ioctl_req *pioctl_req);
+mlan_status wlan_cmd_config_dyn_bw(pmlan_private pmpriv,
+				   HostCmd_DS_COMMAND *cmd,
+				   t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_dyn_bw(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf);
+
+#ifdef UAP_SUPPORT
+/** wacp mode misc ioctl */
+mlan_status wlan_misc_ioctl_wacp_mode(pmlan_adapter pmadapter,
+				      mlan_ioctl_req *pioctl_req);
+#endif
+
+mlan_status wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter,
+					 pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+						HostCmd_DS_COMMAND *cmd,
+						t_u16 cmd_action,
+						t_void *pdata_buf);
+mlan_status wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
+						HostCmd_DS_COMMAND *resp,
+						mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_range_ext(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *cmd,
+			       t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_range_ext(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *resp,
+			       mlan_ioctl_req *pioctl_buf);
+
+/**
+ *  @brief RA based queueing
+ *
+ *  @param priv             A pointer to mlan_private structure
+ *
+ *  @return                 MTRUE or MFALSE
+ */
+static INLINE t_u8
+queuing_ra_based(pmlan_private priv)
+{
+	/*
+	 * Currently we assume if we are in Infra, then DA=RA. This might not be
+	 * true in the future
+	 */
+	if ((priv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA))
+		return MFALSE;
+
+	return MTRUE;
+}
+
+/**
+ *  @brief Copy Rates
+ *
+ *  @param dest             A pointer to Dest Buf
+ *  @param pos		        The position for copy
+ *  @param src		        A pointer to Src Buf
+ *  @param len              The len of Src Buf
+ *
+ *  @return                 Number of Rates copied
+ */
+static INLINE t_u32
+wlan_copy_rates(t_u8 *dest, t_u32 pos, t_u8 *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len && src[i]; i++, pos++) {
+		if (pos >= sizeof(WLAN_802_11_RATES))
+			break;
+		dest[pos] = src[i];
+	}
+
+	return pos;
+}
+
+/**
+ *  @brief strlen
+ *
+ *  @param str		        A pointer to string
+ *
+ *  @return                 Length of string
+ */
+static INLINE t_u32
+wlan_strlen(const char *str)
+{
+	t_u32 i;
+
+	for (i = 0; str[i] != 0; i++) ;
+
+	return i;
+}
+
+/**
+ *  @brief iscdigit
+ *
+ *  @param chr                  A char
+ *
+ *  @return                     Non zero if chr is a hex, else 0
+ */
+static INLINE t_u32
+wlan_isxdigit(t_u8 chr)
+{
+	return (chr <= 'f' && chr >= 'a') || (chr <= 'F' && chr >= 'A') ||
+		(chr <= '9' && chr >= '0');
+}
+
+/**
+ *  @brief isspace
+ *
+ *  @param                       A chr
+ *
+ *  @return                      Non zero if chr is space etc, else 0
+ */
+static INLINE t_u32
+wlan_isspace(t_u8 chr)
+{
+	return chr <= ' ' && (chr == ' ' || (chr <= 13 && chr >= 9));
+}
+
+/** delay unit */
+typedef enum _delay_unit {
+	USEC,
+	MSEC,
+	SEC,
+} t_delay_unit;
+
+/** delay function */
+t_void wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u);
+
+/** delay function wrapper */
+#define wlan_delay(p, n) wlan_delay_func(p, n, SEC)
+/** delay function wrapper */
+#define wlan_mdelay(p, n) wlan_delay_func(p, n, MSEC)
+/** delay function wrapper */
+#define wlan_udelay(p, n) wlan_delay_func(p, n, USEC)
+
+/**
+ *  @brief This function check if there are pending cmd
+ *         in cmd pending Q
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return  MTRUE -- cmd pending
+ *           MFALSE -- no pending cmd
+ */
+static INLINE int
+wlan_is_cmd_pending(mlan_adapter *pmadapter)
+{
+	int ret;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	wlan_request_cmd_lock(pmadapter);
+	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
+						    &pmadapter->cmd_pending_q,
+						    MNULL, MNULL);
+	if (pcmd_node)
+		ret = MTRUE;
+	else
+		ret = MFALSE;
+	wlan_release_cmd_lock(pmadapter);
+	return ret;
+}
+
+/** Get BSS number from priv */
+#define GET_BSS_NUM(priv) ((priv)->bss_num)
+
+/**
+ *  @brief This function returns priv based on the BSS num and BSS type
+ *
+ *  @param pmadapter A pointer to mlan_adapter
+ *  @param bss_num   BSS number
+ *  @param bss_type  BSS type
+ *
+ *  @return          Pointer to mlan_private
+ */
+static INLINE mlan_private *
+wlan_get_priv_by_id(mlan_adapter *pmadapter, t_u32 bss_num, t_u32 bss_type)
+{
+	int i;
+
+	for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (pmadapter->priv[i]) {
+			if ((pmadapter->priv[i]->bss_num == bss_num) &&
+			    (pmadapter->priv[i]->bss_type == bss_type))
+				return pmadapter->priv[i];
+		}
+	}
+	return MNULL;
+}
+
+/**
+ *  @brief This function returns first available priv
+ *  based on the BSS role
+ *
+ *  @param pmadapter A pointer to mlan_adapter
+ *  @param bss_role  BSS role or MLAN_BSS_ROLE_ANY
+ *
+ *  @return          Pointer to mlan_private
+ */
+static INLINE mlan_private *
+wlan_get_priv(mlan_adapter *pmadapter, mlan_bss_role bss_role)
+{
+	int i;
+
+	for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (pmadapter->priv[i]) {
+			if (bss_role == MLAN_BSS_ROLE_ANY ||
+			    GET_BSS_ROLE(pmadapter->priv[i]) == bss_role)
+				return pmadapter->priv[i];
+		}
+	}
+	return MNULL;
+}
+
+/**
+ *  @brief This function counts the number of occurences for a certain
+ *  condition among privs.  Which privs are checked can be configured
+ *  via a second condition.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter
+ *  @param count_cond Function pointer to condition to count on privs
+ *  @param check_cond Function pointer to condition to decide whether priv
+ *                    should be counted or not.  Use MNULL to check all privs.
+ *
+ *  @return          Count of privs where count_cond returned MTRUE.
+ */
+static INLINE int
+wlan_count_priv_cond(mlan_adapter *pmadapter,
+		     t_bool (*count_cond) (pmlan_private pmpriv),
+		     t_bool (*check_cond) (pmlan_private pmpriv))
+{
+	pmlan_private pmpriv;
+	int count = 0;
+	int i;
+
+	if (pmadapter == MNULL || count_cond == MNULL)
+		return 0;
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		pmpriv = pmadapter->priv[i];
+		if (pmpriv) {
+			if ((check_cond == MNULL) ||
+			    (check_cond && check_cond(pmpriv))) {
+				if (count_cond(pmpriv))
+					count++;
+			}
+		}
+	}
+
+	return count;
+}
+
+/**
+ *  @brief This function runs a procedure on each priv.
+ *  Which privs it is run on can be configured via a condition.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter
+ *  @param operation  Function pointer to produedure to operate on priv
+ *  @param check_cond Function pointer to condition to decide whether priv
+ *                    operated on or not.  Use MNULL to run on all privs.
+ *
+ *  @return           Number of privs that operation was run on.
+ */
+static INLINE int
+wlan_do_task_on_privs(mlan_adapter *pmadapter,
+		      t_void (*operation) (pmlan_private pmpriv),
+		      t_bool (*check_cond) (pmlan_private pmpriv))
+{
+	pmlan_private pmpriv;
+	int count = 0;
+	int i;
+
+	if (pmadapter == MNULL || operation == MNULL)
+		return 0;
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		pmpriv = pmadapter->priv[i];
+		if (pmpriv) {
+			if ((check_cond == MNULL) ||
+			    (check_cond && check_cond(pmpriv))) {
+				operation(pmpriv);
+				count++;
+			}
+		}
+	}
+
+	return count;
+}
+
+/**
+ *  @brief This function builds a list of privs that test for a condition
+ *  This is useful if you need to do a number of operations on the same set
+ *  of privs.  For one-off tasks, the above two functions might be better.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter
+ *  @param check_cond Function pointer to condition to decide whether priv
+ *                    should be placed in the list.
+ *  @param ppriv_list Output param.  Externally supplied array of mlan_private*
+ *                    to hold priv's that test positive with check_cond.
+ *                    Array size should be at least pmadapter->priv_num.
+ *
+ *  @return          Number of privs in ppriv_list
+ *
+ *  @sa              wlan_count_priv_cond
+ */
+static INLINE int
+wlan_get_privs_by_cond(mlan_adapter *pmadapter,
+		       t_bool (*check_cond) (pmlan_private pmpriv),
+		       mlan_private **ppriv_list)
+{
+	pmlan_private pmpriv;
+	int count = 0;
+	int i;
+
+	if (pmadapter == MNULL || check_cond == MNULL || ppriv_list == MNULL)
+		return 0;
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		pmpriv = pmadapter->priv[i];
+		if (pmpriv) {
+			if (check_cond(pmpriv))
+				ppriv_list[count++] = pmpriv;
+		}
+	}
+
+	return count;
+}
+
+/**
+ *  @brief This function builds a list of privs that test against two conditions
+ *  This is useful if you need to do a number of operations on the same set
+ *  of privs.  Can choose whether both conditions (AND) or either condition (OR)
+ *  is required.
+ *
+ *  @param pmadapter      A pointer to mlan_adapter
+ *  @param check_cond     Function pointer to condition to decide whether priv
+ *                        should be placed in the list.
+ *  @param check_cond_2   Function pointer to second condition to check.
+ *  @param and_conditions If MTRUE, both conditions must be met (AND),
+ *                        else either condition can be met (OR).
+ *  @param ppriv_list     Output param.  Externally supplied array of
+ * mlan_private* to hold priv's that test positive with check_cond. Array size
+ * should be at least pmadapter->priv_num.
+ *
+ *  @return          Number of privs in ppriv_list
+ *
+ *  @sa              wlan_count_priv_cond, wlan_get_privs_by_cond
+ */
+static INLINE int
+wlan_get_privs_by_two_cond(mlan_adapter *pmadapter,
+			   t_bool (*check_cond) (pmlan_private pmpriv),
+			   t_bool (*check_cond_2) (pmlan_private pmpriv),
+			   t_bool and_conditions, mlan_private **ppriv_list)
+{
+	pmlan_private pmpriv;
+	int count = 0;
+	int i;
+
+	if (pmadapter == MNULL || check_cond == MNULL ||
+	    check_cond_2 == MNULL || ppriv_list == MNULL)
+		return 0;
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		pmpriv = pmadapter->priv[i];
+		if (pmpriv) {
+			if (and_conditions) {
+				if (check_cond(pmpriv) && check_cond_2(pmpriv))
+					ppriv_list[count++] = pmpriv;
+			} else {
+				if (check_cond(pmpriv) || check_cond_2(pmpriv))
+					ppriv_list[count++] = pmpriv;
+			}
+		}
+	}
+
+	return count;
+}
+#endif /* !_MLAN_MAIN_H_ */
diff --git a/wlan_sd8987/mlan/mlan_meas.c b/wlan_sd8987/mlan/mlan_meas.c
new file mode 100755
index 0000000..f6b7cbb
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_meas.c
@@ -0,0 +1,466 @@
+/**
+ * @file mlan_meas.c
+ *
+ *  @brief Implementation of measurement interface code with the app/firmware
+ *
+ *  Driver implementation for sending and retrieving measurement requests
+ *    and responses.
+ *
+ *  Current use is limited to 802.11h.
+ *
+ *  Requires use of the following preprocessor define:
+ *    - ENABLE_MEAS
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    03/24/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_ioctl.h"
+#include "mlan_meas.h"
+
+#ifdef DEBUG_LEVEL2
+/** String descriptions of the different measurement enums.  Debug display */
+static const char *meas_type_str[WLAN_MEAS_NUM_TYPES] = {
+	"basic",
+};
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Retrieve the measurement string representation of a meas_type enum
+ *  Used for debug display only
+ *
+ *  @param meas_type Measurement type enumeration input for string lookup
+ *
+ *  @return         Constant string representing measurement type
+ */
+static const char *
+wlan_meas_get_meas_type_str(MeasType_t meas_type)
+{
+	if (meas_type <= WLAN_MEAS_11H_MAX_TYPE)
+		return meas_type_str[meas_type];
+
+	return "Invld";
+}
+#endif
+
+/**
+ *  @brief Debug print display of the input measurement request
+ *
+ *  @param pmeas_req  Pointer to the measurement request to display
+ *
+ *  @return          N/A
+ */
+static void
+wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+
+	PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_req->mac_addr));
+
+	PRINTM(MINFO, "Meas: Req:  dlgTkn: %d\n", pmeas_req->dialog_token);
+	PRINTM(MINFO, "Meas: Req:    mode: dm[%c] rpt[%c] req[%c]\n",
+	       pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
+	       pmeas_req->req_mode.report ? 'X' : ' ',
+	       pmeas_req->req_mode.request ? 'X' : ' ');
+	PRINTM(MINFO, "Meas: Req:        : en[%c] par[%c]\n",
+	       pmeas_req->req_mode.enable ? 'X' : ' ',
+	       pmeas_req->req_mode.parallel ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_req->meas_type));
+#endif
+
+	switch (pmeas_req->meas_type) {
+	case WLAN_MEAS_BASIC:
+		/* Lazy cheat, fields of bas, cca, rpi union match on the
+		 * request */
+		PRINTM(MINFO, "Meas: Req: chan: %u\n",
+		       pmeas_req->req.basic.channel);
+		PRINTM(MINFO, "Meas: Req: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
+		PRINTM(MINFO, "Meas: Req:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_req->req.basic.duration));
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Req: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Debug print display of the input measurement report
+ *
+ *  @param pmeas_rpt  Pointer to measurement report to display
+ *
+ *  @return          N/A
+ */
+static void
+wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+	MeasType_t type;
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
+	       MAC2STR(pmeas_rpt->mac_addr));
+
+	PRINTM(MINFO, "Meas: Rpt:  dlgTkn: %d\n", pmeas_rpt->dialog_token);
+
+	PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
+	       *(t_u8 *)&pmeas_rpt->rpt_mode,
+	       pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
+	       pmeas_rpt->rpt_mode.late ? 'X' : ' ');
+#ifdef DEBUG_LEVEL2
+	PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
+	       wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
+#endif
+
+	type = wlan_le32_to_cpu(pmeas_rpt->meas_type);
+	switch (type) {
+	case WLAN_MEAS_BASIC:
+		PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
+		       pmeas_rpt->rpt.basic.channel);
+		PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
+		       wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
+		PRINTM(MINFO, "Meas: Rpt:  dur: %u\n",
+		       wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
+		PRINTM(MINFO, "Meas: Rpt:  bas: (%x): unmsd[%c], radar[%c]\n",
+		       *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
+		       pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
+		PRINTM(MINFO, "Meas: Rpt:  bas: unidSig[%c] ofdm[%c] bss[%c]\n",
+		       pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
+		       pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
+		break;
+	default:
+		PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
+		break;
+	}
+
+	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief Retrieve a measurement report from the firmware
+ *
+ *  Callback from command processing when a measurement report is received
+ *    from the firmware.  Perform the following when a report is received:
+ *
+ *   -# Debug displays the report if compiled with the appropriate flags
+ *   -# If we are pending on a specific measurement report token, and it
+ *      matches the received report's token, store the report and wake up
+ *      any pending threads
+ *
+ *  @param pmpriv Private driver information structure
+ *  @param resp HostCmd_DS_COMMAND struct returned from the firmware command
+ *              passing a HostCmd_DS_MEASUREMENT_REPORT structure.
+ *
+ *  @return     MLAN_STATUS_SUCCESS
+ */
+static int
+wlan_meas_cmdresp_get_report(mlan_private *pmpriv,
+			     const HostCmd_DS_COMMAND *resp)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt = &resp->params.meas_rpt;
+
+	ENTER();
+
+	PRINTM(MINFO, "Meas: Rpt: %#x-%u, Seq=%u, Ret=%u\n", resp->command,
+	       resp->size, resp->seq_num, resp->result);
+
+	/* Debug displays the measurement report */
+	wlan_meas_dump_meas_rpt(pmeas_rpt);
+
+	/*
+	 * Check if we are pending on a measurement report and it matches
+	 *  the dialog token of the received report:
+	 */
+	if (pmadapter->state_meas.meas_rpt_pend_on &&
+	    pmadapter->state_meas.meas_rpt_pend_on == pmeas_rpt->dialog_token) {
+		PRINTM(MINFO, "Meas: Rpt: RCV'd Pend on meas #%d\n",
+		       pmadapter->state_meas.meas_rpt_pend_on);
+
+		/* Clear the pending report indicator */
+		pmadapter->state_meas.meas_rpt_pend_on = 0;
+
+		/* Copy the received report into the measurement state for
+		 * retrieval */
+		memcpy_ext(pmadapter, &pmadapter->state_meas.meas_rpt_returned,
+			   pmeas_rpt,
+			   sizeof(pmadapter->state_meas.meas_rpt_returned),
+			   sizeof(pmadapter->state_meas.meas_rpt_returned));
+
+		/*
+		 * Wake up any threads pending on the wait queue
+		 */
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
+	}
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Prepare CMD_MEASURMENT_REPORT firmware command
+ *
+ *  @param pmpriv     Private driver information structure
+ *  @param pcmd_ptr   Output parameter: Pointer to the command being prepared
+ *                    for the firmware
+ *  @param pinfo_buf  HostCmd_DS_MEASUREMENT_REQUEST passed as void data block
+ *
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static int
+wlan_meas_cmd_request(mlan_private *pmpriv,
+		      HostCmd_DS_COMMAND *pcmd_ptr, const void *pinfo_buf)
+{
+	const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req =
+		(HostCmd_DS_MEASUREMENT_REQUEST *)pinfo_buf;
+
+	ENTER();
+
+	pcmd_ptr->command = HostCmd_CMD_MEASUREMENT_REQUEST;
+	pcmd_ptr->size = sizeof(HostCmd_DS_MEASUREMENT_REQUEST) + S_DS_GEN;
+
+	memcpy_ext(pmpriv->adapter, &pcmd_ptr->params.meas_req, pmeas_req,
+		   sizeof(pcmd_ptr->params.meas_req),
+		   sizeof(pcmd_ptr->params.meas_req));
+
+	PRINTM(MINFO, "Meas: Req: %#x-%u, Seq=%u, Ret=%u\n", pcmd_ptr->command,
+	       pcmd_ptr->size, pcmd_ptr->seq_num, pcmd_ptr->result);
+
+	wlan_meas_dump_meas_req(pmeas_req);
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Retrieve a measurement report from the firmware
+ *
+ *  The firmware will send a EVENT_MEAS_REPORT_RDY event when it
+ *    completes or receives a measurement report.  The event response
+ *    handler will then start a HostCmd_CMD_MEASUREMENT_REPORT firmware command
+ *    which gets completed for transmission to the firmware in this routine.
+ *
+ *  @param pmpriv    Private driver information structure
+ *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
+ *                   for the firmware
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+static int
+wlan_meas_cmd_get_report(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd_ptr)
+{
+	ENTER();
+
+	pcmd_ptr->command = HostCmd_CMD_MEASUREMENT_REPORT;
+	pcmd_ptr->size = sizeof(HostCmd_DS_MEASUREMENT_REPORT) + S_DS_GEN;
+
+	memset(pmpriv->adapter, &pcmd_ptr->params.meas_rpt, 0x00,
+	       sizeof(pcmd_ptr->params.meas_rpt));
+
+	/*
+	 * Set the meas_rpt.mac_addr to our mac address to get a meas report,
+	 *   setting the mac to another STA address instructs the firmware
+	 *   to transmit this measurement report frame instead
+	 */
+	memcpy_ext(pmpriv->adapter, pcmd_ptr->params.meas_rpt.mac_addr,
+		   pmpriv->curr_addr,
+		   sizeof(pcmd_ptr->params.meas_rpt.mac_addr),
+		   sizeof(pcmd_ptr->params.meas_rpt.mac_addr));
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global functions
+********************************************************/
+
+/**
+ *  @brief Send the input measurement request to the firmware.
+ *
+ *  If the dialog token in the measurement request is set to 0, the function
+ *    will use an local static auto-incremented token in the measurement
+ *    request.  This ensures the dialog token is always set.
+ *
+ *  If wait_for_resp_timeout is set, the function will block its return on
+ *     a timeout or returned measurement report that matches the requests
+ *     dialog token.
+ *
+ *  @param pmpriv                  Private driver information structure
+ *  @param pmeas_req               Pointer to the measurement request to send
+ *  @param wait_for_resp_timeout   Timeout value of the measurement request
+ *                                 in ms.
+ *  @param pioctl_req              Pointer to IOCTL request buffer
+ *  @param pmeas_rpt               Output parameter: Pointer for the resulting
+ *                                 measurement report
+ *
+ *  @return
+ *    - 0 for success
+ *    - -ETIMEDOUT if the measurement report does not return before
+ *      the timeout expires
+ *    - Error return from wlan_prepare_cmd routine otherwise
+ */
+int
+wlan_meas_util_send_req(mlan_private *pmpriv,
+			HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req,
+			t_u32 wait_for_resp_timeout,
+			pmlan_ioctl_req pioctl_req,
+			HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
+{
+	static t_u8 auto_dialog_tok;
+	wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
+	int ret;
+
+	ENTER();
+
+	/* If dialogTok was set to 0 or not provided, autoset */
+	pmeas_req->dialog_token =
+		(pmeas_req->dialog_token ? pmeas_req->dialog_token :
+		 ++auto_dialog_tok);
+
+	/* Check for rollover of the dialog token.  Avoid using 0 as a token */
+	pmeas_req->dialog_token =
+		(pmeas_req->dialog_token ? pmeas_req->dialog_token : 1);
+
+	/*
+	 * If the request is to pend waiting for the result, set the dialog
+	 * token of this measurement request in the state structure.  The
+	 * measurement report handling routines can then check the incoming
+	 * measurement reports for a match with this dialog token.
+	 */
+	if (wait_for_resp_timeout) {
+		pmeas_state->meas_rpt_pend_on = pmeas_req->dialog_token;
+		PRINTM(MINFO, "Meas: Req: START Pend on meas #%d\n",
+		       pmeas_req->dialog_token);
+	}
+
+	/* Send the measurement request to the firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MEASUREMENT_REQUEST,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       (void *)pmeas_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Prepare the HostCmd_DS_Command structure for a measurement command.
+ *
+ *  Use the Command field to determine if the command being set up is for
+ *     11h and call one of the local command handlers accordingly for:
+ *
+ *        - HostCmd_CMD_MEASUREMENT_REQUEST
+ *        - HostCmd_CMD_MEASUREMENT_REPORT
+ *
+ *  @param pmpriv     Private driver information structure
+ *  @param pcmd_ptr   Output parameter: Pointer to the command being prepared
+ *                    for the firmware
+ *  @param pinfo_buf  Void buffer passthrough with data necessary for a
+ *                    specific command type
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+int
+wlan_meas_cmd_process(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd_ptr,
+		      const void *pinfo_buf)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	switch (pcmd_ptr->command) {
+	case HostCmd_CMD_MEASUREMENT_REQUEST:
+		ret = wlan_meas_cmd_request(pmpriv, pcmd_ptr, pinfo_buf);
+		break;
+	case HostCmd_CMD_MEASUREMENT_REPORT:
+		ret = wlan_meas_cmd_get_report(pmpriv, pcmd_ptr);
+		break;
+	default:
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	pcmd_ptr->command = wlan_cpu_to_le16(pcmd_ptr->command);
+	pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle the command response from the firmware for a measurement
+ *         command
+ *
+ *  Use the Command field to determine if the command response being
+ *    is for meas.  Call the local command response handler accordingly for:
+ *
+ *        - HostCmd_CMD_802_MEASUREMENT_REQUEST
+ *        - HostCmd_CMD_802_MEASUREMENT_REPORT
+ *
+ *  @param pmpriv Private driver information structure
+ *  @param resp   HostCmd_DS_COMMAND struct returned from the firmware command
+ *
+ *  @return     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+wlan_meas_cmdresp_process(mlan_private *pmpriv, const HostCmd_DS_COMMAND *resp)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	switch (resp->command) {
+	case HostCmd_CMD_MEASUREMENT_REQUEST:
+		PRINTM(MINFO, "Meas: Req Resp: Sz=%u, Seq=%u, Ret=%u\n",
+		       resp->size, resp->seq_num, resp->result);
+		break;
+	case HostCmd_CMD_MEASUREMENT_REPORT:
+		ret = wlan_meas_cmdresp_get_report(pmpriv, resp);
+		break;
+	default:
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_meas.h b/wlan_sd8987/mlan/mlan_meas.h
new file mode 100755
index 0000000..079cf3b
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_meas.h
@@ -0,0 +1,57 @@
+/**
+ *  @file mlan_meas.h
+ *
+ *  @brief Interface for the measurement module implemented in mlan_meas.c
+ *
+ *  Driver interface functions and type declarations for the measurement module
+ *    implemented in mlan_meas.c
+ *
+ *  @sa mlan_meas.c
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    03/25/2009: initial version
+************************************************************/
+
+#ifndef _MLAN_MEAS_H_
+#define _MLAN_MEAS_H_
+
+#include "mlan_fw.h"
+
+/* Send a given measurement request to the firmware, report back the result */
+extern int
+
+wlan_meas_util_send_req(pmlan_private pmpriv,
+			pHostCmd_DS_MEASUREMENT_REQUEST pmeas_req,
+			t_u32 wait_for_resp_timeout,
+			pmlan_ioctl_req pioctl_req,
+			pHostCmd_DS_MEASUREMENT_REPORT pmeas_rpt);
+
+/* Setup a measurement command before it is sent to the firmware */
+extern int wlan_meas_cmd_process(mlan_private *pmpriv,
+				 HostCmd_DS_COMMAND *pcmd_ptr,
+				 const t_void *pinfo_buf);
+
+/* Handle a given measurement command response from the firmware */
+extern int wlan_meas_cmdresp_process(mlan_private *pmpriv,
+				     const HostCmd_DS_COMMAND *resp);
+
+#endif /* _MLAN_MEAS_H_ */
diff --git a/wlan_sd8987/mlan/mlan_misc.c b/wlan_sd8987/mlan/mlan_misc.c
new file mode 100755
index 0000000..b377ce0
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_misc.c
@@ -0,0 +1,6772 @@
+/**
+ * @file mlan_misc.c
+ *
+ *  @brief This file include miscellaneous functions for MLAN module
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    05/11/2009: initial version
+************************************************************/
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif /* STA_SUPPORT */
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#if defined(PCIE) || defined(SDIO)
+/**
+ *  @brief Check pending irq
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return        MTRUE/MFALSE;
+ */
+static t_u8
+wlan_pending_interrupt(pmlan_adapter pmadapter)
+{
+	if (!IS_USB(pmadapter->card_type) && pmadapter->ireg)
+		return MTRUE;
+	return MFALSE;
+}
+#endif
+
+/** Custom IE auto index and mask */
+#define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff
+/** Custom IE mask for delete operation */
+#define MLAN_CUSTOM_IE_DELETE_MASK 0
+/** Custom IE mask for create new index */
+#define MLAN_CUSTOM_IE_NEW_MASK 0x8000
+/** Custom IE header size */
+#define MLAN_CUSTOM_IE_HDR_SIZE (sizeof(custom_ie) - MAX_IE_SIZE)
+
+/**
+ *  @brief Check if current custom IE index is used on other interfaces.
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *  @param idx		index to check for in use
+ *
+ *  @return		MLAN_STATUS_SUCCESS --unused, otherwise used.
+ */
+static mlan_status
+wlan_is_custom_ie_index_unused(pmlan_private pmpriv, t_u16 idx)
+{
+	t_u8 i = 0;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	pmlan_private priv;
+	ENTER();
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		priv = pmadapter->priv[i];
+		/* Check for other interfaces only */
+		if (priv && priv->bss_index != pmpriv->bss_index) {
+			if (priv->mgmt_ie[idx].mgmt_subtype_mask &&
+			    priv->mgmt_ie[idx].ie_length) {
+				/* used entry found */
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get the custom IE index
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *  @param mask	mask value for which the index to be returned
+ *  @param ie_data	a pointer to custom_ie structure
+ *  @param idx		will hold the computed index
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_custom_ioctl_get_autoidx(pmlan_private pmpriv,
+			      pmlan_ioctl_req pioctl_req,
+			      t_u16 mask, custom_ie *ie_data, t_u16 *idx)
+{
+	t_u16 index = 0, insert = MFALSE;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* Determine the index where the IE needs to be inserted */
+	while (!insert) {
+		while (index < MIN(pmpriv->adapter->max_mgmt_ie_index,
+				   MAX_MGMT_IE_INDEX)) {
+			if (pmpriv->mgmt_ie[index].mgmt_subtype_mask ==
+			    MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+				index++;
+				continue;
+			}
+			if (pmpriv->mgmt_ie[index].mgmt_subtype_mask == mask) {
+				/* Duplicate IE should be avoided */
+				if (pmpriv->mgmt_ie[index].ie_length) {
+					if (!memcmp(pmpriv->adapter,
+						    pmpriv->mgmt_ie[index]
+						    .ie_buffer,
+						    ie_data->ie_buffer,
+						    pmpriv->mgmt_ie[index]
+						    .ie_length)) {
+						PRINTM(MINFO,
+						       "IE with the same mask exists at index %d mask=0x%x\n",
+						       index, mask);
+						*idx = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+						goto done;
+					}
+				}
+				/* Check if enough space is available */
+				if (pmpriv->mgmt_ie[index].ie_length +
+				    ie_data->ie_length > MAX_IE_SIZE) {
+					index++;
+					continue;
+				}
+				insert = MTRUE;
+				break;
+			}
+			index++;
+		}
+		if (!insert) {
+			for (index = 0;
+			     index < MIN(pmpriv->adapter->max_mgmt_ie_index,
+					 MAX_MGMT_IE_INDEX); index++) {
+				if (pmpriv->mgmt_ie[index].ie_length == 0) {
+					/*
+					 * Check if this index is in use
+					 * by other interface If yes,
+					 * move ahead to next index
+					 */
+					if (MLAN_STATUS_SUCCESS ==
+					    wlan_is_custom_ie_index_unused
+					    (pmpriv, index)) {
+						insert = MTRUE;
+						break;
+					} else {
+						PRINTM(MINFO,
+						       "Skipping IE index %d in use.\n",
+						       index);
+					}
+				}
+			}
+		}
+		if (index == pmpriv->adapter->max_mgmt_ie_index && !insert) {
+			PRINTM(MERROR, "Failed to Set the IE buffer\n");
+			if (pioctl_req)
+				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	*idx = index;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Delete custom IE
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *  @param ie_data	a pointer to custom_ie structure
+ *  @param idx		index supplied
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+
+static mlan_status
+wlan_custom_ioctl_auto_delete(pmlan_private pmpriv,
+			      pmlan_ioctl_req pioctl_req,
+			      custom_ie *ie_data, t_u16 idx)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u16 index = 0, insert = MFALSE, del_len;
+	t_u8 del_ie[MAX_IE_SIZE], ie[MAX_IE_SIZE];
+	t_s32 cnt, tmp_len = 0;
+	t_u8 *tmp_ie;
+
+	ENTER();
+	memset(pmpriv->adapter, del_ie, 0, MAX_IE_SIZE);
+	memcpy_ext(pmpriv->adapter, del_ie, ie_data->ie_buffer,
+		   ie_data->ie_length, MAX_IE_SIZE);
+	del_len = MIN(MAX_IE_SIZE - 1, ie_data->ie_length);
+
+	if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
+		ie_data->ie_index = 0;
+
+	for (index = 0;
+	     index < MIN(pmadapter->max_mgmt_ie_index, MAX_MGMT_IE_INDEX);
+	     index++) {
+		if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx &&
+		    idx < MAX_MGMT_IE_INDEX)
+			index = idx;
+		tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
+		tmp_len = pmpriv->mgmt_ie[index].ie_length;
+		cnt = 0;
+		while (tmp_len) {
+			if (!memcmp(pmpriv->adapter, tmp_ie, del_ie, del_len)) {
+				memcpy_ext(pmpriv->adapter, ie,
+					   pmpriv->mgmt_ie[index].ie_buffer,
+					   cnt, MAX_IE_SIZE);
+				if (pmpriv->mgmt_ie[index].ie_length >
+				    (cnt + del_len))
+					memcpy_ext(pmpriv->adapter, &ie[cnt],
+						   &pmpriv->mgmt_ie[index].
+						   ie_buffer[MIN
+							     ((MAX_IE_SIZE - 1),
+							      (cnt + del_len))],
+						   (pmpriv->mgmt_ie[index]
+						    .ie_length - (cnt +
+								  del_len)),
+						   MAX_IE_SIZE - cnt);
+				memset(pmpriv->adapter,
+				       &pmpriv->mgmt_ie[index].ie_buffer, 0,
+				       sizeof(pmpriv->mgmt_ie[index].
+					      ie_buffer));
+				memcpy_ext(pmpriv->adapter,
+					   &pmpriv->mgmt_ie[index].ie_buffer,
+					   ie,
+					   pmpriv->mgmt_ie[index].ie_length -
+					   del_len, MAX_IE_SIZE);
+				pmpriv->mgmt_ie[index].ie_length -= del_len;
+				if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
+					/* set a bit to indicate caller about
+					 * update */
+					ie_data->ie_index |=
+						(((t_u16)1) << index);
+				insert = MTRUE;
+				tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
+				tmp_len = pmpriv->mgmt_ie[index].ie_length;
+				cnt = 0;
+				continue;
+			}
+			tmp_ie++;
+			tmp_len--;
+			cnt++;
+		}
+		if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
+			break;
+	}
+	if (index == pmadapter->max_mgmt_ie_index && !insert) {
+		PRINTM(MERROR, "Failed to Clear IE buffer\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief send host cmd
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_host_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
+			       (t_void *)&misc->param.hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Send function init/shutdown command to firmware
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_init_shutdown(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd;
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_INIT)
+		cmd = HostCmd_CMD_FUNC_INIT;
+	else if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_SHUTDOWN)
+		cmd = HostCmd_CMD_FUNC_SHUTDOWN;
+	else {
+		PRINTM(MERROR, "Unsupported parameter\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, cmd, HostCmd_ACT_GEN_SET, 0,
+			       (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get debug information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+mlan_status
+wlan_get_info_debug_info(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *info;
+	mlan_debug_info *debug_info = MNULL;
+	t_u32 i;
+	t_u8 *ptid;
+
+	ENTER();
+
+	info = (mlan_ds_get_info *)pioctl_req->pbuf;
+	debug_info = (mlan_debug_info *)info->param.debug_info;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		ptid = ac_to_tid[WMM_AC_BK];
+		debug_info->wmm_ac_bk = pmpriv->wmm.packets_out[ptid[0]] +
+			pmpriv->wmm.packets_out[ptid[1]];
+		ptid = ac_to_tid[WMM_AC_BE];
+		debug_info->wmm_ac_be = pmpriv->wmm.packets_out[ptid[0]] +
+			pmpriv->wmm.packets_out[ptid[1]];
+		ptid = ac_to_tid[WMM_AC_VI];
+		debug_info->wmm_ac_vi = pmpriv->wmm.packets_out[ptid[0]] +
+			pmpriv->wmm.packets_out[ptid[1]];
+		ptid = ac_to_tid[WMM_AC_VO];
+		debug_info->wmm_ac_vo = pmpriv->wmm.packets_out[ptid[0]] +
+			pmpriv->wmm.packets_out[ptid[1]];
+		debug_info->max_tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
+		debug_info->tx_buf_size = (t_u32)pmadapter->tx_buf_size;
+		debug_info->curr_tx_buf_size =
+			(t_u32)pmadapter->curr_tx_buf_size;
+		debug_info->rx_tbl_num =
+			wlan_get_rxreorder_tbl(pmpriv, debug_info->rx_tbl);
+		debug_info->tx_tbl_num =
+			wlan_get_txbastream_tbl(pmpriv, debug_info->tx_tbl);
+		debug_info->ralist_num =
+			wlan_get_ralist_info(pmpriv, debug_info->ralist);
+		debug_info->tdls_peer_num =
+			wlan_get_tdls_list(pmpriv, debug_info->tdls_peer_list);
+		debug_info->ps_mode = pmadapter->ps_mode;
+		debug_info->ps_state = pmadapter->ps_state;
+#ifdef STA_SUPPORT
+		debug_info->is_deep_sleep = pmadapter->is_deep_sleep;
+#endif /* STA_SUPPORT */
+		debug_info->pm_wakeup_card_req = pmadapter->pm_wakeup_card_req;
+		debug_info->pm_wakeup_fw_try = pmadapter->pm_wakeup_fw_try;
+		debug_info->pm_wakeup_in_secs = pmadapter->pm_wakeup_in_secs;
+		debug_info->pm_wakeup_timeout = pmadapter->pm_wakeup_timeout;
+		debug_info->is_hs_configured = pmadapter->is_hs_configured;
+		debug_info->hs_activated = pmadapter->hs_activated;
+		debug_info->pps_uapsd_mode = pmadapter->pps_uapsd_mode;
+		debug_info->sleep_pd = pmadapter->sleep_period.period;
+		debug_info->qos_cfg = pmpriv->wmm_qosinfo;
+		debug_info->tx_lock_flag = pmadapter->tx_lock_flag;
+		debug_info->port_open = pmpriv->port_open;
+		debug_info->bypass_pkt_count = pmadapter->bypass_pkt_count;
+		debug_info->scan_processing = pmadapter->scan_processing;
+		debug_info->mlan_processing = pmadapter->mlan_processing;
+		debug_info->main_lock_flag = pmadapter->main_lock_flag;
+		debug_info->main_process_cnt = pmadapter->main_process_cnt;
+		debug_info->delay_task_flag = pmadapter->delay_task_flag;
+		debug_info->num_cmd_host_to_card_failure =
+			pmadapter->dbg.num_cmd_host_to_card_failure;
+		debug_info->num_cmd_sleep_cfm_host_to_card_failure =
+			pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
+		debug_info->num_tx_host_to_card_failure =
+			pmadapter->dbg.num_tx_host_to_card_failure;
+		debug_info->num_alloc_buffer_failure =
+			pmadapter->dbg.num_alloc_buffer_failure;
+		debug_info->num_pkt_dropped = pmadapter->dbg.num_pkt_dropped;
+
+		debug_info->num_event_deauth = pmadapter->dbg.num_event_deauth;
+		debug_info->num_event_disassoc =
+			pmadapter->dbg.num_event_disassoc;
+		debug_info->num_event_link_lost =
+			pmadapter->dbg.num_event_link_lost;
+		debug_info->num_cmd_deauth = pmadapter->dbg.num_cmd_deauth;
+		debug_info->num_cmd_assoc_success =
+			pmadapter->dbg.num_cmd_assoc_success;
+		debug_info->num_cmd_assoc_failure =
+			pmadapter->dbg.num_cmd_assoc_failure;
+		debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
+		debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
+		debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
+		memcpy_ext(pmadapter, debug_info->last_cmd_id,
+			   pmadapter->dbg.last_cmd_id,
+			   sizeof(pmadapter->dbg.last_cmd_id),
+			   sizeof(debug_info->last_cmd_id));
+		memcpy_ext(pmadapter, debug_info->last_cmd_act,
+			   pmadapter->dbg.last_cmd_act,
+			   sizeof(pmadapter->dbg.last_cmd_act),
+			   sizeof(debug_info->last_cmd_act));
+		debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
+		memcpy_ext(pmadapter, debug_info->last_cmd_resp_id,
+			   pmadapter->dbg.last_cmd_resp_id,
+			   sizeof(pmadapter->dbg.last_cmd_resp_id),
+			   sizeof(debug_info->last_cmd_resp_id));
+		debug_info->last_cmd_resp_index =
+			pmadapter->dbg.last_cmd_resp_index;
+		memcpy_ext(pmadapter, debug_info->last_event,
+			   pmadapter->dbg.last_event,
+			   sizeof(pmadapter->dbg.last_event),
+			   sizeof(debug_info->last_event));
+		debug_info->last_event_index = pmadapter->dbg.last_event_index;
+		debug_info->num_no_cmd_node = pmadapter->dbg.num_no_cmd_node;
+		debug_info->pending_cmd =
+			(pmadapter->curr_cmd) ?
+			pmadapter->dbg.last_cmd_id
+			[pmadapter->dbg.last_cmd_index] : 0;
+		debug_info->dnld_cmd_in_secs = pmadapter->dnld_cmd_in_secs;
+#ifdef SDIO
+		if (IS_SD(pmadapter->card_type)) {
+			debug_info->num_cmdevt_card_to_host_failure =
+				pmadapter->dbg.num_cmdevt_card_to_host_failure;
+			debug_info->num_rx_card_to_host_failure =
+				pmadapter->dbg.num_rx_card_to_host_failure;
+			debug_info->num_int_read_failure =
+				pmadapter->dbg.num_int_read_failure;
+			debug_info->last_int_status =
+				pmadapter->dbg.last_int_status;
+			debug_info->mp_rd_bitmap =
+				pmadapter->pcard_sd->mp_rd_bitmap;
+			debug_info->mp_wr_bitmap =
+				pmadapter->pcard_sd->mp_wr_bitmap;
+			debug_info->curr_rd_port =
+				pmadapter->pcard_sd->curr_rd_port;
+			debug_info->curr_wr_port =
+				pmadapter->pcard_sd->curr_wr_port;
+			debug_info->mp_invalid_update =
+				pmadapter->pcard_sd->mp_invalid_update;
+			debug_info->num_of_irq =
+				pmadapter->pcard_sd->num_of_irq;
+			memcpy_ext(pmadapter, debug_info->mp_update,
+				   pmadapter->pcard_sd->mp_update,
+				   sizeof(pmadapter->pcard_sd->mp_update),
+				   sizeof(debug_info->mp_update));
+			memcpy_ext(pmadapter, debug_info->mpa_tx_count,
+				   pmadapter->pcard_sd->mpa_tx_count,
+				   sizeof(pmadapter->pcard_sd->mpa_tx_count),
+				   sizeof(debug_info->mpa_tx_count));
+			debug_info->mpa_sent_last_pkt =
+				pmadapter->pcard_sd->mpa_sent_last_pkt;
+			debug_info->mpa_sent_no_ports =
+				pmadapter->pcard_sd->mpa_sent_no_ports;
+			debug_info->last_recv_wr_bitmap =
+				pmadapter->pcard_sd->last_recv_wr_bitmap;
+			debug_info->last_recv_rd_bitmap =
+				pmadapter->pcard_sd->last_recv_rd_bitmap;
+			debug_info->mp_data_port_mask =
+				pmadapter->pcard_sd->mp_data_port_mask;
+			debug_info->last_mp_index =
+				pmadapter->pcard_sd->last_mp_index;
+			memcpy_ext(pmadapter, debug_info->last_mp_wr_bitmap,
+				   pmadapter->pcard_sd->last_mp_wr_bitmap,
+				   sizeof(pmadapter->pcard_sd->
+					  last_mp_wr_bitmap),
+				   sizeof(debug_info->last_mp_wr_bitmap));
+			memcpy_ext(pmadapter, debug_info->last_mp_wr_ports,
+				   pmadapter->pcard_sd->last_mp_wr_ports,
+				   sizeof(pmadapter->pcard_sd->
+					  last_mp_wr_ports),
+				   sizeof(debug_info->last_mp_wr_ports));
+			memcpy_ext(pmadapter, debug_info->last_mp_wr_len,
+				   pmadapter->pcard_sd->last_mp_wr_len,
+				   sizeof(pmadapter->pcard_sd->last_mp_wr_len),
+				   sizeof(debug_info->last_mp_wr_len));
+			memcpy_ext(pmadapter, debug_info->last_mp_wr_info,
+				   pmadapter->pcard_sd->last_mp_wr_info,
+				   sizeof(pmadapter->pcard_sd->last_mp_wr_info),
+				   sizeof(debug_info->last_mp_wr_info));
+			memcpy_ext(pmadapter, debug_info->last_curr_wr_port,
+				   pmadapter->pcard_sd->last_curr_wr_port,
+				   sizeof(pmadapter->pcard_sd->
+					  last_curr_wr_port),
+				   sizeof(debug_info->last_curr_wr_port));
+			debug_info->mpa_buf = pmadapter->pcard_sd->mpa_buf;
+			debug_info->mpa_buf_size =
+				pmadapter->pcard_sd->mpa_buf_size;
+			debug_info->sdio_rx_aggr =
+				pmadapter->pcard_sd->sdio_rx_aggr_enable;
+			memcpy_ext(pmadapter, debug_info->mpa_rx_count,
+				   pmadapter->pcard_sd->mpa_rx_count,
+				   sizeof(pmadapter->pcard_sd->mpa_rx_count),
+				   sizeof(debug_info->mpa_rx_count));
+			debug_info->mp_aggr_pkt_limit =
+				pmadapter->pcard_sd->mp_aggr_pkt_limit;
+		}
+#endif
+#ifdef PCIE
+		if (IS_PCIE(pmadapter->card_type)) {
+			debug_info->txbd_rdptr =
+				pmadapter->pcard_pcie->txbd_rdptr;
+			debug_info->txbd_wrptr =
+				pmadapter->pcard_pcie->txbd_wrptr;
+			debug_info->rxbd_rdptr =
+				pmadapter->pcard_pcie->rxbd_rdptr;
+			debug_info->rxbd_wrptr =
+				pmadapter->pcard_pcie->rxbd_wrptr;
+			debug_info->eventbd_rdptr =
+				pmadapter->pcard_pcie->evtbd_rdptr;
+			debug_info->eventbd_wrptr =
+				pmadapter->pcard_pcie->evtbd_wrptr;
+			debug_info->txbd_ring_vbase =
+				pmadapter->pcard_pcie->txbd_ring_vbase;
+			debug_info->txbd_ring_size =
+				pmadapter->pcard_pcie->txbd_ring_size;
+			debug_info->rxbd_ring_vbase =
+				pmadapter->pcard_pcie->rxbd_ring_vbase;
+			debug_info->rxbd_ring_size =
+				pmadapter->pcard_pcie->rxbd_ring_size;
+			debug_info->evtbd_ring_vbase =
+				pmadapter->pcard_pcie->evtbd_ring_vbase;
+			debug_info->evtbd_ring_size =
+				pmadapter->pcard_pcie->evtbd_ring_size;
+			debug_info->txrx_bd_size =
+				pmadapter->pcard_pcie->txrx_bd_size;
+		}
+#endif
+		debug_info->data_sent = pmadapter->data_sent;
+		debug_info->data_sent_cnt = pmadapter->data_sent_cnt;
+		debug_info->cmd_sent = pmadapter->cmd_sent;
+		debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
+		debug_info->tx_pkts_queued =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmpriv->wmm.tx_pkts_queued, MNULL,
+					 MNULL);
+#ifdef UAP_SUPPORT
+		debug_info->num_bridge_pkts =
+			util_scalar_read(pmadapter->pmoal_handle,
+					 &pmadapter->pending_bridge_pkts,
+					 pmadapter->callbacks.moal_spin_lock,
+					 pmadapter->callbacks.moal_spin_unlock);
+		debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
+#endif
+		debug_info->fw_hang_report = pmadapter->fw_hang_report;
+		debug_info->mlan_processing = pmadapter->mlan_processing;
+		debug_info->mlan_rx_processing = pmadapter->mlan_rx_processing;
+		debug_info->rx_pkts_queued = pmadapter->rx_pkts_queued;
+		debug_info->mlan_adapter = pmadapter;
+		debug_info->mlan_adapter_size = sizeof(mlan_adapter);
+		debug_info->mlan_priv_num = pmadapter->priv_num;
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			debug_info->mlan_priv[i] = pmadapter->priv[i];
+			debug_info->mlan_priv_size[i] = sizeof(mlan_private);
+		}
+	}
+
+	pioctl_req->data_read_written =
+		sizeof(mlan_debug_info) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the MAC control configuration.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_mac_control(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		misc->param.mac_ctrl = pmpriv->curr_pkt_filter;
+	} else {
+		pmpriv->curr_pkt_filter = misc->param.mac_ctrl;
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+		/* Send command to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &misc->param.mac_ctrl);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This timer function handles wakeup card timeout.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return        N/A
+ */
+t_void
+wlan_wakeup_card_timeout_func(void *function_context)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)function_context;
+	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+
+	ENTER();
+
+	PRINTM(MERROR, "%s: ps_state=%d\n", __FUNCTION__, pmadapter->ps_state);
+	if (pmadapter->ps_state != PS_STATE_AWAKE) {
+		PRINTM_NETINTF(MERROR, pmpriv);
+		PRINTM(MERROR, "Wakeup card timeout!\n");
+		pmadapter->pm_wakeup_timeout++;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+	}
+	pmadapter->wakeup_fw_timer_is_set = MFALSE;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set/Get HS configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status
+wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pm = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u32 prev_cond = 0;
+
+	ENTER();
+
+	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+	switch (pioctl_req->action) {
+	case MLAN_ACT_SET:
+#ifdef STA_SUPPORT
+		if (pmadapter->pps_uapsd_mode) {
+			PRINTM(MINFO,
+			       "Host Sleep IOCTL is blocked in UAPSD/PPS mode\n");
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			status = MLAN_STATUS_FAILURE;
+			break;
+		}
+#endif /* STA_SUPPORT */
+		if (pm->param.hs_cfg.is_invoke_hostcmd == MTRUE) {
+			if (pm->param.hs_cfg.conditions ==
+			    HOST_SLEEP_CFG_CANCEL) {
+				if (pmadapter->is_hs_configured == MFALSE) {
+					/* Already cancelled */
+					break;
+				}
+				/* Save previous condition */
+				prev_cond = pmadapter->hs_cfg.conditions;
+				pmadapter->hs_cfg.conditions =
+					pm->param.hs_cfg.conditions;
+			} else if (pmadapter->hs_cfg.conditions ==
+				   HOST_SLEEP_CFG_CANCEL) {
+				/* Return failure if no parameters for HS enable
+				 */
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				status = MLAN_STATUS_FAILURE;
+				break;
+			}
+			status = wlan_prepare_cmd(pmpriv,
+						  HostCmd_CMD_802_11_HS_CFG_ENH,
+						  HostCmd_ACT_GEN_SET, 0,
+						  (t_void *)pioctl_req,
+						  (t_void *)(&pmadapter->
+							     hs_cfg));
+			if (status == MLAN_STATUS_SUCCESS)
+				status = MLAN_STATUS_PENDING;
+			if (pm->param.hs_cfg.conditions ==
+			    HOST_SLEEP_CFG_CANCEL) {
+				/* Restore previous condition */
+				pmadapter->hs_cfg.conditions = prev_cond;
+			}
+		} else {
+			pmadapter->hs_cfg.conditions =
+				pm->param.hs_cfg.conditions;
+			pmadapter->hs_cfg.gpio = (t_u8)pm->param.hs_cfg.gpio;
+			pmadapter->hs_cfg.gap = (t_u8)pm->param.hs_cfg.gap;
+			pmadapter->param_type_ind =
+				(t_u8)pm->param.hs_cfg.param_type_ind;
+			pmadapter->ind_gpio = (t_u8)pm->param.hs_cfg.ind_gpio;
+			pmadapter->level = (t_u8)pm->param.hs_cfg.level;
+			pmadapter->param_type_ext =
+				(t_u8)pm->param.hs_cfg.param_type_ext;
+			pmadapter->event_force_ignore =
+				pm->param.hs_cfg.event_force_ignore;
+			pmadapter->event_use_ext_gap =
+				pm->param.hs_cfg.event_use_ext_gap;
+			pmadapter->ext_gap = pm->param.hs_cfg.ext_gap;
+			pmadapter->gpio_wave = pm->param.hs_cfg.gpio_wave;
+			pmadapter->hs_wake_interval =
+				pm->param.hs_cfg.hs_wake_interval;
+		}
+		break;
+	case MLAN_ACT_GET:
+		pm->param.hs_cfg.conditions = pmadapter->hs_cfg.conditions;
+		pm->param.hs_cfg.gpio = pmadapter->hs_cfg.gpio;
+		pm->param.hs_cfg.gap = pmadapter->hs_cfg.gap;
+		pm->param.hs_cfg.param_type_ind = pmadapter->param_type_ind;
+		pm->param.hs_cfg.ind_gpio = pmadapter->ind_gpio;
+		pm->param.hs_cfg.level = pmadapter->level;
+		pm->param.hs_cfg.param_type_ext = pmadapter->param_type_ext;
+		pm->param.hs_cfg.event_force_ignore =
+			pmadapter->event_force_ignore;
+		pm->param.hs_cfg.event_use_ext_gap =
+			pmadapter->event_use_ext_gap;
+		pm->param.hs_cfg.ext_gap = pmadapter->ext_gap;
+		pm->param.hs_cfg.gpio_wave = pmadapter->gpio_wave;
+		pm->param.hs_cfg.hs_wake_interval = pmadapter->hs_wake_interval;
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set Robustcoex gpiocfg
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status
+wlan_misc_robustcoex(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action;
+	mlan_ds_misc_cfg *robust_coex_cfg =
+		(mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ROBUSTCOEX,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &robust_coex_cfg->param.robustcoexparams);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get DMCS config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_dmcs_config(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action;
+	mlan_ds_misc_cfg *dmcs_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DMCS_CONFIG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       &dmcs_cfg->param.dmcs_policy);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+#if defined(PCIE)
+/**
+ *  @brief Enable SSU support
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status
+wlan_misc_ssu(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = HostCmd_ACT_GEN_GET;
+	mlan_ds_misc_cfg *ssu_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_DEFAULT)
+		cmd_action = HostCmd_ACT_GEN_SET_DEFAULT;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SSU, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       &ssu_cfg->param.ssu_params);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set the hal/phy cfg params.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status
+wlan_misc_hal_phy_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *hal_phy_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	t_u16 cmd_act;
+
+	ENTER();
+
+	cmd_act = HostCmd_ACT_GEN_SET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_HAL_PHY_CFG, cmd_act, 0,
+			       (t_void *)pioctl_req,
+			       &hal_phy_cfg->param.hal_phy_cfg_params);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function allocates a mlan_buffer.
+ *
+ *  @param pmadapter Pointer to mlan_adapter
+ *  @param data_len   Data length
+ *  @param head_room  head_room reserved in mlan_buffer
+ *  @param malloc_flag  flag to user moal_malloc
+ *  @return           mlan_buffer pointer or MNULL
+ */
+pmlan_buffer
+wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len,
+		       t_u32 head_room, t_u32 malloc_flag)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_buffer pmbuf = MNULL;
+	t_u32 buf_size = 0;
+	t_u8 *tmp_buf = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+#ifdef SDIO
+	/* make sure that the data length is at least SDIO block size */
+	if (IS_SD(pmadapter->card_type))
+		data_len = (data_len + MLAN_SDIO_BLOCK_SIZE - 1) /
+			MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
+#endif
+
+	/* head_room is not implemented for malloc mlan buffer */
+
+	switch (malloc_flag) {
+	case MOAL_MALLOC_BUFFER:
+		buf_size = sizeof(mlan_buffer) + data_len + DMA_ALIGNMENT;
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
+				       MLAN_MEM_DEF | MLAN_MEM_DMA,
+				       (t_u8 **)&pmbuf);
+		if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
+			pmbuf = MNULL;
+			goto exit;
+		}
+		memset(pmadapter, pmbuf, 0, sizeof(mlan_buffer));
+
+		pmbuf->pdesc = MNULL;
+		/* Align address */
+		pmbuf->pbuf = (t_u8 *)ALIGN_ADDR((t_u8 *)pmbuf +
+						 sizeof(mlan_buffer),
+						 DMA_ALIGNMENT);
+		pmbuf->data_offset = 0;
+		pmbuf->data_len = data_len;
+		pmbuf->flags |= MLAN_BUF_FLAG_MALLOC_BUF;
+		break;
+
+	case MOAL_ALLOC_MLAN_BUFFER:
+		/* use moal_alloc_mlan_buffer, head_room supported */
+		ret = pcb->moal_alloc_mlan_buffer(pmadapter->pmoal_handle,
+						  data_len + DMA_ALIGNMENT +
+						  head_room, &pmbuf);
+		if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
+			PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n");
+			goto exit;
+		}
+		pmbuf->data_offset = head_room;
+		tmp_buf = (t_u8 *)ALIGN_ADDR(pmbuf->pbuf + pmbuf->data_offset,
+					     DMA_ALIGNMENT);
+		pmbuf->data_offset +=
+			(t_u32)(tmp_buf - (pmbuf->pbuf + pmbuf->data_offset));
+		pmbuf->data_len = data_len;
+		pmbuf->flags = 0;
+		break;
+	}
+
+exit:
+	LEAVE();
+	return pmbuf;
+}
+
+/**
+ *  @brief This function frees a mlan_buffer.
+ *
+ *  @param pmadapter  Pointer to mlan_adapter
+ *  @param pmbuf      Pointer to mlan_buffer
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+
+	if (pcb && pmbuf) {
+		if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF)
+			util_scalar_decrement(pmadapter->pmoal_handle,
+					      &pmadapter->pending_bridge_pkts,
+					      pmadapter->callbacks.
+					      moal_spin_lock,
+					      pmadapter->callbacks.
+					      moal_spin_unlock);
+		if (pmbuf->flags & MLAN_BUF_FLAG_MALLOC_BUF)
+			pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmbuf);
+		else
+			pcb->moal_free_mlan_buffer(pmadapter->pmoal_handle,
+						   pmbuf);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Delay function implementation
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param delay            Delay value
+ *  @param u                Units of delay (sec, msec or usec)
+ *
+ *  @return                 N/A
+ */
+t_void
+wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u)
+{
+	t_u32 now_tv_sec, now_tv_usec;
+	t_u32 upto_tv_sec, upto_tv_usec;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pcb->moal_udelay) {
+		if (u == SEC)
+			delay *= 1000000;
+		else if (u == MSEC)
+			delay *= 1000;
+		pcb->moal_udelay(pmadapter->pmoal_handle, delay);
+	} else {
+		pcb->moal_get_system_time(pmadapter->pmoal_handle, &upto_tv_sec,
+					  &upto_tv_usec);
+
+		switch (u) {
+		case SEC:
+			upto_tv_sec += delay;
+			break;
+		case MSEC:
+			delay *= 1000;
+			/* fall through */
+		case USEC:
+			upto_tv_sec += (delay / 1000000);
+			upto_tv_usec += (delay % 1000000);
+			break;
+		}
+
+		do {
+			pcb->moal_get_system_time(pmadapter->pmoal_handle,
+						  &now_tv_sec, &now_tv_usec);
+			if (now_tv_sec > upto_tv_sec) {
+				LEAVE();
+				return;
+			}
+
+			if ((now_tv_sec == upto_tv_sec) &&
+			    (now_tv_usec >= upto_tv_usec)) {
+				LEAVE();
+				return;
+			}
+		} while (MTRUE);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief BSS remove
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_bss_ioctl_bss_remove(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	ENTER();
+	wlan_cancel_bss_pending_cmd(pmadapter, pioctl_req->bss_index);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/**
+ *  @brief Set/Get BSS role
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_bss_ioctl_bss_role(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_VERSION_EXT dummy;
+#ifdef USB
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pmlan_buffer pmbuf;
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+	t_u8 bss_mode;
+#endif
+	t_u8 i, global_band = 0;
+	int j;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		bss->param.bss_role = GET_BSS_ROLE(pmpriv);
+	} else {
+		if (GET_BSS_ROLE(pmpriv) == bss->param.bss_role) {
+			PRINTM(MIOCTL, "BSS ie already in the desired role!\n");
+			goto done;
+		}
+		mlan_block_rx_process(pmadapter, MTRUE);
+		/** Switch BSS role */
+		wlan_free_priv(pmpriv);
+
+#ifdef USB
+		if (IS_USB(pmadapter->card_type)) {
+			while ((pmbuf =
+				(pmlan_buffer)util_dequeue_list(pmadapter->
+								pmoal_handle,
+								&pmadapter->
+								rx_data_queue,
+								pcb->
+								moal_spin_lock,
+								pcb->
+								moal_spin_unlock)))
+			{
+				pcb->moal_recv_complete(pmadapter->pmoal_handle,
+							pmbuf,
+							pmadapter->rx_data_ep,
+							MLAN_STATUS_FAILURE);
+			}
+		}
+#endif
+		pmpriv->bss_role = bss->param.bss_role;
+		if (pmpriv->bss_type == MLAN_BSS_TYPE_UAP)
+			pmpriv->bss_type = MLAN_BSS_TYPE_STA;
+		else if (pmpriv->bss_type == MLAN_BSS_TYPE_STA)
+			pmpriv->bss_type = MLAN_BSS_TYPE_UAP;
+		/* Initialize private structures */
+		wlan_init_priv(pmpriv);
+		mlan_block_rx_process(pmadapter, MFALSE);
+		/* Initialize function table */
+		for (j = 0; mlan_ops[j]; j++) {
+			if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmpriv)) {
+				memcpy_ext(pmadapter, &pmpriv->ops, mlan_ops[j],
+					   sizeof(mlan_operations),
+					   sizeof(mlan_operations));
+			}
+		}
+
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i] &&
+			    GET_BSS_ROLE(pmadapter->priv[i]) ==
+			    MLAN_BSS_ROLE_STA)
+				global_band |= pmadapter->priv[i]->config_bands;
+		}
+
+		if (global_band != pmadapter->config_bands) {
+			if (wlan_set_regiontable
+			    (pmpriv, (t_u8)pmadapter->region_code,
+			     global_band | pmadapter->adhoc_start_band)) {
+				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+
+			if (wlan_11d_set_universaltable(pmpriv,
+							global_band |
+							pmadapter->
+							adhoc_start_band)) {
+				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+			pmadapter->config_bands = global_band;
+		}
+
+		/* Issue commands to initialize firmware */
+#if defined(WIFI_DIRECT_SUPPORT)
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+			bss_mode = BSS_MODE_WIFIDIRECT_CLIENT;
+		else
+			bss_mode = BSS_MODE_WIFIDIRECT_GO;
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       &bss_mode);
+		if (ret)
+			goto done;
+#endif
+		ret = pmpriv->ops.init_cmd(pmpriv, MFALSE);
+		if (ret == MLAN_STATUS_FAILURE)
+			goto done;
+
+		/* Issue dummy Get command to complete the ioctl */
+		memset(pmadapter, &dummy, 0, sizeof(HostCmd_DS_VERSION_EXT));
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
+				       HostCmd_ACT_GEN_GET, 0,
+				       (t_void *)pioctl_req, (t_void *)&dummy);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set the custom IE
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *  @param send_ioctl	Flag to indicate if ioctl should be sent with cmd
+ *                      (MTRUE if from moal/user, MFALSE if internal)
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req, t_bool send_ioctl)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	custom_ie *ie_data = MNULL;
+	t_u16 cmd_action = 0, index, mask, i, len, app_data_len;
+	t_s32 ioctl_len;
+	t_u8 *tmp_ie;
+
+	ENTER();
+
+	if ((misc->param.cust_ie.len == 0) ||
+	    (misc->param.cust_ie.len == sizeof(t_u16))) {
+		pioctl_req->action = MLAN_ACT_GET;
+		/* Get the IE */
+		cmd_action = HostCmd_ACT_GEN_GET;
+	} else {
+		/* ioctl_len : ioctl length from application, start with
+		 * misc->param.cust_ie.len and reach upto 0 */
+		ioctl_len = misc->param.cust_ie.len;
+
+		/* app_data_len : length from application, start with 0
+		 * and reach upto ioctl_len */
+		app_data_len = sizeof(MrvlIEtypesHeader_t);
+		misc->param.cust_ie.len = 0;
+
+		while (ioctl_len > 0) {
+			ie_data = (custom_ie *)(((t_u8 *)&misc->param.cust_ie) +
+						app_data_len);
+			ioctl_len -=
+				(ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
+			app_data_len +=
+				(ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
+
+			index = ie_data->ie_index;
+			mask = ie_data->mgmt_subtype_mask;
+
+			/* Need to be Autohandled */
+			if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == index) {
+				/* Automatic Deletion */
+				if (mask == MLAN_CUSTOM_IE_DELETE_MASK) {
+					ret = wlan_custom_ioctl_auto_delete
+						(pmpriv, pioctl_req, ie_data,
+						 index);
+					/* if IE to delete is not found, return
+					 * error */
+					if (ret == MLAN_STATUS_FAILURE)
+						goto done;
+					index = ie_data->ie_index;
+					memset(pmadapter, ie_data, 0,
+					       sizeof(custom_ie) *
+					       MAX_MGMT_IE_INDEX_TO_FW);
+					len = 0;
+					for (i = 0;
+					     i < pmadapter->max_mgmt_ie_index;
+					     i++) {
+						/* Check if index is updated
+						 * before sending to FW */
+						if (index & ((t_u16)1) << i) {
+							memcpy_ext(pmadapter,
+								   (t_u8 *)
+								   ie_data +
+								   len, &i,
+								   sizeof
+								   (ie_data->
+								    ie_index),
+								   sizeof
+								   (ie_data->
+								    ie_index));
+							len += sizeof(ie_data->
+								      ie_index);
+							memcpy_ext(pmadapter,
+								   (t_u8 *)
+								   ie_data +
+								   len,
+								   &pmpriv->
+								   mgmt_ie[i]
+								   .
+								   mgmt_subtype_mask,
+								   sizeof
+								   (ie_data->
+								    mgmt_subtype_mask),
+								   sizeof
+								   (ie_data->
+								    mgmt_subtype_mask));
+							len += sizeof(ie_data->
+								      mgmt_subtype_mask);
+							memcpy_ext(pmadapter,
+								   (t_u8 *)
+								   ie_data +
+								   len,
+								   &pmpriv->
+								   mgmt_ie[i]
+								   .ie_length,
+								   sizeof
+								   (ie_data->
+								    ie_length),
+								   sizeof
+								   (ie_data->
+								    ie_length));
+							len += sizeof(ie_data->
+								      ie_length);
+							if (pmpriv->mgmt_ie[i]
+							    .ie_length) {
+								memcpy_ext
+									(pmadapter,
+									 (t_u8
+									  *)
+									 ie_data
+									 + len,
+									 &pmpriv->
+									 mgmt_ie
+									 [i]
+									 .
+									 ie_buffer,
+									 pmpriv->
+									 mgmt_ie
+									 [i]
+									 .
+									 ie_length,
+									 pmpriv->
+									 mgmt_ie
+									 [i]
+									 .
+									 ie_length);
+								len += pmpriv->
+									mgmt_ie
+									[i]
+									.
+									ie_length;
+							}
+						}
+					}
+					misc->param.cust_ie.len += len;
+					pioctl_req->action = MLAN_ACT_SET;
+					cmd_action = HostCmd_ACT_GEN_SET;
+				} else {	/* Automatic Addition */
+					if (MLAN_STATUS_FAILURE ==
+					    wlan_custom_ioctl_get_autoidx
+					    (pmpriv, pioctl_req, mask, ie_data,
+					     &index)) {
+						PRINTM(MERROR,
+						       "Failed to Set the IE buffer\n");
+						ret = MLAN_STATUS_FAILURE;
+						goto done;
+					}
+					mask &= ~MLAN_CUSTOM_IE_NEW_MASK;
+					if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
+					    index ||
+					    index >= MAX_MGMT_IE_INDEX) {
+						ret = MLAN_STATUS_SUCCESS;
+						goto done;
+					}
+					tmp_ie = (t_u8 *)&pmpriv->mgmt_ie[index]
+						.ie_buffer;
+					memcpy_ext(pmadapter,
+						   tmp_ie +
+						   pmpriv->mgmt_ie[index]
+						   .ie_length,
+						   &ie_data->ie_buffer,
+						   ie_data->ie_length,
+						   ie_data->ie_length);
+					pmpriv->mgmt_ie[index].ie_length +=
+						ie_data->ie_length;
+					pmpriv->mgmt_ie[index].ie_index = index;
+					pmpriv->mgmt_ie[index]
+						.mgmt_subtype_mask = mask;
+
+					pioctl_req->action = MLAN_ACT_SET;
+					cmd_action = HostCmd_ACT_GEN_SET;
+					ie_data->ie_index = index;
+					ie_data->ie_length =
+						pmpriv->mgmt_ie[index].
+						ie_length;
+					memcpy_ext(pmadapter,
+						   &ie_data->ie_buffer,
+						   &pmpriv->mgmt_ie[index]
+						   .ie_buffer,
+						   pmpriv->mgmt_ie[index].
+						   ie_length, MAX_IE_SIZE);
+					misc->param.cust_ie.len +=
+						pmpriv->mgmt_ie[index]
+						.ie_length +
+						MLAN_CUSTOM_IE_HDR_SIZE;
+				}
+			} else {
+				if (index >= pmadapter->max_mgmt_ie_index ||
+				    index >= MAX_MGMT_IE_INDEX) {
+					PRINTM(MERROR,
+					       "Invalid custom IE index %d\n",
+					       index);
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+				/* Set/Clear the IE and save it */
+				if (ie_data->mgmt_subtype_mask ==
+				    MLAN_CUSTOM_IE_DELETE_MASK &&
+				    ie_data->ie_length) {
+					PRINTM(MINFO, "Clear the IE buffer\n");
+					ret = wlan_custom_ioctl_auto_delete
+						(pmpriv, pioctl_req, ie_data,
+						 index);
+					/* if IE to delete is not found, return
+					 * error */
+					if (ret == MLAN_STATUS_FAILURE)
+						goto done;
+					memset(pmadapter, ie_data, 0,
+					       sizeof(custom_ie) *
+					       MAX_MGMT_IE_INDEX_TO_FW);
+					memcpy_ext(pmadapter, (t_u8 *)ie_data,
+						   &pmpriv->mgmt_ie[index],
+						   pmpriv->mgmt_ie[index].
+						   ie_length +
+						   MLAN_CUSTOM_IE_HDR_SIZE,
+						   pmpriv->mgmt_ie[index].
+						   ie_length +
+						   MLAN_CUSTOM_IE_HDR_SIZE);
+				} else {
+					/*
+					 * Check if this index is being used on
+					 * any other interfaces. If yes, then
+					 * the request needs to be rejected.
+					 */
+					ret = wlan_is_custom_ie_index_unused
+						(pmpriv, index);
+					if (ret == MLAN_STATUS_FAILURE) {
+						PRINTM(MERROR,
+						       "IE index is used by other interface.\n");
+						PRINTM(MERROR,
+						       "Set or delete on index %d is not allowed.\n",
+						       index);
+						pioctl_req->status_code =
+							MLAN_ERROR_IOCTL_FAIL;
+						goto done;
+					}
+					PRINTM(MINFO, "Set the IE buffer\n");
+					if (ie_data->mgmt_subtype_mask ==
+					    MLAN_CUSTOM_IE_DELETE_MASK)
+						ie_data->ie_length = 0;
+					else {
+						if ((pmpriv->mgmt_ie[index]
+						     .mgmt_subtype_mask ==
+						     ie_data->mgmt_subtype_mask)
+						    && (pmpriv->mgmt_ie[index]
+							.ie_length ==
+							ie_data->ie_length) &&
+						    !memcmp(pmpriv->adapter,
+							    pmpriv->
+							    mgmt_ie[index]
+							    .ie_buffer,
+							    ie_data->ie_buffer,
+							    ie_data->
+							    ie_length)) {
+							PRINTM(MIOCTL,
+							       "same custom ie already configured!\n");
+							if (ioctl_len <= 0 &&
+							    misc->param.cust_ie.
+							    len == 0) {
+								goto done;
+							} else {
+								/* remove
+								 * matching IE
+								 * from app
+								 * buffer */
+								app_data_len -=
+									ie_data->
+									ie_length
+									+
+									MLAN_CUSTOM_IE_HDR_SIZE;
+								memmove(pmadapter, (t_u8 *)ie_data, ie_data->ie_buffer + ie_data->ie_length, ioctl_len);
+								continue;
+							}
+						}
+					}
+					memset(pmadapter,
+					       &pmpriv->mgmt_ie[index], 0,
+					       sizeof(custom_ie));
+					memcpy_ext(pmadapter,
+						   &pmpriv->mgmt_ie[index],
+						   ie_data, sizeof(custom_ie),
+						   sizeof(custom_ie));
+				}
+
+				misc->param.cust_ie.len +=
+					pmpriv->mgmt_ie[index].ie_length +
+					MLAN_CUSTOM_IE_HDR_SIZE;
+				pioctl_req->action = MLAN_ACT_SET;
+				cmd_action = HostCmd_ACT_GEN_SET;
+			}
+		}
+	}
+
+	/* Send command to firmware */
+	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MGMT_IE_LIST,
+				       cmd_action, 0,
+				       (send_ioctl) ? (t_void *)pioctl_req :
+				       MNULL, &misc->param.cust_ie);
+	}
+#ifdef UAP_SUPPORT
+	else if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+		ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+				       cmd_action, 0,
+				       (send_ioctl) ? (t_void *)pioctl_req :
+				       MNULL,
+				       (send_ioctl) ? MNULL : &misc->param.
+				       cust_ie);
+	}
+#endif
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read/write adapter register
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0, cmd_no;
+
+	ENTER();
+
+	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	switch (reg_mem->param.reg_rw.type) {
+	case MLAN_REG_MAC:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	case MLAN_REG_MAC2:
+#endif
+		cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
+		break;
+	case MLAN_REG_BBP:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	case MLAN_REG_BBP2:
+#endif
+		cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
+		break;
+	case MLAN_REG_RF:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	case MLAN_REG_RF2:
+#endif
+		cmd_no = HostCmd_CMD_RF_REG_ACCESS;
+		break;
+	case MLAN_REG_CAU:
+		cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
+		break;
+	case MLAN_REG_PSU:
+		cmd_no = HostCmd_CMD_TARGET_ACCESS;
+		break;
+	case MLAN_REG_BCA:
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	case MLAN_REG_BCA2:
+#endif
+		cmd_no = HostCmd_CMD_BCA_REG_ACCESS;
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, cmd_no, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&reg_mem->param.reg_rw);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read the EEPROM contents of the card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_reg_mem_ioctl_read_eeprom(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_EEPROM_ACCESS,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       (t_void *)&reg_mem->param.rd_eeprom);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read/write memory of device
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_reg_mem_ioctl_mem_rw(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&reg_mem->param.mem_rw);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will check if station list is empty
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   MFALSE/MTRUE
+ */
+t_u8
+wlan_is_station_list_empty(mlan_private *priv)
+{
+	ENTER();
+	if (!(util_peek_list(priv->adapter->pmoal_handle, &priv->sta_list,
+			     priv->adapter->callbacks.moal_spin_lock,
+			     priv->adapter->callbacks.moal_spin_unlock))) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station
+ * list table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+sta_node *
+wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr;
+
+	ENTER();
+
+	if (!mac) {
+		LEAVE();
+		return MNULL;
+	}
+	sta_ptr =
+		(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					   &priv->sta_list, MNULL, MNULL);
+
+	while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
+		if (!memcmp(priv->adapter, sta_ptr->mac_addr, mac,
+			    MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return sta_ptr;
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function will add a pointer to station entry in station list
+ *          table with the give mac address, if it does not exist already
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+sta_node *
+wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+
+	ENTER();
+
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr)
+		goto done;
+	if (priv->adapter->callbacks.moal_malloc(priv->adapter->pmoal_handle,
+						 sizeof(sta_node), MLAN_MEM_DEF,
+						 (t_u8 **)&sta_ptr)) {
+		PRINTM(MERROR, "Failed to allocate memory for station node\n");
+		LEAVE();
+		return MNULL;
+	}
+	memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
+	memcpy_ext(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+	util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
+			       (pmlan_linked_list)sta_ptr,
+			       priv->adapter->callbacks.moal_spin_lock,
+			       priv->adapter->callbacks.moal_spin_unlock);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+	    IsAuthenticatorEnabled(priv->psapriv))
+		authenticator_init_client(priv->psapriv,
+					  &sta_ptr->cm_connectioninfo, mac);
+#endif
+done:
+	LEAVE();
+	return sta_ptr;
+}
+
+/**
+ *  @brief This function will delete a station entry from station list
+ *
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     station's mac address
+ *
+ *  @return	   N/A
+ */
+t_void
+wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
+{
+	sta_node *sta_ptr = MNULL;
+	ENTER();
+	sta_ptr = wlan_get_station_entry(priv, mac);
+	if (sta_ptr) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+		    IsAuthenticatorEnabled(priv->psapriv))
+			authenticator_free_client(priv->psapriv,
+						  sta_ptr->cm_connectioninfo);
+#endif
+		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
+				 (pmlan_linked_list)sta_ptr,
+				 priv->adapter->callbacks.moal_spin_lock,
+				 priv->adapter->callbacks.moal_spin_unlock);
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Clean up wapi station list
+ *
+ *  @param priv  Pointer to the mlan_private driver data struct
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_delete_station_list(pmlan_private priv)
+{
+	sta_node *sta_ptr;
+
+	ENTER();
+	while ((sta_ptr =
+		(sta_node *)util_dequeue_list(priv->adapter->pmoal_handle,
+					      &priv->sta_list,
+					      priv->adapter->callbacks.
+					      moal_spin_lock,
+					      priv->adapter->callbacks.
+					      moal_spin_unlock))) {
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+		    IsAuthenticatorEnabled(priv->psapriv))
+			authenticator_free_client(priv->psapriv,
+						  sta_ptr->cm_connectioninfo);
+#endif
+		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
+						    (t_u8 *)sta_ptr);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Get tdls peer list
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param buf          A pointer to tdls_peer_info buf
+ *  @return             number of tdls peer
+ */
+int
+wlan_get_tdls_list(mlan_private *priv, tdls_peer_info *buf)
+{
+	tdls_peer_info *peer_info = buf;
+	sta_node *sta_ptr = MNULL;
+	int count = 0;
+	ENTER();
+	if (priv->bss_type != MLAN_BSS_TYPE_STA) {
+		LEAVE();
+		return count;
+	}
+	sta_ptr =
+		(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					   &priv->sta_list,
+					   priv->adapter->callbacks.
+					   moal_spin_lock,
+					   priv->adapter->callbacks.
+					   moal_spin_unlock);
+	if (!sta_ptr) {
+		LEAVE();
+		return count;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		if (sta_ptr->status == TDLS_SETUP_COMPLETE) {
+			peer_info->snr = sta_ptr->snr;
+			peer_info->nf = sta_ptr->nf;
+			memcpy_ext(priv->adapter, peer_info->mac_addr,
+				   sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH,
+				   MLAN_MAC_ADDR_LENGTH);
+			memcpy_ext(priv->adapter, peer_info->ht_cap,
+				   &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t),
+				   sizeof(peer_info->ht_cap));
+			memcpy_ext(priv->adapter, peer_info->ext_cap,
+				   &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t),
+				   sizeof(peer_info->ext_cap));
+			memcpy_ext(priv->adapter, peer_info->vht_cap,
+				   &sta_ptr->vht_cap,
+				   sizeof(IEEEtypes_VHTCap_t),
+				   sizeof(peer_info->vht_cap));
+			peer_info++;
+			count++;
+		}
+		sta_ptr = sta_ptr->pnext;
+		if (count >= MLAN_MAX_TDLS_PEER_SUPPORTED)
+			break;
+	}
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief Set the TDLS configuration to FW.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tdls_config(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	tdls_all_config *tdls_all_cfg =
+		(tdls_all_config *)misc->param.tdls_config.tdls_data;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	tdls_tear_down_event *tdls_evt =
+		(tdls_tear_down_event *)pevent->event_buf;
+	sta_node *sta_ptr = MNULL;
+	MrvlIEtypes_Data_t *pMrvlTlv = MNULL;
+	t_u8 *pos = MNULL;
+	t_u16 remain_len = 0;
+
+	ENTER();
+
+	if (misc->param.tdls_config.tdls_action == WLAN_TDLS_TEAR_DOWN_REQ) {
+		sta_ptr =
+			wlan_get_station_entry(pmpriv,
+					       tdls_all_cfg->u.tdls_tear_down.
+					       peer_mac_addr);
+		if (sta_ptr && sta_ptr->external_tdls) {
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id = MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
+			pevent->event_len = sizeof(tdls_tear_down_event);
+			memcpy_ext(pmpriv->adapter,
+				   (t_u8 *)tdls_evt->peer_mac_addr,
+				   tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			tdls_evt->reason_code =
+				tdls_all_cfg->u.tdls_tear_down.reason_code;
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
+					pevent);
+			LEAVE();
+			return ret;
+		}
+	}
+	if (misc->param.tdls_config.tdls_action == WLAN_HOST_TDLS_CONFIG) {
+		pmpriv->host_tdls_uapsd_support =
+			tdls_all_cfg->u.host_tdls_cfg.uapsd_support;
+		pmpriv->host_tdls_cs_support =
+			tdls_all_cfg->u.host_tdls_cfg.cs_support;
+		pos = tdls_all_cfg->u.host_tdls_cfg.tlv_buffer;
+		remain_len = tdls_all_cfg->u.host_tdls_cfg.tlv_len;
+		while (remain_len > sizeof(MrvlIEtypesHeader_t)) {
+			remain_len -= sizeof(MrvlIEtypesHeader_t);
+			pMrvlTlv = (MrvlIEtypes_Data_t *)pos;
+			switch (pMrvlTlv->header.type) {
+			case SUPPORTED_CHANNELS:
+				pmpriv->chan_supp_len =
+					(t_u8)MIN(pMrvlTlv->header.len,
+						  MAX_IE_SIZE);
+				memset(pmadapter, pmpriv->chan_supp, 0,
+				       sizeof(pmpriv->chan_supp));
+				memcpy_ext(pmadapter, pmpriv->chan_supp,
+					   pMrvlTlv->data, pMrvlTlv->header.len,
+					   MAX_IE_SIZE);
+				DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
+					    pmpriv->chan_supp,
+					    pmpriv->chan_supp_len);
+				break;
+			case REGULATORY_CLASS:
+				pmpriv->supp_regulatory_class_len =
+					(t_u8)MIN(pMrvlTlv->header.len,
+						  MAX_IE_SIZE);
+				memset(pmadapter, pmpriv->supp_regulatory_class,
+				       0,
+				       sizeof(pmpriv->supp_regulatory_class));
+				memcpy_ext(pmadapter,
+					   pmpriv->supp_regulatory_class,
+					   pMrvlTlv->data, pMrvlTlv->header.len,
+					   MAX_IE_SIZE);
+				DBG_HEXDUMP(MCMD_D,
+					    "TDLS supported regulatory class",
+					    pmpriv->supp_regulatory_class,
+					    pmpriv->supp_regulatory_class_len);
+				break;
+			default:
+				break;
+			}
+			remain_len -= pMrvlTlv->header.len;
+			pos += sizeof(MrvlIEtypesHeader_t) +
+				pMrvlTlv->header.len;
+		}
+		LEAVE();
+		return ret;
+	}
+	pioctl_req->action = MLAN_ACT_SET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       &misc->param.tdls_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief enable tdls config for cs and uapsd.
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *  @param enable   	MTRUE/MFALSE
+ *
+ *  @return
+ */
+t_void
+wlan_tdls_config(pmlan_private pmpriv, t_u8 enable)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_tdls_config *tdls_config = MNULL;
+	tdls_all_config *tdls_all_cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
+			       (t_u8 **)&tdls_config);
+	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
+		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
+		LEAVE();
+		return;
+	}
+	memset(pmadapter, (t_u8 *)tdls_config, 0,
+	       sizeof(mlan_ds_misc_tdls_config));
+	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
+	tdls_all_cfg->u.tdls_config.enable = enable;
+	tdls_config->tdls_action = WLAN_TDLS_CONFIG;
+	/* Send command to firmware */
+	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
+			 0, MNULL, tdls_config);
+	PRINTM(MCMND, "tdls_config: enable=%d\n", enable);
+
+	if (tdls_config)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
+
+	LEAVE();
+}
+
+/**
+ *  @brief set tdls channel switch parameters.
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *
+ *  @return
+ */
+static t_void
+wlan_tdls_cs_param_config(pmlan_private pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_tdls_config *tdls_config = MNULL;
+	tdls_all_config *tdls_all_cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
+			       (t_u8 **)&tdls_config);
+	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
+		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
+		LEAVE();
+		return;
+	}
+	memset(pmadapter, (t_u8 *)tdls_config, 0,
+	       sizeof(mlan_ds_misc_tdls_config));
+
+	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
+	tdls_config->tdls_action = WLAN_TDLS_CS_PARAMS;
+	tdls_all_cfg->u.tdls_cs_params.unit_time = 2;
+	tdls_all_cfg->u.tdls_cs_params.threshold_otherlink = 10;
+	tdls_all_cfg->u.tdls_cs_params.threshold_directlink = 0;
+
+	/* Send command to firmware */
+	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
+			 0, MNULL, tdls_config);
+
+	if (tdls_config)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
+
+	LEAVE();
+}
+
+/**
+ *  @brief start tdls channel switch
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *  @param peer_mac_addr 	A pointer to peer mac address
+ *  @param pioctl_buf   A pointer to ioctl request buffer
+ *
+ *  @return
+ */
+static t_void
+wlan_tdls_cs_start(pmlan_private pmpriv, t_u8 *peer_mac_addr,
+		   pmlan_ioctl_req pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_tdls_config *tdls_config = MNULL;
+	tdls_all_config *tdls_all_cfg = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
+			       (t_u8 **)&tdls_config);
+	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
+		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
+		LEAVE();
+		return;
+	}
+	memset(pmadapter, (t_u8 *)tdls_config, 0,
+	       sizeof(mlan_ds_misc_tdls_config));
+
+	if (pioctl_buf) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		memcpy_ext(pmpriv->adapter, tdls_config,
+			   &misc->param.tdls_config,
+			   sizeof(mlan_ds_misc_tdls_config),
+			   sizeof(mlan_ds_misc_tdls_config));
+		tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
+		if (tdls_all_cfg->u.tdls_chan_switch.primary_channel > 14) {
+			tdls_all_cfg->u.tdls_chan_switch.
+				secondary_channel_offset =
+				wlan_get_second_channel_offset(pmpriv,
+							       tdls_all_cfg->u.
+							       tdls_chan_switch.
+							       primary_channel);
+		}
+		PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
+		       tdls_all_cfg->u.tdls_chan_switch.primary_channel);
+	} else {
+		tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
+		tdls_config->tdls_action = WLAN_TDLS_INIT_CHAN_SWITCH;
+		memcpy_ext(pmpriv->adapter,
+			   tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
+			   peer_mac_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		tdls_all_cfg->u.tdls_chan_switch.primary_channel =
+			pmpriv->tdls_cs_channel;
+		if (pmpriv->tdls_cs_channel > 14) {
+			tdls_all_cfg->u.tdls_chan_switch.band = BAND_5GHZ;
+			tdls_all_cfg->u.tdls_chan_switch.
+				secondary_channel_offset =
+				wlan_get_second_channel_offset(pmpriv,
+							       pmpriv->
+							       tdls_cs_channel);
+		} else {
+			tdls_all_cfg->u.tdls_chan_switch.band = BAND_2GHZ;
+		}
+		PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
+		       pmpriv->tdls_cs_channel);
+	}
+	tdls_all_cfg->u.tdls_chan_switch.switch_time = 10;
+	tdls_all_cfg->u.tdls_chan_switch.switch_timeout = 16;
+	tdls_all_cfg->u.tdls_chan_switch.regulatory_class = 12;
+	tdls_all_cfg->u.tdls_chan_switch.periodicity = 1;
+
+	/* Send command to firmware */
+	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
+			 0, MNULL, tdls_config);
+
+	if (tdls_config)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
+
+	LEAVE();
+}
+
+#if 0
+/**
+ *  @brief stop tdls channel switch
+ *
+ *  @param pmpriv	A pointer to mlan_private structure
+ *  @param peer_mac_addr 	A pointer to peer mac address
+ *  @param pioctl_buf   A pointer to command buffer
+ *  @return
+ */
+static t_void
+wlan_tdls_cs_stop(pmlan_private pmpriv, t_u8 *peer_mac_addr)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	mlan_ds_misc_tdls_config *tdls_config = MNULL;
+	tdls_all_config *tdls_all_cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
+			       (t_u8 **)&tdls_config);
+	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
+		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
+		LEAVE();
+		return;
+	}
+	memset(pmadapter, (t_u8 *)tdls_config, 0,
+	       sizeof(mlan_ds_misc_tdls_config));
+
+	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
+	tdls_config->tdls_action = WLAN_TDLS_STOP_CHAN_SWITCH;
+
+	memcpy_ext(pmpriv->adapter,
+		   tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
+		   peer_mac_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	PRINTM(MCMND, "Stop TDLS CS\n");
+	/* Send command to firmware */
+	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
+			 0, MNULL, tdls_config);
+
+	if (tdls_config)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
+
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief Set/Get the TDLS off channel.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tdls_cs_channel(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (MLAN_ACT_GET == pioctl_req->action)
+		misc->param.tdls_cs_channel = pmpriv->tdls_cs_channel;
+	else if (MLAN_ACT_SET == pioctl_req->action) {
+		pmpriv->tdls_cs_channel = misc->param.tdls_cs_channel;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the TDLS idle time.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tdls_idle_time(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (MLAN_ACT_GET == pioctl_req->action) {
+		misc->param.tdls_idle_time = pmpriv->tdls_idle_time;
+	} else if (MLAN_ACT_SET == pioctl_req->action) {
+		pmpriv->tdls_idle_time = misc->param.tdls_idle_time;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set the TDLS operation to FW.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tdls_oper(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_ds_misc_tdls_oper *ptdls_oper = &misc->param.tdls_oper;
+	t_u8 event_buf[100];
+	mlan_event *ptdls_event = (mlan_event *)event_buf;
+	tdls_tear_down_event *tdls_evt =
+		(tdls_tear_down_event *)ptdls_event->event_buf;
+	sta_node *sta_ptr = MNULL;
+	t_u8 i = 0;
+
+	ENTER();
+	sta_ptr = wlan_get_station_entry(pmpriv, ptdls_oper->peer_mac);
+	switch (ptdls_oper->tdls_action) {
+	case WLAN_TDLS_ENABLE_LINK:
+		if (sta_ptr && (sta_ptr->status != TDLS_SETUP_FAILURE)) {
+			PRINTM(MMSG, "TDLS: Enable link " MACSTR " success\n",
+			       MAC2STR(ptdls_oper->peer_mac));
+			sta_ptr->status = TDLS_SETUP_COMPLETE;
+			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+			if (!pmpriv->txaggrctrl)
+				wlan_11n_send_delba_to_peer(pmpriv,
+							    pmpriv->
+							    curr_bss_params.
+							    bss_descriptor.
+							    mac_address);
+			if (sta_ptr->HTcap.ieee_hdr.element_id == HT_CAPABILITY) {
+				sta_ptr->is_11n_enabled = MTRUE;
+				if (GETHT_MAXAMSDU
+				    (sta_ptr->HTcap.ht_cap.ht_cap_info))
+					sta_ptr->max_amsdu =
+						MLAN_TX_DATA_BUF_SIZE_8K;
+				else
+					sta_ptr->max_amsdu =
+						MLAN_TX_DATA_BUF_SIZE_4K;
+				for (i = 0; i < MAX_NUM_TID; i++) {
+					if (sta_ptr->is_11n_enabled)
+						sta_ptr->ampdu_sta[i] =
+							pmpriv->aggr_prio_tbl[i]
+						.ampdu_user;
+					else
+						sta_ptr->ampdu_sta[i] =
+							BA_STREAM_NOT_ALLOWED;
+				}
+				memset(pmpriv->adapter, sta_ptr->rx_seq, 0xff,
+				       sizeof(sta_ptr->rx_seq));
+			}
+			wlan_restore_tdls_packets(pmpriv, ptdls_oper->peer_mac,
+						  TDLS_SETUP_COMPLETE);
+			if (ISSUPP_EXTCAP_TDLS_CHAN_SWITCH
+			    (sta_ptr->ExtCap.ext_cap)) {
+				wlan_tdls_config(pmpriv, MTRUE);
+				wlan_tdls_cs_param_config(pmpriv);
+				/**tdls cs start*/
+				if (pmpriv->tdls_cs_channel &&
+				    pmpriv->tdls_cs_channel !=
+				    pmpriv->curr_bss_params.bss_descriptor.
+				    channel)
+					wlan_tdls_cs_start(pmpriv,
+							   ptdls_oper->peer_mac,
+							   MNULL);
+			}
+		} else {
+			PRINTM(MMSG, "TDLS: Enable link " MACSTR " fail\n",
+			       MAC2STR(ptdls_oper->peer_mac));
+			/*for supplicant 2.0, we need send event to request
+			 *teardown, *for latest supplicant, we only need return
+			 *fail, and supplicant will send teardown packet and
+			 *disable tdls link*/
+			if (sta_ptr) {
+				ptdls_event->bss_index = pmpriv->bss_index;
+				ptdls_event->event_id =
+					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
+				ptdls_event->event_len =
+					sizeof(tdls_tear_down_event);
+				memcpy_ext(pmpriv->adapter,
+					   (t_u8 *)tdls_evt->peer_mac_addr,
+					   ptdls_oper->peer_mac,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				tdls_evt->reason_code =
+					MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
+				wlan_recv_event(pmpriv,
+						MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
+						ptdls_event);
+				wlan_restore_tdls_packets(pmpriv,
+							  ptdls_oper->peer_mac,
+							  TDLS_TEAR_DOWN);
+				if (sta_ptr->is_11n_enabled) {
+					wlan_cleanup_reorder_tbl(pmpriv,
+								 ptdls_oper->
+								 peer_mac);
+					wlan_11n_cleanup_txbastream_tbl(pmpriv,
+									ptdls_oper->
+									peer_mac);
+				}
+				wlan_delete_station_entry(pmpriv,
+							  ptdls_oper->peer_mac);
+				if (MTRUE == wlan_is_station_list_empty(pmpriv))
+					pmadapter->tdls_status = TDLS_NOT_SETUP;
+				else
+					pmadapter->tdls_status =
+						TDLS_IN_BASE_CHANNEL;
+			}
+			ret = MLAN_STATUS_FAILURE;
+		}
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+				MNULL);
+		break;
+	case WLAN_TDLS_DISABLE_LINK:
+		/* Send command to firmware to delete tdls link */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_OPERATION,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req, ptdls_oper);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+		break;
+	case WLAN_TDLS_CREATE_LINK:
+		PRINTM(MIOCTL, "CREATE TDLS LINK\n");
+		if (sta_ptr && sta_ptr->status == TDLS_SETUP_INPROGRESS) {
+			PRINTM(MIOCTL, "We already create the link\n");
+			break;
+		}
+		if (!sta_ptr)
+			sta_ptr =
+				wlan_add_station_entry(pmpriv,
+						       misc->param.tdls_oper.
+						       peer_mac);
+		if (sta_ptr) {
+			sta_ptr->status = TDLS_SETUP_INPROGRESS;
+			sta_ptr->external_tdls = MTRUE;
+			wlan_hold_tdls_packets(pmpriv,
+					       misc->param.tdls_oper.peer_mac);
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_OPERATION,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req, ptdls_oper);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+		break;
+	case WLAN_TDLS_CONFIG_LINK:
+		if (!sta_ptr || sta_ptr->status == TDLS_SETUP_FAILURE) {
+			PRINTM(MERROR, "Can not CONFIG TDLS Link\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_OPERATION,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req, ptdls_oper);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+		break;
+	case WLAN_TDLS_INIT_CHAN_SWITCH:
+		if (sta_ptr &&
+		    ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap)) {
+			wlan_tdls_config(pmpriv, MTRUE);
+			wlan_tdls_cs_param_config(pmpriv);
+			/**tdls cs start*/
+			wlan_tdls_cs_start(pmpriv, ptdls_oper->peer_mac,
+					   pioctl_req);
+		}
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+				MNULL);
+		break;
+	default:
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get AP's ext capability
+ *
+ *  @param pmpriv	A pointer to mlan_adapter structure
+ *  @param ext_cap  A pointer to ExtCap_t structure
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static void
+wlan_get_ap_ext_cap(mlan_private *pmpriv, ExtCap_t *ext_cap)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	BSSDescriptor_t *pbss_desc;
+	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+	memset(pmadapter, ext_cap, 0, sizeof(ExtCap_t));
+	if (pbss_desc->pext_cap) {
+		memcpy_ext(pmadapter, (t_u8 *)ext_cap,
+			   (t_u8 *)pbss_desc->pext_cap +
+			   sizeof(IEEEtypes_Header_t),
+			   pbss_desc->pext_cap->ieee_hdr.len, sizeof(ExtCap_t));
+	}
+	return;
+}
+
+/**
+ *  @brief Set the TDLS operation to FW.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tdls_get_ies(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_ds_misc_tdls_ies *tdls_ies = &misc->param.tdls_ies;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	BSSDescriptor_t *pbss_desc;
+	t_u32 usr_dot_11n_dev_cap;
+	IEEEtypes_ExtCap_t *ext_cap = MNULL;
+	ExtCap_t ap_ext_cap;
+	IEEEtypes_HTCap_t *ht_cap = MNULL;
+	IEEEtypes_HTInfo_t *ht_info = MNULL;
+	IEEEtypes_VHTCap_t *vht_cap = MNULL;
+	IEEEtypes_VHTOprat_t *vht_oprat = MNULL;
+	IEEEtypes_AssocRsp_t *passoc_rsp = MNULL;
+	IEEEtypes_AID_t *aid_info = MNULL;
+	t_u8 supp_chan[] = { 1, 11 };
+	t_u8 regulatory_class[] = { 1, /**current class*/
+		1, 2, 3, 4, 12, 22, 23, 24,
+		25, 27, 28, 29, 30, 32, 33
+	};							  /**list
+								     regulatory
+								     class*/
+	IEEEtypes_Generic_t *pSupp_chan = MNULL, *pRegulatory_class = MNULL;
+	sta_node *sta_ptr = MNULL;
+	ENTER();
+
+	/* We don't need peer information for TDLS setup */
+	if (!(tdls_ies->flags & TDLS_IE_FLAGS_SETUP))
+		sta_ptr = wlan_get_station_entry(pmpriv, tdls_ies->peer_mac);
+	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+	wlan_get_ap_ext_cap(pmpriv, &ap_ext_cap);
+	if (pbss_desc->bss_band & BAND_A)
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
+	else
+		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
+
+	/** fill the extcap */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_EXTCAP) {
+		ext_cap = (IEEEtypes_ExtCap_t *)tdls_ies->ext_cap;
+		ext_cap->ieee_hdr.element_id = EXT_CAPABILITY;
+		ext_cap->ieee_hdr.len = sizeof(ExtCap_t);
+		SET_EXTCAP_TDLS(ext_cap->ext_cap);
+		RESET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
+		RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
+
+		if (pmpriv->host_tdls_uapsd_support) {
+			/* uapsd in tdls confirm frame */
+			if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
+				if (sta_ptr &&
+				    ISSUPP_EXTCAP_TDLS_UAPSD(sta_ptr->ExtCap.
+							     ext_cap))
+					SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
+			} else {
+				SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
+			}
+		}
+		/*  channel switch support */
+		if (pmpriv->host_tdls_cs_support &&
+		    !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
+			/* channel switch in tdls confirm frame */
+			if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
+				if (sta_ptr &&
+				    ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->
+								   ExtCap.
+								   ext_cap))
+					SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->
+								    ext_cap);
+			} else {
+				SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
+			}
+		}
+
+		RESET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap->ext_cap);
+		if ((pmadapter->fw_bands & BAND_AAC) &&
+		    (MFALSE == wlan_is_ap_in_11ac_mode(pmpriv)))
+			SET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap->ext_cap);
+		/* if peer does not support wider bandwidth, don't set wider
+		 * bandwidth*/
+		if (sta_ptr && sta_ptr->rate_len &&
+		    !ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(sta_ptr->ExtCap.
+							ext_cap))
+			RESET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap->ext_cap);
+		DBG_HEXDUMP(MCMD_D, "TDLS extcap", tdls_ies->ext_cap,
+			    sizeof(IEEEtypes_ExtCap_t));
+	}
+
+	/** default qos info is 0xf, compare with peer device qos info for tdls
+	 * confirm */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_QOS_INFO) {
+		if (sta_ptr && sta_ptr->rate_len)
+			tdls_ies->QosInfo = sta_ptr->qos_info & 0xf;
+		PRINTM(MCMND, "TDLS Qos info=0x%x\n", tdls_ies->QosInfo);
+	}
+
+	/** fill the htcap based on hwspec */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_HTCAP) {
+		ht_cap = (IEEEtypes_HTCap_t *)tdls_ies->ht_cap;
+		memset(pmadapter, ht_cap, 0, sizeof(IEEEtypes_HTCap_t));
+		if ((sta_ptr &&
+		     !ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap))
+		    || IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap))
+			wlan_fill_ht_cap_ie(pmpriv, ht_cap,
+					    pbss_desc->bss_band);
+		else if (pmpriv->host_tdls_cs_support &&
+			 (pmadapter->fw_bands & BAND_A))
+			wlan_fill_ht_cap_ie(pmpriv, ht_cap, BAND_A);
+		else
+			wlan_fill_ht_cap_ie(pmpriv, ht_cap,
+					    pbss_desc->bss_band);
+		DBG_HEXDUMP(MCMD_D, "TDLS htcap", tdls_ies->ht_cap,
+			    sizeof(IEEEtypes_HTCap_t));
+	}
+	/** if peer did not support 11AC, do not add vht related ie */
+	if (sta_ptr && sta_ptr->rate_len &&
+	    (sta_ptr->vht_cap.ieee_hdr.element_id != VHT_CAPABILITY))
+		tdls_ies->flags &=
+			~(TDLS_IE_FLAGS_VHTCAP | TDLS_IE_FLAGS_VHTOPRAT |
+			  TDLS_IE_FLAGS_AID);
+	/** fill the vhtcap based on hwspec */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_VHTCAP) {
+		vht_cap = (IEEEtypes_VHTCap_t *)tdls_ies->vht_cap;
+		memset(pmadapter, vht_cap, 0, sizeof(IEEEtypes_VHTCap_t));
+		wlan_fill_vht_cap_ie(pmpriv, vht_cap, pbss_desc->bss_band);
+		if (ht_cap)
+			SETHT_SUPPCHANWIDTH(ht_cap->ht_cap.ht_cap_info);
+		DBG_HEXDUMP(MCMD_D, "TDLS vhtcap", tdls_ies->vht_cap,
+			    sizeof(IEEEtypes_VHTCap_t));
+	}
+	/** fill the vhtoperation based on hwspec */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_VHTOPRAT) {
+		vht_oprat = (IEEEtypes_VHTOprat_t *)tdls_ies->vht_oprat;
+		memset(pmadapter, vht_oprat, 0, sizeof(IEEEtypes_VHTOprat_t));
+		if (sta_ptr &&
+		    (sta_ptr->vht_cap.ieee_hdr.element_id == VHT_CAPABILITY) &&
+		    (pbss_desc->bss_band & BAND_A)) {
+			wlan_fill_tdls_vht_oprat_ie(pmpriv, vht_oprat, sta_ptr);
+		}
+		if (sta_ptr)
+			memcpy_ext(pmadapter, &sta_ptr->vht_oprat,
+				   tdls_ies->vht_oprat,
+				   sizeof(IEEEtypes_VHTOprat_t),
+				   sizeof(IEEEtypes_VHTOprat_t));
+		DBG_HEXDUMP(MCMD_D, "TDLS vht_oprat", tdls_ies->vht_oprat,
+			    sizeof(IEEEtypes_VHTOprat_t));
+	}
+	/** fill the AID info */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_AID) {
+		if (pmpriv->curr_bss_params.host_mlme)
+			passoc_rsp =
+				(IEEEtypes_AssocRsp_t *)(pmpriv->assoc_rsp_buf +
+							 sizeof
+							 (IEEEtypes_MgmtHdr_t));
+		else
+			passoc_rsp =
+				(IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf;
+		aid_info = (IEEEtypes_AID_t *)tdls_ies->aid_info;
+		memset(pmadapter, aid_info, 0, sizeof(IEEEtypes_AID_t));
+		aid_info->ieee_hdr.element_id = AID_INFO;
+		aid_info->ieee_hdr.len = sizeof(t_u16);
+		aid_info->AID = wlan_le16_to_cpu(passoc_rsp->a_id);
+		PRINTM(MCMND, "TDLS AID=0x%x\n", aid_info->AID);
+	}
+	/** fill the htinfo */
+	if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
+		ht_info = (IEEEtypes_HTInfo_t *)tdls_ies->ht_info;
+		pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+		ht_info->ieee_hdr.element_id = HT_OPERATION;
+		ht_info->ieee_hdr.len = sizeof(HTInfo_t);
+		ht_info->ht_info.pri_chan = pbss_desc->channel;
+		/* follow AP's channel bandwidth */
+		if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
+		    pbss_desc->pht_info &&
+		    ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.
+					  field2)) {
+			ht_info->ht_info.field2 =
+				pbss_desc->pht_info->ht_info.field2;
+		} else {
+			ht_info->ht_info.field2 =
+				wlan_get_second_channel_offset(pmpriv,
+							       pbss_desc->
+							       channel);
+		}
+		if (vht_oprat &&
+		    vht_oprat->ieee_hdr.element_id == VHT_OPERATION) {
+			ht_info->ht_info.field2 =
+				wlan_get_second_channel_offset(pmpriv,
+							       pbss_desc->
+							       channel);
+			ht_info->ht_info.field2 |= MBIT(2);
+		}
+		if (sta_ptr)
+			memcpy_ext(pmadapter, &sta_ptr->HTInfo,
+				   tdls_ies->ht_info,
+				   sizeof(IEEEtypes_HTInfo_t),
+				   sizeof(IEEEtypes_HTInfo_t));
+		DBG_HEXDUMP(MCMD_D, "TDLS htinfo", tdls_ies->ht_info,
+			    sizeof(IEEEtypes_HTInfo_t));
+	}
+
+	/** supported channels andl regulatory IE*/
+	if (pmpriv->host_tdls_cs_support &&
+	    (tdls_ies->flags & TDLS_IE_FLAGS_SUPP_CS_IE) &&
+	    !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
+		/** supported channels IE*/
+		pSupp_chan = (IEEEtypes_Generic_t *)tdls_ies->supp_chan;
+		pSupp_chan->ieee_hdr.element_id = SUPPORTED_CHANNELS;
+		if (pmpriv->chan_supp_len) {
+			pSupp_chan->ieee_hdr.len = pmpriv->chan_supp_len;
+			memcpy_ext(pmadapter, pSupp_chan->data,
+				   pmpriv->chan_supp, pmpriv->chan_supp_len,
+				   sizeof(pSupp_chan->data));
+		} else {
+			pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
+			memcpy_ext(pmadapter, pSupp_chan->data, supp_chan,
+				   sizeof(supp_chan), sizeof(pSupp_chan->data));
+		}
+		DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
+			    tdls_ies->supp_chan,
+			    pSupp_chan->ieee_hdr.len +
+			    sizeof(IEEEtypes_Header_t));
+
+		/**fill supported Regulatory Class IE*/
+		pRegulatory_class =
+			(IEEEtypes_Generic_t *)tdls_ies->regulatory_class;
+		pRegulatory_class->ieee_hdr.element_id = REGULATORY_CLASS;
+		if (pmpriv->supp_regulatory_class_len) {
+			pRegulatory_class->ieee_hdr.len =
+				pmpriv->supp_regulatory_class_len;
+			memcpy_ext(pmadapter, pRegulatory_class->data,
+				   pmpriv->supp_regulatory_class,
+				   pmpriv->supp_regulatory_class_len,
+				   sizeof(pRegulatory_class->data));
+		} else {
+			pRegulatory_class->ieee_hdr.len =
+				sizeof(regulatory_class);
+			memcpy_ext(pmadapter, pRegulatory_class->data,
+				   regulatory_class, sizeof(regulatory_class),
+				   sizeof(pRegulatory_class->data));
+		}
+		DBG_HEXDUMP(MCMD_D, "TDLS supported regulatory class",
+			    tdls_ies->regulatory_class,
+			    pRegulatory_class->ieee_hdr.len +
+			    sizeof(IEEEtypes_Header_t));
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set mimo switch configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_radio_ioctl_mimo_switch_cfg(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_radio_cfg *radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MIMO_SWITCH, 0, 0,
+			       (t_void *)pioctl_req,
+			       &(radio_cfg->param.mimo_switch_cfg));
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get extended version information
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_info_ver_ext(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       &pinfo->param.ver_ext.version_str_sel);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get link layer statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_ioctl_link_statistic(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	/* Check buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	switch (pioctl_req->action) {
+	case MLAN_ACT_GET:
+		cmd_action = HostCmd_ACT_GEN_GET;
+		break;
+	case MLAN_ACT_SET:
+		cmd_action = HostCmd_ACT_GEN_SET;
+		break;
+	case MLAN_ACT_CLEAR:
+		cmd_action = HostCmd_ACT_GEN_REMOVE;
+		break;
+	default:
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_LINK_STATS,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get TX/RX histogram statistic
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_tx_rx_histogram(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_TX_RX_PKT_STATS,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       &(pmisc->param.tx_rx_histogram));
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef DEBUG_LEVEL1
+/**
+ *  @brief Set driver debug bit masks in order to enhance performance
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_set_drvdbg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Set driver debug bit masks */
+	mlan_drvdbg = misc->param.drvdbg;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Rx mgmt frame forward register
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Set passthru mask for mgmt frame */
+	pmpriv->mgmt_frame_passthru_mask = misc->param.mgmt_subtype_mask;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_MGMT_IND,
+			       pioctl_req->action, 0, (t_void *)pioctl_req,
+			       &misc->param.mgmt_subtype_mask);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *   @brief This function processes the 802.11 mgmt Frame
+ *
+ *   @param priv            A pointer to mlan_private
+ *
+ *   @param payload         A pointer to the received buffer
+ *   @param payload_len     Length of the received buffer
+ *   @param prx_pd          A pointer to RxPD
+ *
+ *   @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_802dot11_mgmt_pkt(mlan_private *priv,
+			       t_u8 *payload, t_u32 payload_len, RxPD *prx_pd)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	wlan_802_11_header *pieee_pkt_hdr = MNULL;
+	t_u16 sub_type = 0;
+	t_u8 *event_buf = MNULL;
+	mlan_event *pevent = MNULL;
+	t_u8 unicast = 0;
+	t_u8 broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	IEEE80211_MGMT *mgmt = MNULL;
+	t_u8 category = 0;
+	t_u8 action_code = 0;
+#ifdef UAP_SUPPORT
+	sta_node *sta_ptr = MNULL;
+	MrvlIETypes_MgmtFrameSet_t *tlv;
+	pmlan_buffer pmbuf;
+#endif
+
+	ENTER();
+	if (payload_len > (MAX_EVENT_SIZE - sizeof(mlan_event))) {
+		PRINTM(MERROR, "Dropping large mgmt frame,len =%d\n",
+		       payload_len);
+		LEAVE();
+		return ret;
+	}
+	/* Check  packet type-subtype and compare with mgmt_passthru_mask
+	 * If event is needed to host, just eventify it */
+	pieee_pkt_hdr = (wlan_802_11_header *)payload;
+	sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(pieee_pkt_hdr->frm_ctl);
+	if (((1 << sub_type) & priv->mgmt_frame_passthru_mask) == 0) {
+		PRINTM(MINFO, "Dropping mgmt frame for subtype %d snr=%d.\n",
+		       sub_type, prx_pd->snr);
+		LEAVE();
+		return ret;
+	}
+	switch (sub_type) {
+	case SUBTYPE_ASSOC_REQUEST:
+	case SUBTYPE_REASSOC_REQUEST:
+#ifdef UAP_SUPPORT
+		if (priv->uap_host_based & UAP_FLAG_HOST_MLME) {
+			PRINTM_NETINTF(MMSG, priv);
+			if (!memcmp(pmadapter, pieee_pkt_hdr->addr3,
+				    priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
+				PRINTM(MMSG,
+				       "wlan: HostMlme MICRO_AP_STA_ASSOC "
+				       MACSTR "\n",
+				       MAC2STR(pieee_pkt_hdr->addr2));
+				mgmt = (IEEE80211_MGMT *)payload;
+				sta_ptr =
+					wlan_add_station_entry(priv,
+							       pieee_pkt_hdr->
+							       addr2);
+				if (sta_ptr) {
+					sta_ptr->capability =
+						wlan_le16_to_cpu(mgmt->u.
+								 assoc_req.
+								 capab_info);
+					pmbuf = wlan_alloc_mlan_buffer
+						(pmadapter, payload_len, 0,
+						 MOAL_MALLOC_BUFFER);
+					if (pmbuf) {
+						PRINTM(MCMND,
+						       "check sta capability\n");
+						pmbuf->data_len =
+							ASSOC_EVENT_FIX_SIZE;
+						tlv = (MrvlIETypes_MgmtFrameSet_t *)(pmbuf->pbuf + pmbuf->data_offset + pmbuf->data_len);
+						tlv->type =
+							wlan_cpu_to_le16
+							(TLV_TYPE_MGMT_FRAME);
+						tlv->len =
+							sizeof
+							(IEEEtypes_FrameCtl_t);
+						memcpy_ext(pmadapter,
+							   (t_u8 *)&tlv->
+							   frame_control,
+							   &pieee_pkt_hdr->
+							   frm_ctl,
+							   sizeof
+							   (IEEEtypes_FrameCtl_t),
+							   sizeof
+							   (IEEEtypes_FrameCtl_t));
+						pmbuf->data_len +=
+							sizeof
+							(MrvlIETypes_MgmtFrameSet_t);
+						memcpy_ext(pmadapter,
+							   pmbuf->pbuf +
+							   pmbuf->data_offset +
+							   pmbuf->data_len,
+							   payload +
+							   sizeof
+							   (wlan_802_11_header),
+							   payload_len -
+							   sizeof
+							   (wlan_802_11_header),
+							   payload_len -
+							   sizeof
+							   (wlan_802_11_header));
+						pmbuf->data_len +=
+							payload_len -
+							sizeof
+							(wlan_802_11_header);
+						tlv->len +=
+							payload_len -
+							sizeof
+							(wlan_802_11_header);
+						tlv->len =
+							wlan_cpu_to_le16(tlv->
+									 len);
+						DBG_HEXDUMP(MCMD_D, "assoc_req",
+							    pmbuf->pbuf +
+							    pmbuf->data_offset,
+							    pmbuf->data_len);
+						wlan_check_sta_capability(priv,
+									  pmbuf,
+									  sta_ptr);
+						wlan_free_mlan_buffer(pmadapter,
+								      pmbuf);
+					}
+				}
+			} else {
+				PRINTM(MMSG,
+				       "wlan: Drop MICRO_AP_STA_ASSOC " MACSTR
+				       " from unknown BSSID " MACSTR "\n",
+				       MAC2STR(pieee_pkt_hdr->addr2),
+				       MAC2STR(pieee_pkt_hdr->addr3));
+			}
+		}
+		unicast = MTRUE;
+		break;
+#endif
+	case SUBTYPE_AUTH:
+		unicast = MTRUE;
+		PRINTM_NETINTF(MMSG, priv);
+		PRINTM(MMSG, "wlan: HostMlme Auth received from " MACSTR "\n",
+		       MAC2STR(pieee_pkt_hdr->addr2));
+		break;
+	case SUBTYPE_PROBE_RESP:
+		unicast = MTRUE;
+		break;
+	case SUBTYPE_DISASSOC:
+	case SUBTYPE_DEAUTH:
+		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
+			   MLAN_MAC_ADDR_LENGTH))
+			unicast = MTRUE;
+#ifdef UAP_SUPPORT
+		if (priv->uap_host_based & UAP_FLAG_HOST_MLME) {
+			if (!memcmp(pmadapter, pieee_pkt_hdr->addr3,
+				    priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
+				PRINTM_NETINTF(MMSG, priv);
+				PRINTM(MMSG,
+				       "wlan: HostMlme Deauth Receive from "
+				       MACSTR "\n",
+				       MAC2STR(pieee_pkt_hdr->addr2));
+			}
+		}
+#endif
+		if (priv->bss_role == MLAN_BSS_ROLE_STA) {
+			if (priv->curr_bss_params.host_mlme) {
+				if (memcmp(pmadapter, pieee_pkt_hdr->addr3,
+					   (t_u8 *)priv->curr_bss_params.
+					   bss_descriptor.mac_address,
+					   MLAN_MAC_ADDR_LENGTH)) {
+					PRINTM(MCMND,
+					       "Dropping Deauth frame from other bssid: type=%d "
+					       MACSTR "\n", sub_type,
+					       MAC2STR(pieee_pkt_hdr->addr3));
+					LEAVE();
+					return ret;
+				}
+				PRINTM_NETINTF(MMSG, priv);
+				PRINTM(MMSG,
+				       "wlan: HostMlme Disconnected: sub_type=%d\n",
+				       sub_type);
+				pmadapter->pending_disconnect_priv = priv;
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+			}
+		}
+		break;
+	case SUBTYPE_ACTION:
+		category = *(payload + sizeof(wlan_802_11_header));
+		action_code = *(payload + sizeof(wlan_802_11_header) + 1);
+		if (category == IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK) {
+			PRINTM(MINFO,
+			       "Drop BLOCK ACK action frame: action_code=%d\n",
+			       action_code);
+			LEAVE();
+			return ret;
+		}
+		if ((category == IEEE_MGMT_ACTION_CATEGORY_PUBLIC) &&
+		    (action_code == BSS_20_40_COEX)) {
+			PRINTM(MINFO,
+			       "Drop 20/40 BSS Coexistence Management frame\n");
+			LEAVE();
+			return ret;
+		}
+		if ((category == CATEGORY_PUBLIC) &&
+		    (action_code == TDLS_DISCOVERY_RESPONSE)) {
+			pcb->moal_updata_peer_signal(pmadapter->pmoal_handle,
+						     priv->bss_index,
+						     pieee_pkt_hdr->addr2,
+						     prx_pd->snr, prx_pd->nf);
+			PRINTM(MINFO,
+			       "Rx: TDLS discovery response, nf=%d, snr=%d\n",
+			       prx_pd->nf, prx_pd->snr);
+		}
+		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
+			   MLAN_MAC_ADDR_LENGTH))
+			unicast = MTRUE;
+		break;
+	default:
+		break;
+	}
+	if (unicast == MTRUE) {
+		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, priv->curr_addr,
+			   MLAN_MAC_ADDR_LENGTH)) {
+			PRINTM(MINFO,
+			       "Dropping mgmt frame for others: type=%d " MACSTR
+			       "\n", sub_type, MAC2STR(pieee_pkt_hdr->addr1));
+			LEAVE();
+			return ret;
+		}
+	}
+	/* Allocate memory for event buffer */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
+			       MLAN_MEM_DEF, &event_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
+		PRINTM(MERROR, "Could not allocate buffer for event buf\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pevent = (pmlan_event)event_buf;
+	pevent->bss_index = priv->bss_index;
+	mgmt = (IEEE80211_MGMT *)payload;
+	if (!priv->curr_bss_params.host_mlme &&
+	    sub_type == SUBTYPE_ACTION &&
+	    mgmt->u.ft_resp.category == FT_CATEGORY &&
+	    mgmt->u.ft_resp.action == FT_ACTION_RESPONSE &&
+	    mgmt->u.ft_resp.status_code == 0) {
+		PRINTM(MCMND, "FT Action response received\n");
+#define FT_ACTION_HEAD_LEN (24 + 6 + 16)
+		pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
+		pevent->event_len =
+			payload_len + MLAN_MAC_ADDR_LENGTH - FT_ACTION_HEAD_LEN;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   &mgmt->u.ft_resp.target_ap_addr,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		memcpy_ext(pmadapter,
+			   (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+			   payload + FT_ACTION_HEAD_LEN,
+			   payload_len - FT_ACTION_HEAD_LEN,
+			   pevent->event_len - MLAN_MAC_ADDR_LENGTH);
+	} else if (!priv->curr_bss_params.host_mlme &&
+		   sub_type == SUBTYPE_AUTH &&
+		   mgmt->u.auth.auth_alg == MLAN_AUTH_MODE_FT &&
+		   mgmt->u.auth.auth_transaction == 2 &&
+		   mgmt->u.auth.status_code == 0) {
+		PRINTM(MCMND, "FT auth response received \n");
+#define AUTH_PACKET_LEN (24 + 6 + 6)
+		pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
+		pevent->event_len =
+			payload_len + MLAN_MAC_ADDR_LENGTH - AUTH_PACKET_LEN;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		memcpy_ext(pmadapter,
+			   (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
+			   payload + AUTH_PACKET_LEN,
+			   payload_len - AUTH_PACKET_LEN,
+			   pevent->event_len - MLAN_MAC_ADDR_LENGTH);
+	} else {
+		pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
+		pevent->event_len = payload_len + sizeof(pevent->event_id);
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   (t_u8 *)&pevent->event_id, sizeof(pevent->event_id),
+			   pevent->event_len);
+		memcpy_ext(pmadapter,
+			   (t_u8 *)(pevent->event_buf +
+				    sizeof(pevent->event_id)), payload,
+			   payload_len, payload_len);
+	}
+	wlan_recv_event(priv, pevent->event_id, pevent);
+	if (event_buf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Extended capabilities configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (MLAN_ACT_GET == pioctl_req->action)
+		memcpy_ext(pmpriv->adapter, &misc->param.ext_cap,
+			   &pmpriv->def_ext_cap, sizeof(misc->param.ext_cap),
+			   sizeof(misc->param.ext_cap));
+	else if (MLAN_ACT_SET == pioctl_req->action) {
+		memcpy_ext(pmpriv->adapter, &pmpriv->ext_cap,
+			   &misc->param.ext_cap, sizeof(misc->param.ext_cap),
+			   sizeof(pmpriv->ext_cap));
+		/* Save default Extended Capability */
+		memcpy_ext(pmpriv->adapter, &pmpriv->def_ext_cap,
+			   &pmpriv->ext_cap, sizeof(pmpriv->ext_cap),
+			   sizeof(pmpriv->def_ext_cap));
+		if (pmpriv->config_bands & BAND_AAC)
+			SET_EXTCAP_OPERMODENTF(pmpriv->ext_cap);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check whether Extended Capabilities IE support
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *
+ *  @return                   MTRUE or MFALSE;
+ */
+t_u32
+wlan_is_ext_capa_support(mlan_private *pmpriv)
+{
+	ENTER();
+
+	if (ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap) ||
+	    ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap) ||
+	    ISSUPP_EXTCAP_BSS_TRANSITION(pmpriv->ext_cap)
+	    || ISSUPP_EXTCAP_QOS_MAP(pmpriv->ext_cap)
+	    || ISSUPP_EXTCAP_OPERMODENTF(pmpriv->ext_cap)
+		) {
+		LEAVE();
+		return MTRUE;
+	} else {
+		LEAVE();
+		return MFALSE;
+	}
+}
+#endif
+
+/**
+ *  @brief Set hotspot enable/disable
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_hotspot_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (MLAN_ACT_GET == pioctl_req->action)
+		misc->param.hotspot_cfg = pmpriv->hotspot_cfg;
+	else if (MLAN_ACT_SET == pioctl_req->action)
+		pmpriv->hotspot_cfg = misc->param.hotspot_cfg;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Add Extended Capabilities IE
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pbss_desc          A pointer to BSSDescriptor_t structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *
+ *  @return                   N/A
+ */
+void
+wlan_add_ext_capa_info_ie(mlan_private *pmpriv,
+			  BSSDescriptor_t *pbss_desc, t_u8 **pptlv_out)
+{
+	MrvlIETypes_ExtCap_t *pext_cap = MNULL;
+
+	ENTER();
+
+	pext_cap = (MrvlIETypes_ExtCap_t *)*pptlv_out;
+	memset(pmpriv->adapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
+	pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
+	pext_cap->header.len = wlan_cpu_to_le16(sizeof(ExtCap_t));
+	if (pmpriv->adapter->ecsa_enable)
+		SET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
+	else
+		RESET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
+	if (pbss_desc && pbss_desc->multi_bssid_ap)
+		SET_EXTCAP_MULTI_BSSID(pmpriv->ext_cap);
+	if (wlan_check_11ax_twt_supported(pmpriv, pbss_desc))
+		SET_EXTCAP_TWT_REQ(pmpriv->ext_cap);
+	memcpy_ext(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
+		   sizeof(pmpriv->ext_cap), sizeof(pext_cap->ext_cap));
+	*pptlv_out += sizeof(MrvlIETypes_ExtCap_t);
+
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief Get OTP user data
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_otp_user_data(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+
+	if (misc->param.otp_user_data.user_data_length > MAX_OTP_USER_DATA_LEN) {
+		PRINTM(MERROR, "Invalid OTP user data length\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return ret;
+	}
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_OTP_READ_USER_DATA,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       &misc->param.otp_user_data);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will search for the specific ie
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to event buf
+ *  @param sta_ptr A pointer to sta_node
+ *
+ *  @return	       N/A
+ */
+void
+wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
+			  sta_node *sta_ptr)
+{
+	t_u16 tlv_type, tlv_len;
+	t_u16 frame_control, frame_sub_type = 0;
+	t_u8 *assoc_req_ie = MNULL;
+	t_u8 ie_len = 0, assoc_ie_len = 0;
+	IEEEtypes_HTCap_t *pht_cap = MNULL;
+	IEEEtypes_VHTCap_t *pvht_cap = MNULL;
+	IEEEtypes_Extension_t *phe_cap = MNULL;
+#ifdef UAP_SUPPORT
+	t_u8 *ext_rate = MNULL, *erp = MNULL;
+#endif
+
+	int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
+	MrvlIEtypesHeader_t *tlv =
+		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+					ASSOC_EVENT_FIX_SIZE);
+	MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
+
+	ENTER();
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		if (tlv_type == TLV_TYPE_MGMT_FRAME) {
+			mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
+			memcpy_ext(priv->adapter, &frame_control,
+				   (t_u8 *)&(mgmt_tlv->frame_control),
+				   sizeof(frame_control),
+				   sizeof(frame_control));
+			frame_sub_type =
+				IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE
+				(frame_control);
+			if ((mgmt_tlv->frame_control.type == 0) &&
+			    ((frame_sub_type == SUBTYPE_BEACON)
+#ifdef UAP_SUPPORT
+			     || (frame_sub_type == SUBTYPE_ASSOC_REQUEST) ||
+			     (frame_sub_type == SUBTYPE_REASSOC_REQUEST)
+#endif
+			    )) {
+				if (frame_sub_type == SUBTYPE_BEACON)
+					assoc_ie_len =
+						sizeof(IEEEtypes_Beacon_t);
+#ifdef UAP_SUPPORT
+				else if (frame_sub_type ==
+					 SUBTYPE_ASSOC_REQUEST)
+					assoc_ie_len =
+						sizeof(IEEEtypes_AssocRqst_t);
+				else if (frame_sub_type ==
+					 SUBTYPE_REASSOC_REQUEST)
+					assoc_ie_len =
+						sizeof(IEEEtypes_ReAssocRqst_t);
+#endif
+				ie_len = tlv_len -
+					sizeof(IEEEtypes_FrameCtl_t) -
+					assoc_ie_len;
+				assoc_req_ie =
+					(t_u8 *)tlv +
+					sizeof(MrvlIETypes_MgmtFrameSet_t) +
+					assoc_ie_len;
+				sta_ptr->is_wmm_enabled =
+					wlan_is_wmm_ie_present(priv->adapter,
+							       assoc_req_ie,
+							       ie_len);
+				PRINTM(MCMND, "STA: is_wmm_enabled=%d\n",
+				       sta_ptr->is_wmm_enabled);
+				pht_cap = (IEEEtypes_HTCap_t *)
+					wlan_get_specific_ie(priv, assoc_req_ie,
+							     ie_len,
+							     HT_CAPABILITY, 0);
+				if (pht_cap) {
+					PRINTM(MCMND, "STA supports 11n\n");
+					sta_ptr->is_11n_enabled = MTRUE;
+					memcpy_ext(priv->adapter,
+						   (t_u8 *)&sta_ptr->HTcap,
+						   pht_cap,
+						   sizeof(IEEEtypes_HTCap_t),
+						   sizeof(IEEEtypes_HTCap_t));
+					if (GETHT_MAXAMSDU
+					    (wlan_le16_to_cpu
+					     (pht_cap->ht_cap.ht_cap_info)))
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_8K;
+					else
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_4K;
+				} else {
+					PRINTM(MCMND,
+					       "STA doesn't support 11n\n");
+				}
+				pvht_cap = (IEEEtypes_VHTCap_t *)
+					wlan_get_specific_ie(priv, assoc_req_ie,
+							     ie_len,
+							     VHT_CAPABILITY, 0);
+				if (pvht_cap &&
+				    (priv->is_11ac_enabled == MTRUE)) {
+					PRINTM(MCMND, "STA supports 11ac\n");
+					sta_ptr->is_11ac_enabled = MTRUE;
+					if (GET_VHTCAP_MAXMPDULEN
+					    (wlan_le32_to_cpu
+					     (pvht_cap->vht_cap.
+					      vht_cap_info)) == 2)
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_12K;
+					else if (GET_VHTCAP_MAXMPDULEN
+						 (wlan_le32_to_cpu
+						  (pvht_cap->vht_cap.
+						   vht_cap_info)) == 1)
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_8K;
+					else
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_4K;
+				} else {
+					PRINTM(MCMND,
+					       "STA doesn't support 11ac\n");
+				}
+				phe_cap = (IEEEtypes_Extension_t *)
+					wlan_get_specific_ie(priv, assoc_req_ie,
+							     ie_len, EXTENSION,
+							     HE_CAPABILITY);
+				if (phe_cap && (priv->is_11ax_enabled == MTRUE)) {
+					PRINTM(MCMND, "STA supports 11ax\n");
+					sta_ptr->is_11ax_enabled = MTRUE;
+					memcpy_ext(priv->adapter,
+						   (t_u8 *)&sta_ptr->he_cap,
+						   phe_cap,
+						   phe_cap->ieee_hdr.len +
+						   sizeof(IEEEtypes_Header_t),
+						   sizeof(IEEEtypes_HECap_t));
+					sta_ptr->he_cap.ieee_hdr.len =
+						MIN(phe_cap->ieee_hdr.len,
+						    sizeof(IEEEtypes_HECap_t) -
+						    sizeof(IEEEtypes_Header_t));
+				} else {
+					PRINTM(MCMND,
+					       "STA doesn't support 11ax\n");
+				}
+#ifdef UAP_SUPPORT
+				/* Note: iphone6 does not have ERP_INFO */
+				ext_rate =
+					wlan_get_specific_ie(priv, assoc_req_ie,
+							     ie_len,
+							     EXTENDED_SUPPORTED_RATES,
+							     0);
+				erp = wlan_get_specific_ie(priv, assoc_req_ie,
+							   ie_len, ERP_INFO, 0);
+				if (!ext_rate)
+					PRINTM(MCMND,
+					       "STA doesn't support EXTENDED_SUPPORTED_RATES\n");
+				if (!erp)
+					PRINTM(MCMND,
+					       "STA doesn't support ERP_INFO\n");
+				if (sta_ptr->is_11ax_enabled) {
+					if (priv->uap_channel <= 14)
+						sta_ptr->bandmode = BAND_GAX;
+					else
+						sta_ptr->bandmode = BAND_AAX;
+				} else if (sta_ptr->is_11ac_enabled) {
+					if (priv->uap_channel <= 14)
+						sta_ptr->bandmode = BAND_GAC;
+					else
+						sta_ptr->bandmode = BAND_AAC;
+				} else if (sta_ptr->is_11n_enabled) {
+					if (priv->uap_channel <= 14)
+						sta_ptr->bandmode = BAND_GN;
+					else
+						sta_ptr->bandmode = BAND_AN;
+				} else if (ext_rate || erp) {
+					if (priv->uap_channel <= 14)
+						sta_ptr->bandmode = BAND_G;
+					else
+						sta_ptr->bandmode = BAND_A;
+				} else
+					sta_ptr->bandmode = BAND_B;
+#endif
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+				if (IsAuthenticatorEnabled(priv->psapriv))
+					authenticator_get_sta_security_info
+						(priv->psapriv,
+						 sta_ptr->cm_connectioninfo,
+						 assoc_req_ie, ie_len);
+#endif
+				break;
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+	LEAVE();
+
+	return;
+}
+
+/**
+ *  @brief check if WMM ie present.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pbuf     A pointer to IE buffer
+ *  @param buf_len  IE buffer len
+ *
+ *  @return         MTRUE/MFALSE
+ */
+t_u8
+wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len)
+{
+	t_u16 bytes_left = buf_len;
+	IEEEtypes_ElementId_e element_id;
+	t_u8 *pcurrent_ptr = pbuf;
+	t_u8 element_len;
+	t_u16 total_ie_len;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	t_u8 find_wmm_ie = MFALSE;
+
+	ENTER();
+
+	/* Process variable IE */
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+			       "bytes left < IE length\n");
+			bytes_left = 0;
+			continue;
+		}
+		switch (element_id) {
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+			if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+				    wmm_oui, sizeof(wmm_oui))) {
+				find_wmm_ie = MTRUE;
+				PRINTM(MINFO, "find WMM IE\n");
+			}
+			break;
+		default:
+			break;
+		}
+		pcurrent_ptr += element_len + 2;
+		/* Need to account for IE ID and IE Len */
+		bytes_left -= (element_len + 2);
+		if (find_wmm_ie)
+			break;
+	}
+
+	LEAVE();
+	return find_wmm_ie;
+}
+
+/**
+ *  @brief This function will search for the specific ie
+ *
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param ie_buf  A pointer to ie_buf
+ *  @param ie_len  total ie length
+ *  @param id      ie's id
+ *  @param ext_id  ie's extension id
+ *
+ *  @return	       ie's poiner or MNULL
+ */
+t_u8 *
+wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
+		     IEEEtypes_ElementId_e id, t_u8 ext_id)
+{
+	t_u32 bytes_left = ie_len;
+	t_u8 *pcurrent_ptr = ie_buf;
+	t_u16 total_ie_len;
+	t_u8 *ie_ptr = MNULL;
+	IEEEtypes_ElementId_e element_id;
+	t_u8 element_len;
+	t_u8 element_eid;
+
+	ENTER();
+
+	DBG_HEXDUMP(MDAT_D, "ie", ie_buf, ie_len);
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		element_eid = *((t_u8 *)pcurrent_ptr + 2);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+			       "bytes left < IE length\n");
+			break;
+		}
+		if ((!ext_id && element_id == id) ||
+		    (id == EXTENSION && element_id == id &&
+		     ext_id == element_eid)) {
+			PRINTM(MCMND, "Find IE: id=%d ext_id=%d\n", id, ext_id);
+			DBG_HEXDUMP(MCMD_D, "IE", pcurrent_ptr, total_ie_len);
+			ie_ptr = pcurrent_ptr;
+			break;
+		}
+		pcurrent_ptr += element_len + 2;
+		/* Need to account for IE ID and IE Len */
+		bytes_left -= (element_len + 2);
+	}
+
+	LEAVE();
+
+	return ie_ptr;
+}
+
+/**
+ *  @brief Get pm info
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		        MLAN_STATUS_SUCCESS --success
+ */
+mlan_status
+wlan_get_pm_info(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	pm_cfg->param.ps_info.is_suspend_allowed = MTRUE;
+	wlan_request_cmd_lock(pmadapter);
+	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
+			   MNULL, MNULL) ||
+	    pmadapter->curr_cmd || !wlan_bypass_tx_list_empty(pmadapter) ||
+	    !wlan_wmm_lists_empty(pmadapter)
+#if defined(SDIO) || defined(PCIE)
+	    || wlan_pending_interrupt(pmadapter)
+#endif
+		) {
+		pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
+#if defined(SDIO) || defined(PCIE)
+		PRINTM(MIOCTL,
+		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d irq_pending=%d\n",
+		       util_peek_list(pmadapter->pmoal_handle,
+				      &pmadapter->cmd_pending_q, MNULL, MNULL),
+		       pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
+		       wlan_bypass_tx_list_empty(pmadapter),
+		       wlan_pending_interrupt(pmadapter));
+#else
+		PRINTM(MIOCTL,
+		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d\n",
+		       util_peek_list(pmadapter->pmoal_handle,
+				      &pmadapter->cmd_pending_q, MNULL, MNULL),
+		       pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
+		       wlan_bypass_tx_list_empty(pmadapter));
+#endif
+	}
+	wlan_release_cmd_lock(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get hs wakeup reason
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		        MLAN_STATUS_SUCCESS --success
+ */
+mlan_status
+wlan_get_hs_wakeup_reason(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	pmlan_ds_pm_cfg pm_cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_HS_WAKEUP_REASON,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       &pm_cfg->param.wakeup_reason);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get radio status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_radio_ioctl_radio_ctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmadapter->radio_on == radio_cfg->param.radio_on_off) {
+			ret = MLAN_STATUS_SUCCESS;
+			goto exit;
+		} else {
+			if (pmpriv->media_connected == MTRUE) {
+				ret = MLAN_STATUS_FAILURE;
+				goto exit;
+			}
+			cmd_action = HostCmd_ACT_GEN_SET;
+		}
+	} else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RADIO_CONTROL,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &radio_cfg->param.radio_on_off);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get antenna configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_ds_ant_cfg *ant_cfg = MNULL;
+	mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = MNULL;
+
+	ENTER();
+
+	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	if (IS_STREAM_2X2(pmadapter->feature_control))
+		ant_cfg = &radio_cfg->param.ant_cfg;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		/* User input validation */
+		if (IS_STREAM_2X2(pmadapter->feature_control)) {
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+			if (IS_CARD9098(pmadapter->card_type) ||
+			    IS_CARD9097(pmadapter->card_type)) {
+				ant_cfg->tx_antenna &= 0x0303;
+				ant_cfg->rx_antenna &= 0x0303;
+				/** 2G antcfg TX */
+				if (ant_cfg->tx_antenna & 0x00FF) {
+					pmadapter->user_htstream &= ~0xF0;
+					pmadapter->user_htstream |=
+						(bitcount(ant_cfg->tx_antenna &
+							  0x00FF)
+						 << 4);
+				}
+				/* 5G antcfg tx */
+				if (ant_cfg->tx_antenna & 0xFF00) {
+					pmadapter->user_htstream &= ~0xF000;
+					pmadapter->user_htstream |=
+						(bitcount(ant_cfg->tx_antenna &
+							  0xFF00)
+						 << 12);
+				}
+				/* 2G antcfg RX */
+				if (ant_cfg->rx_antenna & 0x00FF) {
+					pmadapter->user_htstream &= ~0xF;
+					pmadapter->user_htstream |=
+						bitcount(ant_cfg->
+							 rx_antenna & 0x00FF);
+				}
+				/* 5G antcfg RX */
+				if (ant_cfg->rx_antenna & 0xFF00) {
+					pmadapter->user_htstream &= ~0xF00;
+					pmadapter->user_htstream |=
+						(bitcount(ant_cfg->rx_antenna &
+							  0xFF00)
+						 << 8);
+				}
+				PRINTM(MCMND,
+				       "user_htstream=0x%x, tx_antenna=0x%x >rx_antenna=0x%x\n",
+				       pmadapter->user_htstream,
+				       ant_cfg->tx_antenna,
+				       ant_cfg->rx_antenna);
+			} else {
+#endif
+
+				ant_cfg->tx_antenna &= 0x0003;
+				ant_cfg->rx_antenna &= 0x0003;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+			}
+#endif
+			if (!ant_cfg->tx_antenna ||
+			    bitcount(ant_cfg->tx_antenna & 0x00FF) >
+			    pmadapter->number_of_antenna ||
+			    bitcount(ant_cfg->tx_antenna & 0xFF00) >
+			    pmadapter->number_of_antenna) {
+				PRINTM(MERROR,
+				       "Invalid TX antenna setting: 0x%x\n",
+				       ant_cfg->tx_antenna);
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto exit;
+			}
+			if (ant_cfg->rx_antenna) {
+				if (bitcount(ant_cfg->rx_antenna & 0x00FF) >
+				    pmadapter->number_of_antenna ||
+				    bitcount(ant_cfg->rx_antenna & 0xFF00) >
+				    pmadapter->number_of_antenna) {
+					PRINTM(MERROR,
+					       "Invalid RX antenna setting: 0x%x\n",
+					       ant_cfg->rx_antenna);
+					pioctl_req->status_code =
+						MLAN_ERROR_INVALID_PARAMETER;
+					ret = MLAN_STATUS_FAILURE;
+					goto exit;
+				}
+			} else
+				ant_cfg->rx_antenna = ant_cfg->tx_antenna;
+		} else if (!radio_cfg->param.ant_cfg_1x1.antenna ||
+			   ((radio_cfg->param.ant_cfg_1x1.antenna !=
+			     RF_ANTENNA_AUTO) &&
+			    (radio_cfg->param.ant_cfg_1x1.antenna & 0xFFFC))) {
+			PRINTM(MERROR, "Invalid antenna setting\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		cmd_action = HostCmd_ACT_GEN_SET;
+	} else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Cast it to t_u16, antenna mode for command
+	 * HostCmd_CMD_802_11_RF_ANTENNA requires 2 bytes */
+	if (!IS_STREAM_2X2(pmadapter->feature_control))
+		ant_cfg_1x1 = &radio_cfg->param.ant_cfg_1x1;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       (IS_STREAM_2X2(pmadapter->feature_control)) ?
+			       (t_void *)ant_cfg : (t_void *)ant_cfg_1x1);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get rate bitmap
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_get_rate_bitmap(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set rate bitmap
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_set_rate_bitmap(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_rate *ds_rate = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 *bitmap_rates = MNULL;
+
+	ENTER();
+
+	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
+	bitmap_rates = ds_rate->param.rate_cfg.bitmap_rates;
+
+	PRINTM(MINFO,
+	       "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
+	       "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
+	       "IsRateAuto=%d, DataRate=%d\n",
+	       bitmap_rates[17], bitmap_rates[16], bitmap_rates[15],
+	       bitmap_rates[14], bitmap_rates[13], bitmap_rates[12],
+	       bitmap_rates[11], bitmap_rates[10], bitmap_rates[9],
+	       bitmap_rates[8], bitmap_rates[7], bitmap_rates[6],
+	       bitmap_rates[5], bitmap_rates[4], bitmap_rates[3],
+	       bitmap_rates[2], bitmap_rates[1], bitmap_rates[0],
+	       pmpriv->is_data_rate_auto, pmpriv->data_rate);
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       (t_void *)bitmap_rates);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get rate value
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_get_rate_value(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_rate *rate = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	rate = (mlan_ds_rate *)pioctl_req->pbuf;
+	rate->param.rate_cfg.is_rate_auto = pmpriv->is_data_rate_auto;
+	pioctl_req->data_read_written =
+		sizeof(mlan_rate_cfg_t) + MLAN_SUB_COMMAND_SIZE;
+
+	/* If not connected, set rate to the lowest in each band */
+	if (pmpriv->media_connected != MTRUE) {
+		if (pmpriv->config_bands & (BAND_B | BAND_G)) {
+			/* Return the lowest supported rate for BG band */
+			rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
+		} else if (pmpriv->config_bands & (BAND_A | BAND_B)) {
+			/* Return the lowest supported rate for A band */
+			rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
+		} else if (pmpriv->config_bands & BAND_A) {
+			/* Return the lowest supported rate for A band */
+			rate->param.rate_cfg.rate = SupportedRates_A[0] & 0x7f;
+		} else if (pmpriv->config_bands & BAND_G) {
+			/* Return the lowest supported rate for G band */
+			rate->param.rate_cfg.rate = SupportedRates_G[0] & 0x7f;
+		} else if (pmpriv->config_bands & BAND_B) {
+			/* Return the lowest supported rate for B band */
+			rate->param.rate_cfg.rate = SupportedRates_B[0] & 0x7f;
+		} else if (pmpriv->config_bands & BAND_GN) {
+			/* Return the lowest supported rate for N band */
+			rate->param.rate_cfg.rate = SupportedRates_N[0] & 0x7f;
+		} else {
+			PRINTM(MMSG, "Invalid Band 0x%x\n",
+			       pmpriv->config_bands);
+		}
+
+	} else {
+		/* Send request to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+				       HostCmd_ACT_GEN_GET, 0,
+				       (t_void *)pioctl_req, MNULL);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set rate value
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_set_rate_value(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_rate *ds_rate = MNULL;
+	WLAN_802_11_RATES rates;
+	t_u8 *rate = MNULL;
+	int rate_index = 0;
+	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+	t_u32 i = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
+
+	if (ds_rate->param.rate_cfg.is_rate_auto) {
+		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+		/* Support all HR/DSSS rates */
+		bitmap_rates[0] = 0x000F;
+		/* Support all OFDM rates */
+		bitmap_rates[1] = 0x00FF;
+		/* Rates talbe [0] HR/DSSS,[1] OFDM,[2..9] HT,[10..17] VHT */
+		/* Support all HT-MCSs rate */
+		for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 3 - 8; i++)
+			bitmap_rates[i + 2] = 0xFFFF;
+		bitmap_rates[9] = 0x3FFF;
+		/* Support all VHT-MCSs rate */
+		for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 10; i++)
+			bitmap_rates[i + 10] = 0x03FF;	/* 10 Bits valid */
+	} else {
+		memset(pmadapter, rates, 0, sizeof(rates));
+		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
+					   (pmpriv->bss_mode ==
+					    MLAN_BSS_MODE_INFRA) ?
+					   pmpriv->config_bands :
+					   pmadapter->adhoc_start_band, rates);
+		rate = rates;
+		for (i = 0; (rate[i] && i < WLAN_SUPPORTED_RATES); i++) {
+			PRINTM(MINFO, "Rate=0x%X  Wanted=0x%X\n", rate[i],
+			       ds_rate->param.rate_cfg.rate);
+			if ((rate[i] & 0x7f) ==
+			    (ds_rate->param.rate_cfg.rate & 0x7f))
+				break;
+		}
+		if ((i < WLAN_SUPPORTED_RATES && !rate[i]) ||
+		    (i == WLAN_SUPPORTED_RATES)) {
+			PRINTM(MERROR,
+			       "The fixed data rate 0x%X is out "
+			       "of range\n", ds_rate->param.rate_cfg.rate);
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+		rate_index =
+			wlan_data_rate_to_index(pmadapter,
+						ds_rate->param.rate_cfg.rate);
+		/* Only allow b/g rates to be set */
+		if (rate_index >= MLAN_RATE_INDEX_HRDSSS0 &&
+		    rate_index <= MLAN_RATE_INDEX_HRDSSS3)
+			bitmap_rates[0] = 1 << rate_index;
+		else {
+			rate_index -= 1;	/* There is a 0x00 in the table */
+			if (rate_index >= MLAN_RATE_INDEX_OFDM0 &&
+			    rate_index <= MLAN_RATE_INDEX_OFDM7)
+				bitmap_rates[1] = 1 << (rate_index -
+							MLAN_RATE_INDEX_OFDM0);
+		}
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       bitmap_rates);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get rate index
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_get_rate_index(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set rate index
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_set_rate_index(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	t_u32 rate_index;
+	t_u32 rate_format;
+	t_u32 nss;
+	t_u32 i;
+	mlan_ds_rate *ds_rate = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+	int tx_mcs_supp = GET_TXMCSSUPP(pmpriv->usr_dev_mcs_support);
+
+	ENTER();
+
+	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
+	rate_format = ds_rate->param.rate_cfg.rate_format;
+	nss = ds_rate->param.rate_cfg.nss;
+	rate_index = ds_rate->param.rate_cfg.rate;
+
+	if (ds_rate->param.rate_cfg.is_rate_auto) {
+		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+		/* Rates talbe [0]: HR/DSSS;[1]: OFDM; [2..9] HT; */
+		/* Support all HR/DSSS rates */
+		bitmap_rates[0] = 0x000F;
+		/* Support all OFDM rates */
+		bitmap_rates[1] = 0x00FF;
+		/* Support all HT-MCSs rate */
+		for (i = 2; i < 9; i++)
+			bitmap_rates[i] = 0xFFFF;
+		bitmap_rates[9] = 0x3FFF;
+		/* [10..17] VHT */
+		/* Support all VHT-MCSs rate for NSS 1 and 2 */
+		for (i = 10; i < 12; i++)
+			bitmap_rates[i] = 0x03FF;	/* 10 Bits valid */
+		/* Set to 0 as default value for all other NSSs */
+		for (i = 12; i < 17; i++)
+			bitmap_rates[i] = 0x0;
+		/* [18..25] HE */
+		/* Support all HE-MCSs rate for NSS1 and 2 */
+		for (i = 18; i < 20; i++)
+			bitmap_rates[i] = 0x0FFF;
+		for (i = 20; i < NELEMENTS(bitmap_rates); i++)
+			bitmap_rates[i] = 0x0;
+	} else {
+		PRINTM(MINFO, "Rate index is %d\n", rate_index);
+		if ((rate_format == MLAN_RATE_FORMAT_HT) &&
+		    (rate_index > MLAN_RATE_INDEX_MCS7 &&
+		     rate_index <= MLAN_RATE_INDEX_MCS15) &&
+		    (tx_mcs_supp < 2)) {
+			PRINTM(MERROR,
+			       "HW don't support 2x2, rate_index=%d hw_mcs_supp=0x%x\n",
+			       rate_index, pmpriv->usr_dev_mcs_support);
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
+		if (rate_format == MLAN_RATE_FORMAT_LG) {
+			/* Bitmap of HR/DSSS rates */
+			if (rate_index <= MLAN_RATE_INDEX_HRDSSS3) {
+				bitmap_rates[0] = 1 << rate_index;
+				ret = MLAN_STATUS_SUCCESS;
+				/* Bitmap of OFDM rates */
+			} else if ((rate_index >= MLAN_RATE_INDEX_OFDM0) &&
+				   (rate_index <= MLAN_RATE_INDEX_OFDM7)) {
+				bitmap_rates[1] = 1 << (rate_index -
+							MLAN_RATE_INDEX_OFDM0);
+				ret = MLAN_STATUS_SUCCESS;
+			}
+		} else if (rate_format == MLAN_RATE_FORMAT_HT) {
+			if (rate_index <= MLAN_RATE_INDEX_MCS32) {
+				bitmap_rates[2 + (rate_index / 16)] =
+					1 << (rate_index % 16);
+				ret = MLAN_STATUS_SUCCESS;
+			}
+		}
+		if (rate_format == MLAN_RATE_FORMAT_VHT) {
+			if ((rate_index <= MLAN_RATE_INDEX_MCS9) &&
+			    (MLAN_RATE_NSS1 <= nss) &&
+			    (nss <= MLAN_RATE_NSS2)) {
+				bitmap_rates[10 + nss - MLAN_RATE_NSS1] =
+					(1 << rate_index);
+				ret = MLAN_STATUS_SUCCESS;
+			}
+		}
+		if (rate_format == MLAN_RATE_FORMAT_HE) {
+			if (IS_FW_SUPPORT_11AX(pmadapter)) {
+				if ((rate_index <= MLAN_RATE_INDEX_MCS11) &&
+				    (MLAN_RATE_NSS1 <= nss) &&
+				    (nss <= MLAN_RATE_NSS2)) {
+					bitmap_rates[18 + nss -
+						     MLAN_RATE_NSS1] =
+						(1 << rate_index);
+					ret = MLAN_STATUS_SUCCESS;
+				}
+			} else {
+				PRINTM(MERROR,
+				       "Error! Fw doesn't support 11AX\n");
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+
+		if (ret == MLAN_STATUS_FAILURE) {
+			PRINTM(MERROR, "Invalid MCS index=%d. \n", rate_index);
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	PRINTM(MINFO,
+	       "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
+	       "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
+	       "IsRateAuto=%d, DataRate=%d\n",
+	       bitmap_rates[17], bitmap_rates[16], bitmap_rates[15],
+	       bitmap_rates[14], bitmap_rates[13], bitmap_rates[12],
+	       bitmap_rates[11], bitmap_rates[10], bitmap_rates[9],
+	       bitmap_rates[8], bitmap_rates[7], bitmap_rates[6],
+	       bitmap_rates[5], bitmap_rates[4], bitmap_rates[3],
+	       bitmap_rates[2], bitmap_rates[1], bitmap_rates[0],
+	       pmpriv->is_data_rate_auto, pmpriv->data_rate);
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       (t_void *)bitmap_rates);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Rate configuration command handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status
+wlan_rate_ioctl_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_rate *rate = MNULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	rate = (mlan_ds_rate *)pioctl_req->pbuf;
+	if (rate->param.rate_cfg.rate_type == MLAN_RATE_BITMAP) {
+		if (pioctl_req->action == MLAN_ACT_GET)
+			status = wlan_rate_ioctl_get_rate_bitmap(pmadapter,
+								 pioctl_req);
+		else
+			status = wlan_rate_ioctl_set_rate_bitmap(pmadapter,
+								 pioctl_req);
+	} else if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) {
+		if (pioctl_req->action == MLAN_ACT_GET)
+			status = wlan_rate_ioctl_get_rate_value(pmadapter,
+								pioctl_req);
+		else
+			status = wlan_rate_ioctl_set_rate_value(pmadapter,
+								pioctl_req);
+	} else {
+		if (pioctl_req->action == MLAN_ACT_GET)
+			status = wlan_rate_ioctl_get_rate_index(pmadapter,
+								pioctl_req);
+		else
+			status = wlan_rate_ioctl_set_rate_index(pmadapter,
+								pioctl_req);
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get data rates
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_rate_ioctl_get_data_rate(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pioctl_req->action != MLAN_ACT_GET) {
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get remain on channel setting
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_radio_ioctl_remain_chan_cfg(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_REMAIN_ON_CHANNEL,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &radio_cfg->param.remain_chan);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ *  @brief Set/Get wifi_direct_mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_bss_ioctl_wifi_direct_mode(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = MNULL;
+
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_WIFI_DIRECT_MODE_CONFIG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &bss->param.wfd_mode);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get p2p config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_p2p_config(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_P2P_PARAMS_CONFIG, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       &misc_cfg->param.p2p_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/Get GPIO TSF Latch config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_gpio_tsf_latch_config(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc_cfg->param.gpio_tsf_latch_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get TSF info
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_get_tsf_info(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc_cfg->param.tsf_info);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set coalesce config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_coalesce_cfg(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_COALESCE_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       &misc_cfg->param.coalesce_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set USB packet aggregation parameters
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_aggr_ctrl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_PACKET_AGGR_CTRL, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       &misc->param.aggr_params);
+
+	if (ret == MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef USB
+/**
+ *  @brief Get/Set USB packet aggregation parameters
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_usb_aggr_ctrl(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	if (pmadapter->pcard_usb->fw_usb_aggr == MFALSE) {
+		PRINTM(MERROR, "USB aggregation not supported by FW\n");
+		pioctl_req->status_code = MLAN_ERROR_CMD_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv,
+			       HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc->param.usb_aggr_params);
+
+	if (ret == MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Get/Set Tx control configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_txcontrol(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		pmpriv->pkt_tx_ctrl = misc->param.tx_control;
+	else
+		misc->param.tx_control = pmpriv->pkt_tx_ctrl;
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+/**
+ *  @brief Get/Set RX packet coalescing configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_rx_pkt_coalesce_config(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_PKT_COALESCE_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc->param.rx_coalesce);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Is any uAP started or STA connected?
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MTRUE/MFALSE
+ */
+t_bool
+wlan_check_interface_active(mlan_adapter *pmadapter)
+{
+	t_bool ret = MFALSE;
+	pmlan_private pmpriv;
+	int i;
+
+	if (pmadapter == MNULL)
+		return MFALSE;
+
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		pmpriv = pmadapter->priv[i];
+		if (pmpriv) {
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+				ret = pmpriv->uap_bss_started;
+			else
+#endif
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+				ret = pmpriv->media_connected;
+		}
+		if (ret)
+			return MTRUE;
+	}
+
+	return MFALSE;
+}
+
+/**
+ *  @brief Get/Set DFS REPEATER mode
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_dfs_repeater_cfg(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		/* Make sure no interface is active
+		 * before setting the dfs repeater mode
+		 */
+		if (wlan_check_interface_active(pmadapter)) {
+			PRINTM(MMSG, "DFS-Repeater active priv found,"
+			       " skip enabling the mode.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		cmd_action = HostCmd_ACT_GEN_SET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_DFS_REPEATER_MODE, cmd_action, 0,
+			       (t_void *)pioctl_req, &misc->param.dfs_repeater);
+
+done:
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Low Power Mode
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_low_pwr_mode(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCMD_CONFIG_LOW_POWER_MODE,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       &misc->param.low_pwr_mode);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure PMIC in Firmware
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_pmic_configure(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_PMIC_CONFIGURE,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/*  @brief Set/Get CW Mode Level control
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_cwmode_ctrl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CW_MODE_CTRL, cmd_action, 0,
+			       (t_void *)pioctl_req, &misc->param.cwmode);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief push value to stack
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s        A pointer to mef_stack
+ *  @param len          Length of value
+ *  @param val          A pointer to value
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+inline mlan_status
+push_n(pmlan_adapter pmadapter, mef_stack *s, t_u8 len, t_u8 *val)
+{
+	if ((s->sp + len) <= MAX_NUM_STACK_BYTES) {
+		memcpy_ext(pmadapter, s->byte + s->sp, val, len,
+			   MAX_NUM_STACK_BYTES - s->sp);
+		s->sp += len;
+		return MLAN_STATUS_SUCCESS;
+	} else {
+		PRINTM(MERROR, "Stack is full\n");
+		return MLAN_STATUS_FAILURE;
+	}
+}
+
+/**
+ *  @brief push value to stack accoring to operand type
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s        A pointer to mef_stack
+ *  @param op           A pointer to mef_op
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+inline mlan_status
+mef_push(pmlan_adapter pmadapter, mef_stack *s, mef_op *op)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 nbytes;
+	switch (op->operand_type) {
+	case OPERAND_DNUM:
+		ret = push_n(pmadapter, s, 4, op->val);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = push_n(pmadapter, s, 1, &op->operand_type);
+		else
+			ret = MLAN_STATUS_FAILURE;
+		break;
+	case OPERAND_BYTE_SEQ:
+		nbytes = op->val[0];
+		if (MLAN_STATUS_SUCCESS ==
+		    push_n(pmadapter, s, nbytes, op->val + 1) &&
+		    MLAN_STATUS_SUCCESS == push_n(pmadapter, s, 1, op->val) &&
+		    MLAN_STATUS_SUCCESS ==
+		    push_n(pmadapter, s, 1, &op->operand_type))
+			ret = MLAN_STATUS_SUCCESS;
+		else
+			ret = MLAN_STATUS_FAILURE;
+		break;
+	default:
+		ret = push_n(pmadapter, s, 1, &op->operand_type);
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief push dnum filter to stack
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s        A pointer to mef_stack
+ *  @param filter       A pointer to filter item
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+static mlan_status
+push_filter_dnum_eq(pmlan_adapter pmadapter, mef_stack *s, mef_filter_t *filter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 dnum;
+	mef_op op;
+
+	ENTER();
+
+	if (!filter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (filter->fill_flag != (FILLING_TYPE | FILLING_PATTERN |
+				  FILLING_OFFSET | FILLING_NUM_BYTES)) {
+		PRINTM(MERROR, "Filter item fill error\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Format of decimal num:
+	 * |   5 bytes  |    5 bytes    |    5 bytes    |        1 byte | |
+	 * pattern  |     offset    |  num of bytes |  type (TYPE_DNUM_EQ)  |
+	 */
+
+	/* push pattern */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_DNUM;
+	dnum = filter->pattern;
+	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push offset */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_DNUM;
+	dnum = filter->offset;
+	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push num of bytes */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_DNUM;
+	dnum = filter->num_bytes;
+	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push type */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = TYPE_DNUM_EQ;
+	ret = mef_push(pmadapter, s, &op);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief push byte_eq filter to stack
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s            A pointer to mef_stack
+ *  @param filter       A pointer to filter item
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+static mlan_status
+push_filter_byte_eq(pmlan_adapter pmadapter, mef_stack *s, mef_filter_t *filter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 dnum;
+	mef_op op;
+
+	ENTER();
+
+	if (!filter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (filter->fill_flag != (FILLING_TYPE | FILLING_REPEAT |
+				  FILLING_BYTE_SEQ | FILLING_OFFSET)) {
+		PRINTM(MERROR, "Filter item fill error\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Format of decimal num:
+	 * |   5 bytes  |      val      |    5 bytes    |        1 byte | |
+	 * repeat   |   bytes seq   |    offset     |  type (TYPE_BYTE_EQ)  |
+	 */
+
+	/* push repeat */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_DNUM;
+	dnum = filter->repeat;
+	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push bytes seq */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_BYTE_SEQ;
+	op.val[0] = filter->num_byte_seq;
+	memcpy_ext(pmadapter, &op.val[1], filter->byte_seq,
+		   filter->num_byte_seq, MAX_NUM_BYTE_SEQ);
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push offset */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_DNUM;
+	dnum = filter->offset;
+	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push type */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = TYPE_BYTE_EQ;
+	ret = mef_push(pmadapter, s, &op);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief push bite_eq filter to stack
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s            A pointer to mef_stack
+ *  @param filter       A pointer to filter item
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+static mlan_status
+push_filter_bit_eq(pmlan_adapter pmadapter, mef_stack *s, mef_filter_t *filter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 dnum;
+	mef_op op;
+
+	ENTER();
+
+	if (!filter) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (filter->fill_flag != (FILLING_TYPE | FILLING_REPEAT |
+				  FILLING_BYTE_SEQ | FILLING_OFFSET)) {
+		PRINTM(MERROR, "Filter item fill error\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Format of decimal num:
+	 * |   val      |    5 bytes    |      val      |        1 byte | |
+	 * bytes seq  |    offset     |    mask seq   |  type (TYPE_BIT_EQ)   |
+	 */
+
+	/* push bytes seq */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_BYTE_SEQ;
+	op.val[0] = filter->num_byte_seq;
+	memcpy_ext(pmadapter, &op.val[1], filter->byte_seq,
+		   filter->num_byte_seq, MAX_NUM_BYTE_SEQ);
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push offset */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_DNUM;
+	dnum = filter->offset;
+	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push mask seq */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = OPERAND_BYTE_SEQ;
+	op.val[0] = filter->num_mask_seq;
+	memcpy_ext(pmadapter, &op.val[1], filter->mask_seq,
+		   filter->num_mask_seq, MAX_NUM_BYTE_SEQ);
+	ret = mef_push(pmadapter, s, &op);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* push type */
+	memset(pmadapter, &op, 0, sizeof(op));
+	op.operand_type = TYPE_BIT_EQ;
+	ret = mef_push(pmadapter, s, &op);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief push filter to stack
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s        A pointer to mef_stack
+ *  @param filter       A pointer to filter item
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+static mlan_status
+wlan_push_filter(pmlan_adapter pmadapter, mef_stack *s, mef_filter_t *filter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	switch (filter->type) {
+	case TYPE_DNUM_EQ:
+		ret = push_filter_dnum_eq(pmadapter, s, filter);
+		break;
+	case TYPE_BYTE_EQ:
+		ret = push_filter_byte_eq(pmadapter, s, filter);
+		break;
+	case TYPE_BIT_EQ:
+		ret = push_filter_bit_eq(pmadapter, s, filter);
+		break;
+	default:
+		PRINTM(MERROR, "Invalid filter type\n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+	return ret;
+}
+
+/**
+ *  @brief generate mef data
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param s        A pointer to mef_stack
+ *  @param entry        A pointer to mef_entry_t
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+static mlan_status
+wlan_generate_mef_filter_stack(pmlan_adapter pmadapter,
+			       mef_stack *s, mef_entry_t *entry)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mef_op op;
+	int i;
+
+	ENTER();
+
+	for (i = 0; i < entry->filter_num; i++) {
+		ret = wlan_push_filter(pmadapter, s, &entry->filter_item[i]);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR, "push filter to stack error\n");
+			goto done;
+		}
+		if (i != 0) {
+			memset(pmadapter, &op, 0, sizeof(op));
+			op.operand_type = entry->rpn[i];
+			ret = mef_push(pmadapter, s, &op);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "push filter rpn error\n");
+				goto done;
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set the mef entries to firmware
+ *
+ *  @param pmpriv        A pointer to mlan_private structure
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pmef      A pointer to mef_cfg structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status
+wlan_set_mef_entry(mlan_private *pmpriv,
+		   pmlan_adapter pmadapter, mef_cfg_data * pmef)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cmd *hostcmd;
+	HostCmd_DS_GEN *hostcmd_hdr;
+	HostCmd_DS_MEF_CFG *mef_hdr;
+	mef_entry_header *entry_hdr;
+	mef_stack *stack;
+	mef_entry_t *pentry;
+	t_u8 *buf;
+	t_u32 i, buf_len;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	if (pmef->entry_num > MAX_NUM_ENTRIES) {
+		PRINTM(MERROR, "Too many entries\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pcb = &pmadapter->callbacks;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+			       (t_u8 **)&hostcmd);
+	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+		PRINTM(MERROR, "Failed to allocate cmd data buffer\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_handle;
+	}
+
+	/** Fill the cmd header data*/
+	memset(pmadapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+	buf = hostcmd->cmd;
+	hostcmd_hdr = (HostCmd_DS_GEN *)buf;
+	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+	buf_len = S_DS_GEN;
+
+	/** Fill HostCmd_DS_MEF_CFG*/
+	mef_hdr = (HostCmd_DS_MEF_CFG *)(buf + buf_len);
+	mef_hdr->criteria = wlan_cpu_to_le32(pmef->criteria);
+	mef_hdr->nentries = wlan_cpu_to_le16(pmef->entry_num);
+	buf_len += sizeof(HostCmd_DS_MEF_CFG);
+
+	/** generate mef entry data*/
+	for (i = 0, pentry = pmef->pentry; i < pmef->entry_num; i++, pentry++) {
+		/** Fill entry header data*/
+		entry_hdr = (mef_entry_header *)(buf + buf_len);
+		entry_hdr->mode = pentry->mode;
+		entry_hdr->action = pentry->action;
+		buf_len += sizeof(mef_entry_header);
+
+		/** Fill Stack data*/
+		stack = (mef_stack *)(buf + buf_len);
+		ret = wlan_generate_mef_filter_stack(pmadapter, stack, pentry);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR, "Generate mef data error\n");
+			goto err_handle;
+		}
+		buf_len += (stack->sp + sizeof(stack->sp));
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = wlan_cpu_to_le32(buf_len);
+
+	DBG_HEXDUMP(MCMD_D, "MEF DATA", (t_u8 *)hostcmd, buf_len + 4);
+
+	/** Send command to firmware*/
+	ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)MNULL,
+			       (t_void *)hostcmd);
+
+err_handle:
+	if (hostcmd)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+done:
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  @brief generate Host_CMD_MEF_CFG cmd data to firmware
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or FAIL
+ */
+mlan_status
+wlan_process_mef_cfg_cmd(mlan_private *pmpriv, pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+	mef_cfg_data mef;
+	mef_entry_t *pentry;
+	mef_entry *pmef;
+	t_u16 entry_num = 0;
+
+	ENTER();
+
+	pcb = &pmadapter->callbacks;
+
+	/** check how many entries in adapter*/
+	pmef = &pmadapter->entry_cfg;
+	entry_num += pmef->enable_autoarp_entry;
+	entry_num += pmef->num_wowlan_entry;
+	entry_num += pmef->num_ipv6_ns_offload;
+	if (!entry_num) {
+		PRINTM(MIOCTL, "No filter entries\n");
+		goto done;
+	}
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mef_entry_t) * entry_num, MLAN_MEM_DEF,
+			       (t_u8 **)&mef.pentry);
+	if (ret != MLAN_STATUS_SUCCESS || mef.pentry == MNULL) {
+		PRINTM(MERROR, "Failed to allocate cmd data buffer\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_handle;
+	}
+	/** Fill mef_cfg structure*/
+	mef.criteria = pmef->criteria;
+	mef.entry_num = entry_num;
+	memset(pmadapter, mef.pentry, 0, sizeof(mef_entry_t) * entry_num);
+	pentry = mef.pentry;
+	/** Fill mef_entry_t structure*/
+	/** Copy Auto arp response entry*/
+	if (pmef->enable_autoarp_entry) {
+		memcpy_ext(pmadapter, pentry, &pmef->entry[5],
+			   sizeof(mef_entry_t), sizeof(mef_entry_t));
+		pentry += pmef->enable_autoarp_entry;
+	}
+	/** Copy wowlan entry*/
+	if (pmef->num_wowlan_entry) {
+		memcpy_ext(pmadapter, pentry, &pmef->entry[6],
+			   sizeof(mef_entry_t), sizeof(mef_entry_t));
+		pentry += pmef->num_wowlan_entry;
+	}
+	/** Copy IPv6 NS message offload entry */
+	if (pmef->num_ipv6_ns_offload)
+		memcpy_ext(pmadapter, pentry, &pmef->entry[7],
+			   sizeof(mef_entry_t), sizeof(mef_entry_t));
+
+	/** Set Entries to firmware*/
+	ret = wlan_set_mef_entry(pmpriv, pmadapter, &mef);
+	if (ret != MLAN_STATUS_SUCCESS)
+		PRINTM(MERROR, "Set MEF entries error\n");
+
+err_handle:
+	if (mef.pentry)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)mef.pentry);
+done:
+	LEAVE();
+	return ret;
+}
+
+/*  @brief Get/Set NV-FLT-CONFIG parameters
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	mlan_ds_misc_mef_flt_cfg *mef_cfg = MNULL;
+	mef_entry *pmef = MNULL;
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mef_cfg = &misc_cfg->param.mef_flt_cfg;
+	pmef = &pmadapter->entry_cfg;
+	switch (pioctl_req->action) {
+	case MLAN_ACT_SET:
+		if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN) {
+			pmef->num_wowlan_entry = 1;
+			pmef->criteria |= mef_cfg->criteria;
+			memcpy_ext(pmadapter, &pmef->entry[6],
+				   &mef_cfg->mef_entry, sizeof(mef_entry_t),
+				   sizeof(mef_entry_t));
+		}
+		if (mef_cfg->mef_act_type == MEF_ACT_IPV6_NS) {
+			pmef->num_ipv6_ns_offload = 1;
+			pmef->criteria |= mef_cfg->criteria;
+			memcpy_ext(pmadapter, &pmef->entry[7],
+				   &mef_cfg->mef_entry, sizeof(mef_entry_t),
+				   sizeof(mef_entry_t));
+		}
+		/** Set AUTO ARP Entry to adapter*/
+		if (mef_cfg->mef_act_type == MEF_ACT_AUTOARP) {
+			if (mef_cfg->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP) {
+				pmef->enable_autoarp_entry = 1;
+				pmef->criteria |= mef_cfg->criteria;
+				memcpy_ext(pmadapter, &pmef->entry[5],
+					   &mef_cfg->mef_entry,
+					   sizeof(mef_entry_t),
+					   sizeof(mef_entry_t));
+				if (MLAN_STATUS_SUCCESS !=
+				    wlan_process_mef_cfg_cmd(pmadapter->
+							     priv[pioctl_req->
+								  bss_index],
+							     pmadapter))
+					PRINTM(MERROR,
+					       "Set MEF Entries Error\n");
+			} else if (mef_cfg->op_code & MLAN_IPADDR_OP_IP_REMOVE) {
+				pmef->enable_autoarp_entry = 0;
+				memset(pmadapter, &pmef->entry[5], 0,
+				       sizeof(mef_entry_t));
+			}
+		}
+		break;
+	case MLAN_ACT_GET:
+		if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN)
+			memcpy_ext(pmadapter, &mef_cfg->mef_entry,
+				   &pmef->entry[6], sizeof(mef_entry_t),
+				   sizeof(mef_entry_t));
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get WPA passphrase for esupplicant
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_sec_ioctl_passphrase(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	t_u16 cmd_action = 0;
+#ifdef STA_SUPPORT
+	BSSDescriptor_t *pbss_desc;
+	int i = 0;
+#endif
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
+	    !IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
+		if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
+			SupplicantQueryPassphrase(pmpriv->psapriv,
+						  (void *)&sec->param.
+						  passphrase);
+		else if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
+			SupplicantClearPMK(pmpriv->psapriv,
+					   (void *)&sec->param.passphrase);
+		else
+			SupplicantSetPassphrase(pmpriv->psapriv,
+						(void *)&sec->param.passphrase);
+
+		LEAVE();
+		return ret;
+	}
+#endif
+
+	if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
+		LEAVE();
+		return ret;
+	}
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
+			cmd_action = HostCmd_ACT_GEN_REMOVE;
+		else
+			cmd_action = HostCmd_ACT_GEN_SET;
+	} else if (pioctl_req->action == MLAN_ACT_CLEAR) {
+		cmd_action = HostCmd_ACT_GEN_REMOVE;
+	} else {
+		if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY) {
+#ifdef STA_SUPPORT
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
+			    sec->param.passphrase.ssid.ssid_len == 0) {
+				i = wlan_find_bssid_in_list(pmpriv,
+							    (t_u8 *)&sec->param.
+							    passphrase.bssid,
+							    MLAN_BSS_MODE_AUTO);
+				if (i >= 0) {
+					pbss_desc = &pmadapter->pscan_table[i];
+					memcpy_ext(pmadapter,
+						   &sec->param.passphrase.ssid,
+						   &pbss_desc->ssid,
+						   sizeof(mlan_802_11_ssid),
+						   sizeof(mlan_802_11_ssid));
+					memset(pmadapter,
+					       &sec->param.passphrase.bssid, 0,
+					       MLAN_MAC_ADDR_LENGTH);
+					PRINTM(MINFO,
+					       "PSK_QUERY: found ssid=%s\n",
+					       sec->param.passphrase.ssid.ssid);
+				}
+			} else
+#endif
+				memset(pmadapter, &sec->param.passphrase.bssid,
+				       0, MLAN_MAC_ADDR_LENGTH);
+		}
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PMK, cmd_action,
+			       0, (t_void *)pioctl_req, (t_void *)sec);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set per packet Txctl and Rxinfo configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_per_pkt_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	pmpriv->rx_pkt_info = MFALSE;
+	if (misc->param.txrx_pkt_ctrl & RX_PKT_INFO)
+		pmpriv->rx_pkt_info = MTRUE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get region code
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_region(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	int i;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		misc->param.region_code = pmadapter->region_code;
+	} else {
+		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+			PRINTM(MERROR,
+			       "ForceRegionRule is set in the on-chip OTP"
+			       " memory\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (misc->param.region_code == region_code_index[i]) {
+				pmadapter->region_code =
+					(t_u16)misc->param.region_code;
+				break;
+			}
+		}
+		/* It's unidentified region code */
+		if (i >= MRVDRV_MAX_REGION_CODE) {
+			PRINTM(MERROR, "Region Code not identified\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pmadapter->cfp_code_bg = misc->param.region_code;
+		pmadapter->cfp_code_a = misc->param.region_code;
+		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+					 pmadapter->config_bands |
+					 pmadapter->adhoc_start_band)) {
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure GPIO independent reset
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_ind_rst_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INDEPENDENT_RESET_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       (t_void *)&misc->param.ind_rst_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Get timestamp from firmware
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "No support set tsf!");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GET_TSF, cmd_action, 0,
+			       (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Create custom regulatory cfg
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "No support set channel region cfg!");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check operating class validation
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_operclass_validation(pmlan_adapter pmadapter,
+				     mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u8 channel, oper_class;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	channel = misc->param.bw_chan_oper.channel;
+	oper_class = misc->param.bw_chan_oper.oper_class;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		ret = wlan_check_operclass_validation(pmpriv, channel,
+						      oper_class);
+	} else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Get Region channel power setting
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_rgchnpwr_cfg(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Get CHAN_TPRC setting
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_get_chan_trpc_cfg(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CHANNEL_TRPC_CONFIG, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       (t_void *)&misc->param.trpc_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get non-global operating class
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_oper_class(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u8 channel, bandwidth, oper_class = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	channel = misc->param.bw_chan_oper.channel;
+	switch (misc->param.bw_chan_oper.bandwidth) {
+	case 20:
+		bandwidth = BW_20MHZ;
+		break;
+	case 40:
+		bandwidth = BW_40MHZ;
+		break;
+	case 80:
+		bandwidth = BW_80MHZ;
+		break;
+	default:
+		bandwidth = BW_20MHZ;
+		break;
+	}
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		ret = wlan_get_curr_oper_class(pmpriv, channel, bandwidth,
+					       &oper_class);
+		misc->param.bw_chan_oper.oper_class = oper_class;
+	} else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief config dynamic bandwidth
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_fw_dump_event(pmlan_adapter pmadapter,
+			      mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FW_DUMP_EVENT, cmd_action, 0,
+			       (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief config boot sleep
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_bootsleep(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action 0x%x\n",
+		       pioctl_req->action);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_BOOT_SLEEP, cmd_action, 0,
+			       (t_void *)pioctl_req, &misc->param.boot_sleep);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Infra/Ad-hoc band configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_radio_ioctl_band_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	t_u32 i, global_band = 0;
+	t_u32 infra_band = 0;
+	t_u32 adhoc_band = 0;
+	t_u32 adhoc_channel = 0;
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		infra_band = radio_cfg->param.band_cfg.config_bands;
+		adhoc_band = radio_cfg->param.band_cfg.adhoc_start_band;
+		adhoc_channel = radio_cfg->param.band_cfg.adhoc_channel;
+
+		/* SET Infra band */
+		if ((infra_band | pmadapter->fw_bands) & ~pmadapter->fw_bands) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		/* SET Ad-hoc Band */
+		if ((adhoc_band | pmadapter->fw_bands) & ~pmadapter->fw_bands) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (!adhoc_band)
+			adhoc_band = pmadapter->adhoc_start_band;
+
+		for (i = 0; i < pmadapter->priv_num; i++) {
+			if (pmadapter->priv[i] &&
+			    pmadapter->priv[i] != pmpriv &&
+			    GET_BSS_ROLE(pmadapter->priv[i]) ==
+			    MLAN_BSS_ROLE_STA)
+				global_band |=
+					(t_u32)pmadapter->priv[i]->config_bands;
+		}
+		global_band |= infra_band;
+
+		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+					 global_band | adhoc_band)) {
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#ifdef STA_SUPPORT
+		if (wlan_11d_set_universaltable(pmpriv,
+						global_band | adhoc_band)) {
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#endif
+		pmpriv->config_bands = infra_band;
+		pmadapter->config_bands = global_band;
+
+		pmadapter->adhoc_start_band = adhoc_band;
+		pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
+
+#ifdef STA_SUPPORT
+		/*
+		 * If no adhoc_channel is supplied verify if the existing
+		 * adhoc channel compiles with new adhoc_band
+		 */
+		if (!adhoc_channel) {
+			if (!wlan_find_cfp_by_band_and_channel
+			    (pmadapter, pmadapter->adhoc_start_band,
+			     pmpriv->adhoc_channel)) {
+				/* Pass back the default channel */
+				radio_cfg->param.band_cfg.adhoc_channel =
+					DEFAULT_AD_HOC_CHANNEL;
+				if ((pmadapter->adhoc_start_band & BAND_A)
+					) {
+					radio_cfg->param.band_cfg.
+						adhoc_channel =
+						DEFAULT_AD_HOC_CHANNEL_A;
+				}
+			}
+		} else {
+			/* Return error if adhoc_band and adhoc_channel
+			 * combination is invalid
+			 */
+			if (!wlan_find_cfp_by_band_and_channel
+			    (pmadapter, pmadapter->adhoc_start_band,
+			     (t_u16)adhoc_channel)) {
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+			pmpriv->adhoc_channel = (t_u8)adhoc_channel;
+		}
+
+#endif
+
+	} else {
+		/* Infra Bands   */
+		radio_cfg->param.band_cfg.config_bands = pmpriv->config_bands;
+		/* Adhoc Band    */
+		radio_cfg->param.band_cfg.adhoc_start_band =
+			pmadapter->adhoc_start_band;
+		/* Adhoc Channel */
+		radio_cfg->param.band_cfg.adhoc_channel = pmpriv->adhoc_channel;
+		/* FW support Bands */
+		radio_cfg->param.band_cfg.fw_bands = pmadapter->fw_bands;
+		PRINTM(MINFO, "Global config band = %d\n",
+		       pmadapter->config_bands);
+#ifdef STA_SUPPORT
+#endif
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Rx Abort Cfg
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_rxabortcfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_ABORT_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       &(pmisc->param.rx_abort_cfg));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Rx Abort Cfg ext
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_rxabortcfg_ext(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_ABORT_CFG_EXT, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       &(pmisc->param.rx_abort_cfg_ext));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Dot11mc unassociated FTM CFG
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmlan_adapter pmadapter,
+					pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &(pmisc->param.dot11mc_unassoc_ftm_cfg));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Tx ampdu protection mode
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tx_ampdu_prot_mode(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_AMPDU_PROT_MODE,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &(pmisc->param.tx_ampdu_prot_mode));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Rate adapt config
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_rate_adapt_cfg(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RATE_ADAPT_CFG, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       &(pmisc->param.rate_adapt_cfg));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief CCK Desense config
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_cck_desense_cfg(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CCK_DESENSE_CFG, cmd_action,
+			       0, (t_void *)pioctl_req,
+			       &(pmisc->param.cck_desense_cfg));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief config dynamic bandwidth
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_dyn_bw(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DYN_BW, cmd_action, 0,
+			       (t_void *)pioctl_req, &misc->param.dyn_bw);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get low power mode configuration parameter
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+mlan_status
+wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_power_cfg *pm_cfg = MNULL;
+	t_u16 cmd_action = 0, lpm = 0;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		cmd_action = HostCmd_ACT_GEN_SET;
+		lpm = pm_cfg->param.lpm;
+	}
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_LOW_POWER_MODE_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req, &lpm);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief RF Test Mode config
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = MNULL;
+	mlan_ds_misc_cfg *pmisc = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (!pioctl_req)
+		goto done;
+
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	switch (pmisc->sub_command) {
+	case MLAN_OID_MISC_RF_TEST_GENERIC:
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else
+			cmd_action = HostCmd_ACT_GEN_GET;
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &(pmisc->param.mfg_generic_cfg));
+		break;
+	case MLAN_OID_MISC_RF_TEST_TX_CONT:
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else {
+			PRINTM(MERROR, "Unsupported cmd_action\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &(pmisc->param.mfg_tx_cont));
+		break;
+	case MLAN_OID_MISC_RF_TEST_TX_FRAME:
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else {
+			PRINTM(MERROR, "Unsupported cmd_action\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &(pmisc->param.mfg_tx_frame2));
+		break;
+	case MLAN_OID_MISC_RF_TEST_HE_POWER:
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else {
+			PRINTM(MERROR, "Unsupported cmd_action\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &(pmisc->param.mfg_he_power));
+		break;
+	}
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Range ext mode config
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RANGE_EXT, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       &(pmisc->param.range_ext_mode));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+
+}
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief set wacp mode
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return            MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_wacp_mode(IN pmlan_adapter pmadapter,
+			  IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	ret = wlan_prepare_cmd(pmpriv,
+			       HOST_CMD_APCMD_SYS_CONFIGURE,
+			       cmd_action,
+			       0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&misc->param.wacp_mode);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif
diff --git a/wlan_sd8987/mlan/mlan_module.c b/wlan_sd8987/mlan/mlan_module.c
new file mode 100755
index 0000000..724c794
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_module.c
@@ -0,0 +1,68 @@
+/** @file mlan_module.c
+ *
+ *  @brief This file declares the exported symbols from MLAN.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    12/08/2008: initial version
+******************************************************/
+
+#ifdef LINUX
+#include <linux/module.h>
+#include "mlan_decl.h"
+#include "mlan_ioctl.h"
+
+EXPORT_SYMBOL(mlan_register);
+EXPORT_SYMBOL(mlan_unregister);
+EXPORT_SYMBOL(mlan_init_fw);
+EXPORT_SYMBOL(mlan_set_init_param);
+EXPORT_SYMBOL(mlan_dnld_fw);
+EXPORT_SYMBOL(mlan_shutdown_fw);
+#ifdef USB
+EXPORT_SYMBOL(mlan_write_data_async_complete);
+EXPORT_SYMBOL(mlan_recv);
+#endif
+EXPORT_SYMBOL(mlan_send_packet);
+EXPORT_SYMBOL(mlan_ioctl);
+EXPORT_SYMBOL(mlan_main_process);
+EXPORT_SYMBOL(mlan_rx_process);
+EXPORT_SYMBOL(mlan_select_wmm_queue);
+EXPORT_SYMBOL(mlan_process_deaggr_pkt);
+#if defined(SDIO) || defined(PCIE)
+EXPORT_SYMBOL(mlan_interrupt);
+#if defined(SYSKT)
+EXPORT_SYMBOL(mlan_hs_callback);
+#endif /* SYSKT_MULTI || SYSKT */
+#endif /* SDIO || PCIE */
+
+EXPORT_SYMBOL(mlan_pm_wakeup_card);
+EXPORT_SYMBOL(mlan_is_main_process_running);
+#ifdef PCIE
+EXPORT_SYMBOL(mlan_set_int_mode);
+#endif
+EXPORT_SYMBOL(mlan_disable_host_int);
+EXPORT_SYMBOL(mlan_enable_host_int);
+
+MODULE_DESCRIPTION("M-WLAN MLAN Driver");
+MODULE_AUTHOR("NXP");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
+#endif /* LINUX */
diff --git a/wlan_sd8987/mlan/mlan_pcie.c b/wlan_sd8987/mlan/mlan_pcie.c
new file mode 100755
index 0000000..2aa9e1a
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_pcie.c
@@ -0,0 +1,4575 @@
+/** @file mlan_pcie.c
+ *
+ *  @brief This file contains PCI-E specific code
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/01/2012: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_pcie.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+#ifdef PCIE8897
+static const struct _mlan_pcie_card_reg mlan_reg_pcie8897 = {
+	.reg_txbd_rdptr = PCIE8897_RD_DATA_PTR_Q0_Q1,
+	.reg_txbd_wrptr = PCIE8897_WR_DATA_PTR_Q0_Q1,
+	.reg_rxbd_rdptr = PCIE8897_RD_DATA_PTR_Q0_Q1,
+	.reg_rxbd_wrptr = PCIE8897_WR_DATA_PTR_Q0_Q1,
+	.reg_evtbd_rdptr = REG_EVTBD_RDPTR,
+	.reg_evtbd_wrptr = REG_EVTBD_WRPTR,
+	.reg_host_int_mask = PCIE_HOST_INT_MASK,
+	.reg_host_int_status_mask = PCIE_HOST_INT_STATUS_MASK,
+	.reg_host_int_status = PCIE_HOST_INT_STATUS,
+	.reg_cpu_int_event = PCIE_CPU_INT_EVENT,
+	.reg_ip_rev = PCIE_IP_REV_REG,
+	.reg_drv_ready = REG_DRV_READY,
+	.reg_cpu_int_status = PCIE_CPU_INT_STATUS,
+	.reg_scratch_0 = PCIE_SCRATCH_0_REG,
+	.reg_scratch_1 = PCIE_SCRATCH_1_REG,
+	.reg_scratch_2 = PCIE_SCRATCH_2_REG,
+	.reg_scratch_3 = PCIE_SCRATCH_3_REG,
+	.host_intr_mask = HOST_INTR_MASK,
+	.host_intr_dnld_done = HOST_INTR_DNLD_DONE,
+	.host_intr_upld_rdy = HOST_INTR_UPLD_RDY,
+	.host_intr_cmd_done = HOST_INTR_CMD_DONE,
+	.host_intr_event_rdy = HOST_INTR_EVENT_RDY,
+	.txrx_rw_ptr_mask = 0x000003FF,
+	.txrx_rw_ptr_wrap_mask = 0x000007FF,
+	.txrx_rw_ptr_rollover_ind = MBIT(10),
+	.use_adma = MFALSE,
+	.msi_int_wr_clr = MTRUE,
+};
+
+static const struct _mlan_card_info mlan_card_info_pcie8897 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 0,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef PCIE8997
+static const struct _mlan_pcie_card_reg mlan_reg_pcie8997 = {
+	.reg_txbd_rdptr = PCIE8997_RD_DATA_PTR_Q0_Q1,
+	.reg_txbd_wrptr = PCIE8997_WR_DATA_PTR_Q0_Q1,
+	.reg_rxbd_rdptr = PCIE8997_RD_DATA_PTR_Q0_Q1,
+	.reg_rxbd_wrptr = PCIE8997_WR_DATA_PTR_Q0_Q1,
+	.reg_evtbd_rdptr = REG_EVTBD_RDPTR,
+	.reg_evtbd_wrptr = REG_EVTBD_WRPTR,
+	.reg_host_int_mask = PCIE_HOST_INT_MASK,
+	.reg_host_int_status_mask = PCIE_HOST_INT_STATUS_MASK,
+	.reg_host_int_status = PCIE_HOST_INT_STATUS,
+	.reg_cpu_int_event = PCIE_CPU_INT_EVENT,
+	.reg_ip_rev = PCIE_IP_REV_REG,
+	.reg_drv_ready = REG_DRV_READY,
+	.reg_cpu_int_status = PCIE_CPU_INT_STATUS,
+	.reg_scratch_0 = PCIE_SCRATCH_0_REG,
+	.reg_scratch_1 = PCIE_SCRATCH_1_REG,
+	.reg_scratch_2 = PCIE_SCRATCH_2_REG,
+	.reg_scratch_3 = PCIE_SCRATCH_3_REG,
+	.host_intr_mask = HOST_INTR_MASK,
+	.host_intr_dnld_done = HOST_INTR_DNLD_DONE,
+	.host_intr_upld_rdy = HOST_INTR_UPLD_RDY,
+	.host_intr_cmd_done = HOST_INTR_CMD_DONE,
+	.host_intr_event_rdy = HOST_INTR_EVENT_RDY,
+	.txrx_rw_ptr_mask = 0x00000FFF,
+	.txrx_rw_ptr_wrap_mask = 0x00001FFF,
+	.txrx_rw_ptr_rollover_ind = MBIT(12),
+	.use_adma = MFALSE,
+	.msi_int_wr_clr = MTRUE,
+};
+
+static const struct _mlan_card_info mlan_card_info_pcie8997 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef PCIE9097
+static const struct _mlan_pcie_card_reg mlan_reg_pcie9097_b0 = {
+	.reg_txbd_rdptr = PCIE9098_TXBD_RDPTR,
+	.reg_txbd_wrptr = PCIE9098_TXBD_WRPTR,
+	.reg_rxbd_rdptr = PCIE9098_RXBD_RDPTR,
+	.reg_rxbd_wrptr = PCIE9098_RXBD_WRPTR,
+	.reg_evtbd_rdptr = PCIE9098_EVTBD_RDPTR,
+	.reg_evtbd_wrptr = PCIE9098_EVTBD_WRPTR,
+	.reg_host_int_mask = PCIE9097_B0_HOST_INT_MASK,
+	.reg_host_int_status_mask = PCIE9097_B0_HOST_INT_STATUS_MASK,
+	.reg_host_int_status = PCIE9097_B0_HOST_INT_STATUS,
+	.reg_host_int_clr_sel = PCIE9097_B0_HOST_INT_CLR_SEL,
+	.reg_cpu_int_event = PCIE9098_CPU_INT_EVENT,
+	.reg_ip_rev = PCIE9098_DEV_ID_REG,
+	.reg_drv_ready = PCIE9098_DRV_READY,
+	.reg_cpu_int_status = PCIE9098_CPU_INT_STATUS,
+	.reg_rev_id = PCIE9098_REV_ID_REG,
+	.reg_scratch_0 = PCIE9098_SCRATCH_0_REG,
+	.reg_scratch_1 = PCIE9098_SCRATCH_1_REG,
+	.reg_scratch_2 = PCIE9098_SCRATCH_2_REG,
+	.reg_scratch_3 = PCIE9098_SCRATCH_3_REG,
+	.reg_scratch_6 = PCIE9098_SCRATCH_6_REG,
+	.reg_scratch_7 = PCIE9098_SCRATCH_7_REG,
+	.host_intr_mask = PCIE9098_HOST_INTR_MASK,
+	.host_intr_dnld_done = PCIE9098_HOST_INTR_DNLD_DONE,
+	.host_intr_upld_rdy = PCIE9098_HOST_INTR_UPLD_RDY,
+	.host_intr_cmd_done = PCIE9098_HOST_INTR_CMD_DONE,
+	.host_intr_event_rdy = PCIE9098_HOST_INTR_EVENT_RDY,
+	.host_intr_cmd_dnld = PCIE9098_HOST_INTR_CMD_DNLD,
+	.use_adma = MTRUE,
+	.msi_int_wr_clr = MTRUE,
+};
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+static const struct _mlan_pcie_card_reg mlan_reg_pcie9098 = {
+	.reg_txbd_rdptr = PCIE9098_TXBD_RDPTR,
+	.reg_txbd_wrptr = PCIE9098_TXBD_WRPTR,
+	.reg_rxbd_rdptr = PCIE9098_RXBD_RDPTR,
+	.reg_rxbd_wrptr = PCIE9098_RXBD_WRPTR,
+	.reg_evtbd_rdptr = PCIE9098_EVTBD_RDPTR,
+	.reg_evtbd_wrptr = PCIE9098_EVTBD_WRPTR,
+	.reg_host_int_mask = PCIE9098_HOST_INT_MASK,
+	.reg_host_int_status_mask = PCIE9098_HOST_INT_STATUS_MASK,
+	.reg_host_int_status = PCIE9098_HOST_INT_STATUS,
+	.reg_host_int_clr_sel = PCIE9098_HOST_INT_CLR_SEL,
+	.reg_cpu_int_event = PCIE9098_CPU_INT_EVENT,
+	.reg_ip_rev = PCIE9098_DEV_ID_REG,
+	.reg_drv_ready = PCIE9098_DRV_READY,
+	.reg_cpu_int_status = PCIE9098_CPU_INT_STATUS,
+	.reg_rev_id = PCIE9098_REV_ID_REG,
+	.reg_scratch_0 = PCIE9098_SCRATCH_0_REG,
+	.reg_scratch_1 = PCIE9098_SCRATCH_1_REG,
+	.reg_scratch_2 = PCIE9098_SCRATCH_2_REG,
+	.reg_scratch_3 = PCIE9098_SCRATCH_3_REG,
+	.reg_scratch_6 = PCIE9098_SCRATCH_6_REG,
+	.reg_scratch_7 = PCIE9098_SCRATCH_7_REG,
+	.host_intr_mask = PCIE9098_HOST_INTR_MASK,
+	.host_intr_dnld_done = PCIE9098_HOST_INTR_DNLD_DONE,
+	.host_intr_upld_rdy = PCIE9098_HOST_INTR_UPLD_RDY,
+	.host_intr_cmd_done = PCIE9098_HOST_INTR_CMD_DONE,
+	.host_intr_event_rdy = PCIE9098_HOST_INTR_EVENT_RDY,
+	.host_intr_cmd_dnld = PCIE9098_HOST_INTR_CMD_DNLD,
+	.use_adma = MTRUE,
+	.msi_int_wr_clr = MTRUE,
+};
+
+static const struct _mlan_card_info mlan_card_info_pcie9098 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+static mlan_status wlan_pcie_delete_evtbd_ring(pmlan_adapter pmadapter);
+static mlan_status wlan_pcie_delete_rxbd_ring(pmlan_adapter pmadapter);
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/**
+ *  @brief This function init the adma setting
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param adma_type  TX/RX data, event, cmd/cmdresp
+ *  @param pbase      physical address
+ *  @param size       desc num/dma_size
+ *  @param init       init flag
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_init_adma(mlan_adapter *pmadapter, t_u8 type,
+	       t_u64 pbase, t_u16 size, t_u8 init)
+{
+	t_u32 dma_cfg, dma_cfg2, dma_cfg3, int_mapping;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 q_addr = 0;
+	t_u8 direction = 0;
+	t_u8 dma_mode = 0;
+	t_u32 msix_data;
+	t_u32 msix_vector;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	if (init)
+		PRINTM(MCMND, "Init ADMA: type=%d, size=%d init=%d\n", type,
+		       size, init);
+	switch (type) {
+	case ADMA_TX_DATA:
+		q_addr = ADMA_CHAN0_Q0;
+		direction = ADMA_HOST_TO_DEVICE;
+		dma_mode = DMA_MODE_DUAL_DESC;
+		msix_vector = ADMA_VECTOR_CHAN0_Q0;
+		break;
+	case ADMA_RX_DATA:
+		q_addr = ADMA_CHAN1_Q0;
+		direction = ADMA_DEVICE_TO_HOST;
+		dma_mode = DMA_MODE_DUAL_DESC;
+		msix_vector = AMDA_VECTOR_CHAN1_Q0;
+		break;
+	case ADMA_EVENT:
+		q_addr = ADMA_CHAN1_Q1;
+		direction = ADMA_DEVICE_TO_HOST;
+		dma_mode = DMA_MODE_DUAL_DESC;
+		msix_vector = AMDA_VECTOR_CHAN1_Q1;
+		break;
+	case ADMA_CMD:
+		q_addr = ADMA_CHAN2_Q0;
+		direction = ADMA_HOST_TO_DEVICE;
+		dma_mode = DMA_MODE_DIRECT;
+		msix_vector = AMDA_VECTOR_CHAN2_Q0;
+		break;
+	case ADMA_CMDRESP:
+		q_addr = ADMA_CHAN2_Q1;
+		direction = ADMA_DEVICE_TO_HOST;
+		dma_mode = DMA_MODE_DIRECT;
+		msix_vector = AMDA_VECTOR_CHAN2_Q1;
+		break;
+	default:
+		PRINTM(MERROR, "unknow adma type\n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+	if (ret)
+		goto done;
+	if (init) {
+		if (dma_mode == DMA_MODE_DUAL_DESC) {
+			if (direction == ADMA_HOST_TO_DEVICE)
+				int_mapping = DEST_INT_TO_DEVICE;
+			else
+				int_mapping = DEST_INT_TO_HOST;
+		} else {
+			int_mapping = 0;
+		}
+		/* set INT_MAPPING register */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_INT_MAPPING,
+					(t_u32)int_mapping)) {
+			PRINTM(MERROR,
+			       "Failed to write ADMA_INT_MAPPING register.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Read the dma_cfg2 register */
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       q_addr + ADMA_DMA_CFG2, &dma_cfg2)) {
+			PRINTM(MERROR, "Fail to read DMA CFG2 register\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		dma_cfg2 &= ~(ADMA_SRC_DMA_DONE_INT_BYPASS_EN |
+			      ADMA_DST_DMA_DONE_INT_BYPASS_EN |
+			      ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN |
+			      ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN |
+			      ADMA_MSI_LEGACY_ENABLE | ADMA_MSIX_ENABLE |
+			      ADMA_MSIX_INT_SRC_DST_SEL);
+
+		if (dma_mode == DMA_MODE_DUAL_DESC) {
+			if (direction == ADMA_HOST_TO_DEVICE) {
+				dma_cfg2 |= ADMA_SRC_DMA_DONE_INT_BYPASS_EN;
+				if (pmadapter->pcard_pcie->pcie_int_mode !=
+				    PCIE_INT_MODE_MSIX)
+					dma_cfg2 |=
+						ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN;
+			} else {
+				/* Read the dma_cfg3 register */
+				if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+						       q_addr + ADMA_DMA_CFG3,
+						       &dma_cfg3)) {
+					PRINTM(MERROR,
+					       "Fail to read DMA CFG3 register\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+				dma_cfg3 |= ADMA_Q_PTR_CLR;
+				if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+							q_addr + ADMA_DMA_CFG3,
+							(t_u32)dma_cfg3)) {
+					PRINTM(MERROR,
+					       "Failed to write ADMA_DMA_CFG3.\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+
+				dma_cfg2 |= ADMA_DST_DMA_DONE_INT_BYPASS_EN;
+				if (pmadapter->pcard_pcie->pcie_int_mode !=
+				    PCIE_INT_MODE_MSIX)
+					dma_cfg2 |=
+						ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN;
+			}
+		} else {
+			if (direction == ADMA_HOST_TO_DEVICE)
+				dma_cfg2 |= ADMA_SRC_ADDR_IS_HOST;
+			else
+				dma_cfg2 |= ADMA_DST_ADDR_IS_HOST;
+		}
+
+		if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
+			if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+					       q_addr + ADMA_MSIX_DOORBELL_DATA,
+					       &msix_data)) {
+				PRINTM(MERROR,
+				       "Fail to read DMA MSIX data register\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			msix_data &= ~ADMA_MSIX_VECTOR_MASK;
+			msix_data &= ~ADMA_MSIX_PF_MASK;
+			msix_data |= msix_vector;
+			msix_data |= pmadapter->pcard_pcie->func_num
+				<< ADMA_MSIX_PF_BIT;
+			PRINTM(MCMND, "msix_data=0x%x\n", msix_data);
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						q_addr +
+						ADMA_MSIX_DOORBELL_DATA,
+						(t_u32)msix_data)) {
+				PRINTM(MERROR,
+				       "Failed to write DMA DOORBELL_DATA.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			dma_cfg2 |= ADMA_MSIX_ENABLE;
+		} else
+			dma_cfg2 |= ADMA_MSI_LEGACY_ENABLE;
+		PRINTM(MCMND, "dma_cfg2=0x%x\n", dma_cfg2);
+
+		/* enable INT_BYPASS_EN in the dma_cfg2 register */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_DMA_CFG2,
+					(t_u32)dma_cfg2)) {
+			PRINTM(MERROR, "Failed to write DMA CFG2.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	/* Read the TX ring read pointer set by firmware */
+	if (pcb->moal_read_reg(pmadapter->pmoal_handle, q_addr + ADMA_DMA_CFG,
+			       &dma_cfg)) {
+		PRINTM(MERROR, "Fail to read DMA CFG register\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (direction == ADMA_HOST_TO_DEVICE) {
+		/* Write the lower 32bits of the physical address to
+		 * ADMA_SRC_LOW */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_SRC_LOW, (t_u32)pbase)) {
+			PRINTM(MERROR, "Failed to write ADMA_SRC_LOW.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Write the upper 32bits of the physical address to
+		 * ADMA_SRC_HIGH */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_SRC_HIGH,
+					(t_u32)((t_u64)pbase >> 32))) {
+			PRINTM(MERROR, "Failed to write ADMA_SRC_HIGH.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if (init) {
+			/** Enable DMA done interrupt */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						q_addr +
+						ADMA_SRC_INT_STATUS_MASK,
+						DEF_ADMA_INT_MASK)) {
+				PRINTM(MERROR,
+				       "Failed to write ADMA_SRC_INT_STATUS_MASK.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						q_addr + ADMA_SRC_INT_MASK,
+						DEF_ADMA_INT_MASK)) {
+				PRINTM(MERROR,
+				       "Failed to write ADMA_SRC_INT_MASK.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		if (dma_mode == DMA_MODE_DUAL_DESC) {
+			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+				     SRC_NUM_DESC_MASK | DMA_SIZE_MASK);
+			dma_cfg |= (t_u32)size << SRC_NUM_DESC_BIT;
+			dma_cfg |= DESC_MODE_RING << 2;
+		} else {
+			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+				     SRC_NUM_DESC_MASK | DST_NUM_DESC_MASK |
+				     DMA_SIZE_MASK);
+			dma_cfg |= (t_u32)size << DMA_SIZE_BIT;
+		}
+	} else {
+		/* Write the lower 32bits of the physical address to
+		 * ADMA_DST_LOW */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_DST_LOW, (t_u32)pbase)) {
+			PRINTM(MERROR, "Failed to write ADMA_DST_LOW.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Write the upper 32bits of the physical address to
+		 * ADMA_DST_HIGH */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_DST_HIGH,
+					(t_u32)((t_u64)pbase >> 32))) {
+			PRINTM(MERROR, "Failed to write ADMA_DST_HIGH.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if (init && (dma_mode == DMA_MODE_DUAL_DESC)) {
+			/** Enable DMA done interrupt */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						q_addr +
+						ADMA_DST_INT_STATUS_MASK,
+						DEF_ADMA_INT_MASK)) {
+				PRINTM(MERROR,
+				       "Failed to write ADMA_SRC_INT_STATUS_MASK.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						q_addr + ADMA_DST_INT_MASK,
+						DEF_ADMA_INT_MASK)) {
+				PRINTM(MERROR,
+				       "Failed to write ADMA_SRC_INT_MASK.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		if (dma_mode == DMA_MODE_DUAL_DESC) {
+			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+				     DST_NUM_DESC_MASK | DMA_SIZE_MASK);
+			dma_cfg |= (t_u32)size << DST_NUM_DESC_BIT;
+			dma_cfg |= DESC_MODE_RING << 2;
+		} else {
+			dma_cfg &= ~(DESC_MODE_MASK | DMA_MODE_MASK |
+				     SRC_NUM_DESC_MASK | DST_NUM_DESC_MASK);
+		}
+	}
+	dma_cfg |= (t_u32)dma_mode;
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle, q_addr + ADMA_DMA_CFG,
+				dma_cfg)) {
+		PRINTM(MERROR, "Fail to set DMA CFG register\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (type == ADMA_CMD && !init) {
+		/* Write 1 to src_wr_ptr to trigger direct dma */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					q_addr + ADMA_SRC_RW_PTR, 1)) {
+			PRINTM(MERROR, "Failed to write ADMA_SRC_HIGH.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function init the adma ring size from user input
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      N/A
+ */
+static void
+wlan_pcie_init_adma_ring_size(mlan_adapter *pmadapter)
+{
+	t_u16 num_desc = 0;
+	t_u16 ring_size = 0;
+
+	ring_size = pmadapter->init_para.ring_size;
+	if (!ring_size)
+		return;
+	if (ring_size < MAX_TXRX_BD)
+		ring_size = MAX_TXRX_BD;
+	else if (ring_size > ADMA_MAX_TXRX_BD)
+		ring_size = ADMA_MAX_TXRX_BD;
+	if (ring_size != pmadapter->pcard_pcie->txrx_bd_size) {
+		ring_size = ring_size >> 1;
+		while (ring_size > 0) {
+			ring_size = ring_size >> 1;
+			num_desc++;
+		}
+		pmadapter->pcard_pcie->txrx_bd_size = 1 << num_desc;
+		pmadapter->pcard_pcie->txrx_num_desc = num_desc;
+	}
+	PRINTM(MMSG, "ring_size =%d num_desc=%d\n",
+	       pmadapter->pcard_pcie->txrx_bd_size,
+	       pmadapter->pcard_pcie->txrx_num_desc);
+	return;
+}
+
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/**
+ *  @brief This function set the host interrupt select mask
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param enable     0-disable 1-enable
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_set_host_int_select_mask(mlan_adapter *pmadapter, t_u8 enable)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 int_sel_mask = 0;
+	t_u32 int_clr_mask = 0;
+	ENTER();
+
+	if (enable) {
+		int_sel_mask = PCIE9098_HOST_INTR_SEL_MASK;
+		int_clr_mask = pmadapter->pcard_pcie->reg->host_intr_mask;
+	}
+
+	/* Simply write the mask to the register */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle, PCIE9098_HOST_INT_SEL,
+				int_sel_mask)) {
+		PRINTM(MWARN, "Set host interrupt select register failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+		if (!pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+			/** enable read to clear interrupt */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						pmadapter->pcard_pcie->reg->
+						reg_host_int_clr_sel,
+						int_clr_mask)) {
+				PRINTM(MWARN,
+				       "enable read to clear interrupt failed\n");
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/**
+ *  @brief This function handles command response completion
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pmbuf        A pointer to mlan_buffer
+ *
+ *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_send_vdll_complete(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pcmdbuf;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	/*unmap the cmd pmbuf, so the cpu can not access the memory in the
+	 * command node*/
+	pcmdbuf = pmadapter->pcard_pcie->vdll_cmd_buf;
+	if (pcmdbuf) {
+		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+				       pcmdbuf->pbuf + pcmdbuf->data_offset,
+				       pcmdbuf->buf_pa, pcmdbuf->data_len,
+				       PCI_DMA_TODEVICE);
+		pmadapter->pcard_pcie->vdll_cmd_buf = MNULL;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function downloads VDLL image to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to mlan_buffer
+ *
+ *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_send_vdll(mlan_adapter *pmadapter, mlan_buffer *pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u16 *tmp;
+	t_u8 *payload;
+
+	ENTER();
+	pmadapter->cmd_sent = MTRUE;
+	payload = pmbuf->pbuf + pmbuf->data_offset;
+
+	tmp = (t_u16 *)&payload[0];
+	*tmp = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	tmp = (t_u16 *)&payload[2];
+	*tmp = wlan_cpu_to_le16(MLAN_TYPE_VDLL);
+
+	if (MLAN_STATUS_FAILURE ==
+	    pcb->moal_map_memory(pmadapter->pmoal_handle,
+				 pmbuf->pbuf + pmbuf->data_offset,
+				 &pmbuf->buf_pa, pmbuf->data_len,
+				 PCI_DMA_TODEVICE)) {
+		PRINTM(MERROR,
+		       "PCIE - Download VDLL block: moal_map_memory failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pmadapter->pcard_pcie->vdll_cmd_buf = pmbuf;
+	/* issue the DMA */
+	/* send the VDLL block down to the firmware */
+	wlan_init_adma(pmadapter, ADMA_CMD, pmbuf->buf_pa, pmbuf->data_len,
+		       MFALSE);
+
+	PRINTM(MINFO, "PCIE - Download VDLL Block: successful.\n");
+done:
+	if (ret == MLAN_STATUS_FAILURE)
+		pmadapter->cmd_sent = MFALSE;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function disables the host interrupt
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_disable_host_int_mask(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_host_int_mask,
+				0x00000000)) {
+		PRINTM(MWARN, "Disable host interrupt failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupt
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_enable_host_int_mask(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	ENTER();
+	/* Simply write the mask to the register */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_host_int_mask,
+				pmadapter->pcard_pcie->reg->host_intr_mask)) {
+		PRINTM(MWARN, "Enable host interrupt failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param enable   0-disable 1-enable
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_enable_host_int_status_mask(mlan_adapter *pmadapter, t_u8 enable)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 host_int_status_mask = 0;
+	ENTER();
+	if (enable)
+		host_int_status_mask =
+			pmadapter->pcard_pcie->reg->host_intr_mask;
+	/* Enable host int status mask */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->
+				reg_host_int_status_mask,
+				host_int_status_mask)) {
+		PRINTM(MWARN, "Enable host interrupt status mask failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_disable_pcie_host_int(mlan_adapter *pmadapter)
+{
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_pcie_enable_host_int_status_mask(pmadapter, MFALSE);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+	    (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
+		ret = wlan_pcie_set_host_int_select_mask(pmadapter, MFALSE);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+#endif
+	ret = wlan_pcie_disable_host_int_mask(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and
+ *  handle it accordingly.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_clear_pending_int_status(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 pcie_ireg = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX)
+		goto done;
+	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_pcie->reg->reg_host_int_status,
+			       &pcie_ireg)) {
+		PRINTM(MERROR, "Read host int status register failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+		PRINTM(MMSG, "pcie_ireg=0x%x\n", pcie_ireg);
+		if (pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						pmadapter->pcard_pcie->reg->
+						reg_host_int_status,
+						~pcie_ireg)) {
+				PRINTM(MERROR,
+				       "Write host int status  register failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_enable_pcie_host_int(mlan_adapter *pmadapter)
+{
+	mlan_status ret;
+
+	ENTER();
+	wlan_clear_pending_int_status(pmadapter);
+	ret = wlan_pcie_enable_host_int_status_mask(pmadapter, MTRUE);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+	    (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
+		ret = wlan_pcie_set_host_int_select_mask(pmadapter, MTRUE);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+#endif
+	ret = wlan_pcie_enable_host_int_mask(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function creates buffer descriptor ring for TX
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_create_txbd_ring(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 i;
+#if defined(PCIE8997) || defined(PCIE8897)
+	pmlan_pcie_data_buf ptx_bd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	padma_dual_desc_buf padma_bd_buf;
+#endif
+
+	ENTER();
+	/*
+	 * driver maintaines the write pointer and firmware maintaines the read
+	 * pointer.
+	 */
+	pmadapter->pcard_pcie->txbd_wrptr = 0;
+	pmadapter->pcard_pcie->txbd_pending = 0;
+	pmadapter->pcard_pcie->txbd_rdptr = 0;
+
+	/* allocate shared memory for the BD ring and divide the same in to
+	   several descriptors */
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma)
+		pmadapter->pcard_pcie->txbd_ring_size =
+			sizeof(mlan_pcie_data_buf) *
+			pmadapter->pcard_pcie->txrx_bd_size;
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma)
+		pmadapter->pcard_pcie->txbd_ring_size =
+			sizeof(adma_dual_desc_buf) *
+			pmadapter->pcard_pcie->txrx_bd_size;
+#endif
+	PRINTM(MINFO, "TX ring: allocating %d bytes\n",
+	       pmadapter->pcard_pcie->txbd_ring_size);
+
+	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+					  pmadapter->pcard_pcie->txbd_ring_size,
+					  &pmadapter->pcard_pcie->
+					  txbd_ring_vbase,
+					  &pmadapter->pcard_pcie->
+					  txbd_ring_pbase);
+
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+		       __FUNCTION__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	PRINTM(MINFO,
+	       "TX ring: - base: %p, pbase: %#x:%x,"
+	       "len: %x\n",
+	       pmadapter->pcard_pcie->txbd_ring_vbase,
+	       (t_u32)((t_u64)pmadapter->pcard_pcie->txbd_ring_pbase >> 32),
+	       (t_u32)pmadapter->pcard_pcie->txbd_ring_pbase,
+	       pmadapter->pcard_pcie->txbd_ring_size);
+
+	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
+		pmadapter->pcard_pcie->tx_buf_list[i] = MNULL;
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf
+				 *) (pmadapter->pcard_pcie->txbd_ring_vbase +
+				     (sizeof(adma_dual_desc_buf) * i));
+			pmadapter->pcard_pcie->txbd_ring[i] =
+				(t_void *)padma_bd_buf;
+			padma_bd_buf->paddr = 0;
+			padma_bd_buf->len = 0;
+			padma_bd_buf->flags =
+				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_SRC_HOST |
+				ADMA_BD_FLAG_SOP | ADMA_BD_FLAG_EOP;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+		}
+#endif
+
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			ptx_bd_buf =
+				(mlan_pcie_data_buf
+				 *)(pmadapter->pcard_pcie->txbd_ring_vbase +
+				    (sizeof(mlan_pcie_data_buf) * i));
+			pmadapter->pcard_pcie->txbd_ring[i] =
+				(t_void *)ptx_bd_buf;
+			ptx_bd_buf->paddr = 0;
+			ptx_bd_buf->len = 0;
+			ptx_bd_buf->flags = 0;
+			ptx_bd_buf->frag_len = 0;
+			ptx_bd_buf->offset = 0;
+		}
+#endif
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees TX buffer descriptor ring
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_delete_txbd_ring(mlan_adapter *pmadapter)
+{
+	t_u32 i;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+	mlan_pcie_data_buf *ptx_bd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+	ENTER();
+
+	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
+		if (pmadapter->pcard_pcie->tx_buf_list[i]) {
+			pmbuf = pmadapter->pcard_pcie->tx_buf_list[i];
+			pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+					       pmbuf->pbuf + pmbuf->data_offset,
+					       pmbuf->buf_pa,
+					       MLAN_RX_DATA_BUF_SIZE,
+					       PCI_DMA_TODEVICE);
+			wlan_write_data_complete(pmadapter, pmbuf,
+						 MLAN_STATUS_FAILURE);
+		}
+		pmadapter->pcard_pcie->tx_buf_list[i] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			ptx_bd_buf = (mlan_pcie_data_buf *)
+				pmadapter->pcard_pcie->txbd_ring[i];
+
+			if (ptx_bd_buf) {
+				ptx_bd_buf->paddr = 0;
+				ptx_bd_buf->len = 0;
+				ptx_bd_buf->flags = 0;
+				ptx_bd_buf->frag_len = 0;
+				ptx_bd_buf->offset = 0;
+			}
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf = (adma_dual_desc_buf *)
+				pmadapter->pcard_pcie->txbd_ring[i];
+
+			if (padma_bd_buf) {
+				padma_bd_buf->paddr = 0;
+				padma_bd_buf->len = 0;
+				padma_bd_buf->flags = 0;
+				padma_bd_buf->pkt_size = 0;
+				padma_bd_buf->reserved = 0;
+			}
+		}
+#endif
+		pmadapter->pcard_pcie->txbd_ring[i] = MNULL;
+	}
+
+	if (pmadapter->pcard_pcie->txbd_ring_vbase) {
+		pmadapter->callbacks.moal_mfree_consistent(pmadapter->
+							   pmoal_handle,
+							   pmadapter->
+							   pcard_pcie->
+							   txbd_ring_size,
+							   pmadapter->
+							   pcard_pcie->
+							   txbd_ring_vbase,
+							   pmadapter->
+							   pcard_pcie->
+							   txbd_ring_pbase);
+	}
+	pmadapter->pcard_pcie->txbd_pending = 0;
+	pmadapter->pcard_pcie->txbd_ring_size = 0;
+	pmadapter->pcard_pcie->txbd_wrptr = 0;
+	pmadapter->pcard_pcie->txbd_rdptr = 0;
+	pmadapter->pcard_pcie->txbd_ring_vbase = MNULL;
+	pmadapter->pcard_pcie->txbd_ring_pbase = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function creates buffer descriptor ring for RX
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_create_rxbd_ring(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+	t_u32 i;
+#if defined(PCIE8997) || defined(PCIE8897)
+	mlan_pcie_data_buf *prxbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+	ENTER();
+
+	pmadapter->pcard_pcie->rxbd_rdptr = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+	/*
+	 * driver maintaines the write pointer and firmware maintaines the read
+	 * pointer. The read pointer starts at 0 (zero) while the write pointer
+	 * starts at zero with rollover bit set
+	 */
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		pmadapter->pcard_pcie->rxbd_wrptr =
+			pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+		/* allocate shared memory for the BD ring and divide the same in
+		   to several descriptors */
+		pmadapter->pcard_pcie->rxbd_ring_size =
+			sizeof(mlan_pcie_data_buf) *
+			pmadapter->pcard_pcie->txrx_bd_size;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	/*
+	 * driver maintaines the write pointer and firmware maintaines the read
+	 * pointer. The read pointer starts at 0 (zero) while the write pointer
+	 * starts at pmadapter->pcard_pcie->txrx_bd_size;
+	 */
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		pmadapter->pcard_pcie->rxbd_wrptr =
+			pmadapter->pcard_pcie->txrx_bd_size;
+		pmadapter->pcard_pcie->rxbd_ring_size =
+			sizeof(adma_dual_desc_buf) *
+			pmadapter->pcard_pcie->txrx_bd_size;
+	}
+#endif
+
+	PRINTM(MINFO, "RX ring: allocating %d bytes\n",
+	       pmadapter->pcard_pcie->rxbd_ring_size);
+
+	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+					  pmadapter->pcard_pcie->rxbd_ring_size,
+					  &pmadapter->pcard_pcie->
+					  rxbd_ring_vbase,
+					  &pmadapter->pcard_pcie->
+					  rxbd_ring_pbase);
+
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+		       __FUNCTION__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	PRINTM(MINFO,
+	       "RX ring: - base: %p, pbase: %#x:%x,"
+	       "len: %#x\n",
+	       pmadapter->pcard_pcie->rxbd_ring_vbase,
+	       (t_u32)((t_u64)pmadapter->pcard_pcie->rxbd_ring_pbase >> 32),
+	       (t_u32)pmadapter->pcard_pcie->rxbd_ring_pbase,
+	       pmadapter->pcard_pcie->rxbd_ring_size);
+
+	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
+		/* Allocate buffer here so that firmware can DMA data on it */
+		pmbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_RX_DATA_BUF_SIZE,
+					       MLAN_RX_HEADER_LEN,
+					       MOAL_ALLOC_MLAN_BUFFER);
+		if (!pmbuf) {
+			PRINTM(MERROR,
+			       "RX ring create : Unable to allocate mlan_buffer\n");
+			wlan_pcie_delete_rxbd_ring(pmadapter);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmadapter->pcard_pcie->rx_buf_list[i] = pmbuf;
+
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_map_memory(pmadapter->pmoal_handle,
+					 pmbuf->pbuf + pmbuf->data_offset,
+					 &pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
+					 PCI_DMA_FROMDEVICE)) {
+			PRINTM(MERROR,
+			       "Rx ring create : moal_map_memory failed\n");
+			wlan_pcie_delete_rxbd_ring(pmadapter);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		PRINTM(MINFO,
+		       "RX ring: add new mlan_buffer base: %p, "
+		       "buf_base: %p, buf_pbase: %#x:%x, "
+		       "buf_len: %#x\n",
+		       pmbuf, pmbuf->pbuf, (t_u32)((t_u64)pmbuf->buf_pa >> 32),
+		       (t_u32)pmbuf->buf_pa, pmbuf->data_len);
+
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			prxbd_buf =
+				(mlan_pcie_data_buf
+				 *)(pmadapter->pcard_pcie->rxbd_ring_vbase +
+				    (sizeof(mlan_pcie_data_buf) * i));
+			pmadapter->pcard_pcie->rxbd_ring[i] =
+				(t_void *)prxbd_buf;
+			prxbd_buf->paddr = pmbuf->buf_pa;
+			prxbd_buf->len = (t_u16)pmbuf->data_len;
+			prxbd_buf->flags = MLAN_BD_FLAG_SOP | MLAN_BD_FLAG_EOP;
+			prxbd_buf->offset = 0;
+			prxbd_buf->frag_len = (t_u16)pmbuf->data_len;
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf
+				 *) (pmadapter->pcard_pcie->rxbd_ring_vbase +
+				     (sizeof(adma_dual_desc_buf) * i));
+			pmadapter->pcard_pcie->rxbd_ring[i] =
+				(t_void *)padma_bd_buf;
+			padma_bd_buf->paddr = pmbuf->buf_pa;
+			padma_bd_buf->len =
+				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+			padma_bd_buf->flags =
+				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+		}
+#endif
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees RX buffer descriptor ring
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_delete_rxbd_ring(mlan_adapter *pmadapter)
+{
+	t_u32 i;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+	mlan_pcie_data_buf *prxbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+	ENTER();
+	for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
+		if (pmadapter->pcard_pcie->rx_buf_list[i]) {
+			pmbuf = pmadapter->pcard_pcie->rx_buf_list[i];
+			pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+					       pmbuf->pbuf + pmbuf->data_offset,
+					       pmbuf->buf_pa,
+					       MLAN_RX_DATA_BUF_SIZE,
+					       PCI_DMA_FROMDEVICE);
+			wlan_free_mlan_buffer(pmadapter,
+					      pmadapter->pcard_pcie->
+					      rx_buf_list[i]);
+		}
+		pmadapter->pcard_pcie->rx_buf_list[i] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			prxbd_buf = (mlan_pcie_data_buf *)
+				pmadapter->pcard_pcie->rxbd_ring[i];
+
+			if (prxbd_buf) {
+				prxbd_buf->paddr = 0;
+				prxbd_buf->offset = 0;
+				prxbd_buf->frag_len = 0;
+			}
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf = (adma_dual_desc_buf *)
+				pmadapter->pcard_pcie->rxbd_ring[i];
+
+			if (padma_bd_buf) {
+				padma_bd_buf->paddr = 0;
+				padma_bd_buf->flags = 0;
+				padma_bd_buf->pkt_size = 0;
+				padma_bd_buf->reserved = 0;
+				padma_bd_buf->len = 0;
+			}
+		}
+#endif
+		pmadapter->pcard_pcie->rxbd_ring[i] = MNULL;
+	}
+
+	if (pmadapter->pcard_pcie->rxbd_ring_vbase)
+		pmadapter->callbacks.moal_mfree_consistent(pmadapter->
+							   pmoal_handle,
+							   pmadapter->
+							   pcard_pcie->
+							   rxbd_ring_size,
+							   pmadapter->
+							   pcard_pcie->
+							   rxbd_ring_vbase,
+							   pmadapter->
+							   pcard_pcie->
+							   rxbd_ring_pbase);
+	pmadapter->pcard_pcie->rxbd_ring_size = 0;
+	pmadapter->pcard_pcie->rxbd_rdptr = 0;
+	pmadapter->pcard_pcie->rxbd_wrptr = 0;
+	pmadapter->pcard_pcie->rxbd_ring_vbase = MNULL;
+	pmadapter->pcard_pcie->rxbd_ring_pbase = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function creates buffer descriptor ring for Events
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_create_evtbd_ring(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+	t_u32 i;
+#if defined(PCIE8997) || defined(PCIE8897)
+	pmlan_pcie_evt_buf pevtbd_buf;
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+	ENTER();
+	/*
+	 * driver maintaines the write pointer and firmware maintaines the read
+	 * pointer. The read pointer starts at 0 (zero) while the write pointer
+	 * starts at zero with rollover bit set
+	 */
+	pmadapter->pcard_pcie->evtbd_rdptr = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		pmadapter->pcard_pcie->evtbd_wrptr = EVT_RW_PTR_ROLLOVER_IND;
+		pmadapter->pcard_pcie->evtbd_ring_size =
+			sizeof(mlan_pcie_evt_buf) * MLAN_MAX_EVT_BD;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		pmadapter->pcard_pcie->evtbd_wrptr = MLAN_MAX_EVT_BD;
+		pmadapter->pcard_pcie->evtbd_ring_size =
+			sizeof(adma_dual_desc_buf) * MLAN_MAX_EVT_BD;
+	}
+#endif
+	PRINTM(MINFO, "Evt ring: allocating %d bytes\n",
+	       pmadapter->pcard_pcie->evtbd_ring_size);
+
+	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+					  pmadapter->pcard_pcie->
+					  evtbd_ring_size,
+					  &pmadapter->pcard_pcie->
+					  evtbd_ring_vbase,
+					  &pmadapter->pcard_pcie->
+					  evtbd_ring_pbase);
+
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+		       __FUNCTION__);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	PRINTM(MINFO,
+	       "Evt ring: - base: %p, pbase: %#x:%x,"
+	       "len: %#x\n",
+	       pmadapter->pcard_pcie->evtbd_ring_vbase,
+	       (t_u32)((t_u64)pmadapter->pcard_pcie->evtbd_ring_pbase >> 32),
+	       (t_u32)pmadapter->pcard_pcie->evtbd_ring_pbase,
+	       pmadapter->pcard_pcie->evtbd_ring_size);
+
+	for (i = 0; i < MLAN_MAX_EVT_BD; i++) {
+		/* Allocate buffer here so that firmware can DMA data on it */
+		pmbuf = wlan_alloc_mlan_buffer(pmadapter, MAX_EVENT_SIZE,
+					       MLAN_RX_HEADER_LEN,
+					       MOAL_ALLOC_MLAN_BUFFER);
+		if (!pmbuf) {
+			PRINTM(MERROR,
+			       "Event ring create : Unable to allocate mlan_buffer\n");
+			wlan_pcie_delete_evtbd_ring(pmadapter);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmadapter->pcard_pcie->evt_buf_list[i] = pmbuf;
+
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_map_memory(pmadapter->pmoal_handle,
+					 pmbuf->pbuf + pmbuf->data_offset,
+					 &pmbuf->buf_pa, MAX_EVENT_SIZE,
+					 PCI_DMA_FROMDEVICE)) {
+			PRINTM(MERROR,
+			       "Event ring create : moal_map_memory failed\n");
+			wlan_pcie_delete_evtbd_ring(pmadapter);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			pevtbd_buf =
+				(mlan_pcie_evt_buf
+				 *)(pmadapter->pcard_pcie->evtbd_ring_vbase +
+				    (sizeof(mlan_pcie_evt_buf) * i));
+			pmadapter->pcard_pcie->evtbd_ring[i] =
+				(t_void *)pevtbd_buf;
+			pevtbd_buf->paddr = pmbuf->buf_pa;
+			pevtbd_buf->len = (t_u16)pmbuf->data_len;
+			pevtbd_buf->flags = 0;
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf
+				 *) (pmadapter->pcard_pcie->evtbd_ring_vbase +
+				     (sizeof(adma_dual_desc_buf) * i));
+			pmadapter->pcard_pcie->evtbd_ring[i] =
+				(t_void *)padma_bd_buf;
+			padma_bd_buf->paddr = pmbuf->buf_pa;
+			padma_bd_buf->len =
+				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+			padma_bd_buf->flags =
+				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+		}
+#endif
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees event buffer descriptor ring
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_delete_evtbd_ring(mlan_adapter *pmadapter)
+{
+	t_u32 i;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+	mlan_pcie_evt_buf *pevtbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+	ENTER();
+	for (i = 0; i < MLAN_MAX_EVT_BD; i++) {
+		if (pmadapter->pcard_pcie->evt_buf_list[i]) {
+			pmbuf = pmadapter->pcard_pcie->evt_buf_list[i];
+			pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+					       pmbuf->pbuf + pmbuf->data_offset,
+					       pmbuf->buf_pa, MAX_EVENT_SIZE,
+					       PCI_DMA_FROMDEVICE);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		}
+
+		pmadapter->pcard_pcie->evt_buf_list[i] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			pevtbd_buf = (mlan_pcie_evt_buf *)
+				pmadapter->pcard_pcie->evtbd_ring[i];
+
+			if (pevtbd_buf) {
+				pevtbd_buf->paddr = 0;
+				pevtbd_buf->len = 0;
+				pevtbd_buf->flags = 0;
+			}
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf = (adma_dual_desc_buf *)
+				pmadapter->pcard_pcie->evtbd_ring[i];
+
+			if (padma_bd_buf) {
+				padma_bd_buf->paddr = 0;
+				padma_bd_buf->len = 0;
+				padma_bd_buf->flags = 0;
+				padma_bd_buf->pkt_size = 0;
+				padma_bd_buf->reserved = 0;
+			}
+		}
+#endif
+		pmadapter->pcard_pcie->evtbd_ring[i] = MNULL;
+	}
+
+	if (pmadapter->pcard_pcie->evtbd_ring_vbase)
+		pmadapter->callbacks.moal_mfree_consistent(pmadapter->
+							   pmoal_handle,
+							   pmadapter->
+							   pcard_pcie->
+							   evtbd_ring_size,
+							   pmadapter->
+							   pcard_pcie->
+							   evtbd_ring_vbase,
+							   pmadapter->
+							   pcard_pcie->
+							   evtbd_ring_pbase);
+
+	pmadapter->pcard_pcie->evtbd_rdptr = 0;
+	pmadapter->pcard_pcie->evtbd_wrptr = 0;
+	pmadapter->pcard_pcie->evtbd_ring_size = 0;
+	pmadapter->pcard_pcie->evtbd_ring_vbase = MNULL;
+	pmadapter->pcard_pcie->evtbd_ring_pbase = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates buffer for CMD and CMDRSP
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_alloc_cmdrsp_buf(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pmbuf = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	/** Virtual base address of command response */
+	t_u8 *cmdrsp_vbase;
+	/** Physical base address of command response */
+	t_u64 cmdrsp_pbase = 0;
+
+	ENTER();
+
+	/* Allocate memory for receiving command response data */
+	pmbuf = wlan_alloc_mlan_buffer(pmadapter, 0, 0, MOAL_MALLOC_BUFFER);
+	if (!pmbuf) {
+		PRINTM(MERROR,
+		       "Command resp buffer create : Unable to allocate mlan_buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+					  MRVDRV_SIZE_OF_CMD_BUFFER,
+					  &cmdrsp_vbase, &cmdrsp_pbase);
+
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+		       __FUNCTION__);
+		/* free pmbuf */
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pmbuf->buf_pa = cmdrsp_pbase;
+	pmbuf->pbuf = cmdrsp_vbase;
+	pmbuf->data_offset = 0;
+	pmbuf->data_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	pmbuf->total_pcie_buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+	pmadapter->pcard_pcie->cmdrsp_buf = pmbuf;
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees CMD and CMDRSP buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_delete_cmdrsp_buf(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pmbuf = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *cmdrsp_vbase;
+	t_u64 cmdrsp_pbase;
+	ENTER();
+
+	if (!pmadapter) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (pmadapter->pcard_pcie->cmdrsp_buf) {
+		pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+		cmdrsp_vbase = pmbuf->pbuf;
+		cmdrsp_pbase = pmbuf->buf_pa;
+		if (cmdrsp_vbase)
+			pmadapter->callbacks.moal_mfree_consistent(pmadapter->
+								   pmoal_handle,
+								   pmbuf->
+								   total_pcie_buf_len,
+								   cmdrsp_vbase,
+								   cmdrsp_pbase);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+	}
+	if (pmadapter->pcard_pcie->cmd_buf) {
+		pmbuf = pmadapter->pcard_pcie->cmd_buf;
+		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->buf_pa, MRVDRV_SIZE_OF_CMD_BUFFER,
+				       PCI_DMA_TODEVICE);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define PCIE_TXBD_EMPTY(wrptr, rdptr, mask, rollover_ind)                      \
+	(((wrptr & mask) == (rdptr & mask)) &&                                 \
+	 ((wrptr & rollover_ind) == (rdptr & rollover_ind)))
+
+/**
+ *  @brief This function flushes the TX buffer descriptor ring
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_flush_txbd_ring(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+
+	ENTER();
+
+	if (!PCIE_TXBD_EMPTY(pmadapter->pcard_pcie->txbd_wrptr,
+			     pmadapter->pcard_pcie->txbd_rdptr,
+			     txrx_rw_ptr_mask, txrx_rw_ptr_rollover_ind)) {
+		pmadapter->pcard_pcie->txbd_flush = MTRUE;
+		/* write pointer already set at last send */
+		/* send dnld-rdy intr again, wait for completion */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					pmadapter->pcard_pcie->reg->
+					reg_cpu_int_event, CPU_INTR_DNLD_RDY)) {
+			PRINTM(MERROR,
+			       "SEND DATA (FLUSH): failed to assert dnld-rdy interrupt.\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function check the tx pending buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param rdptr      tx rdptr
+ *
+ *  @return           MTRUE/MFALSE;
+ */
+static t_u8
+wlan_check_tx_pending_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		if (((pmadapter->pcard_pcie->txbd_rdptr & txrx_rw_ptr_mask) !=
+		     (rdptr & txrx_rw_ptr_mask)) ||
+		    ((pmadapter->pcard_pcie->txbd_rdptr &
+		      txrx_rw_ptr_rollover_ind) !=
+		     (rdptr & txrx_rw_ptr_rollover_ind)))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		if ((pmadapter->pcard_pcie->txbd_rdptr &
+		     ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+	return MFALSE;
+}
+
+/**
+ *  @brief This function unmaps and frees downloaded data buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_send_data_complete(mlan_adapter *pmadapter)
+{
+	const t_u32 num_tx_buffs = pmadapter->pcard_pcie->txrx_bd_size;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf;
+	t_u32 wrdoneidx;
+	t_u32 rdptr;
+	t_u32 unmap_count = 0;
+#if defined(PCIE8997) || defined(PCIE8897)
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+	mlan_pcie_data_buf *ptx_bd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+	t_u32 wrptr;
+#endif
+
+	ENTER();
+
+	/* Read the TX ring read pointer set by firmware */
+	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_pcie->reg->reg_txbd_rdptr,
+			       &rdptr)) {
+		PRINTM(MERROR,
+		       "SEND DATA COMP: failed to read REG_TXBD_RDPTR\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	PRINTM(MINFO, "SEND DATA COMP:  rdptr_prev=0x%x, rdptr=0x%x\n",
+	       pmadapter->pcard_pcie->txbd_rdptr, rdptr);
+
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma)
+		rdptr = rdptr >> TXBD_RW_PTR_START;
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		wrptr = rdptr & 0xffff;
+		rdptr = rdptr >> ADMA_RPTR_START;
+		if (wrptr != pmadapter->pcard_pcie->txbd_wrptr)
+			PRINTM(MERROR, "wlan: Unexpected wrptr 0x%x 0x%x\n",
+			       wrptr, pmadapter->pcard_pcie->txbd_wrptr);
+	}
+#endif
+
+	/* free from previous txbd_rdptr to current txbd_rdptr */
+	while (wlan_check_tx_pending_buffer(pmadapter, rdptr)) {
+		wrdoneidx =
+			pmadapter->pcard_pcie->txbd_rdptr & (num_tx_buffs - 1);
+		pmbuf = pmadapter->pcard_pcie->tx_buf_list[wrdoneidx];
+		if (pmbuf) {
+			PRINTM(MDAT_D,
+			       "SEND DATA COMP: Detach pmbuf %p at tx_ring[%d], pmadapter->txbd_rdptr=0x%x\n",
+			       pmbuf, wrdoneidx,
+			       pmadapter->pcard_pcie->txbd_rdptr);
+			ret = pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+						     pmbuf->pbuf +
+						     pmbuf->data_offset,
+						     pmbuf->buf_pa,
+						     pmbuf->data_len,
+						     PCI_DMA_TODEVICE);
+			if (ret == MLAN_STATUS_FAILURE) {
+				PRINTM(MERROR, "%s: moal_unmap_memory failed\n",
+				       __FUNCTION__);
+				break;
+			}
+			unmap_count++;
+			pmadapter->pcard_pcie->txbd_pending--;
+#if defined(PCIE8997) || defined(PCIE8897)
+			if (pmadapter->pcard_pcie->txbd_flush)
+				wlan_write_data_complete(pmadapter, pmbuf,
+							 MLAN_STATUS_FAILURE);
+			else
+#endif
+				wlan_write_data_complete(pmadapter, pmbuf,
+							 MLAN_STATUS_SUCCESS);
+		}
+
+		pmadapter->pcard_pcie->tx_buf_list[wrdoneidx] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			ptx_bd_buf =
+				(mlan_pcie_data_buf *)pmadapter->pcard_pcie->
+				txbd_ring[wrdoneidx];
+			ptx_bd_buf->paddr = 0;
+			ptx_bd_buf->len = 0;
+			ptx_bd_buf->flags = 0;
+			ptx_bd_buf->frag_len = 0;
+			ptx_bd_buf->offset = 0;
+			pmadapter->pcard_pcie->txbd_rdptr++;
+			if ((pmadapter->pcard_pcie->txbd_rdptr &
+			     txrx_rw_ptr_mask) == num_tx_buffs)
+				pmadapter->pcard_pcie->txbd_rdptr =
+					((pmadapter->pcard_pcie->txbd_rdptr &
+					  txrx_rw_ptr_rollover_ind) ^
+					 txrx_rw_ptr_rollover_ind);
+		}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf *) pmadapter->pcard_pcie->
+				txbd_ring[wrdoneidx];
+			padma_bd_buf->paddr = 0;
+			padma_bd_buf->len = 0;
+			padma_bd_buf->flags = 0;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+			pmadapter->pcard_pcie->txbd_rdptr++;
+			pmadapter->pcard_pcie->txbd_rdptr &=
+				ADMA_RW_PTR_WRAP_MASK;
+		}
+#endif
+	}
+
+	if (unmap_count)
+		pmadapter->data_sent = MFALSE;
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (pmadapter->pcard_pcie->txbd_flush) {
+		if (PCIE_TXBD_EMPTY(pmadapter->pcard_pcie->txbd_wrptr,
+				    pmadapter->pcard_pcie->txbd_rdptr,
+				    txrx_rw_ptr_mask, txrx_rw_ptr_rollover_ind))
+			pmadapter->pcard_pcie->txbd_flush = MFALSE;
+		else
+			wlan_pcie_flush_txbd_ring(pmadapter);
+	}
+#endif
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define PCIE_TXBD_NOT_FULL(wrptr, rdptr, mask, rollover_ind)                   \
+	(((wrptr & mask) != (rdptr & mask)) ||                                 \
+	 ((wrptr & rollover_ind) == (rdptr & rollover_ind)))
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+#define ADMA_TXBD_IS_FULL(wrptr, rdptr, mask, rollover_ind)                                        \
+	(((wrptr & mask) == (rdptr & mask)) &&         \
+	 ((wrptr & rollover_ind) !=                                \
+	  (rdptr & rollover_ind)))
+#endif
+
+static t_u8
+wlan_check_txbd_not_full(mlan_adapter *pmadapter)
+{
+	t_u32 txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind;
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+		txrx_rw_ptr_rollover_ind =
+			pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+		if (PCIE_TXBD_NOT_FULL(pmadapter->pcard_pcie->txbd_wrptr,
+				       pmadapter->pcard_pcie->txbd_rdptr,
+				       txrx_rw_ptr_mask,
+				       txrx_rw_ptr_rollover_ind))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		txrx_rw_ptr_mask = pmadapter->pcard_pcie->txrx_bd_size - 1;
+		txrx_rw_ptr_rollover_ind = pmadapter->pcard_pcie->txrx_bd_size;
+		if (!ADMA_TXBD_IS_FULL(pmadapter->pcard_pcie->txbd_wrptr,
+				       pmadapter->pcard_pcie->txbd_rdptr,
+				       txrx_rw_ptr_mask,
+				       txrx_rw_ptr_rollover_ind))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+	return MFALSE;
+}
+
+/**
+ *  @brief This function downloads data to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param type      packet type
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ *  @param tx_param  A pointer to mlan_tx_param
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_send_data(mlan_adapter *pmadapter, t_u8 type,
+		    mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+	t_u32 reg_txbd_wrptr = pmadapter->pcard_pcie->reg->reg_txbd_wrptr;
+#if defined(PCIE8997) || defined(PCIE8897)
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+	mlan_pcie_data_buf *ptx_bd_buf = MNULL;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf = MNULL;
+#endif
+	const t_u32 num_tx_buffs = pmadapter->pcard_pcie->txrx_bd_size;
+	mlan_status ret = MLAN_STATUS_PENDING;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 rxbd_val = 0;
+	t_u32 wrindx;
+	t_u16 *tmp;
+	t_u8 *payload;
+	t_u32 wr_ptr_start = 0;
+
+	ENTER();
+
+	if (!(pmadapter && pmbuf)) {
+		PRINTM(MERROR, "%s() has no buffer", __FUNCTION__);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (!(pmbuf->pbuf && pmbuf->data_len)) {
+		PRINTM(MERROR, "Invalid parameter <%p, %#x>\n", pmbuf->pbuf,
+		       pmbuf->data_len);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MINFO, "SEND DATA: <Rd: %#x, Wr: %#x>\n",
+	       pmadapter->pcard_pcie->txbd_rdptr,
+	       pmadapter->pcard_pcie->txbd_wrptr);
+
+	if (wlan_check_txbd_not_full(pmadapter)) {
+		pmadapter->data_sent = MTRUE;
+
+		payload = pmbuf->pbuf + pmbuf->data_offset;
+		tmp = (t_u16 *)&payload[0];
+		*tmp = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+		tmp = (t_u16 *)&payload[2];
+		*tmp = wlan_cpu_to_le16(type);
+
+		/* Map pmbuf, and attach to tx ring */
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_map_memory(pmadapter->pmoal_handle,
+					 pmbuf->pbuf + pmbuf->data_offset,
+					 &pmbuf->buf_pa, pmbuf->data_len,
+					 PCI_DMA_TODEVICE)) {
+			PRINTM(MERROR,
+			       "SEND DATA: failed to moal_map_memory\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		wrindx = pmadapter->pcard_pcie->txbd_wrptr & (num_tx_buffs - 1);
+		PRINTM(MDAT_D,
+		       "SEND DATA: Attach pmbuf %p at tx_ring[%d], txbd_wrptr=0x%x\n",
+		       pmbuf, wrindx, pmadapter->pcard_pcie->txbd_wrptr);
+		pmadapter->pcard_pcie->tx_buf_list[wrindx] = pmbuf;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			wr_ptr_start = TXBD_RW_PTR_START;
+			ptx_bd_buf =
+				(mlan_pcie_data_buf *)pmadapter->pcard_pcie->
+				txbd_ring[wrindx];
+			ptx_bd_buf->paddr = pmbuf->buf_pa;
+			ptx_bd_buf->len = (t_u16)pmbuf->data_len;
+			ptx_bd_buf->flags = MLAN_BD_FLAG_SOP | MLAN_BD_FLAG_EOP;
+			ptx_bd_buf->frag_len = (t_u16)pmbuf->data_len;
+			ptx_bd_buf->offset = 0;
+			pmadapter->pcard_pcie->last_tx_pkt_size[wrindx] =
+				pmbuf->data_len;
+			pmadapter->pcard_pcie->txbd_wrptr++;
+			if ((pmadapter->pcard_pcie->txbd_wrptr &
+			     txrx_rw_ptr_mask) == num_tx_buffs)
+				pmadapter->pcard_pcie->txbd_wrptr =
+					((pmadapter->pcard_pcie->txbd_wrptr &
+					  txrx_rw_ptr_rollover_ind) ^
+					 txrx_rw_ptr_rollover_ind);
+			rxbd_val = pmadapter->pcard_pcie->rxbd_wrptr &
+				pmadapter->pcard_pcie->reg->
+				txrx_rw_ptr_wrap_mask;
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			wr_ptr_start = ADMA_WPTR_START;
+			padma_bd_buf =
+				(adma_dual_desc_buf *) pmadapter->pcard_pcie->
+				txbd_ring[wrindx];
+			padma_bd_buf->paddr = pmbuf->buf_pa;
+			padma_bd_buf->len =
+				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+			padma_bd_buf->flags =
+				ADMA_BD_FLAG_SOP | ADMA_BD_FLAG_EOP |
+				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_SRC_HOST;
+			if (padma_bd_buf->len < ADMA_MIN_PKT_SIZE)
+				padma_bd_buf->len = ADMA_MIN_PKT_SIZE;
+			padma_bd_buf->pkt_size = pmbuf->data_len;
+			pmadapter->pcard_pcie->last_tx_pkt_size[wrindx] =
+				pmbuf->data_len;
+			pmadapter->pcard_pcie->txbd_wrptr++;
+			pmadapter->pcard_pcie->txbd_wrptr &=
+				ADMA_RW_PTR_WRAP_MASK;
+		}
+#endif
+		pmadapter->pcard_pcie->txbd_pending++;
+		PRINTM(MINFO, "REG_TXBD_WRPT(0x%x) = 0x%x\n", reg_txbd_wrptr,
+		       ((pmadapter->pcard_pcie->txbd_wrptr << wr_ptr_start) |
+			rxbd_val));
+		/* Write the TX ring write pointer in to REG_TXBD_WRPTR */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle, reg_txbd_wrptr,
+					(pmadapter->pcard_pcie->txbd_wrptr
+					 << wr_ptr_start) | rxbd_val)) {
+			PRINTM(MERROR,
+			       "SEND DATA: failed to write REG_TXBD_WRPTR\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done_unmap;
+		}
+		PRINTM(MINFO, "SEND DATA: Updated <Rd: %#x, Wr: %#x>\n",
+		       pmadapter->pcard_pcie->txbd_rdptr,
+		       pmadapter->pcard_pcie->txbd_wrptr);
+
+		if (wlan_check_txbd_not_full(pmadapter))
+			pmadapter->data_sent = MFALSE;
+		else
+			wlan_pcie_send_data_complete(pmadapter);
+		if (pmadapter->data_sent)
+			pmadapter->data_sent_cnt++;
+
+		PRINTM(MINFO, "Sent packet to firmware successfully\n");
+	} else {
+		PRINTM(MERROR,
+		       "TX Ring full, can't send anymore packets to firmware\n");
+		PRINTM(MINFO, "SEND DATA (FULL!): <Rd: %#x, Wr: %#x>\n",
+		       pmadapter->pcard_pcie->txbd_rdptr,
+		       pmadapter->pcard_pcie->txbd_wrptr);
+		pmadapter->data_sent = MTRUE;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			/* Send the TX ready interrupt */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						pmadapter->pcard_pcie->reg->
+						reg_cpu_int_event,
+						CPU_INTR_DNLD_RDY))
+				PRINTM(MERROR,
+				       "SEND DATA (FULL): failed to assert dnld-rdy interrupt\n");
+		}
+#endif
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	LEAVE();
+	return ret;
+
+done_unmap:
+	if (MLAN_STATUS_FAILURE ==
+	    pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+				   pmbuf->pbuf + pmbuf->data_offset,
+				   pmbuf->buf_pa, pmbuf->data_len,
+				   PCI_DMA_TODEVICE)) {
+		PRINTM(MERROR, "SEND DATA: failed to moal_unmap_memory\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pcard_pcie->txbd_pending--;
+	pmadapter->pcard_pcie->tx_buf_list[wrindx] = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma && ptx_bd_buf) {
+		ptx_bd_buf->paddr = 0;
+		ptx_bd_buf->len = 0;
+		ptx_bd_buf->flags = 0;
+		ptx_bd_buf->frag_len = 0;
+		ptx_bd_buf->offset = 0;
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma && padma_bd_buf) {
+		padma_bd_buf->paddr = 0;
+		padma_bd_buf->len = 0;
+		padma_bd_buf->flags = 0;
+		padma_bd_buf->pkt_size = 0;
+		padma_bd_buf->reserved = 0;
+	}
+#endif
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function check the rx pending buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param rdptr      rx rdptr
+ *
+ *  @return           MTRUE/MFALSE;
+ */
+static t_u8
+wlan_check_rx_pending_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		if (((rdptr & txrx_rw_ptr_mask) !=
+		     (pmadapter->pcard_pcie->rxbd_rdptr & txrx_rw_ptr_mask)) ||
+		    ((rdptr & txrx_rw_ptr_rollover_ind) !=
+		     (pmadapter->pcard_pcie->rxbd_rdptr &
+		      txrx_rw_ptr_rollover_ind)))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		if ((pmadapter->pcard_pcie->rxbd_rdptr &
+		     ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+	return MFALSE;
+}
+
+/**
+ *  @brief This function check if the rx pending buffer is full
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param rdptr           rx rdptr
+ *  @param rxbd_rdptr      rxbd_rdptr
+ *
+ *  @return           MTRUE/MFALSE;
+ */
+static t_u8
+wlan_is_rx_pending_full(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		PRINTM(MDATA,
+		       "local wrptr: 0x%x(0x%x) -> reg rdptr: 0x%x(0x%x)\n",
+		       (pmadapter->pcard_pcie->rxbd_wrptr & txrx_rw_ptr_mask),
+		       (pmadapter->pcard_pcie->
+			rxbd_wrptr & txrx_rw_ptr_rollover_ind),
+		       (rdptr & txrx_rw_ptr_mask),
+		       (rdptr & txrx_rw_ptr_rollover_ind));
+		if (((rdptr & txrx_rw_ptr_mask) ==
+		     (pmadapter->pcard_pcie->rxbd_wrptr & txrx_rw_ptr_mask)) &&
+		    ((rdptr & txrx_rw_ptr_rollover_ind) ==
+		     (pmadapter->pcard_pcie->
+		      rxbd_wrptr & txrx_rw_ptr_rollover_ind)))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		PRINTM(MDATA, "local wrptr: 0x%x -> reg rdptr: 0x%x\n",
+		       (pmadapter->pcard_pcie->
+			rxbd_wrptr & ADMA_RW_PTR_WRAP_MASK),
+		       (rdptr & ADMA_RW_PTR_WRAP_MASK));
+		if ((rdptr & ADMA_RW_PTR_WRAP_MASK) ==
+		    (pmadapter->pcard_pcie->rxbd_wrptr & ADMA_RW_PTR_WRAP_MASK))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+	return MFALSE;
+}
+
+/**
+ *  @brief This function handles received buffer ring and
+ *  dispatches packets to upper
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_process_recv_data(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 rdptr, rd_index;
+	mlan_buffer *pmbuf = MNULL;
+	t_u32 txbd_val = 0;
+	t_u16 rx_len, rx_type;
+	const t_u32 num_rx_buffs = pmadapter->pcard_pcie->txrx_bd_size;
+	t_u32 reg_rxbd_rdptr = pmadapter->pcard_pcie->reg->reg_rxbd_rdptr;
+#if defined(PCIE8997) || defined(PCIE8897)
+	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
+	t_u32 txrx_rw_ptr_rollover_ind =
+		pmadapter->pcard_pcie->reg->txrx_rw_ptr_rollover_ind;
+	mlan_pcie_data_buf *prxbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+	t_u32 in_ts_sec, in_ts_usec;
+
+	ENTER();
+
+	/* Read the RX ring Read pointer set by firmware */
+	if (pcb->moal_read_reg(pmadapter->pmoal_handle, reg_rxbd_rdptr, &rdptr)) {
+		PRINTM(MERROR, "RECV DATA: failed to read REG_RXBD_RDPTR\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma)
+		rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+
+	if (pmadapter->tp_state_on && wlan_is_rx_pending_full(pmadapter, rdptr)) {
+		PRINTM(MDATA, "RX FULL!\n");
+		pmadapter->callbacks.moal_tp_accounting_rx_param(pmadapter->
+								 pmoal_handle,
+								 6, 0);
+	}
+	while (wlan_check_rx_pending_buffer(pmadapter, rdptr)) {
+		/* detach pmbuf (with data) from Rx Ring */
+		rd_index =
+			pmadapter->pcard_pcie->rxbd_rdptr & (num_rx_buffs - 1);
+		if (rd_index > (t_u32)(pmadapter->pcard_pcie->txrx_bd_size - 1)) {
+			PRINTM(MERROR, "RECV DATA: Invalid Rx buffer index.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmbuf = pmadapter->pcard_pcie->rx_buf_list[rd_index];
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+					   pmbuf->pbuf + pmbuf->data_offset,
+					   pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
+					   PCI_DMA_FROMDEVICE)) {
+			PRINTM(MERROR,
+			       "RECV DATA: moal_unmap_memory failed.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmadapter->pcard_pcie->rx_buf_list[rd_index] = MNULL;
+		PRINTM(MDAT_D,
+		       "RECV DATA: Detach pmbuf %p at rx_ring[%d], pmadapter->rxbd_rdptr=0x%x\n",
+		       pmbuf, rd_index, pmadapter->pcard_pcie->rxbd_rdptr);
+
+		/* Get data length from interface header -
+		   first 2 bytes are len, second 2 bytes are type */
+		rx_len = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
+		rx_len = wlan_le16_to_cpu(rx_len);
+		rx_type = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + 2));
+		rx_type = wlan_le16_to_cpu(rx_type);
+
+		PRINTM(MINFO,
+		       "RECV DATA: <Wr: %#x, Rd: %#x>, Len=%d rx_type=%d\n",
+		       pmadapter->pcard_pcie->rxbd_wrptr, rdptr, rx_len,
+		       rx_type);
+
+		if (rx_len <= MLAN_RX_DATA_BUF_SIZE) {
+			/* send buffer to host (which will free it) */
+			pmbuf->data_len = rx_len - PCIE_INTF_HEADER_LEN;
+			pmbuf->data_offset += PCIE_INTF_HEADER_LEN;
+			//rx_trace 5
+			if (pmadapter->tp_state_on) {
+				pmadapter->callbacks.
+					moal_tp_accounting(pmadapter->
+							   pmoal_handle, pmbuf,
+							   5 /*RX_DROP_P1 */ );
+				pcb->moal_get_system_time(pmadapter->
+							  pmoal_handle,
+							  &in_ts_sec,
+							  &in_ts_usec);
+				pmbuf->in_ts_sec = in_ts_sec;
+				pmbuf->in_ts_usec = in_ts_usec;
+			}
+			if (pmadapter->tp_state_drop_point ==
+			    5 /*RX_DROP_P1 */ ) {
+				pmadapter->ops.data_complete(pmadapter, pmbuf,
+							     ret);
+			} else {
+				PRINTM(MINFO,
+				       "RECV DATA: Received packet from FW successfully\n");
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+				util_enqueue_list_tail(pmadapter->pmoal_handle,
+						       &pmadapter->
+						       rx_data_queue,
+						       (pmlan_linked_list)pmbuf,
+						       MNULL, MNULL);
+				pmadapter->rx_pkts_queued++;
+				if (pmadapter->tp_state_on)
+					pmadapter->callbacks.
+						moal_tp_accounting_rx_param
+						(pmadapter->pmoal_handle, 1,
+						 pmadapter->rx_pkts_queued);
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+
+				pmadapter->data_received = MTRUE;
+			}
+			/* Create new buffer and attach it to Rx Ring */
+			pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+						       MLAN_RX_DATA_BUF_SIZE,
+						       MLAN_RX_HEADER_LEN,
+						       MOAL_ALLOC_MLAN_BUFFER);
+			if (!pmbuf) {
+				PRINTM(MERROR,
+				       "RECV DATA: Unable to allocate mlan_buffer\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		} else {
+			/* Queue the mlan_buffer again */
+			PRINTM(MERROR, "PCIE: Drop invalid packet, length=%d",
+			       rx_len);
+		}
+
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_map_memory(pmadapter->pmoal_handle,
+					 pmbuf->pbuf + pmbuf->data_offset,
+					 &pmbuf->buf_pa, MLAN_RX_DATA_BUF_SIZE,
+					 PCI_DMA_FROMDEVICE)) {
+			PRINTM(MERROR, "RECV DATA: moal_map_memory failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		PRINTM(MDAT_D,
+		       "RECV DATA: Attach new pmbuf %p at rx_ring[%d]\n", pmbuf,
+		       rd_index);
+		pmadapter->pcard_pcie->rx_buf_list[rd_index] = pmbuf;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			prxbd_buf =
+				(mlan_pcie_data_buf *)pmadapter->pcard_pcie->
+				rxbd_ring[rd_index];
+			prxbd_buf->paddr = pmbuf->buf_pa;
+			prxbd_buf->len = (t_u16)pmbuf->data_len;
+			prxbd_buf->flags = MLAN_BD_FLAG_SOP | MLAN_BD_FLAG_EOP;
+			prxbd_buf->offset = 0;
+			prxbd_buf->frag_len = (t_u16)pmbuf->data_len;
+
+			/* update rxbd's rdptrs */
+			if ((++pmadapter->pcard_pcie->rxbd_rdptr &
+			     txrx_rw_ptr_mask) ==
+			    pmadapter->pcard_pcie->txrx_bd_size) {
+				pmadapter->pcard_pcie->rxbd_rdptr =
+					((pmadapter->pcard_pcie->
+					  rxbd_rdptr & txrx_rw_ptr_rollover_ind)
+					 ^ txrx_rw_ptr_rollover_ind);
+			}
+
+			/* update rxbd's wrptrs */
+			if ((++pmadapter->pcard_pcie->rxbd_wrptr &
+			     txrx_rw_ptr_mask) ==
+			    pmadapter->pcard_pcie->txrx_bd_size) {
+				pmadapter->pcard_pcie->rxbd_wrptr =
+					((pmadapter->pcard_pcie->
+					  rxbd_wrptr & txrx_rw_ptr_rollover_ind)
+					 ^ txrx_rw_ptr_rollover_ind);
+			}
+			txbd_val = pmadapter->pcard_pcie->txbd_wrptr &
+				pmadapter->pcard_pcie->reg->
+				txrx_rw_ptr_wrap_mask;
+			txbd_val = txbd_val << TXBD_RW_PTR_START;
+		}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf *) pmadapter->pcard_pcie->
+				rxbd_ring[rd_index];
+			padma_bd_buf->paddr = pmbuf->buf_pa;
+			padma_bd_buf->len =
+				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+			padma_bd_buf->flags =
+				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+			pmadapter->pcard_pcie->rxbd_rdptr++;
+			pmadapter->pcard_pcie->rxbd_wrptr++;
+			pmadapter->pcard_pcie->rxbd_rdptr &=
+				ADMA_RW_PTR_WRAP_MASK;
+			pmadapter->pcard_pcie->rxbd_wrptr &=
+				ADMA_RW_PTR_WRAP_MASK;
+		}
+#endif
+		PRINTM(MINFO, "RECV DATA: Updated <Wr: %#x, Rd: %#x>\n",
+		       pmadapter->pcard_pcie->rxbd_wrptr, rdptr);
+
+		/* Write the RX ring write pointer in to REG_RXBD_WRPTR */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					pmadapter->pcard_pcie->reg->
+					reg_rxbd_wrptr,
+					pmadapter->pcard_pcie->
+					rxbd_wrptr | txbd_val)) {
+			PRINTM(MERROR,
+			       "RECV DATA: failed to write REG_RXBD_WRPTR\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Read the RX ring read pointer set by firmware */
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle, reg_rxbd_rdptr,
+				       &rdptr)) {
+			PRINTM(MERROR,
+			       "RECV DATA: failed to read REG_RXBD_RDPTR\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma)
+			rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads command to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ *
+ *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_send_cmd(mlan_adapter *pmadapter, mlan_buffer *pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_PENDING;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *payload = MNULL;
+
+	ENTER();
+	if (!(pmadapter && pmbuf)) {
+		PRINTM(MERROR, "%s() has no buffer", __FUNCTION__);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (!(pmbuf->pbuf && pmbuf->data_len)) {
+		PRINTM(MERROR, "Invalid parameter <%p, %#x>\n", pmbuf->pbuf,
+		       pmbuf->data_len);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Make sure a command response buffer is available */
+	if (!pmadapter->pcard_pcie->cmdrsp_buf) {
+		PRINTM(MERROR,
+		       "No response buffer available, send command failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	pmadapter->cmd_sent = MTRUE;
+	payload = pmbuf->pbuf + pmbuf->data_offset;
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(MLAN_TYPE_CMD);
+
+	if (MLAN_STATUS_FAILURE ==
+	    pcb->moal_map_memory(pmadapter->pmoal_handle,
+				 pmbuf->pbuf + pmbuf->data_offset,
+				 &pmbuf->buf_pa, MLAN_RX_CMD_BUF_SIZE,
+				 PCI_DMA_TODEVICE)) {
+		PRINTM(MERROR, "Command buffer : moal_map_memory failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pcard_pcie->cmd_buf = pmbuf;
+
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		/* To send a command, the driver will:
+		   1. Write the 64bit physical address of the data buffer to
+		   SCRATCH1 + SCRATCH0
+		   2. Ring the door bell (i.e. set the door bell interrupt)
+
+		   In response to door bell interrupt, the firmware will
+		   perform the DMA of the command packet (first header to obtain
+		   the total length and then rest of the command).
+		 */
+
+		if (pmadapter->pcard_pcie->cmdrsp_buf) {
+			/* Write the lower 32bits of the cmdrsp buffer physical
+			   address */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						REG_CMDRSP_ADDR_LO,
+						(t_u32)pmadapter->pcard_pcie->
+						cmdrsp_buf->buf_pa)) {
+				PRINTM(MERROR,
+				       "Failed to write download command to boot code.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			/* Write the upper 32bits of the cmdrsp buffer physical
+			   address */
+			if (pcb->
+			    moal_write_reg(pmadapter->pmoal_handle,
+					   REG_CMDRSP_ADDR_HI,
+					   (t_u32)((t_u64)pmadapter->
+						   pcard_pcie->cmdrsp_buf->
+						   buf_pa >> 32))) {
+				PRINTM(MERROR,
+				       "Failed to write download command to boot code.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+
+		/* Write the lower 32bits of the physical address to
+		 * REG_CMD_ADDR_LO */
+		if (pcb->
+		    moal_write_reg(pmadapter->pmoal_handle, REG_CMD_ADDR_LO,
+				   (t_u32)pmadapter->pcard_pcie->cmd_buf->
+				   buf_pa)) {
+			PRINTM(MERROR,
+			       "Failed to write download command to boot code.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Write the upper 32bits of the physical address to
+		 * REG_CMD_ADDR_HI */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					REG_CMD_ADDR_HI,
+					(t_u32)((t_u64)pmadapter->pcard_pcie->
+						cmd_buf->buf_pa >> 32))) {
+			PRINTM(MERROR,
+			       "Failed to write download command to boot code.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Write the command length to REG_CMD_SIZE */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle, REG_CMD_SIZE,
+					pmadapter->pcard_pcie->cmd_buf->
+					data_len)) {
+			PRINTM(MERROR,
+			       "Failed to write command length to REG_CMD_SIZE\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Ring the door bell */
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					pmadapter->pcard_pcie->reg->
+					reg_cpu_int_event,
+					CPU_INTR_DOOR_BELL)) {
+			PRINTM(MERROR,
+			       "Failed to assert door-bell interrupt.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		/* To send a command, the driver will:
+		   1. driver prepare the cmdrep buffer for adma
+		   2. driver programs dma_mode field to direct programming mode
+		   and programs dma_size field to define DMA data transfer size.
+		   3. driver programs src_base_addr register to define source
+		   location of DMA data
+		   4. driver sets src_wptr to 1 to initiate DMA operation
+		 */
+		wlan_init_adma(pmadapter, ADMA_CMDRESP,
+			       pmadapter->pcard_pcie->cmdrsp_buf->buf_pa,
+			       MRVDRV_SIZE_OF_CMD_BUFFER, MFALSE);
+		wlan_init_adma(pmadapter, ADMA_CMD,
+			       pmadapter->pcard_pcie->cmd_buf->buf_pa,
+			       pmadapter->pcard_pcie->cmd_buf->data_len,
+			       MFALSE);
+	}
+#endif
+done:
+	if ((ret == MLAN_STATUS_FAILURE) && pmadapter)
+		pmadapter->cmd_sent = MFALSE;
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define MLAN_SLEEP_COOKIE_DEF 0xBEEFBEEF
+#define MAX_DELAY_LOOP_COUNT 100
+
+static void
+mlan_delay_for_sleep_cookie(mlan_adapter *pmadapter, t_u32 max_delay_loop_cnt)
+{
+	t_u8 *buffer;
+	t_u32 sleep_cookie = 0;
+	t_u32 count = 0;
+	pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+
+	for (count = 0; count < max_delay_loop_cnt; count++) {
+		buffer = pmbuf->pbuf;
+		sleep_cookie = *(t_u32 *)buffer;
+
+		if (sleep_cookie == MLAN_SLEEP_COOKIE_DEF) {
+			PRINTM(MINFO, "sleep cookie FOUND at count = %d!!\n",
+			       count);
+			break;
+		}
+		wlan_udelay(pmadapter, 20);
+	}
+
+	if (count >= max_delay_loop_cnt)
+		PRINTM(MINFO, "sleep cookie not found!!\n");
+}
+#endif
+
+/**
+ *  @brief This function handles command complete interrupt
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_process_cmd_resp(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+	pmlan_buffer cmd_buf = MNULL;
+	t_u16 resp_len = 0;
+
+	ENTER();
+
+	PRINTM(MINFO, "Rx CMD Response\n");
+
+	if (pmbuf == MNULL) {
+		PRINTM(MMSG, "Rx CMD response pmbuf is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Get data length from interface header -
+	   first 2 bytes are len, second 2 bytes are type */
+	resp_len = *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
+
+	pmadapter->upld_len = wlan_le16_to_cpu(resp_len);
+	pmadapter->upld_len -= PCIE_INTF_HEADER_LEN;
+	cmd_buf = pmadapter->pcard_pcie->cmd_buf;
+	if (cmd_buf) {
+		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+				       cmd_buf->pbuf + cmd_buf->data_offset,
+				       cmd_buf->buf_pa, WLAN_UPLD_SIZE,
+				       PCI_DMA_TODEVICE);
+		pmadapter->pcard_pcie->cmd_buf = MNULL;
+	}
+	if (!pmadapter->curr_cmd) {
+		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+			wlan_process_sleep_confirm_resp(pmadapter,
+							pmbuf->pbuf +
+							pmbuf->data_offset +
+							PCIE_INTF_HEADER_LEN,
+							pmadapter->upld_len);
+			/* We are sending sleep confirm done interrupt in the
+			 * middle of sleep handshake. There is a corner case
+			 * when Tx done interrupt is received from firmware
+			 * during sleep handshake due to which host and firmware
+			 * power states go out of sync causing Tx data timeout
+			 * problem. Hence sleep confirm done interrupt is sent
+			 * at the end of sleep handshake to fix the problem
+			 *
+			 * Host could be reading the interrupt during polling
+			 * (while loop) or to address a FW interrupt. In either
+			 * case, after clearing the interrupt driver needs to
+			 * send a sleep confirm event at the end of processing
+			 * command response right here. This marks the end of
+			 * the sleep handshake with firmware.
+			 */
+			wlan_pcie_enable_host_int_mask(pmadapter);
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						pmadapter->pcard_pcie->reg->
+						reg_cpu_int_event,
+						CPU_INTR_SLEEP_CFM_DONE)) {
+				PRINTM(MERROR, "Write register failed\n");
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+#if defined(PCIE8997) || defined(PCIE8897)
+			mlan_delay_for_sleep_cookie(pmadapter,
+						    MAX_DELAY_LOOP_COUNT);
+#endif
+		}
+		memcpy_ext(pmadapter, pmadapter->upld_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   PCIE_INTF_HEADER_LEN,
+			   pmadapter->upld_len, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	} else {
+		pmadapter->cmd_resp_received = MTRUE;
+		pmbuf->data_len = pmadapter->upld_len;
+		pmbuf->data_offset += PCIE_INTF_HEADER_LEN;
+		pmadapter->curr_cmd->respbuf = pmbuf;
+
+		/* Take the pointer and set it to CMD node and will
+		   return in the response complete callback */
+		pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			/* Clear the cmd-rsp buffer address in scratch
+			   registers. This will prevent firmware from writing to
+			   the same response buffer again. */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						REG_CMDRSP_ADDR_LO, 0)) {
+				PRINTM(MERROR,
+				       "Rx CMD: failed to clear cmd_rsp address.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			/* Write the upper 32bits of the cmdrsp buffer physical
+			   address */
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						REG_CMDRSP_ADDR_HI, 0)) {
+				PRINTM(MERROR,
+				       "Rx CMD: failed to clear cmd_rsp address.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			/* Clear the cmd-rsp buffer address in adma registers.
+			   This will prevent firmware from writing to the same
+			   response buffer again. */
+			if (wlan_init_adma(pmadapter, ADMA_CMDRESP, 0, 0,
+					   MFALSE)) {
+				PRINTM(MERROR,
+				       "Rx CMD: failed to clear cmd_rsp address.\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+#endif
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles command response completion
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pmbuf        A pointer to mlan_buffer
+ *
+ *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_cmdrsp_complete(mlan_adapter *pmadapter,
+			  mlan_buffer *pmbuf, mlan_status status)
+{
+
+	ENTER();
+
+	/*return the cmd response pmbuf */
+	if (pmbuf) {
+		pmbuf->data_len = MRVDRV_SIZE_OF_CMD_BUFFER;
+		pmbuf->data_offset -= PCIE_INTF_HEADER_LEN;
+		pmadapter->pcard_pcie->cmdrsp_buf = pmbuf;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function check pending evt buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param rdptr      evt rdptr
+ *
+ *  @return           MTRUE/MFALSE;
+ */
+static t_u8
+wlan_check_evt_buffer(mlan_adapter *pmadapter, t_u32 rdptr)
+{
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		if (((rdptr & EVT_RW_PTR_MASK) !=
+		     (pmadapter->pcard_pcie->evtbd_rdptr & EVT_RW_PTR_MASK)) ||
+		    ((rdptr & EVT_RW_PTR_ROLLOVER_IND) !=
+		     (pmadapter->pcard_pcie->evtbd_rdptr &
+		      EVT_RW_PTR_ROLLOVER_IND)))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		if ((pmadapter->pcard_pcie->evtbd_rdptr &
+		     ADMA_RW_PTR_WRAP_MASK) != (rdptr & ADMA_RW_PTR_WRAP_MASK))
+			return MTRUE;
+		else
+			return MFALSE;
+	}
+#endif
+	return MFALSE;
+}
+
+/**
+ *  @brief This function handles FW event ready interrupt
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_process_event_ready(mlan_adapter *pmadapter)
+{
+	t_u32 rd_index =
+		pmadapter->pcard_pcie->evtbd_rdptr & (MLAN_MAX_EVT_BD - 1);
+	t_u32 rdptr, event;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(PCIE8997) || defined(PCIE8897)
+	mlan_pcie_evt_buf *pevtbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+	ENTER();
+
+	if (pmadapter->event_received) {
+		PRINTM(MINFO, "Event being processed, do not "
+		       "process this interrupt just yet\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	if (rd_index >= MLAN_MAX_EVT_BD) {
+		PRINTM(MINFO, "Invalid rd_index...\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Read the event ring read pointer set by firmware */
+	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_pcie->reg->reg_evtbd_rdptr,
+			       &rdptr)) {
+		PRINTM(MERROR, "EvtRdy: failed to read REG_EVTBD_RDPTR\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma)
+		rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+	PRINTM(MINFO, "EvtRdy: Initial <Wr: 0x%x, Rd: 0x%x>\n",
+	       pmadapter->pcard_pcie->evtbd_wrptr, rdptr);
+	if (wlan_check_evt_buffer(pmadapter, rdptr)) {
+		mlan_buffer *pmbuf_evt;
+		t_u16 evt_len;
+
+		PRINTM(MINFO, "EvtRdy: Read Index: %d\n", rd_index);
+		pmbuf_evt = pmadapter->pcard_pcie->evt_buf_list[rd_index];
+
+		/*unmap the pmbuf for CPU Access */
+		pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+				       pmbuf_evt->pbuf + pmbuf_evt->data_offset,
+				       pmbuf_evt->buf_pa, MAX_EVENT_SIZE,
+				       PCI_DMA_FROMDEVICE);
+
+		/* Take the pointer and set it to event pointer in adapter
+		   and will return back after event handling callback */
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			pevtbd_buf =
+				(mlan_pcie_evt_buf *)pmadapter->pcard_pcie->
+				evtbd_ring[rd_index];
+			pevtbd_buf->paddr = 0;
+			pevtbd_buf->len = 0;
+			pevtbd_buf->flags = 0;
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf *) pmadapter->pcard_pcie->
+				evtbd_ring[rd_index];
+			padma_bd_buf->paddr = 0;
+			padma_bd_buf->len = 0;
+			padma_bd_buf->flags = 0;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+		}
+#endif
+		pmadapter->pcard_pcie->evt_buf_list[rd_index] = MNULL;
+
+		event = *((t_u32 *)&pmbuf_evt->pbuf[pmbuf_evt->data_offset +
+						    PCIE_INTF_HEADER_LEN]);
+		pmadapter->event_cause = wlan_le32_to_cpu(event);
+		/* The first 4bytes will be the event transfer header
+		   len is 2 bytes followed by type which is 2 bytes */
+		evt_len = *((t_u16 *)&pmbuf_evt->pbuf[pmbuf_evt->data_offset]);
+		evt_len = wlan_le16_to_cpu(evt_len);
+
+		if ((evt_len > 0) && (evt_len > MLAN_EVENT_HEADER_LEN) &&
+		    (evt_len - MLAN_EVENT_HEADER_LEN < MAX_EVENT_SIZE))
+			memcpy_ext(pmadapter, pmadapter->event_body,
+				   pmbuf_evt->pbuf + pmbuf_evt->data_offset +
+				   MLAN_EVENT_HEADER_LEN,
+				   evt_len - MLAN_EVENT_HEADER_LEN,
+				   sizeof(pmadapter->event_body));
+
+		pmbuf_evt->data_offset += PCIE_INTF_HEADER_LEN;
+		pmbuf_evt->data_len = evt_len - PCIE_INTF_HEADER_LEN;
+		PRINTM(MINFO, "Event length: %d\n", pmbuf_evt->data_len);
+
+		pmadapter->event_received = MTRUE;
+		pmadapter->pmlan_buffer_event = pmbuf_evt;
+		pmadapter->pcard_pcie->evtbd_rdptr++;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			if ((pmadapter->pcard_pcie->evtbd_rdptr &
+			     EVT_RW_PTR_MASK) == MLAN_MAX_EVT_BD) {
+				pmadapter->pcard_pcie->evtbd_rdptr =
+					((pmadapter->pcard_pcie->evtbd_rdptr &
+					  EVT_RW_PTR_ROLLOVER_IND) ^
+					 EVT_RW_PTR_ROLLOVER_IND);
+			}
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma)
+			pmadapter->pcard_pcie->evtbd_rdptr &=
+				ADMA_RW_PTR_WRAP_MASK;
+#endif
+
+		/* Do not update the event write pointer here, wait till the
+		   buffer is released. This is just to make things simpler,
+		   we need to find a better method of managing these buffers.
+		 */
+	} else {
+		PRINTM(MINTR, "------>EVENT DONE\n");
+		if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+					pmadapter->pcard_pcie->reg->
+					reg_cpu_int_event,
+					CPU_INTR_EVENT_DONE)) {
+			PRINTM(MERROR,
+			       "Failed to asset event done interrupt\n");
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles event completion
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pmbuf        A pointer to mlan_buffer
+ *
+ *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_event_complete(mlan_adapter *pmadapter,
+			 mlan_buffer *pmbuf, mlan_status status)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 wrptr =
+		pmadapter->pcard_pcie->evtbd_wrptr & (MLAN_MAX_EVT_BD - 1);
+	t_u32 rdptr;
+#if defined(PCIE8997) || defined(PCIE8897)
+	mlan_pcie_evt_buf *pevtbd_buf;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	adma_dual_desc_buf *padma_bd_buf;
+#endif
+
+	ENTER();
+	if (!pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (wrptr >= MLAN_MAX_EVT_BD) {
+		PRINTM(MERROR, "EvtCom: Invalid wrptr 0x%x\n", wrptr);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Read the event ring read pointer set by firmware */
+	if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_pcie->reg->reg_evtbd_rdptr,
+			       &rdptr)) {
+		PRINTM(MERROR, "EvtCom: failed to read REG_EVTBD_RDPTR\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma)
+		rdptr = rdptr >> ADMA_RPTR_START;
+#endif
+
+	if (!pmadapter->pcard_pcie->evt_buf_list[wrptr]) {
+		pmbuf->data_len = MAX_EVENT_SIZE;
+		pmbuf->data_offset -= PCIE_INTF_HEADER_LEN;
+
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_map_memory(pmadapter->pmoal_handle,
+					 pmbuf->pbuf + pmbuf->data_offset,
+					 &pmbuf->buf_pa, MAX_EVENT_SIZE,
+					 PCI_DMA_FROMDEVICE)) {
+			PRINTM(MERROR, "EvtCom: failed to moal_map_memory\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		pmadapter->pcard_pcie->evt_buf_list[wrptr] = pmbuf;
+#if defined(PCIE8997) || defined(PCIE8897)
+		if (!pmadapter->pcard_pcie->reg->use_adma) {
+			pevtbd_buf =
+				(mlan_pcie_evt_buf *)pmadapter->pcard_pcie->
+				evtbd_ring[wrptr];
+			pevtbd_buf->paddr = pmbuf->buf_pa;
+			pevtbd_buf->len = (t_u16)pmbuf->data_len;
+			pevtbd_buf->flags = 0;
+		}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->use_adma) {
+			padma_bd_buf =
+				(adma_dual_desc_buf *) pmadapter->pcard_pcie->
+				evtbd_ring[wrptr];
+			padma_bd_buf->paddr = pmbuf->buf_pa;
+			padma_bd_buf->len =
+				ALIGN_SZ(pmbuf->data_len, ADMA_ALIGN_SIZE);
+			padma_bd_buf->flags = 0;
+			padma_bd_buf->flags =
+				ADMA_BD_FLAG_INT_EN | ADMA_BD_FLAG_DST_HOST;
+			padma_bd_buf->pkt_size = 0;
+			padma_bd_buf->reserved = 0;
+		}
+#endif
+		pmbuf = MNULL;
+	} else {
+		PRINTM(MINFO,
+		       "EvtCom: ERROR: Buffer is still valid at "
+		       "index %d, <%p, %p>\n",
+		       wrptr, pmadapter->pcard_pcie->evt_buf_list[wrptr],
+		       pmbuf);
+	}
+
+	pmadapter->pcard_pcie->evtbd_wrptr++;
+
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		if ((pmadapter->pcard_pcie->evtbd_wrptr & EVT_RW_PTR_MASK) ==
+		    MLAN_MAX_EVT_BD) {
+			pmadapter->pcard_pcie->evtbd_wrptr =
+				((pmadapter->pcard_pcie->evtbd_wrptr &
+				  EVT_RW_PTR_ROLLOVER_IND) ^
+				 EVT_RW_PTR_ROLLOVER_IND);
+		}
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma)
+		pmadapter->pcard_pcie->evtbd_wrptr &= ADMA_RW_PTR_WRAP_MASK;
+#endif
+	PRINTM(MINFO, "EvtCom: Updated <Wr: 0x%x, Rd: 0x%x>\n",
+	       pmadapter->pcard_pcie->evtbd_wrptr, rdptr);
+
+	/* Write the event ring write pointer in to REG_EVTBD_WRPTR */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_evtbd_wrptr,
+				pmadapter->pcard_pcie->evtbd_wrptr)) {
+		PRINTM(MERROR, "EvtCom: failed to write REG_EVTBD_WRPTR\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+done:
+	/* Free the buffer for failure case */
+	if (ret && pmbuf)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	PRINTM(MINFO, "EvtCom: Check Events Again\n");
+	ret = wlan_pcie_process_event_ready(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads boot command to the card.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pmbuf        A pointer to mlan_buffer
+ *
+ *  @return 	        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_send_boot_cmd(mlan_adapter *pmadapter, mlan_buffer *pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (!pmadapter || !pmbuf) {
+		PRINTM(MERROR, "NULL Pointer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (MLAN_STATUS_FAILURE ==
+	    pcb->moal_map_memory(pmadapter->pmoal_handle,
+				 pmbuf->pbuf + pmbuf->data_offset,
+				 &pmbuf->buf_pa, WLAN_UPLD_SIZE,
+				 PCI_DMA_TODEVICE)) {
+		PRINTM(MERROR, "BootCmd: failed to moal_map_memory\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (!(pmbuf->pbuf && pmbuf->data_len && pmbuf->buf_pa)) {
+		PRINTM(MERROR, "%s: Invalid buffer <%p, %#x:%x, len=%d>\n",
+		       __func__, pmbuf->pbuf,
+		       (t_u32)((t_u64)pmbuf->buf_pa >> 32),
+		       (t_u32)pmbuf->buf_pa, pmbuf->data_len);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Write the lower 32bits of the physical address to scratch
+	 * register 0 */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_scratch_0,
+				(t_u32)pmbuf->buf_pa)) {
+		PRINTM(MERROR,
+		       "Failed to write download command to boot code\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Write the upper 32bits of the physical address to scratch
+	 * register 1 */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_scratch_1,
+				(t_u32)((t_u64)pmbuf->buf_pa >> 32))) {
+		PRINTM(MERROR,
+		       "Failed to write download command to boot code\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Write the command length to scratch register 2 */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_scratch_2,
+				pmbuf->data_len)) {
+		PRINTM(MERROR,
+		       "Failed to write command length to scratch register 2\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Ring the door bell */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_cpu_int_event,
+				CPU_INTR_DOOR_BELL)) {
+		PRINTM(MERROR, "Failed to assert door-bell interrupt\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	LEAVE();
+	return ret;
+
+done:
+	if (MLAN_STATUS_FAILURE ==
+	    pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+				   pmbuf->pbuf + pmbuf->data_offset,
+				   pmbuf->buf_pa, WLAN_UPLD_SIZE,
+				   PCI_DMA_TODEVICE))
+		PRINTM(MERROR, "BootCmd: failed to moal_unmap_memory\n");
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function init rx port in firmware
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pcie_init_fw(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 txbd_val = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		txbd_val = pmadapter->pcard_pcie->txbd_wrptr &
+			pmadapter->pcard_pcie->reg->txrx_rw_ptr_wrap_mask;
+		txbd_val = txbd_val << TXBD_RW_PTR_START;
+	}
+#endif
+	/* Write the RX ring write pointer in to REG_RXBD_WRPTR */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_rxbd_wrptr,
+				pmadapter->pcard_pcie->rxbd_wrptr | txbd_val)) {
+		PRINTM(MERROR, "Init FW: failed to write REG_RXBD_WRPTR\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* Write the event ring write pointer in to REG_EVTBD_WRPTR */
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_evtbd_wrptr,
+				pmadapter->pcard_pcie->evtbd_wrptr)) {
+		PRINTM(MERROR, "Init FW: failed to write REG_EVTBD_WRPTR\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+done:
+	return ret;
+}
+
+/**
+ *  @brief  This function downloads FW blocks to device
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param fw			A pointer to firmware image
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_prog_fw_w_helper(mlan_adapter *pmadapter, mlan_fw_image *fw)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *firmware = fw->pfw_buf;
+	t_u32 firmware_len = fw->fw_len;
+	t_u32 offset = 0;
+	mlan_buffer *pmbuf = MNULL;
+	t_u32 txlen, tries, len;
+	t_u32 block_retry_cnt = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+#if defined(PCIE9098)
+	t_u32 rev_id_reg = 0;
+	t_u32 revision_id = 0;
+#endif
+	t_u8 check_fw_status = MFALSE;
+	t_u32 fw_dnld_status = 0;
+	t_u32 fw_dnld_offset = 0;
+	t_u8 mic_retry = 0;
+
+	ENTER();
+	if (!pmadapter) {
+		PRINTM(MERROR, "adapter structure is not valid\n");
+		goto done;
+	}
+
+	if (!firmware || !firmware_len) {
+		PRINTM(MERROR,
+		       "No firmware image found! Terminating download\n");
+		goto done;
+	}
+
+	PRINTM(MINFO, "Downloading FW image (%d bytes)\n", firmware_len);
+
+	if (wlan_disable_pcie_host_int(pmadapter)) {
+		PRINTM(MERROR, "prog_fw: Disabling interrupts failed\n");
+		goto done;
+	}
+
+	pmbuf = wlan_alloc_mlan_buffer(pmadapter, WLAN_UPLD_SIZE, 0,
+				       MOAL_ALLOC_MLAN_BUFFER);
+	if (!pmbuf) {
+		PRINTM(MERROR, "prog_fw: Unable to allocate mlan_buffer\n");
+		goto done;
+	}
+#if defined(PCIE9098)
+	if (IS_PCIE9098(pmadapter->card_type)) {
+		rev_id_reg = pmadapter->pcard_pcie->reg->reg_rev_id;
+		ret = pcb->moal_read_reg(pmadapter->pmoal_handle, rev_id_reg,
+					 &revision_id);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "Failed to read PCIe revision id register\n");
+			goto done;
+		}
+		/* Skyhawk A0, need to check both CRC and MIC error */
+		if (revision_id >= CHIP_9098_REV_A0)
+			check_fw_status = MTRUE;
+	}
+#endif
+	/* For PCIE9097, need check both CRC and MIC error */
+#if defined(PCIE9097)
+	if (IS_PCIE9097(pmadapter->card_type))
+		check_fw_status = MTRUE;
+#endif
+
+	/* Perform firmware data transfer */
+	do {
+		t_u32 ireg_intr = 0;
+		t_u32 read_retry_cnt = 0;
+
+		/* More data? */
+		if (offset >= firmware_len)
+			break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+						 pmadapter->pcard_pcie->reg->
+						 reg_scratch_2, &len);
+			if (ret) {
+				PRINTM(MWARN,
+				       "Failed reading length from boot code\n");
+				goto done;
+			}
+			if (len || offset)
+				break;
+			wlan_udelay(pmadapter, 10);
+		}
+
+		if (!len) {
+			break;
+		} else if (len > WLAN_UPLD_SIZE) {
+			PRINTM(MERROR,
+			       "FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			goto done;
+		}
+
+		txlen = len;
+
+		if (len & MBIT(0)) {
+			if (check_fw_status) {
+				/* Get offset from fw dnld offset Register */
+				ret = pcb->moal_read_reg(pmadapter->
+							 pmoal_handle,
+							 pmadapter->pcard_pcie->
+							 reg->reg_scratch_6,
+							 &fw_dnld_offset);
+				if (ret != MLAN_STATUS_SUCCESS) {
+					PRINTM(MERROR,
+					       "FW download failure @ %d, reading fw dnld offset failed\n",
+					       offset);
+					goto done;
+				}
+				/* Get CRC MIC error from fw dnld status
+				 * Register */
+				ret = pcb->moal_read_reg(pmadapter->
+							 pmoal_handle,
+							 pmadapter->pcard_pcie->
+							 reg->reg_scratch_7,
+							 &fw_dnld_status);
+				if (ret != MLAN_STATUS_SUCCESS) {
+					PRINTM(MERROR,
+					       "FW download failure @ %d, reading fw dnld status failed\n",
+					       offset);
+					goto done;
+				}
+				PRINTM(MERROR,
+				       "FW download error: status=0x%x offset = 0x%x fw offset = 0x%x\n",
+				       fw_dnld_status, offset, fw_dnld_offset);
+			}
+			block_retry_cnt++;
+			if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
+				PRINTM(MERROR,
+				       "FW download failure @ %d, over max "
+				       "retry count\n", offset);
+				goto done;
+			}
+			PRINTM(MERROR,
+			       "FW CRC error indicated by the "
+			       "helper: len = 0x%04X, txlen = %d\n",
+			       len, txlen);
+			len &= ~MBIT(0);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+			if (fw_dnld_status & (MBIT(6) | MBIT(7))) {
+				offset = 0;
+				mic_retry++;
+				if (mic_retry > MAX_FW_RETRY) {
+					PRINTM(MERROR,
+					       "FW download failure @ %d, over max "
+					       "mic retry count\n", offset);
+					goto done;
+				}
+			}
+		} else {
+			block_retry_cnt = 0;
+			/* Set blocksize to transfer - checking for last block
+			 */
+			if (firmware_len - offset < txlen)
+				txlen = firmware_len - offset;
+
+			PRINTM(MINFO, ".");
+
+			/* Copy payload to buffer */
+			memmove(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
+				&firmware[offset], txlen);
+			pmbuf->data_len = txlen;
+		}
+
+		/* Send the boot command to device */
+		if (wlan_pcie_send_boot_cmd(pmadapter, pmbuf)) {
+			PRINTM(MERROR,
+			       "Failed to send firmware download command\n");
+			goto done;
+		}
+		/* Wait for the command done interrupt */
+		do {
+			if (read_retry_cnt > MAX_READ_REG_RETRY) {
+				PRINTM(MERROR,
+				       "prog_fw: Failed to get command done interrupt "
+				       "retry count = %d\n", read_retry_cnt);
+				goto done;
+			}
+			if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+					       pmadapter->pcard_pcie->reg->
+					       reg_cpu_int_status,
+					       &ireg_intr)) {
+				PRINTM(MERROR,
+				       "prog_fw: Failed to read "
+				       "interrupt status during fw dnld\n");
+				/* buffer was mapped in send_boot_cmd, unmap
+				 * first */
+				pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+						       pmbuf->pbuf +
+						       pmbuf->data_offset,
+						       pmbuf->buf_pa,
+						       WLAN_UPLD_SIZE,
+						       PCI_DMA_TODEVICE);
+				goto done;
+			}
+			read_retry_cnt++;
+			pcb->moal_usleep_range(pmadapter->pmoal_handle, 10, 20);
+		} while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
+			 CPU_INTR_DOOR_BELL);
+		/* got interrupt - can unmap buffer now */
+		if (MLAN_STATUS_FAILURE ==
+		    pcb->moal_unmap_memory(pmadapter->pmoal_handle,
+					   pmbuf->pbuf + pmbuf->data_offset,
+					   pmbuf->buf_pa, WLAN_UPLD_SIZE,
+					   PCI_DMA_TODEVICE)) {
+			PRINTM(MERROR,
+			       "prog_fw: failed to moal_unmap_memory\n");
+			goto done;
+		}
+		offset += txlen;
+	} while (MTRUE);
+
+	PRINTM(MMSG, "FW download over, size %d bytes\n", offset);
+
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	if (pmbuf)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *	@brief This function get pcie device from card type
+ *
+ *	@param pmadapter  A pointer to mlan_adapter structure
+ *	@return 		  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_get_pcie_device(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 card_type = pmadapter->card_type;
+
+	ENTER();
+
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_pcie_card),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->pcard_pcie);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_pcie) {
+		PRINTM(MERROR, "Failed to allocate pcard_pcie\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	switch (card_type) {
+#ifdef PCIE8897
+	case CARD_TYPE_PCIE8897:
+		pmadapter->pcard_pcie->reg = &mlan_reg_pcie8897;
+		pmadapter->pcard_info = &mlan_card_info_pcie8897;
+		pmadapter->pcard_pcie->txrx_bd_size = MAX_TXRX_BD;
+		break;
+#endif
+#ifdef PCIE8997
+	case CARD_TYPE_PCIE8997:
+		pmadapter->pcard_pcie->reg = &mlan_reg_pcie8997;
+		pmadapter->pcard_info = &mlan_card_info_pcie8997;
+		pmadapter->pcard_pcie->txrx_bd_size = MAX_TXRX_BD;
+		break;
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	case CARD_TYPE_PCIE9097:
+	case CARD_TYPE_PCIE9098:
+		pmadapter->pcard_pcie->reg = &mlan_reg_pcie9098;
+		pmadapter->pcard_info = &mlan_card_info_pcie9098;
+		pmadapter->pcard_pcie->txrx_bd_size = ADMA_DEF_TXRX_BD;
+		pmadapter->pcard_pcie->txrx_num_desc = TXRX_DEF_NUM_DESC;
+#ifdef PCIE9097
+		if (card_type == CARD_TYPE_PCIE9097 &&
+		    pmadapter->card_rev == CHIP_9097_REV_B0)
+			pmadapter->pcard_pcie->reg = &mlan_reg_pcie9097_b0;
+#endif
+		break;
+#endif
+	default:
+		PRINTM(MERROR, "can't get right pcie card type \n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief PCIE wakeup handler
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return 	      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pcie_wakeup(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 data = 0;
+	ENTER();
+	/* Enable interrupts or any chip access will wakeup device */
+	ret = pmadapter->callbacks.moal_read_reg(pmadapter->pmoal_handle,
+						 pmadapter->pcard_pcie->reg->
+						 reg_ip_rev, &data);
+
+	if (ret == MLAN_STATUS_SUCCESS) {
+		PRINTM(MINFO,
+		       "PCIE wakeup: Read PCI register to wakeup device ...\n");
+	} else {
+		PRINTM(MINFO, "PCIE wakeup: Failed to wakeup device ...\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ */
+/**
+ *  @param msg_id  A message id
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @return         MLAN_STATUS_FAILURE -- if the intererupt is not for us
+ */
+static mlan_status
+wlan_pcie_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
+{
+	t_u32 pcie_ireg;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_void *pmoal_handle = pmadapter->pmoal_handle;
+	t_void *pint_lock = pmadapter->pint_lock;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+		pcb->moal_spin_lock(pmoal_handle, pint_lock);
+		pmadapter->ireg = 1;
+		pcb->moal_spin_unlock(pmoal_handle, pint_lock);
+	} else if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
+		pcie_ireg = (1 << msg_id) &
+			pmadapter->pcard_pcie->reg->host_intr_mask;
+		if (pcie_ireg) {
+			if (!pmadapter->pps_uapsd_mode &&
+			    (pmadapter->ps_state == PS_STATE_SLEEP)) {
+				pmadapter->pm_wakeup_fw_try = MFALSE;
+				pmadapter->ps_state = PS_STATE_AWAKE;
+				pmadapter->pm_wakeup_card_req = MFALSE;
+			}
+		}
+		pcb->moal_spin_lock(pmoal_handle, pint_lock);
+		pmadapter->ireg |= pcie_ireg;
+		pcb->moal_spin_unlock(pmoal_handle, pint_lock);
+
+		PRINTM(MINTR, "ireg: 0x%08x\n", pcie_ireg);
+	} else {
+		wlan_pcie_disable_host_int_mask(pmadapter);
+		if (pcb->moal_read_reg(pmoal_handle,
+				       pmadapter->pcard_pcie->reg->
+				       reg_host_int_status, &pcie_ireg)) {
+			PRINTM(MERROR, "Read func%d register failed\n",
+			       pmadapter->pcard_pcie->func_num);
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+			PRINTM(MINTR, "func%d: pcie_ireg=0x%x\n",
+			       pmadapter->pcard_pcie->func_num, pcie_ireg);
+			if (!pmadapter->pps_uapsd_mode &&
+			    (pmadapter->ps_state == PS_STATE_SLEEP)) {
+				/* Potentially for PCIe we could get other
+				 * interrupts like shared. */
+				pmadapter->pm_wakeup_fw_try = MFALSE;
+				pmadapter->ps_state = PS_STATE_AWAKE;
+				pmadapter->pm_wakeup_card_req = MFALSE;
+			}
+			pcb->moal_spin_lock(pmoal_handle, pint_lock);
+			pmadapter->ireg |= pcie_ireg;
+			pcb->moal_spin_unlock(pmoal_handle, pint_lock);
+
+			/* Clear the pending interrupts */
+			if (pcb->moal_write_reg(pmoal_handle,
+						pmadapter->pcard_pcie->reg->
+						reg_host_int_status,
+						~pcie_ireg)) {
+				PRINTM(MWARN, "Write register failed\n");
+				LEAVE();
+				return ret;
+			}
+		} else {
+			wlan_pcie_enable_host_int_mask(pmadapter);
+			PRINTM(MINFO, "This is not our interrupt\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the msix interrupt status and
+ *  handle it accordingly.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_msix_int(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 pcie_ireg = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	pcie_ireg =
+		pmadapter->ireg & pmadapter->pcard_pcie->reg->host_intr_mask;
+	pmadapter->ireg = 0;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+
+	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_dnld_done) {
+		PRINTM(MINFO, "<--- DATA sent Interrupt --->\n");
+		ret = wlan_pcie_send_data_complete(pmadapter);
+		if (ret)
+			goto done;
+	}
+	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_upld_rdy) {
+		PRINTM(MINFO, "Rx DATA\n");
+		ret = wlan_pcie_process_recv_data(pmadapter);
+		if (ret)
+			goto done;
+	}
+	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_event_rdy) {
+		PRINTM(MINFO, "Rx EVENT\n");
+		ret = wlan_pcie_process_event_ready(pmadapter);
+		if (ret)
+			goto done;
+	}
+	if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_done) {
+		if (pmadapter->cmd_sent) {
+			PRINTM(MINFO, "<--- CMD sent Interrupt --->\n");
+			pmadapter->cmd_sent = MFALSE;
+		}
+		ret = wlan_pcie_process_cmd_resp(pmadapter);
+		if (ret)
+			goto done;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->host_intr_cmd_dnld &&
+	    (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_dnld)) {
+		if (pmadapter->cmd_sent)
+			pmadapter->cmd_sent = MFALSE;
+		if (pmadapter->pcard_pcie->vdll_cmd_buf)
+			wlan_pcie_send_vdll_complete(pmadapter);
+		PRINTM(MINFO, "<--- CMD DNLD DONE Interrupt --->\n");
+	}
+#endif
+	PRINTM(MINFO, "cmd_sent=%d data_sent=%d\n", pmadapter->cmd_sent,
+	       pmadapter->data_sent);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and
+ *  handle it accordingly.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_process_pcie_int_status(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 pcie_ireg = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSIX) {
+		wlan_process_msix_int(pmadapter);
+		goto done;
+	}
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	if (pmadapter->pcard_pcie->pcie_int_mode != PCIE_INT_MODE_MSI)
+		pcie_ireg = pmadapter->ireg;
+	pmadapter->ireg = 0;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_pcie->reg->
+				       reg_host_int_status, &pcie_ireg)) {
+			PRINTM(MERROR, "Read func%d register failed\n",
+			       pmadapter->pcard_pcie->func_num);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+			PRINTM(MINTR, "func%d: pcie_ireg=0x%x\n",
+			       pmadapter->pcard_pcie->func_num, pcie_ireg);
+			if (pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+				if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+							pmadapter->pcard_pcie->
+							reg->
+							reg_host_int_status,
+							~pcie_ireg)) {
+					PRINTM(MERROR,
+					       "Write register failed\n");
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			}
+			if (!pmadapter->pps_uapsd_mode &&
+			    (pmadapter->ps_state == PS_STATE_SLEEP)) {
+				/* Potentially for PCIe we could get other
+				 * interrupts like shared. */
+				pmadapter->pm_wakeup_fw_try = MFALSE;
+				pmadapter->ps_state = PS_STATE_AWAKE;
+				pmadapter->pm_wakeup_card_req = MFALSE;
+			}
+		}
+	}
+	while (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_mask) {
+		if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_dnld_done) {
+			pcie_ireg &=
+				~pmadapter->pcard_pcie->reg->
+				host_intr_dnld_done;
+			PRINTM(MINFO, "<--- DATA sent Interrupt --->\n");
+			pmadapter->callbacks.
+				moal_tp_accounting_rx_param(pmadapter->
+							    pmoal_handle, 3, 0);
+
+			ret = wlan_pcie_send_data_complete(pmadapter);
+			if (ret)
+				goto done;
+		}
+		if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_upld_rdy) {
+			pcie_ireg &=
+				~pmadapter->pcard_pcie->reg->host_intr_upld_rdy;
+			PRINTM(MINFO, "Rx DATA\n");
+			pmadapter->callbacks.
+				moal_tp_accounting_rx_param(pmadapter->
+							    pmoal_handle, 0, 0);
+			ret = wlan_pcie_process_recv_data(pmadapter);
+			if (ret)
+				goto done;
+		}
+		if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_event_rdy) {
+			pcie_ireg &=
+				~pmadapter->pcard_pcie->reg->
+				host_intr_event_rdy;
+			PRINTM(MINFO, "Rx EVENT\n");
+			ret = wlan_pcie_process_event_ready(pmadapter);
+			if (ret)
+				goto done;
+		}
+		if (pcie_ireg & pmadapter->pcard_pcie->reg->host_intr_cmd_done) {
+			pcie_ireg &=
+				~pmadapter->pcard_pcie->reg->host_intr_cmd_done;
+			if (pmadapter->cmd_sent) {
+				PRINTM(MINFO, "<--- CMD sent Interrupt --->\n");
+				pmadapter->cmd_sent = MFALSE;
+			}
+			ret = wlan_pcie_process_cmd_resp(pmadapter);
+			if (ret)
+				goto done;
+		}
+#if defined(PCIE9098) || defined(PCIE9097)
+		if (pmadapter->pcard_pcie->reg->host_intr_cmd_dnld &&
+		    (pcie_ireg &
+		     pmadapter->pcard_pcie->reg->host_intr_cmd_dnld)) {
+			pcie_ireg &=
+				~pmadapter->pcard_pcie->reg->host_intr_cmd_dnld;
+			if (pmadapter->cmd_sent)
+				pmadapter->cmd_sent = MFALSE;
+			if (pmadapter->pcard_pcie->vdll_cmd_buf)
+				wlan_pcie_send_vdll_complete(pmadapter);
+			PRINTM(MINFO, "<--- CMD DNLD DONE Interrupt --->\n");
+		}
+#endif
+		if (pmadapter->pcard_pcie->pcie_int_mode == PCIE_INT_MODE_MSI) {
+			pcb->moal_spin_lock(pmadapter->pmoal_handle,
+					    pmadapter->pint_lock);
+			pmadapter->ireg = 0;
+			pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmadapter->pint_lock);
+		}
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_pcie->reg->
+				       reg_host_int_status, &pcie_ireg)) {
+			PRINTM(MERROR, "Read func%d register failed\n",
+			       pmadapter->pcard_pcie->func_num);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+			PRINTM(MINTR, "func%d: Poll pcie_ireg=0x%x\n",
+			       pmadapter->pcard_pcie->func_num, pcie_ireg);
+			if ((pmadapter->pcard_pcie->pcie_int_mode ==
+			     PCIE_INT_MODE_LEGACY) ||
+			    pmadapter->pcard_pcie->reg->msi_int_wr_clr) {
+				if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+							pmadapter->pcard_pcie->
+							reg->
+							reg_host_int_status,
+							~pcie_ireg)) {
+					PRINTM(MWARN,
+					       "Write register failed\n");
+					return MLAN_STATUS_FAILURE;
+				}
+			}
+			if (pmadapter->pcard_pcie->pcie_int_mode !=
+			    PCIE_INT_MODE_MSI) {
+				pcb->moal_spin_lock(pmadapter->pmoal_handle,
+						    pmadapter->pint_lock);
+				pcie_ireg |= pmadapter->ireg;
+				pmadapter->ireg = 0;
+				pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+						      pmadapter->pint_lock);
+			}
+			/* Don't update the pmadapter->pcie_ireg,
+			 * serving the status right now */
+		}
+	}
+	PRINTM(MINFO, "cmd_sent=%d data_sent=%d\n", pmadapter->cmd_sent,
+	       pmadapter->data_sent);
+	if (pmadapter->pcard_pcie->pcie_int_mode != PCIE_INT_MODE_MSI) {
+
+		if (pmadapter->ps_state != PS_STATE_SLEEP ||
+		    pmadapter->pcard_info->supp_ps_handshake)
+			wlan_pcie_enable_host_int_mask(pmadapter);
+
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets DRV_READY register
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param val        Value
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+mlan_status
+wlan_set_drv_ready_reg(mlan_adapter *pmadapter, t_u32 val)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_pcie->reg->reg_drv_ready,
+				val)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interface is present
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param val        Winner status (0: winner)
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+static mlan_status
+wlan_pcie_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+	t_u32 winner = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_pcie->reg->reg_scratch_3,
+			       &winner)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pollnum    Maximum polling number
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 firmware_stat;
+	t_u32 tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_pcie->reg->
+				       reg_scratch_3, &firmware_stat))
+			ret = MLAN_STATUS_FAILURE;
+		else
+			ret = MLAN_STATUS_SUCCESS;
+		if (ret)
+			continue;
+		if (firmware_stat == PCIE_FIRMWARE_READY) {
+			ret = MLAN_STATUS_SUCCESS;
+			break;
+		} else {
+			wlan_mdelay(pmadapter, 100);
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function init the pcie interface
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pcie_init(mlan_adapter *pmadapter)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Setting driver ready signature\n");
+	if (wlan_set_drv_ready_reg(pmadapter, PCIE_FIRMWARE_READY)) {
+		PRINTM(MERROR, "Failed to write driver ready signature\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  This function downloads firmware to card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pcie_dnld_fw(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 poll_num = 1;
+	t_u32 winner = 0;
+
+	ENTER();
+
+	ret = wlan_pcie_init(pmadapter);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR, "WLAN PCIE init failed\n", ret);
+		LEAVE();
+		return ret;
+	}
+	/* Check if firmware is already running */
+	ret = wlan_pcie_check_fw_status(pmadapter, poll_num);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		PRINTM(MMSG, "WLAN FW already running! Skip FW download\n");
+		goto done;
+	}
+	poll_num = MAX_FIRMWARE_POLL_TRIES;
+
+	/* Check if other interface is downloading */
+	ret = wlan_pcie_check_winner_status(pmadapter, &winner);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MFATAL, "WLAN read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MMSG,
+		       "WLAN is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
+		goto poll_fw;
+	}
+
+	/* Download the firmware image via helper */
+	ret = wlan_pcie_prog_fw_w_helper(pmadapter, pmfw);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "prog_fw failed ret=%#x\n", ret);
+		LEAVE();
+		return ret;
+	}
+poll_fw:
+	/* Check if the firmware is downloaded successfully or not */
+	ret = wlan_pcie_check_fw_status(pmadapter, poll_num);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "FW failed to be active in time!\n");
+		ret = MLAN_STATUS_FAILURE;
+		LEAVE();
+		return ret;
+	}
+done:
+
+	/* re-enable host interrupt for mlan after fw dnld is successful */
+	wlan_enable_pcie_host_int(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads data from driver to card.
+ *
+ *  Both commands and data packets are transferred to the card
+ *  by this function. This function adds the PCIE specific header
+ *  to the front of the buffer before transferring. The header
+ *  contains the length of the packet and the type. The firmware
+ *  handles the packets based upon this set type.
+ *
+ *  @param pmpriv    A pointer to mlan_private structure
+ *  @param type	     data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ *  @param tx_param  A pointer to mlan_tx_param (can be MNULL if type is
+ * command)
+ *
+ *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_pcie_host_to_card(pmlan_private pmpriv, t_u8 type,
+		       mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (!pmbuf) {
+		PRINTM(MERROR, "Passed NULL pmbuf to %s\n", __FUNCTION__);
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (type == MLAN_TYPE_DATA)
+		ret = wlan_pcie_send_data(pmadapter, type, pmbuf, tx_param);
+	else if (type == MLAN_TYPE_CMD)
+		ret = wlan_pcie_send_cmd(pmadapter, pmbuf);
+#if defined(PCIE9098) || defined(PCIE9097)
+	else if (type == MLAN_TYPE_VDLL)
+		ret = wlan_pcie_send_vdll(pmadapter, pmbuf);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function allocates the PCIE buffer for SSU
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+	/** Virtual base address of ssu buffer */
+	t_u8 *ssu_vbase;
+	/** Physical base address of ssu buffer */
+	t_u64 ssu_pbase = 0;
+
+	ENTER();
+
+	if (pmadapter->ssu_buf) {
+		PRINTM(MCMND, "ssu buffer already allocated\n");
+		LEAVE();
+		return ret;
+	}
+	/* Allocate buffer here so that firmware can DMA data on it */
+	pmbuf = wlan_alloc_mlan_buffer(pmadapter, 0, 0, MOAL_MALLOC_BUFFER);
+	if (!pmbuf) {
+		PRINTM(MERROR,
+		       "SSU buffer create : Unable to allocate mlan_buffer\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = pcb->moal_malloc_consistent(pmadapter->pmoal_handle,
+					  MLAN_SSU_BUF_SIZE, &ssu_vbase,
+					  &ssu_pbase);
+
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "%s: No free moal_malloc_consistent\n",
+		       __FUNCTION__);
+		/* free pmbuf */
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pmbuf->buf_pa = ssu_pbase;
+	pmbuf->pbuf = ssu_vbase;
+	pmbuf->data_offset = 0;
+	pmbuf->data_len = MLAN_SSU_BUF_SIZE;
+	pmbuf->total_pcie_buf_len = MLAN_SSU_BUF_SIZE;
+
+	PRINTM(MCMND,
+	       "SSU buffer: add new mlan_buffer base: %p, "
+	       "buf_base: %p, data_offset: %x, buf_pbase: %#x:%x, "
+	       "buf_len: %#x\n",
+	       pmbuf, pmbuf->pbuf, pmbuf->data_offset,
+	       (t_u32)((t_u64)pmbuf->buf_pa >> 32), (t_u32)pmbuf->buf_pa,
+	       pmbuf->data_len);
+
+	pmadapter->ssu_buf = pmbuf;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the allocated ssu buffer.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_free_ssu_pcie_buf(pmlan_adapter pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer *pmbuf = MNULL;
+	t_u8 *ssu_vbase;
+	t_u64 ssu_pbase;
+
+	ENTER();
+	if (!pmadapter) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (pmadapter->ssu_buf) {
+		pmbuf = pmadapter->ssu_buf;
+		ssu_vbase = pmbuf->pbuf;
+		ssu_pbase = pmbuf->buf_pa;
+		if (ssu_vbase)
+			pcb->moal_mfree_consistent(pmadapter->pmoal_handle,
+						   pmbuf->total_pcie_buf_len,
+						   ssu_vbase, ssu_pbase);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	}
+	pmadapter->ssu_buf = MNULL;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates the PCIE ring buffers
+ *
+ *  The following initializations steps are followed -
+ *      - Allocate TXBD ring buffers
+ *      - Allocate RXBD ring buffers
+ *      - Allocate event BD ring buffers
+ *      - Allocate command and command response buffer
+ *      - Allocate sleep cookie buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_pcie_ring_buf(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+#if defined(PCIE9098) || defined(PCIE9097)
+	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+	    (pmadapter->card_type == CARD_TYPE_PCIE9097)) {
+		wlan_pcie_init_adma_ring_size(pmadapter);
+	}
+#endif
+	pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+	ret = wlan_pcie_create_txbd_ring(pmadapter);
+	if (ret)
+		goto err_cre_txbd;
+	ret = wlan_pcie_create_rxbd_ring(pmadapter);
+	if (ret)
+		goto err_cre_rxbd;
+	ret = wlan_pcie_create_evtbd_ring(pmadapter);
+	if (ret)
+		goto err_cre_evtbd;
+	ret = wlan_pcie_alloc_cmdrsp_buf(pmadapter);
+	if (ret)
+		goto err_alloc_cmdbuf;
+	return ret;
+err_alloc_cmdbuf:
+	wlan_pcie_delete_evtbd_ring(pmadapter);
+err_cre_evtbd:
+	wlan_pcie_delete_rxbd_ring(pmadapter);
+err_cre_rxbd:
+	wlan_pcie_delete_txbd_ring(pmadapter);
+err_cre_txbd:
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the allocated ring buffers.
+ *
+ *  The following are freed by this function -
+ *      - TXBD ring buffers
+ *      - RXBD ring buffers
+ *      - Event BD ring buffers
+ *      - Command and command response buffer
+ *      - Sleep cookie buffer
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_free_pcie_ring_buf(pmlan_adapter pmadapter)
+{
+	ENTER();
+
+	wlan_pcie_delete_cmdrsp_buf(pmadapter);
+	wlan_pcie_delete_evtbd_ring(pmadapter);
+	wlan_pcie_delete_rxbd_ring(pmadapter);
+	wlan_pcie_delete_txbd_ring(pmadapter);
+	pmadapter->pcard_pcie->cmdrsp_buf = MNULL;
+#ifdef RPTR_MEM_COP
+	if ((pmadapter->card_type == CARD_TYPE_PCIE9098) ||
+	    (pmadapter->card_type == CARD_TYPE_PCIE9097))
+		wlan_pcie_free_rdptrs(pmadapter);
+#endif
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function cleans up packets in the ring buffers.
+ *
+ *  The following are cleaned by this function -
+ *      - TXBD ring buffers
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_clean_pcie_ring_buf(pmlan_adapter pmadapter)
+{
+	ENTER();
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma)
+		wlan_pcie_flush_txbd_ring(pmadapter);
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command to set PCI-Express
+ *  host buffer configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_set_pcie_buf_config(mlan_private *pmpriv)
+{
+	pmlan_adapter pmadapter = MNULL;
+#if defined(PCIE8997) || defined(PCIE8897)
+	HostCmd_DS_PCIE_HOST_BUF_DETAILS host_spec;
+#endif
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter = pmpriv->adapter;
+#if defined(PCIE8997) || defined(PCIE8897)
+	if (!pmadapter->pcard_pcie->reg->use_adma) {
+		memset(pmadapter, &host_spec, 0,
+		       sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS));
+
+		/* Send the ring base addresses and count to firmware */
+		host_spec.txbd_addr_lo =
+			(t_u32)(pmadapter->pcard_pcie->txbd_ring_pbase);
+		host_spec.txbd_addr_hi = (t_u32)(((t_u64)pmadapter->pcard_pcie->
+						  txbd_ring_pbase) >> 32);
+		host_spec.txbd_count = pmadapter->pcard_pcie->txrx_bd_size;
+		host_spec.rxbd_addr_lo =
+			(t_u32)(pmadapter->pcard_pcie->rxbd_ring_pbase);
+		host_spec.rxbd_addr_hi = (t_u32)(((t_u64)pmadapter->pcard_pcie->
+						  rxbd_ring_pbase) >> 32);
+		host_spec.rxbd_count = pmadapter->pcard_pcie->txrx_bd_size;
+		host_spec.evtbd_addr_lo =
+			(t_u32)(pmadapter->pcard_pcie->evtbd_ring_pbase);
+		host_spec.evtbd_addr_hi = (t_u32)(((t_u64)pmadapter->
+						   pcard_pcie->
+						   evtbd_ring_pbase) >> 32);
+		host_spec.evtbd_count = MLAN_MAX_EVT_BD;
+
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_PCIE_HOST_BUF_DETAILS,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       &host_spec);
+		if (ret) {
+			PRINTM(MERROR,
+			       "PCIE_HOST_BUF_CFG: send command failed\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+#endif
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (pmadapter->pcard_pcie->reg->use_adma) {
+		/** config ADMA for Tx Data */
+		wlan_init_adma(pmadapter, ADMA_TX_DATA,
+			       pmadapter->pcard_pcie->txbd_ring_pbase,
+			       pmadapter->pcard_pcie->txrx_num_desc, MTRUE);
+		/** config ADMA for Rx Data */
+		wlan_init_adma(pmadapter, ADMA_RX_DATA,
+			       pmadapter->pcard_pcie->rxbd_ring_pbase,
+			       pmadapter->pcard_pcie->txrx_num_desc, MTRUE);
+		/** config ADMA for Rx Event */
+		wlan_init_adma(pmadapter, ADMA_EVENT,
+			       pmadapter->pcard_pcie->evtbd_ring_pbase,
+			       EVT_NUM_DESC, MTRUE);
+		/** config ADMA for cmd */
+		wlan_init_adma(pmadapter, ADMA_CMD, 0, 0, MTRUE);
+		/** config ADMA for cmdresp */
+		wlan_init_adma(pmadapter, ADMA_CMDRESP,
+			       pmadapter->pcard_pcie->cmdrsp_buf->buf_pa, 0,
+			       MTRUE);
+	}
+#endif
+	wlan_pcie_init_fw(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/**
+ *  @brief This function prepares command PCIE host buffer config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *cmd,
+			   t_u16 cmd_action, t_pvoid pdata_buf)
+{
+	HostCmd_DS_PCIE_HOST_BUF_DETAILS *ppcie_hoost_spec =
+		&cmd->params.pcie_host_spec;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PCIE_HOST_BUF_DETAILS);
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS))
+				     + S_DS_GEN);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		memcpy_ext(pmpriv->adapter, ppcie_hoost_spec, pdata_buf,
+			   sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS),
+			   sizeof(HostCmd_DS_PCIE_HOST_BUF_DETAILS));
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function wakes up the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *  @param timeout          set timeout flag
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pm_pcie_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 age_ts_usec;
+
+	ENTER();
+	PRINTM(MEVENT, "func%d: Wakeup device...\n",
+	       pmadapter->pcard_pcie->func_num);
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->pm_wakeup_in_secs,
+						  &age_ts_usec);
+
+	if (timeout) {
+		pmadapter->callbacks.moal_start_timer(pmadapter->pmoal_handle,
+						      pmadapter->
+						      pwakeup_fw_timer, MFALSE,
+						      MRVDRV_TIMER_3S);
+		pmadapter->wakeup_fw_timer_is_set = MTRUE;
+	}
+
+	ret = wlan_pcie_wakeup(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+static mlan_status
+wlan_pcie_debug_dump(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_buffer pmbuf = pmadapter->pcard_pcie->cmdrsp_buf;
+	ENTER();
+
+	if (pmbuf == MNULL) {
+		PRINTM(MMSG, "Rx CMD response pmbuf is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	PRINTM(MERROR, "Dump Rx CMD Response Buf:\n");
+	DBG_HEXDUMP(MERROR, "CmdResp Buf", pmbuf->pbuf + pmbuf->data_offset,
+		    64);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle data complete
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the mlan_buffer
+ *  @return          N/A
+ */
+static mlan_status
+wlan_pcie_data_complete(pmlan_adapter pmadapter,
+			mlan_buffer *pmbuf, mlan_status status)
+{
+	ENTER();
+
+	wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+mlan_adapter_operations mlan_pcie_ops = {
+	.dnld_fw = wlan_pcie_dnld_fw,
+	.interrupt = wlan_pcie_interrupt,
+	.process_int_status = wlan_process_pcie_int_status,
+	.host_to_card = wlan_pcie_host_to_card,
+	.wakeup_card = wlan_pm_pcie_wakeup_card,
+	.reset_card = wlan_pcie_wakeup,
+	.event_complete = wlan_pcie_event_complete,
+	.data_complete = wlan_pcie_data_complete,
+	.cmdrsp_complete = wlan_pcie_cmdrsp_complete,
+	.handle_rx_packet = wlan_handle_rx_packet,
+	.debug_dump = wlan_pcie_debug_dump,
+	.intf_header_len = PCIE_INTF_HEADER_LEN,
+};
diff --git a/wlan_sd8987/mlan/mlan_pcie.h b/wlan_sd8987/mlan/mlan_pcie.h
new file mode 100755
index 0000000..5f129b4
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_pcie.h
@@ -0,0 +1,501 @@
+/** @file mlan_pcie.h
+ *
+ *  @brief This file contains definitions for PCIE interface.
+ *  driver.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/01/2012: initial version
+********************************************************/
+
+#ifndef _MLAN_PCIE_H_
+#define _MLAN_PCIE_H_
+/** Tx DATA */
+#define ADMA_TX_DATA 0
+/** Rx DATA */
+#define ADMA_RX_DATA 1
+/** EVENT */
+#define ADMA_EVENT 2
+/** CMD */
+#define ADMA_CMD 3
+/** CMD RESP */
+#define ADMA_CMDRESP 4
+/** ADMA direction */
+#define ADMA_HOST_TO_DEVICE 0
+/** ADMA direction Rx */
+#define ADMA_DEVICE_TO_HOST 1
+/** Direct Program mode */
+#define DMA_MODE_DIRECT 0
+/** Single descriptor mode */
+#define DMA_MODE_SINGLE_DESC 1
+/** dual discriptor mode */
+#define DMA_MODE_DUAL_DESC 2
+/** descriptor mode:  ring mode */
+#define DESC_MODE_RING 0
+/** descriptor mode: chain mode */
+#define DESC_MODE_CHAIN 1
+/** DMA size start bit */
+#define DMA_SIZE_BIT 16
+/** DMA size mask */
+#define DMA_SIZE_MASK 0xffff0000
+/** Descriptor mode */
+#define DESC_MODE_MASK 0x0004
+/** DMA MODE MASK */
+#define DMA_MODE_MASK 0x0003
+/** Dest Num Descriptor start bits */
+#define DST_NUM_DESC_BIT 12
+/** Destination Num of Descriptor mask */
+#define DST_NUM_DESC_MASK 0xf000
+/** Src Num Descriptor start bits */
+#define SRC_NUM_DESC_BIT 8
+/** Destination Num of Descriptor mask */
+#define SRC_NUM_DESC_MASK 0x0f00
+/** Virtual Q priority mask */
+#define Q_PRIO_WEIGHT_MASK 0x00f0
+/** DMA cfg register offset*/
+#define ADMA_DMA_CFG 0x0000
+/** source base low */
+#define ADMA_SRC_LOW 0x0004
+/** source base high */
+#define ADMA_SRC_HIGH 0x0008
+/** destination base low */
+#define ADMA_DST_LOW 0x000C
+/** destination base high */
+#define ADMA_DST_HIGH 0x0010
+/** source rd/wr pointer */
+#define ADMA_SRC_RW_PTR 0x0014
+/** destination rd/wr pointer */
+#define ADMA_DST_RW_PTR 0x0018
+/** interrupt direction mapping reg, for each virtual Q, used for
+ * dual-descriptor only, only valid for Q0 */
+#define ADMA_INT_MAPPING 0x001C
+/** destination interrupt to device */
+#define DEST_INT_TO_DEVICE MBIT(0)
+/** destination interrupt to host */
+#define DEST_INT_TO_HOST MBIT(1)
+/** interrupt pending status for each virtual Q, only valid for Q0 */
+#define ADMA_INT_PENDING 0x0020
+/** Default ADMA INT mask, We only enable dma done */
+#define DEF_ADMA_INT_MASK MBIT(0)
+/** source interrupt status mask reg */
+#define ADMA_SRC_INT_STATUS_MASK 0x0024
+/** source interrupt mask reg */
+#define ADMA_SRC_INT_MASK 0x0028
+/** source interrupt status reg */
+#define ADMA_SRC_INT_STATUS 0x002C
+/** destination interrupt status mask reg */
+#define ADMA_DST_INT_STATUS_MASK 0x0030
+/** destination interrupt mask reg */
+#define ADMA_DST_INT_MASK 0x0034
+/** destination interrupt status reg */
+#define ADMA_DST_INT_STATUS 0x0038
+/** DMA cfg2 register */
+#define ADMA_DMA_CFG2 0x003C
+/** ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_MSI_LEGACY_DST_DMA_DONE_INT_BYPASS_EN MBIT(22)
+/** ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_MSI_LEGACY_SRC_DMA_DONE_INT_BYPASS_EN MBIT(21)
+/* If this bit is set, MSIX trigger event will be from DST, other wise MSIX
+ * trigger event will be from SRC */
+#define ADMA_MSIX_INT_SRC_DST_SEL MBIT(20)
+/** Enable MSI/Legacy for this Queue */
+#define ADMA_MSI_LEGACY_ENABLE MBIT(19)
+/** Enable MSIX for this queue */
+#define ADMA_MSIX_ENABLE MBIT(18)
+/** ADMA_DST_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_DST_DMA_DONE_INT_BYPASS_EN MBIT(17)
+/** SRC_DMA_DONE_INT_BYPASS_EN */
+#define ADMA_SRC_DMA_DONE_INT_BYPASS_EN MBIT(16)
+/* Destination Read Pointer Memory Copy Enable */
+#define ADMA_DST_RPTR_MEM_COPY_EN MBIT(11)
+/* Source Read Pointer Memory Copy Enable */
+#define ADMA_SRC_RPTR_MEM_COPY_EN MBIT(10)
+/** Destination address is host */
+#define ADMA_DST_ADDR_IS_HOST MBIT(2)
+/** Source address is host */
+#define ADMA_SRC_ADDR_IS_HOST MBIT(1)
+
+/** DMA cfg3 register */
+#define ADMA_DMA_CFG3 0x0040
+/** ADMA Queue pointer clear */
+#define ADMA_Q_PTR_CLR  MBIT(0)
+/** source rd ptr address low */
+#define ADMA_SRC_RD_PTR_LOW 0x0044
+/** source rd ptr address high */
+#define ADMA_SRC_RD_PTR_HIGH 0x0048
+/** destination rd ptr address low */
+#define ADMA_DST_RD_PTR_LOW 0x004C
+/** destination rd ptr address high */
+#define ADMA_DST_RD_PTR_HIGH 0x0050
+/** source active interrupt mask */
+#define ADMA_SRC_ACTV_INT_MASK 0x0054
+/** destination active interrupt mask */
+#define ADMA_DST_ACTV_INT_MASK 0x0058
+/** Read pointer start from bit 16 */
+#define ADMA_RPTR_START 16
+/** write pointer start from bit 0 */
+#define ADMA_WPTR_START 0
+/** Tx/Rx Read/Write pointer's mask */
+#define TXRX_RW_PTR_MASK (ADMA_MAX_TXRX_BD - 1)
+/** Tx/Rx Read/Write pointer's rollover indicate bit */
+#define TXRX_RW_PTR_ROLLOVER_IND ADMA_MAX_TXRX_BD
+/** Start of packet flag */
+#define ADMA_BD_FLAG_SOP MBIT(0)
+/** End of packet flag */
+#define ADMA_BD_FLAG_EOP MBIT(1)
+/** interrupt enable flag */
+#define ADMA_BD_FLAG_INT_EN MBIT(2)
+/** Source address is host side flag */
+#define ADMA_BD_FLAG_SRC_HOST MBIT(3)
+/** Destination address is host side flag */
+#define ADMA_BD_FLAG_DST_HOST MBIT(4)
+/** ADMA MIN PKT SIZE */
+#define ADMA_MIN_PKT_SIZE 128
+/** ADMA dual descriptor mode requir 8 bytes alignment in buf size */
+#define ADMA_ALIGN_SIZE 8
+/** ADMA RW_PTR wrap mask */
+#define ADMA_RW_PTR_WRAP_MASK 0x00001FFF
+/** ADMA MSIX DOORBEEL DATA */
+#define ADMA_MSIX_DOORBELL_DATA 0x0064
+/** MSIX VECTOR MASK: BIT 0-10 */
+#define ADMA_MSIX_VECTOR_MASK 0x3f
+/** PF mask: BIT 24-28 */
+#define ADMA_MSIX_PF_MASK 0x1f000000
+/** PF start bit */
+#define ADMA_MSIX_PF_BIT 24
+
+#if defined(PCIE9098) || defined(PCIE9097)
+/** PCIE9098 dev_id/vendor id reg */
+#define PCIE9098_DEV_ID_REG 0x0000
+/** PCIE revision ID register */
+#define PCIE9098_REV_ID_REG 0x0008
+/** PCIE IP revision register */
+#define PCIE9098_IP_REV_REG 0x1000
+/** PCIE CPU interrupt events */
+#define PCIE9098_CPU_INT_EVENT 0x1C20
+/** PCIE CPU interrupt status */
+#define PCIE9098_CPU_INT_STATUS 0x1C24
+/** PCIe CPU Interrupt Status Mask */
+#define PCIE9098_CPU_INT2ARM_ISM 0x1C28
+/** PCIE host interrupt status */
+#define PCIE9098_HOST_INT_STATUS 0x1C44
+/** PCIE host interrupt mask */
+#define PCIE9098_HOST_INT_MASK 0x1C48
+/** PCIE host interrupt clear select*/
+#define PCIE9098_HOST_INT_CLR_SEL 0x1C4C
+/** PCIE host interrupt status mask */
+#define PCIE9098_HOST_INT_STATUS_MASK 0x1C50
+/** PCIE host interrupt status */
+#define PCIE9097_B0_HOST_INT_STATUS 0x3C44
+/** PCIE host interrupt mask */
+#define PCIE9097_B0_HOST_INT_MASK 0x3C48
+/** PCIE host interrupt clear select*/
+#define PCIE9097_B0_HOST_INT_CLR_SEL 0x3C4C
+/** PCIE host interrupt status mask */
+#define PCIE9097_B0_HOST_INT_STATUS_MASK 0x3C50
+/** PCIE host interrupt select*/
+#define PCIE9098_HOST_INT_SEL 0x1C58
+/** PCIE data exchange register 0 */
+#define PCIE9098_SCRATCH_0_REG 0x1C60
+/** PCIE data exchange register 1 */
+#define PCIE9098_SCRATCH_1_REG 0x1C64
+/** PCIE data exchange register 2 */
+#define PCIE9098_SCRATCH_2_REG 0x1C68
+/** PCIE data exchange register 3 */
+#define PCIE9098_SCRATCH_3_REG 0x1C6C
+/** PCIE data exchange register 4 */
+#define PCIE9098_SCRATCH_4_REG 0x1C70
+/** PCIE data exchange register 5 */
+#define PCIE9098_SCRATCH_5_REG 0x1C74
+/** PCIE data exchange register 6 */
+#define PCIE9098_SCRATCH_6_REG 0x1C78
+/** PCIE data exchange register 7 */
+#define PCIE9098_SCRATCH_7_REG 0x1C7C
+/** PCIE data exchange register 8 */
+#define PCIE9098_SCRATCH_8_REG 0x1C80
+/** PCIE data exchange register 9 */
+#define PCIE9098_SCRATCH_9_REG 0x1C84
+/** PCIE data exchange register 10 */
+#define PCIE9098_SCRATCH_10_REG 0x1C88
+/** PCIE data exchange register 11 */
+#define PCIE9098_SCRATCH_11_REG 0x1C8C
+/** PCIE data exchange register 12 */
+#define PCIE9098_SCRATCH_12_REG 0x1C90
+/** PCIE data exchange register 13 */
+#define PCIE9098_SCRATCH_13_REG 0x1C94
+/** PCIE data exchange register 14 */
+#define PCIE9098_SCRATCH_14_REG 0x1C98
+/** PCIE data exchange register 15 */
+#define PCIE9098_SCRATCH_15_REG 0x1C9C
+/** ADMA CHAN0_Q0 start address, Tx Data */
+#define ADMA_CHAN0_Q0 0x10000
+/** ADMA CHAN1_Q0 start address, Rx Data */
+#define ADMA_CHAN1_Q0 0x10800
+/** ADMA CHAN1_Q1 start address, Rx Event */
+#define ADMA_CHAN1_Q1 0x10880
+/** ADMA CHAN2_Q0 start address, Tx Command */
+#define ADMA_CHAN2_Q0 0x11000
+/** ADMA CHAN2_Q1 start address, Command Resp */
+#define ADMA_CHAN2_Q1 0x11080
+/** CH0-Q0' src rd/wr ptr */
+#define ADMA_SRC_PTR_CH0_Q0 (ADMA_CHAN0_Q0 + ADMA_SRC_RW_PTR)
+/** CH1-Q1' dest rd/wr ptr */
+#define ADMA_DST_PTR_CH1_Q0 (ADMA_CHAN1_Q0 + ADMA_DST_RW_PTR)
+/** CH1-Q1' dest rd/wr ptr */
+#define ADMA_DST_PTR_CH1_Q1 (ADMA_CHAN1_Q1 + ADMA_DST_RW_PTR)
+/* TX buffer description read pointer */
+#define PCIE9098_TXBD_RDPTR ADMA_SRC_PTR_CH0_Q0
+/* TX buffer description write pointer */
+#define PCIE9098_TXBD_WRPTR ADMA_SRC_PTR_CH0_Q0
+/* RX buffer description read pointer */
+#define PCIE9098_RXBD_RDPTR ADMA_DST_PTR_CH1_Q0
+/* RX buffer description write pointer */
+#define PCIE9098_RXBD_WRPTR ADMA_DST_PTR_CH1_Q0
+/* Event buffer description read pointer */
+#define PCIE9098_EVTBD_RDPTR ADMA_DST_PTR_CH1_Q1
+/* Event buffer description write pointer */
+#define PCIE9098_EVTBD_WRPTR ADMA_DST_PTR_CH1_Q1
+/* Driver ready signature write pointer */
+#define PCIE9098_DRV_READY PCIE9098_SCRATCH_12_REG
+
+/** interrupt bit define for ADMA CHAN0 Q0, For Tx DATA */
+#define ADMA_INT_CHAN0_Q0 MBIT(0)
+/** interrupt bit define for ADMA CHAN1 Q0, For Rx Data */
+#define AMDA_INT_CHAN1_Q0 MBIT(16)
+/** interrupt bit define for ADMA CHAN1 Q1, For Rx Event */
+#define AMDA_INT_CHAN1_Q1 MBIT(17)
+/** interrupt bit define for ADMA CHAN2 Q0, For Tx Command */
+#define AMDA_INT_CHAN2_Q0 MBIT(24)
+/** interrupt bit define for ADMA CHAN2 Q1, For Rx Command Resp */
+#define AMDA_INT_CHAN2_Q1 MBIT(25)
+
+/** interrupt vector number for ADMA CHAN0 Q0, For Tx DATA */
+#define ADMA_VECTOR_CHAN0_Q0 0
+/** interrupt vector number for ADMA CHAN1 Q0, For Rx Data */
+#define AMDA_VECTOR_CHAN1_Q0 16
+/** interrupt vector number for ADMA CHAN1 Q1, For Rx Event */
+#define AMDA_VECTOR_CHAN1_Q1 17
+/** interrupt vector number for ADMA CHAN2 Q0, For Tx Command */
+#define AMDA_VECTOR_CHAN2_Q0 24
+/** interrupt vector number for ADMA CHAN2 Q1, For Rx Command Resp */
+#define AMDA_VECTOR_CHAN2_Q1 25
+
+/** Data sent interrupt for host */
+#define PCIE9098_HOST_INTR_DNLD_DONE ADMA_INT_CHAN0_Q0
+/** Data receive interrupt for host */
+#define PCIE9098_HOST_INTR_UPLD_RDY AMDA_INT_CHAN1_Q0
+/** Command sent interrupt for host */
+#define PCIE9098_HOST_INTR_CMD_DONE AMDA_INT_CHAN2_Q1
+/** Event ready interrupt for host */
+#define PCIE9098_HOST_INTR_EVENT_RDY AMDA_INT_CHAN1_Q1
+/** CMD sent interrupt for host     */
+#define PCIE9098_HOST_INTR_CMD_DNLD MBIT(7)
+
+/** Interrupt mask for host */
+#define PCIE9098_HOST_INTR_MASK                                                \
+	(PCIE9098_HOST_INTR_DNLD_DONE | PCIE9098_HOST_INTR_UPLD_RDY |          \
+	 PCIE9098_HOST_INTR_CMD_DONE | PCIE9098_HOST_INTR_CMD_DNLD |           \
+	 PCIE9098_HOST_INTR_EVENT_RDY)
+
+/** Interrupt select mask for host */
+#define PCIE9098_HOST_INTR_SEL_MASK                                            \
+	(PCIE9098_HOST_INTR_DNLD_DONE | PCIE9098_HOST_INTR_UPLD_RDY |          \
+	 PCIE9098_HOST_INTR_CMD_DONE | PCIE9098_HOST_INTR_EVENT_RDY)
+#endif
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/* PCIE INTERNAL REGISTERS */
+/** PCIE data exchange register 0 */
+#define PCIE_SCRATCH_0_REG 0x0C10
+/** PCIE data exchange register 1 */
+#define PCIE_SCRATCH_1_REG 0x0C14
+/** PCIE CPU interrupt events */
+#define PCIE_CPU_INT_EVENT 0x0C18
+/** PCIE CPU interrupt status */
+#define PCIE_CPU_INT_STATUS 0x0C1C
+
+/** PCIe CPU Interrupt Status Mask */
+#define PCIE_CPU_INT2ARM_ISM 0x0C28
+/** PCIE host interrupt status */
+#define PCIE_HOST_INT_STATUS 0x0C30
+/** PCIE host interrupt mask */
+#define PCIE_HOST_INT_MASK 0x0C34
+/** PCIE host interrupt status mask */
+#define PCIE_HOST_INT_STATUS_MASK 0x0C3C
+/** PCIE data exchange register 2 */
+#define PCIE_SCRATCH_2_REG 0x0C40
+/** PCIE data exchange register 3 */
+#define PCIE_SCRATCH_3_REG 0x0C44
+
+#define PCIE_IP_REV_REG 0x0C48
+
+/** PCIE data exchange register 4 */
+#define PCIE_SCRATCH_4_REG 0x0CD0
+/** PCIE data exchange register 5 */
+#define PCIE_SCRATCH_5_REG 0x0CD4
+/** PCIE data exchange register 6 */
+#define PCIE_SCRATCH_6_REG 0x0CD8
+/** PCIE data exchange register 7 */
+#define PCIE_SCRATCH_7_REG 0x0CDC
+/** PCIE data exchange register 8 */
+#define PCIE_SCRATCH_8_REG 0x0CE0
+/** PCIE data exchange register 9 */
+#define PCIE_SCRATCH_9_REG 0x0CE4
+/** PCIE data exchange register 10 */
+#define PCIE_SCRATCH_10_REG 0x0CE8
+/** PCIE data exchange register 11 */
+#define PCIE_SCRATCH_11_REG 0x0CEC
+/** PCIE data exchange register 12 */
+#define PCIE_SCRATCH_12_REG 0x0CF0
+#endif
+
+#ifdef PCIE8997
+/* PCIE read data pointer for queue 0 and 1 */
+#define PCIE8997_RD_DATA_PTR_Q0_Q1 0xC1A4	/* 0x8000C1A4 */
+/* PCIE read data pointer for queue 2 and 3 */
+#define PCIE8997_RD_DATA_PTR_Q2_Q3 0xC1A8	/* 0x8000C1A8 */
+/* PCIE write data pointer for queue 0 and 1 */
+#define PCIE8997_WR_DATA_PTR_Q0_Q1 0xC174	/* 0x8000C174 */
+/* PCIE write data pointer for queue 2 and 3 */
+#define PCIE8997_WR_DATA_PTR_Q2_Q3 0xC178	/* 0x8000C178 */
+#endif
+#ifdef PCIE8897
+/* PCIE read data pointer for queue 0 and 1 */
+#define PCIE8897_RD_DATA_PTR_Q0_Q1 0xC08C	/* 0x8000C08C */
+/* PCIE read data pointer for queue 2 and 3 */
+#define PCIE8897_RD_DATA_PTR_Q2_Q3 0xC090	/* 0x8000C090 */
+/* PCIE write data pointer for queue 0 and 1 */
+#define PCIE8897_WR_DATA_PTR_Q0_Q1 0xC05C	/* 0x8000C05C */
+/* PCIE write data pointer for queue 2 and 3 */
+#define PCIE8897_WR_DATA_PTR_Q2_Q3 0xC060	/* 0x8000C060 */
+#endif
+
+/** Download ready interrupt for CPU */
+#define CPU_INTR_DNLD_RDY MBIT(0)
+/** Command ready interrupt for CPU */
+#define CPU_INTR_DOOR_BELL MBIT(1)
+/** Confirmation that sleep confirm message has been processed.
+ Device will enter sleep after receiving this interrupt */
+#define CPU_INTR_SLEEP_CFM_DONE MBIT(2)
+/** Reset interrupt for CPU */
+#define CPU_INTR_RESET MBIT(3)
+/** Set Event Done interupt to the FW*/
+#define CPU_INTR_EVENT_DONE MBIT(5)
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/** Data sent interrupt for host */
+#define HOST_INTR_DNLD_DONE MBIT(0)
+/** Data receive interrupt for host */
+#define HOST_INTR_UPLD_RDY MBIT(1)
+/** Command sent interrupt for host */
+#define HOST_INTR_CMD_DONE MBIT(2)
+/** Event ready interrupt for host */
+#define HOST_INTR_EVENT_RDY MBIT(3)
+/** Interrupt mask for host */
+#define HOST_INTR_MASK                                                         \
+	(HOST_INTR_DNLD_DONE | HOST_INTR_UPLD_RDY | HOST_INTR_CMD_DONE |       \
+	 HOST_INTR_EVENT_RDY)
+
+/** Lower 32bits command address holding register */
+#define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG
+/** Upper 32bits command address holding register */
+#define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG
+/** Command length holding register */
+#define REG_CMD_SIZE PCIE_SCRATCH_2_REG
+
+/** Lower 32bits command response address holding register */
+#define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG
+/** Upper 32bits command response address holding register */
+#define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG
+
+/** TxBD's Read/Write pointer start from bit 16 */
+#define TXBD_RW_PTR_START 16
+/** RxBD's Read/Write pointer start from bit 0 */
+#define RXBD_RW_PTR_STRAT 0
+
+#define MLAN_BD_FLAG_SOP MBIT(0)
+#define MLAN_BD_FLAG_EOP MBIT(1)
+#define MLAN_BD_FLAG_XS_SOP MBIT(2)
+#define MLAN_BD_FLAG_XS_EOP MBIT(3)
+
+/* Event buffer description write pointer */
+#define REG_EVTBD_WRPTR PCIE_SCRATCH_10_REG
+/* Event buffer description read pointer */
+#define REG_EVTBD_RDPTR PCIE_SCRATCH_11_REG
+/* Driver ready signature write pointer */
+#define REG_DRV_READY PCIE_SCRATCH_12_REG
+
+/** Event Read/Write pointer mask */
+#define EVT_RW_PTR_MASK 0x0f
+/** Event Read/Write pointer rollover bit */
+#define EVT_RW_PTR_ROLLOVER_IND MBIT(7)
+#endif
+
+/* Define PCIE block size for firmware download */
+#define MLAN_PCIE_BLOCK_SIZE_FW_DNLD 256
+
+/** Extra added macros **/
+#define MLAN_EVENT_HEADER_LEN 8
+
+/** Max interrupt status register read limit */
+#define MAX_READ_REG_RETRY 10000
+
+extern mlan_adapter_operations mlan_pcie_ops;
+
+/* Get pcie device from card type */
+mlan_status wlan_get_pcie_device(pmlan_adapter pmadapter);
+
+/** Set PCIE host buffer configurations */
+mlan_status wlan_set_pcie_buf_config(mlan_private *pmpriv);
+
+/** Init write pointer */
+mlan_status wlan_pcie_init_fw(pmlan_adapter pmadapter);
+
+#if defined(PCIE8997) || defined(PCIE8897)
+/** Prepare command PCIE host buffer config */
+mlan_status wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
+				       pHostCmd_DS_COMMAND cmd,
+				       t_u16 cmd_action, t_pvoid pdata_buf);
+#endif
+
+/** Wakeup PCIE card */
+mlan_status wlan_pcie_wakeup(pmlan_adapter pmadapter);
+
+/** Set DRV_READY register */
+mlan_status wlan_set_drv_ready_reg(mlan_adapter *pmadapter, t_u32 val);
+/** PCIE init */
+mlan_status wlan_pcie_init(mlan_adapter *pmadapter);
+
+/** Read interrupt status */
+mlan_status wlan_process_msix_int(mlan_adapter *pmadapter);
+/** Transfer data to card */
+mlan_status wlan_pcie_host_to_card(pmlan_private pmpriv, t_u8 type,
+				   mlan_buffer *mbuf, mlan_tx_param *tx_param);
+/** Ring buffer allocation function */
+mlan_status wlan_alloc_pcie_ring_buf(pmlan_adapter pmadapter);
+/** Ring buffer deallocation function */
+mlan_status wlan_free_pcie_ring_buf(pmlan_adapter pmadapter);
+/** Ring buffer cleanup function, e.g. on deauth */
+mlan_status wlan_clean_pcie_ring_buf(pmlan_adapter pmadapter);
+mlan_status wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter);
+mlan_status wlan_free_ssu_pcie_buf(pmlan_adapter pmadapter);
+
+#endif /* _MLAN_PCIE_H_ */
diff --git a/wlan_sd8987/mlan/mlan_scan.c b/wlan_sd8987/mlan/mlan_scan.c
new file mode 100755
index 0000000..42577cd
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_scan.c
@@ -0,0 +1,7095 @@
+/** @file mlan_scan.c
+ *
+ *  @brief Functions implementing wlan scan IOCTL and firmware command APIs
+ *
+ *  IOCTL handlers as well as command preparation and response routines
+ *  for sending scan commands to the firmware.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/28/2008: initial version
+******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+/********************************************************
+			Local Constants
+********************************************************/
+/** minimum scan time for passive to active scan */
+#define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150
+
+#define MRVDRV_MAX_CHANNELS_PER_SCAN 38
+/** The maximum number of channels the firmware can scan per command */
+#define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN 4
+
+/**
+ * Number of channels to scan per firmware scan command issuance.
+ *
+ * Number restricted to prevent hitting the limit on the amount of scan data
+ * returned in a single firmware scan command.
+ */
+#define MRVDRV_CHANNELS_PER_SCAN_CMD 4
+
+/** Memory needed to store a max sized Channel List TLV for a firmware scan */
+#define CHAN_TLV_MAX_SIZE                                                      \
+	(sizeof(MrvlIEtypesHeader_t) +                                         \
+	 (MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN * sizeof(ChanScanParamSet_t)))
+
+/** Memory needed to store supported rate */
+#define RATE_TLV_MAX_SIZE                                                      \
+	(sizeof(MrvlIEtypes_RatesParamSet_t) + HOSTCMD_SUPPORTED_RATES)
+
+/** Memory needed to store a max number/size WildCard
+ *  SSID TLV for a firmware scan */
+#define WILDCARD_SSID_TLV_MAX_SIZE                                             \
+	(MRVDRV_MAX_SSID_LIST_LENGTH *                                         \
+	 (sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) +                         \
+	  MRVDRV_MAX_SSID_LENGTH))
+
+/** Memory needed to store a max number/size BSSID TLV for a firmware scan */
+#define BSSID_LIST_TLV_MAX_SIZE                                                \
+	(sizeof(MrvlIEtypesHeader_t) +                                         \
+	 (MRVDRV_MAX_BSSID_LIST * MLAN_MAC_ADDR_LENGTH))
+
+/** WPS TLV MAX size is MAX IE size plus 2 bytes for
+ *  t_u16 MRVL TLV extension */
+#define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2)
+/** Maximum memory needed for a wlan_scan_cmd_config
+ *  with all TLVs at max */
+#define MAX_SCAN_CFG_ALLOC                                                     \
+	(sizeof(wlan_scan_cmd_config) + sizeof(MrvlIEtypes_NumProbes_t) +      \
+	 sizeof(MrvlIETypes_HTCap_t) + CHAN_TLV_MAX_SIZE + RATE_TLV_MAX_SIZE + \
+	 WILDCARD_SSID_TLV_MAX_SIZE + BSSID_LIST_TLV_MAX_SIZE +                \
+	 WPS_TLV_MAX_SIZE)
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/**
+ * Interally used to send a configured scan cmd between
+ * driver routines
+ */
+typedef union {
+	/** Scan configuration (variable length) */
+	wlan_scan_cmd_config config;
+	/** Max allocated block */
+	t_u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
+} wlan_scan_cmd_config_tlv;
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/** Cipher suite definition */
+enum cipher_suite {
+	CIPHER_SUITE_WEP40,
+	CIPHER_SUITE_TKIP,
+	CIPHER_SUITE_CCMP,
+	CIPHER_SUITE_WEP104,
+	CIPHER_SUITE_GCMP,
+	CIPHER_SUITE_GCMP_256,
+	CIPHER_SUITE_CCMP_256,
+	CIPHER_SUITE_MAX
+};
+
+static t_u8 wpa_ouis[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x50, 0xf2, 0x01},	/* WEP40 */
+	{0x00, 0x50, 0xf2, 0x02},	/* TKIP */
+	{0x00, 0x50, 0xf2, 0x04},	/* AES */
+	{0x00, 0x50, 0xf2, 0x05},	/* WEP104 */
+};
+
+static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
+	{0x00, 0x0f, 0xac, 0x01},	/* WEP40 */
+	{0x00, 0x0f, 0xac, 0x02},	/* TKIP */
+	{0x00, 0x0f, 0xac, 0x04},	/* AES */
+	{0x00, 0x0f, 0xac, 0x05},	/* WEP104 */
+	{0x00, 0x0f, 0xac, 0x08},	/* GCMP */
+	{0x00, 0x0f, 0xac, 0x09},	/* GCMP-256 */
+	{0x00, 0x0f, 0xac, 0x0a},	/* CCMP-256 */
+};
+
+/**
+ *  @brief Convert radio type scan parameter to a band config used in join cmd
+ *
+ *  @param radio_type Scan parameter indicating the radio used for a channel
+ *                    in a scan command.
+ *
+ *  @return          Band type conversion of scanBand used in join/assoc cmds
+ *
+ */
+t_u8
+radio_type_to_band(t_u8 radio_type)
+{
+	t_u8 ret_band;
+
+	switch (radio_type) {
+	case BAND_5GHZ:
+		ret_band = BAND_A;
+		break;
+	case BAND_2GHZ:
+	default:
+		ret_band = BAND_G;
+		break;
+	}
+
+	return ret_band;
+}
+
+/**
+ *  @brief This function will update the channel statistics from scan result
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pchanstats_tlv   A pointer to MrvlIEtypes_ChannelStats_t tlv
+ *
+ *  @return                NA
+ */
+static void
+wlan_update_chan_statistics(mlan_private *pmpriv,
+			    MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 i;
+	chan_statistics_t *pchan_stats =
+		(chan_statistics_t *) ((t_u8 *)pchanstats_tlv +
+				       sizeof(MrvlIEtypesHeader_t));
+	t_u8 num_chan = wlan_le16_to_cpu(pchanstats_tlv->header.len) /
+		sizeof(chan_statistics_t);
+
+	ENTER();
+
+	for (i = 0; i < num_chan; i++) {
+		if (pmadapter->idx_chan_stats >= pmadapter->num_in_chan_stats) {
+			PRINTM(MERROR,
+			       "Over flow: idx_chan_stats=%d, num_in_chan_stats=%d\n",
+			       pmadapter->idx_chan_stats,
+			       pmadapter->num_in_chan_stats);
+			break;
+		}
+		pchan_stats->total_networks =
+			wlan_le16_to_cpu(pchan_stats->total_networks);
+		pchan_stats->cca_scan_duration =
+			wlan_le16_to_cpu(pchan_stats->cca_scan_duration);
+		pchan_stats->cca_busy_duration =
+			wlan_le16_to_cpu(pchan_stats->cca_busy_duration);
+		PRINTM(MCMND,
+		       "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
+		       pchan_stats->chan_num, pchan_stats->noise,
+		       pchan_stats->total_networks,
+		       pchan_stats->cca_scan_duration,
+		       pchan_stats->cca_busy_duration);
+		memcpy_ext(pmadapter,
+			   (chan_statistics_t *) & pmadapter->
+			   pchan_stats[pmadapter->idx_chan_stats], pchan_stats,
+			   sizeof(chan_statistics_t),
+			   sizeof(chan_statistics_t));
+		pmadapter->idx_chan_stats++;
+		pchan_stats++;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function will parse a given IE for a given OUI
+ *
+ *  Parse a given WPA/RSN IE to find if it has a given oui in PTK,
+ *  if no OUI found for PTK it returns 0.
+ *
+ *  @param pbss_desc       A pointer to current BSS descriptor
+ *  @return                0 on failure to find OUI, 1 on success.
+ */
+static t_u8
+search_oui_in_ie(mlan_adapter *pmadapter, IEBody *ie_body, t_u8 *oui)
+{
+	t_u8 count;
+
+	count = ie_body->PtkCnt[0];
+
+	ENTER();
+	/* There could be multiple OUIs for PTK hence
+	 * 1) Take the length.
+	 * 2) Check all the OUIs for AES.
+	 * 3) If one of them is AES then pass success.
+	 */
+	while (count) {
+		if (!memcmp(pmadapter, ie_body->PtkBody, oui,
+			    sizeof(ie_body->PtkBody))) {
+			LEAVE();
+			return MLAN_OUI_PRESENT;
+		}
+
+		--count;
+		if (count) {
+			ie_body = (IEBody *)((t_u8 *)ie_body +
+					     sizeof(ie_body->PtkBody));
+		}
+	}
+
+	PRINTM(MINFO, "The OUI %x:%x:%x:%x is not found in PTK\n", oui[0],
+	       oui[1], oui[2], oui[3]);
+	LEAVE();
+	return MLAN_OUI_NOT_PRESENT;
+}
+
+/**
+ *  @brief This function will pass the correct ie and oui to search_oui_in_ie
+ *
+ *  Check the pbss_desc for appropriate IE and then check if RSN IE has AES
+ *  OUI in it. If RSN IE does not have AES in PTK then return 0;
+ *
+ *  @param pbss_desc       A pointer to current BSS descriptor
+ *  @return                0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8
+is_rsn_oui_present(mlan_adapter *pmadapter,
+		   BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
+{
+	t_u8 *oui = MNULL;
+	IEBody *ie_body = MNULL;
+	t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+	ENTER();
+	if (pbss_desc->prsn_ie &&
+	    (pbss_desc->prsn_ie->ieee_hdr.element_id == RSN_IE) &&
+	    (pbss_desc->prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
+		ie_body = (IEBody *)(((t_u8 *)pbss_desc->prsn_ie->data) +
+				     RSN_GTK_OUI_OFFSET);
+		oui = &rsn_oui[cipher_suite][0];
+		ret = search_oui_in_ie(pmadapter, ie_body, oui);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will pass the correct ie and oui to search_oui_in_ie
+ *
+ *  Check the wpa_ie for appropriate IE and then check if RSN IE has AES
+ *  OUI in it. If RSN IE does not have AES in PTK then return 0;
+ *
+ *  @param pmadapter       A pointer to mlan adapter.
+ *  @return                0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8
+is_rsn_oui_present_in_wpa_ie(mlan_private *pmpriv, t_u32 cipher_suite)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 *oui = MNULL;
+	IEBody *ie_body = MNULL;
+	IEEEtypes_Generic_t *prsn_ie = MNULL;
+	t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+	ENTER();
+	prsn_ie = (IEEEtypes_Generic_t *)pmpriv->wpa_ie;
+
+	if (prsn_ie && (prsn_ie->ieee_hdr.element_id == RSN_IE) &&
+	    (prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
+		ie_body = (IEBody *)(prsn_ie->data + RSN_GTK_OUI_OFFSET);
+		oui = &rsn_oui[cipher_suite][0];
+		ret = search_oui_in_ie(pmadapter, ie_body, oui);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will pass the correct ie and oui to search_oui_in_ie
+ *
+ *  Check the pbss_desc for appropriate IE and then check if WPA IE has AES
+ *  OUI in it. If WPA IE does not have AES in PTK then return 0;
+ *
+ *  @param pbss_desc       A pointer to current BSS descriptor
+ *  @return                0 on failure to find AES OUI, 1 on success.
+ */
+static t_u8
+is_wpa_oui_present(mlan_adapter *pmadapter,
+		   BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
+{
+	t_u8 *oui = MNULL;
+	IEBody *ie_body = MNULL;
+	t_u8 ret = MLAN_OUI_NOT_PRESENT;
+
+	ENTER();
+	if (((pbss_desc->pwpa_ie) &&
+	     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
+		ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
+		oui = &wpa_ouis[cipher_suite][0];
+		ret = search_oui_in_ie(pmadapter, ie_body, oui);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief compare config band and a band from the scan result,
+ *  which is defined by functiion radio_type_to_band(t_u8 radio_type) above
+ *
+ *  @param cfg_band:  band configured
+ *         scan_band: band from scan result
+ *
+ *  @return  matched: non-zero. unmatched: 0
+ *
+ */
+static t_u8
+wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
+{
+	t_u8 band;
+	switch (scan_band) {
+	case BAND_A:
+		band = BAND_A | BAND_AN | BAND_AAC;
+		break;
+	case BAND_G:
+	default:
+		band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
+	}
+	return cfg_band & band;
+}
+
+/**
+ *  @brief This function finds the best SSID in the Scan List
+ *
+ *  Search the scan table for the best SSID that also matches the current
+ *   adapter network preference (infrastructure or adhoc)
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @return             index in BSSID list
+ */
+static t_s32
+wlan_find_best_network_in_list(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 mode = pmpriv->bss_mode;
+	t_s32 best_net = -1;
+	t_s32 best_rssi = 0;
+	t_u32 i;
+
+	ENTER();
+
+	PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
+
+	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+		switch (mode) {
+		case MLAN_BSS_MODE_INFRA:
+		case MLAN_BSS_MODE_IBSS:
+			if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
+				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+				    best_rssi) {
+					best_rssi =
+						SCAN_RSSI(pmadapter->
+							  pscan_table[i].rssi);
+					best_net = i;
+				}
+			}
+			break;
+		case MLAN_BSS_MODE_AUTO:
+		default:
+			if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+			    best_rssi) {
+				best_rssi =
+					SCAN_RSSI(pmadapter->pscan_table[i].
+						  rssi);
+				best_net = i;
+			}
+			break;
+		}
+	}
+
+	LEAVE();
+	return best_net;
+}
+
+/**
+ *  @brief Create a channel list for the driver to scan based on region info
+ *
+ *  Use the driver region/band information to construct a comprehensive list
+ *    of channels to scan.  This routine is used for any scan that is not
+ *    provided a specific channel list to scan.
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param puser_scan_in    MNULL or pointer to scan configuration parameters
+ *  @param pscan_chan_list  Output parameter: Resulting channel list to scan
+ *  @param filtered_scan    Flag indicating whether or not a BSSID or SSID
+ * filter is being sent in the command to firmware.  Used to increase the number
+ * of channels sent in a scan command and to disable the firmware channel scan
+ *                          filter.
+ *
+ *  @return                 num of channel
+ */
+static t_u8
+wlan_scan_create_channel_list(mlan_private *pmpriv,
+			      const wlan_user_scan_cfg *puser_scan_in,
+			      ChanScanParamSet_t *pscan_chan_list,
+			      t_u8 filtered_scan)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	region_chan_t *pscan_region;
+	chan_freq_power_t *cfp;
+	t_u32 region_idx;
+	t_u32 chan_idx = 0;
+	t_u32 next_chan;
+	t_u8 scan_type;
+	t_u8 radio_type;
+	t_u8 band;
+	t_u16 scan_dur = 0;
+
+	ENTER();
+
+	for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
+	     region_idx++) {
+		if (wlan_11d_is_enabled(pmpriv) &&
+		    pmpriv->media_connected != MTRUE) {
+			/* Scan all the supported chan for the first scan */
+			if (!pmadapter->universal_channel[region_idx].valid)
+				continue;
+			pscan_region =
+				&pmadapter->universal_channel[region_idx];
+		} else {
+			if (!pmadapter->region_channel[region_idx].valid)
+				continue;
+			pscan_region = &pmadapter->region_channel[region_idx];
+		}
+
+		if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
+		    puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+			radio_type = puser_scan_in->chan_list[0].radio_type &
+				~BAND_SPECIFIED;
+			if (!radio_type && (pscan_region->band != BAND_B) &&
+			    (pscan_region->band != BAND_G))
+				continue;
+			if (radio_type && (pscan_region->band != BAND_A))
+				continue;
+		}
+		PRINTM(MCMD_D,
+		       "create_channel_list: region=%d band=%d num_cfp=%d\n",
+		       pscan_region->region, pscan_region->band,
+		       pscan_region->num_cfp);
+		if ((puser_scan_in &&
+		     (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
+		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			band = pmadapter->adhoc_start_band;
+		else
+			band = pmpriv->config_bands;
+		if (!wlan_is_band_compatible(band, pscan_region->band))
+			continue;
+		for (next_chan = 0; next_chan < pscan_region->num_cfp;
+		     next_chan++) {
+			/* Set the default scan type to the user specified type,
+			 * will later be changed to passive on a per channel
+			 * basis if restricted by regulatory requirements (11d
+			 * or 11h)
+			 */
+			scan_type = pmadapter->scan_type;
+			cfp = pscan_region->pcfp + next_chan;
+			if (cfp->dynamic.flags & NXP_CHANNEL_DISABLED)
+				continue;
+
+			if (wlan_is_chan_passive(pmpriv, pscan_region->band,
+						 (t_u8)cfp->channel)) {
+				/* do not send probe requests on this channel */
+				scan_type = MLAN_SCAN_TYPE_PASSIVE;
+			}
+			switch (pscan_region->band) {
+			case BAND_A:
+				pscan_chan_list[chan_idx].bandcfg.chanBand =
+					BAND_5GHZ;
+				/* Passive scan on DFS channels */
+				if (wlan_11h_radar_detect_required
+				    (pmpriv, (t_u8)cfp->channel) &&
+				    scan_type != MLAN_SCAN_TYPE_PASSIVE)
+					scan_type =
+						MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+				break;
+			case BAND_B:
+			case BAND_G:
+				if (wlan_bg_scan_type_is_passive
+				    (pmpriv, (t_u8)cfp->channel)) {
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+				}
+				pscan_chan_list[chan_idx].bandcfg.chanBand =
+					BAND_2GHZ;
+				break;
+			default:
+				pscan_chan_list[chan_idx].bandcfg.chanBand =
+					BAND_2GHZ;
+				break;
+			}
+
+			if (puser_scan_in &&
+			    puser_scan_in->chan_list[0].scan_time) {
+				scan_dur = (t_u16)puser_scan_in->chan_list[0]
+					.scan_time;
+			} else if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+				   scan_type ==
+				   MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+				scan_dur = pmadapter->passive_scan_time;
+			} else if (filtered_scan) {
+				scan_dur = pmadapter->specific_scan_time;
+			} else {
+				scan_dur = pmadapter->active_scan_time;
+			}
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
+			    pmadapter->passive_to_active_scan ==
+			    MLAN_PASS_TO_ACT_SCAN_EN) {
+				scan_dur = MAX(scan_dur,
+					       MIN_PASSIVE_TO_ACTIVE_SCAN_TIME);
+				pscan_chan_list[chan_idx]
+					.chan_scan_mode.passive_to_active_scan =
+					MTRUE;
+			}
+			pscan_chan_list[chan_idx].max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+			    scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+				pscan_chan_list[chan_idx]
+					.chan_scan_mode.passive_scan = MTRUE;
+				pscan_chan_list[chan_idx]
+					.chan_scan_mode.hidden_ssid_report =
+					MTRUE;
+			} else {
+				pscan_chan_list[chan_idx]
+					.chan_scan_mode.passive_scan = MFALSE;
+			}
+
+			pscan_chan_list[chan_idx].chan_number =
+				(t_u8)cfp->channel;
+			PRINTM(MCMD_D,
+			       "chan=%d, mode=%d, passive_to_active=%d\n",
+			       pscan_chan_list[chan_idx].chan_number,
+			       pscan_chan_list[chan_idx]
+			       .chan_scan_mode.passive_scan,
+			       pscan_chan_list[chan_idx]
+			       .chan_scan_mode.passive_to_active_scan);
+			chan_idx++;
+		}
+	}
+
+	LEAVE();
+	return chan_idx;
+}
+
+/**
+ *  @brief Add WPS IE to probe request frame
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pptlv_out          A pointer to TLV to fill in
+ *
+ *  @return                   N/A
+ */
+static void
+wlan_add_wps_probe_request_ie(mlan_private *pmpriv, t_u8 **pptlv_out)
+{
+	MrvlIEtypesHeader_t *tlv;
+
+	ENTER();
+
+	if (pmpriv->wps.wps_ie.vend_hdr.len) {
+		tlv = (MrvlIEtypesHeader_t *)*pptlv_out;
+		tlv->type = wlan_cpu_to_le16(VENDOR_SPECIFIC_221);
+		tlv->len = wlan_cpu_to_le16(pmpriv->wps.wps_ie.vend_hdr.len);
+		*pptlv_out += sizeof(MrvlIEtypesHeader_t);
+		memcpy_ext(pmpriv->adapter, *pptlv_out,
+			   pmpriv->wps.wps_ie.vend_hdr.oui,
+			   pmpriv->wps.wps_ie.vend_hdr.len,
+			   pmpriv->wps.wps_ie.vend_hdr.len);
+		*pptlv_out += (pmpriv->wps.wps_ie.vend_hdr.len +
+			       sizeof(MrvlIEtypesHeader_t));
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Construct and send multiple scan config commands to the firmware
+ *
+ *  Previous routines have created a wlan_scan_cmd_config with any requested
+ *   TLVs.  This function splits the channel TLV into max_chan_per_scan lists
+ *   and sends the portion of the channel TLV along with the other TLVs
+ *   to the wlan_cmd routines for execution in the firmware.
+ *
+ *  @param pmpriv             A pointer to mlan_private structure
+ *  @param pioctl_buf         A pointer to MLAN IOCTL Request buffer
+ *  @param max_chan_per_scan  Maximum number channels to be included in each
+ *                            scan command sent to firmware
+ *  @param filtered_scan      Flag indicating whether or not a BSSID or SSID
+ *                            filter is being used for the firmware command
+ *                            scan command sent to firmware
+ *  @param pscan_cfg_out      Scan configuration used for this scan.
+ *  @param pchan_tlv_out      Pointer in the pscan_cfg_out where the channel TLV
+ *                            should start.  This is past any other TLVs that
+ *                            must be sent down in each firmware command.
+ *  @param pscan_chan_list    List of channels to scan in max_chan_per_scan
+ * segments
+ *
+ *  @return                   MLAN_STATUS_SUCCESS or error return otherwise
+ */
+static mlan_status
+wlan_scan_channel_list(mlan_private *pmpriv, t_void *pioctl_buf,
+		       t_u32 max_chan_per_scan, t_u8 filtered_scan,
+		       wlan_scan_cmd_config *pscan_cfg_out,
+		       MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
+		       ChanScanParamSet_t *pscan_chan_list)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ChanScanParamSet_t *ptmp_chan_list;
+	ChanScanParamSet_t *pstart_chan;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+	t_u8 *pchan_tlv_out_temp = MNULL;
+	t_u8 *ptlv_temp = MNULL;
+	t_bool foundJPch14 = MFALSE;
+	t_u16 tlv_buf_len = 0;
+	t_u32 tlv_idx;
+	t_u32 total_scan_time;
+	t_u32 done_early;
+	t_u32 cmd_no;
+	t_u32 first_chan = 1;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
+		PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n", pscan_cfg_out,
+		       pchan_tlv_out, pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (!pscan_chan_list->chan_number) {
+		PRINTM(MERROR, "Scan: No channel configured\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* check expiry before preparing scan list - may affect blacklist */
+	wlan_11h_get_csa_closed_channel(pmpriv);
+
+	pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+
+	/* Set the temp channel struct pointer to the start of the desired list
+	 */
+	ptmp_chan_list = pscan_chan_list;
+
+	/*
+	 * Loop through the desired channel list, sending a new firmware scan
+	 * commands for each max_chan_per_scan channels (or for 1,6,11
+	 * individually if configured accordingly)
+	 */
+	while (ptmp_chan_list->chan_number) {
+		tlv_idx = 0;
+		total_scan_time = 0;
+		pchan_tlv_out->header.len = 0;
+		pstart_chan = ptmp_chan_list;
+		done_early = MFALSE;
+
+		/*
+		 * Construct the Channel TLV for the scan command.  Continue to
+		 * insert channel TLVs until:
+		 *   - the tlv_idx hits the maximum configured per scan command
+		 *   - the next channel to insert is 0 (end of desired
+		 *     channel list)
+		 *   - done_early is set (controlling individual
+		 *     scanning of 1,6,11)
+		 */
+		while (tlv_idx < max_chan_per_scan &&
+		       ptmp_chan_list->chan_number && !done_early) {
+			if (wlan_is_chan_blacklisted(pmpriv,
+						     radio_type_to_band
+						     (ptmp_chan_list->bandcfg.
+						      chanBand),
+						     ptmp_chan_list->
+						     chan_number) ||
+			    wlan_is_chan_disabled(pmpriv,
+						  radio_type_to_band
+						  (ptmp_chan_list->bandcfg.
+						   chanBand),
+						  ptmp_chan_list->
+						  chan_number)) {
+				PRINTM(MCMND, "Block scan chan = %d\n",
+				       ptmp_chan_list->chan_number);
+				ptmp_chan_list++;
+				continue;
+			}
+
+			if (first_chan) {
+				ptmp_chan_list->chan_scan_mode.first_chan =
+					MTRUE;
+				first_chan = 0;
+			}
+
+			PRINTM(MCMD_D,
+			       "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
+			       ptmp_chan_list->chan_number,
+			       ptmp_chan_list->bandcfg,
+			       ptmp_chan_list->chan_scan_mode.passive_scan,
+			       ptmp_chan_list->chan_scan_mode.disable_chan_filt,
+			       wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
+
+			if (foundJPch14 == MTRUE) {
+				foundJPch14 = MFALSE;
+				/* Restore the TLV buffer */
+				pchan_tlv_out =
+					(MrvlIEtypes_ChanListParamSet_t *)
+					pchan_tlv_out_temp;
+				pchan_tlv_out->header.type =
+					wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+				pchan_tlv_out->header.len = 0;
+				if (ptlv_temp) {
+					memcpy_ext(pmadapter,
+						   pscan_cfg_out->tlv_buf,
+						   ptlv_temp, tlv_buf_len,
+						   tlv_buf_len);
+					pcb->moal_mfree(pmadapter->pmoal_handle,
+							ptlv_temp);
+					ptlv_temp = MNULL;
+				}
+			}
+
+			/* Special Case: For Japan, Scan on CH14 for 11G rates
+			   is not allowed
+			   Hence Rates TLV needs to be updated to support only
+			   11B rates */
+			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+			     pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
+			    (ptmp_chan_list->chan_number == 14)
+			    && (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)
+				) {
+
+				t_u8 *ptlv_pos = pscan_cfg_out->tlv_buf;
+				t_u16 old_ratetlv_len, new_ratetlv_len;
+				MrvlIEtypesHeader_t *header;
+				MrvlIEtypes_RatesParamSet_t *prates_tlv;
+
+				/* Preserve the current TLV buffer */
+				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+						       MAX_SCAN_CFG_ALLOC -
+						       CHAN_TLV_MAX_SIZE,
+						       MLAN_MEM_DEF,
+						       (t_u8 **)&ptlv_temp);
+				if (ret != MLAN_STATUS_SUCCESS || !ptlv_temp) {
+					PRINTM(MERROR,
+					       "Memory allocation for pscan_cfg_out failed!\n");
+					if (pioctl_req)
+						pioctl_req->status_code =
+							MLAN_ERROR_NO_MEM;
+					LEAVE();
+					return MLAN_STATUS_FAILURE;
+				}
+				pchan_tlv_out_temp = (t_u8 *)pchan_tlv_out;
+				tlv_buf_len = (t_u32)(pchan_tlv_out_temp -
+						      pscan_cfg_out->tlv_buf);
+				memcpy_ext(pmadapter, ptlv_temp, ptlv_pos,
+					   tlv_buf_len,
+					   MAX_SCAN_CFG_ALLOC -
+					   CHAN_TLV_MAX_SIZE);
+
+				/* Search for Rates TLV */
+				while ((!foundJPch14) &&
+				       (ptlv_pos < pchan_tlv_out_temp)) {
+					header = (MrvlIEtypesHeader_t *)
+						ptlv_pos;
+					if (header->type ==
+					    wlan_cpu_to_le16(TLV_TYPE_RATES))
+						foundJPch14 = MTRUE;
+					else
+						ptlv_pos +=
+							(sizeof
+							 (MrvlIEtypesHeader_t) +
+							 wlan_le16_to_cpu
+							 (header->len));
+				}
+
+				if (foundJPch14) {
+					/* Update the TLV buffer with *new*
+					 * Rates TLV and rearrange remaining TLV
+					 * buffer*/
+					prates_tlv =
+						(MrvlIEtypes_RatesParamSet_t *)
+						ptlv_pos;
+					old_ratetlv_len =
+						sizeof(MrvlIEtypesHeader_t) +
+						wlan_le16_to_cpu(prates_tlv->
+								 header.len);
+
+					prates_tlv->header.len =
+						wlan_copy_rates(prates_tlv->
+								rates, 0,
+								SupportedRates_B,
+								sizeof
+								(SupportedRates_B));
+					new_ratetlv_len =
+						sizeof(MrvlIEtypesHeader_t) +
+						prates_tlv->header.len;
+					prates_tlv->header.len =
+						wlan_cpu_to_le16(prates_tlv->
+								 header.len);
+
+					memmove(pmadapter,
+						ptlv_pos + new_ratetlv_len,
+						ptlv_pos + old_ratetlv_len,
+						(t_u32)(pchan_tlv_out_temp -
+							(ptlv_pos +
+							 old_ratetlv_len)));
+					pchan_tlv_out =
+						(MrvlIEtypes_ChanListParamSet_t
+						 *)(pchan_tlv_out_temp -
+						    (old_ratetlv_len -
+						     new_ratetlv_len));
+					pchan_tlv_out->header.type =
+						wlan_cpu_to_le16
+						(TLV_TYPE_CHANLIST);
+					pchan_tlv_out->header.len = 0;
+				}
+			}
+
+			/* Copy the current channel TLV to the command being
+			 * prepared */
+			memcpy_ext(pmadapter,
+				   pchan_tlv_out->chan_scan_param + tlv_idx,
+				   ptmp_chan_list,
+				   sizeof(pchan_tlv_out->chan_scan_param),
+				   sizeof(pchan_tlv_out->chan_scan_param));
+
+			/* Increment the TLV header length by the size appended
+			 */
+			pchan_tlv_out->header.len +=
+				sizeof(pchan_tlv_out->chan_scan_param);
+
+			/*
+			 * The tlv buffer length is set to the number of
+			 * bytes of the between the channel tlv pointer
+			 * and the start of the tlv buffer.  This
+			 * compensates for any TLVs that were appended
+			 * before the channel list.
+			 */
+			pscan_cfg_out->tlv_buf_len = (t_u32)((t_u8 *)
+							     pchan_tlv_out -
+							     pscan_cfg_out->
+							     tlv_buf);
+
+			/* Add the size of the channel tlv header and the data
+			 * length */
+			pscan_cfg_out->tlv_buf_len +=
+				(sizeof(pchan_tlv_out->header) +
+				 pchan_tlv_out->header.len);
+
+			/* Increment the index to the channel tlv we are
+			 * constructing */
+			tlv_idx++;
+
+			/* Count the total scan time per command */
+			total_scan_time +=
+				wlan_le16_to_cpu(ptmp_chan_list->max_scan_time);
+
+			done_early = MFALSE;
+
+			/*
+			 * Stop the loop if the *current* channel is in the
+			 * 1,6,11 set and we are not filtering on a BSSID or
+			 * SSID.
+			 */
+			if (!filtered_scan &&
+			    (ptmp_chan_list->chan_number == 1 ||
+			     ptmp_chan_list->chan_number == 6 ||
+			     ptmp_chan_list->chan_number == 11)) {
+				done_early = MTRUE;
+			}
+
+			/*
+			 * Stop the loop if the *current* channel is 14
+			 * and region code is Japan (0x40 or 0xFF)
+			 */
+			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+			     pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
+			    (ptmp_chan_list->chan_number == 14)) {
+				done_early = MTRUE;
+			}
+
+			/* Increment the tmp pointer to the next channel to be
+			 * scanned */
+			ptmp_chan_list++;
+
+			/*
+			 * Stop the loop if the *next* channel is in the 1,6,11
+			 * set. This will cause it to be the only channel
+			 * scanned on the next interation
+			 */
+			if (!filtered_scan &&
+			    (ptmp_chan_list->chan_number == 1 ||
+			     ptmp_chan_list->chan_number == 6 ||
+			     ptmp_chan_list->chan_number == 11)) {
+				done_early = MTRUE;
+			}
+
+			/*
+			 * Stop the loop if the *next* channel is 14
+			 * and region code is Japan (0x40 or 0xFF)
+			 */
+			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
+			     pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
+			    (ptmp_chan_list->chan_number == 14)) {
+				done_early = MTRUE;
+			}
+			if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+			    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
+				done_early = MFALSE;
+		}
+
+		/* The total scan time should be less than scan command timeout
+		 * value */
+		if (total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME) {
+			PRINTM(MMSG,
+			       "Total scan time %d ms is over limit (%d ms), scan skipped\n",
+			       total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME);
+			if (pioctl_req)
+				pioctl_req->status_code =
+					MLAN_ERROR_CMD_SCAN_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		pchan_tlv_out->header.len =
+			wlan_cpu_to_le16(pchan_tlv_out->header.len);
+
+		pmadapter->pscan_channels = pstart_chan;
+
+		/* Send the scan command to the firmware with the specified cfg
+		 */
+		if (pmadapter->ext_scan
+#ifdef USB8801
+		    && !IS_USB8801(pmadapter->card_type)
+#endif
+			)
+			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
+		else
+			cmd_no = HostCmd_CMD_802_11_SCAN;
+		ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_SET, 0,
+				       MNULL, pscan_cfg_out);
+		if (ret)
+			break;
+	}
+
+	LEAVE();
+
+	if (ptlv_temp)
+		pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
+
+	if (ret)
+		return MLAN_STATUS_FAILURE;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Construct a wlan_scan_cmd_config structure to use in scan commands
+ *
+ *  Application layer or other functions can invoke wlan_scan_networks
+ *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
+ *    This structure is used as the basis of one or many wlan_scan_cmd_config
+ *    commands that are sent to the command processing module and sent to
+ *    firmware.
+ *
+ *  Create a wlan_scan_cmd_config based on the following user supplied
+ *    parameters (if present):
+ *             - SSID filter
+ *             - BSSID filter
+ *             - Number of Probes to be sent
+ *             - Channel list
+ *
+ *  If the SSID or BSSID filter is not present, disable/clear the filter.
+ *  If the number of probes is not set, use the adapter default setting
+ *  Qualify the channel
+ *
+ *  @param pmpriv              A pointer to mlan_private structure
+ *  @param puser_scan_in       MNULL or pointer to scan config parameters
+ *  @param pscan_cfg_out       Output parameter: Resulting scan configuration
+ *  @param ppchan_list_out     Output parameter: Pointer to the start of the
+ *                             channel TLV portion of the output scan config
+ *  @param pscan_chan_list     Output parameter: Pointer to the resulting
+ *                             channel list to scan
+ *  @param pmax_chan_per_scan  Output parameter: Number of channels to scan for
+ *                             each issuance of the firmware scan command
+ *  @param pfiltered_scan      Output parameter: Flag indicating whether or not
+ *                             a BSSID or SSID filter is being sent in the
+ *                             command to firmware. Used to increase the number
+ *                             of channels sent in a scan command and to
+ *                             disable the firmware channel scan filter.
+ *  @param pscan_current_only  Output parameter: Flag indicating whether or not
+ *                             we are only scanning our current active channel
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_setup_scan_config(mlan_private *pmpriv,
+			    wlan_user_scan_cfg *puser_scan_in,
+			    wlan_scan_cmd_config *pscan_cfg_out,
+			    MrvlIEtypes_ChanListParamSet_t **ppchan_list_out,
+			    ChanScanParamSet_t *pscan_chan_list,
+			    t_u8 *pmax_chan_per_scan, t_u8 *pfiltered_scan,
+			    t_u8 *pscan_current_only)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	MrvlIEtypes_NumProbes_t *pnum_probes_tlv;
+	MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv;
+	MrvlIEtypes_RatesParamSet_t *prates_tlv;
+	MrvlIEtypes_Bssid_List_t *pbssid_tlv;
+
+	const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 };
+	t_u8 *ptlv_pos;
+	t_u32 num_probes;
+	t_u32 ssid_len;
+	t_u32 chan_idx;
+	t_u32 chan_list_idx = 0;
+	t_u32 scan_type;
+	t_u16 scan_dur;
+	t_u8 channel;
+	t_u8 radio_type;
+	t_u32 ssid_idx;
+	t_u8 ssid_filter;
+	WLAN_802_11_RATES rates;
+	t_u32 rates_size;
+	MrvlIETypes_HTCap_t *pht_cap;
+
+	MrvlIETypes_VHTCap_t *pvht_cap;
+	MrvlIEtypes_ScanChanGap_t *pscan_gap_tlv;
+	MrvlIEtypes_BssMode_t *pbss_mode;
+	MrvlIEtypes_Extension_t *phe_cap;
+	t_u16 len = 0;
+	t_u8 num_of_channel = 0;
+
+	ENTER();
+
+	/* The tlv_buf_len is calculated for each scan command.  The TLVs added
+	 *   in this routine will be preserved since the routine that sends
+	 *   the command will append channelTLVs at *ppchan_list_out.  The
+	 *   difference between the *ppchan_list_out and the tlv_buf start will
+	 * be used to calculate the size of anything we add in this routine.
+	 */
+	pscan_cfg_out->tlv_buf_len = 0;
+
+	/* Running tlv pointer.  Assigned to ppchan_list_out at end of function
+	 *  so later routines know where channels can be added to the command
+	 * buf
+	 */
+	ptlv_pos = pscan_cfg_out->tlv_buf;
+
+	/* Initialize the scan as un-filtered; the flag is later set to
+	 *   TRUE below if a SSID or BSSID filter is sent in the command
+	 */
+	*pfiltered_scan = MFALSE;
+
+	/* Initialize the scan as not being only on the current channel.  If
+	 *   the channel list is customized, only contains one channel, and
+	 *   is the active channel, this is set true and data flow is not
+	 * halted.
+	 */
+	*pscan_current_only = MFALSE;
+
+	if (puser_scan_in) {
+		ssid_filter = MFALSE;
+
+		/* Set the bss type scan filter, use Adapter setting if unset */
+		pscan_cfg_out->bss_mode =
+			(puser_scan_in->bss_mode ?
+			 (t_u8)puser_scan_in->bss_mode :
+			 (t_u8)pmadapter->scan_mode);
+
+		/* Set the number of probes to send, use Adapter setting if
+		 * unset */
+		num_probes =
+			(puser_scan_in->num_probes ? puser_scan_in->num_probes :
+			 pmadapter->scan_probes);
+		/*
+		 * Set the BSSID filter to the incoming configuration,
+		 *  if non-zero.  If not set, it will remain disabled
+		 * (all zeros).
+		 */
+		memcpy_ext(pmadapter, pscan_cfg_out->specific_bssid,
+			   puser_scan_in->specific_bssid,
+			   sizeof(pscan_cfg_out->specific_bssid),
+			   sizeof(pscan_cfg_out->specific_bssid));
+
+		if (pmadapter->ext_scan) {
+			if (puser_scan_in->bssid_num) {
+				pbssid_tlv =
+					(MrvlIEtypes_Bssid_List_t *)ptlv_pos;
+				pbssid_tlv->header.type = TLV_TYPE_BSSID;
+				pbssid_tlv->header.len =
+					wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH *
+							 puser_scan_in->
+							 bssid_num);
+				memcpy_ext(pmadapter, pbssid_tlv->bssid,
+					   puser_scan_in->bssid_list,
+					   MLAN_MAC_ADDR_LENGTH *
+					   puser_scan_in->bssid_num,
+					   MLAN_MAC_ADDR_LENGTH *
+					   puser_scan_in->bssid_num);
+				ptlv_pos +=
+					sizeof(MrvlIEtypesHeader_t) +
+					MLAN_MAC_ADDR_LENGTH *
+					puser_scan_in->bssid_num;
+				DBG_HEXDUMP(MCMD_D, "scan bssid filter",
+					    pbssid_tlv,
+					    sizeof(MrvlIEtypesHeader_t) +
+					    MLAN_MAC_ADDR_LENGTH *
+					    puser_scan_in->bssid_num);
+			} else if (memcmp
+				   (pmadapter, pscan_cfg_out->specific_bssid,
+				    &zero_mac, sizeof(zero_mac))) {
+				pbssid_tlv =
+					(MrvlIEtypes_Bssid_List_t *)ptlv_pos;
+				pbssid_tlv->header.type = TLV_TYPE_BSSID;
+				pbssid_tlv->header.len =
+					wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+				memcpy_ext(pmadapter, pbssid_tlv->bssid,
+					   puser_scan_in->specific_bssid,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				ptlv_pos += sizeof(MrvlIEtypes_Bssid_List_t);
+			}
+		}
+
+		for (ssid_idx = 0;
+		     ((ssid_idx < NELEMENTS(puser_scan_in->ssid_list)) &&
+		      (*puser_scan_in->ssid_list[ssid_idx].ssid ||
+		       puser_scan_in->ssid_list[ssid_idx].max_len));
+		     ssid_idx++) {
+			ssid_len = wlan_strlen((char *)puser_scan_in->
+					       ssid_list[ssid_idx].ssid);
+
+			pwildcard_ssid_tlv =
+				(MrvlIEtypes_WildCardSsIdParamSet_t *)ptlv_pos;
+			pwildcard_ssid_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
+			pwildcard_ssid_tlv->header.len = (t_u16)(ssid_len +
+								 sizeof
+								 (pwildcard_ssid_tlv->
+								  max_ssid_length));
+			pwildcard_ssid_tlv->max_ssid_length =
+				puser_scan_in->ssid_list[ssid_idx].max_len;
+
+			memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
+				   puser_scan_in->ssid_list[ssid_idx].ssid,
+				   ssid_len, MLAN_MAX_SSID_LENGTH);
+
+			ptlv_pos += (sizeof(pwildcard_ssid_tlv->header) +
+				     pwildcard_ssid_tlv->header.len);
+
+			pwildcard_ssid_tlv->header.len =
+				wlan_cpu_to_le16(pwildcard_ssid_tlv->header.
+						 len);
+
+			PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
+			       pwildcard_ssid_tlv->ssid,
+			       pwildcard_ssid_tlv->max_ssid_length);
+
+			if (ssid_len) {
+				ssid_filter = MTRUE;
+				if (!puser_scan_in->ssid_list[ssid_idx].max_len) {
+					PRINTM(MCMND, "user scan: %s\n",
+					       pwildcard_ssid_tlv->ssid);
+					puser_scan_in->ssid_filter = MTRUE;
+				}
+			}
+		}
+
+		/*
+		 *  The default number of channels sent in the command is low to
+		 *  ensure the response buffer from the firmware does not
+		 *  truncate scan results.  That is not an issue with an SSID or
+		 *  BSSID filter applied to the scan results in the firmware.
+		 */
+		if ((ssid_idx && ssid_filter) ||
+		    memcmp(pmadapter, pscan_cfg_out->specific_bssid, &zero_mac,
+			   sizeof(zero_mac))) {
+			*pfiltered_scan = MTRUE;
+		}
+
+	} else {
+		pscan_cfg_out->bss_mode = (t_u8)pmadapter->scan_mode;
+		num_probes = pmadapter->scan_probes;
+	}
+
+	/*
+	 *  If a specific BSSID or SSID is used, the number of channels in
+	 *  the scan command will be increased to the absolute maximum.
+	 */
+	if (*pfiltered_scan)
+		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+	else
+		*pmax_chan_per_scan = MRVDRV_CHANNELS_PER_SCAN_CMD;
+
+	if (puser_scan_in) {
+		if (puser_scan_in->scan_chan_gap) {
+			*pmax_chan_per_scan =
+				MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+			PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
+			       puser_scan_in->scan_chan_gap);
+			pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+			pscan_gap_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+			pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
+			pscan_gap_tlv->gap = wlan_cpu_to_le16((t_u16)
+							      puser_scan_in->
+							      scan_chan_gap);
+			ptlv_pos +=
+				sizeof(pscan_gap_tlv->header) +
+				pscan_gap_tlv->header.len;
+			pscan_gap_tlv->header.len =
+				wlan_cpu_to_le16(pscan_gap_tlv->header.len);
+		}
+	} else if (pmadapter->scan_chan_gap) {
+		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+		PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
+		       pmadapter->scan_chan_gap);
+		pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
+		pscan_gap_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
+		pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
+		pscan_gap_tlv->gap =
+			wlan_cpu_to_le16((t_u16)pmadapter->scan_chan_gap);
+		ptlv_pos += sizeof(pscan_gap_tlv->header) +
+			pscan_gap_tlv->header.len;
+	}
+	if (pmadapter->ext_scan) {
+		pbss_mode = (MrvlIEtypes_BssMode_t *) ptlv_pos;
+		pbss_mode->header.type = wlan_cpu_to_le16(TLV_TYPE_BSS_MODE);
+		pbss_mode->header.len = sizeof(pbss_mode->bss_mode);
+		pbss_mode->bss_mode = pscan_cfg_out->bss_mode;
+		ptlv_pos += sizeof(pbss_mode->header) + pbss_mode->header.len;
+		pbss_mode->header.len = wlan_cpu_to_le16(pbss_mode->header.len);
+		if (pmadapter->ext_scan_enh) {
+			if (puser_scan_in) {
+				if (puser_scan_in->ext_scan_type ==
+				    EXT_SCAN_ENHANCE)
+					pmadapter->ext_scan_type =
+						EXT_SCAN_ENHANCE;
+				else
+					pmadapter->ext_scan_type =
+						EXT_SCAN_DEFAULT;
+			} else if (pmadapter->ext_scan == EXT_SCAN_TYPE_ENH)
+				pmadapter->ext_scan_type = EXT_SCAN_ENHANCE;
+			else
+				pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+			if (pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
+				*pmax_chan_per_scan =
+					MRVDRV_MAX_CHANNELS_PER_SCAN;
+		}
+	}
+	/* If the input config or adapter has the number of Probes set, add tlv
+	 */
+	if (num_probes) {
+		PRINTM(MINFO, "Scan: num_probes = %d\n", num_probes);
+
+		pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)ptlv_pos;
+		pnum_probes_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
+		pnum_probes_tlv->header.len =
+			sizeof(pnum_probes_tlv->num_probes);
+		pnum_probes_tlv->num_probes =
+			wlan_cpu_to_le16((t_u16)num_probes);
+
+		ptlv_pos += sizeof(pnum_probes_tlv->header) +
+			pnum_probes_tlv->header.len;
+
+		pnum_probes_tlv->header.len =
+			wlan_cpu_to_le16(pnum_probes_tlv->header.len);
+	}
+
+	/* Append rates tlv */
+	memset(pmadapter, rates, 0, sizeof(rates));
+
+	rates_size = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode,
+					      (pmpriv->bss_mode ==
+					       MLAN_BSS_MODE_INFRA) ? pmpriv->
+					      config_bands : pmadapter->
+					      adhoc_start_band, rates);
+
+	prates_tlv = (MrvlIEtypes_RatesParamSet_t *)ptlv_pos;
+	prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+	prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
+	memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
+	ptlv_pos += sizeof(prates_tlv->header) + rates_size;
+
+	PRINTM(MINFO, "SCAN_CMD: Rates size = %d\n", rates_size);
+
+	if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
+	    (pmpriv->config_bands & BAND_GN
+	     || pmpriv->config_bands & BAND_AN)) {
+		pht_cap = (MrvlIETypes_HTCap_t *)ptlv_pos;
+		memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+		pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+		pht_cap->header.len = sizeof(HTCap_t);
+		wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands,
+				     MTRUE);
+		HEXDUMP("SCAN: HT_CAPABILITIES IE", (t_u8 *)pht_cap,
+			sizeof(MrvlIETypes_HTCap_t));
+		ptlv_pos += sizeof(MrvlIETypes_HTCap_t);
+		pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
+	}
+
+	if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
+	    (pmpriv->config_bands & BAND_AAC)) {
+		pvht_cap = (MrvlIETypes_VHTCap_t *)ptlv_pos;
+		memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
+		pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
+		pvht_cap->header.len = sizeof(VHT_capa_t);
+		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands,
+				      MFALSE, MFALSE);
+		HEXDUMP("SCAN: VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
+			sizeof(MrvlIETypes_VHTCap_t));
+		ptlv_pos += sizeof(MrvlIETypes_VHTCap_t);
+		pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
+	}
+
+	if (IS_FW_SUPPORT_11AX(pmadapter) && (pmpriv->config_bands & BAND_AAX)) {
+		phe_cap = (MrvlIEtypes_Extension_t *) ptlv_pos;
+		len = wlan_fill_he_cap_tlv(pmpriv, BAND_A, phe_cap, MFALSE);
+		HEXDUMP("SCAN: HE_CAPABILITIES IE", (t_u8 *)phe_cap, len);
+		ptlv_pos += len;
+	}
+
+	if (wlan_is_ext_capa_support(pmpriv))
+		wlan_add_ext_capa_info_ie(pmpriv, MNULL, &ptlv_pos);
+	if (pmpriv->adapter->ecsa_enable) {
+		t_u8 bandwidth = BW_20MHZ;
+		t_u8 oper_class = 1;
+		t_u32 usr_dot_11n_dev_cap;
+		if (pmpriv->media_connected) {
+			if (pmpriv->config_bands & BAND_A)
+				usr_dot_11n_dev_cap =
+					pmpriv->usr_dot_11n_dev_cap_a;
+			else
+				usr_dot_11n_dev_cap =
+					pmpriv->usr_dot_11n_dev_cap_bg;
+			if (usr_dot_11n_dev_cap & MBIT(17)) {
+				bandwidth = BW_40MHZ;
+				if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+				    && (pmpriv->config_bands & BAND_AAC))
+					bandwidth = BW_80MHZ;
+			}
+			wlan_get_curr_oper_class(pmpriv,
+						 pmpriv->curr_bss_params.
+						 bss_descriptor.channel,
+						 bandwidth, &oper_class);
+		}
+		wlan_add_supported_oper_class_ie(pmpriv, &ptlv_pos, oper_class);
+	}
+	wlan_add_wps_probe_request_ie(pmpriv, &ptlv_pos);
+
+	if (puser_scan_in && puser_scan_in->proberesp_only) {
+		MrvlIEtypes_OnlyProberesp_t *proberesp_only =
+			(MrvlIEtypes_OnlyProberesp_t *) ptlv_pos;
+		memset(pmadapter, proberesp_only, 0,
+		       sizeof(MrvlIEtypes_OnlyProberesp_t));
+		proberesp_only->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_ONLYPROBERESP);
+		proberesp_only->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		proberesp_only->proberesp_only = puser_scan_in->proberesp_only;
+		ptlv_pos += sizeof(MrvlIEtypes_OnlyProberesp_t);
+	}
+
+	if (puser_scan_in && memcmp(pmadapter, puser_scan_in->random_mac,
+				    zero_mac, MLAN_MAC_ADDR_LENGTH)) {
+		MrvlIEtypes_MacAddr_t *randomMacParam =
+			(MrvlIEtypes_MacAddr_t *)ptlv_pos;
+		memset(pmadapter, randomMacParam, 0,
+		       sizeof(MrvlIEtypes_MacAddr_t));
+		randomMacParam->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
+		randomMacParam->header.len =
+			wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+		memcpy_ext(pmadapter, randomMacParam->mac,
+			   puser_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		ptlv_pos += sizeof(MrvlIEtypes_MacAddr_t);
+	}
+	/*
+	 * Set the output for the channel TLV to the address in the tlv buffer
+	 *   past any TLVs that were added in this function (SSID, num_probes).
+	 *   Channel TLVs will be added past this for each scan command,
+	 *   preserving the TLVs that were previously added.
+	 */
+	*ppchan_list_out = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
+
+	if (puser_scan_in && puser_scan_in->chan_list[0].chan_number) {
+		PRINTM(MINFO, "Scan: Using supplied channel list\n");
+
+		for (chan_idx = 0;
+		     chan_idx < WLAN_USER_SCAN_CHAN_MAX &&
+		     puser_scan_in->chan_list[chan_idx].chan_number;
+		     chan_idx++) {
+			radio_type =
+				puser_scan_in->chan_list[chan_idx].radio_type;
+			/*Ignore 5G/2G channels if radio_type do not match
+			 * band*/
+			if (!wlan_is_band_compatible(pmpriv->config_bands,
+						     radio_type_to_band
+						     (radio_type)))
+				continue;
+			(pscan_chan_list + chan_list_idx)->bandcfg.chanBand =
+				radio_type;
+
+			channel =
+				puser_scan_in->chan_list[chan_idx].chan_number;
+			(pscan_chan_list + chan_list_idx)->chan_number =
+				channel;
+
+			scan_type =
+				puser_scan_in->chan_list[chan_idx].scan_type;
+			if (scan_type == MLAN_SCAN_TYPE_UNCHANGED)
+				scan_type = pmadapter->scan_type;
+
+			if (radio_type == BAND_5GHZ) {
+				if (pmadapter->fw_bands & BAND_A)
+					PRINTM(MINFO,
+					       "UserScan request for A Band channel %d!!\n",
+					       channel);
+				else {
+					PRINTM(MERROR,
+					       "Scan in A band is not allowed!!\n");
+					ret = MLAN_STATUS_FAILURE;
+					LEAVE();
+					return ret;
+
+				}
+			}
+
+			if (wlan_is_chan_passive(pmpriv, radio_type, channel)) {
+				/* do not send probe requests on this channel */
+				scan_type = MLAN_SCAN_TYPE_PASSIVE;
+			}
+			/* Prevent active scanning on a radar controlled channel
+			 */
+			if (radio_type == BAND_5GHZ &&
+			    scan_type != MLAN_SCAN_TYPE_PASSIVE) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_11h_radar_detect_required
+					    (pmpriv, channel)) {
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+					}
+			}
+			if (radio_type == BAND_2GHZ &&
+			    scan_type != MLAN_SCAN_TYPE_PASSIVE) {
+				if (pmadapter->active_scan_triggered == MFALSE)
+					if (wlan_bg_scan_type_is_passive
+					    (pmpriv, channel)) {
+						scan_type =
+							MLAN_SCAN_TYPE_PASSIVE;
+					}
+			}
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+			    scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+				(pscan_chan_list + chan_list_idx)
+					->chan_scan_mode.passive_scan = MTRUE;
+				(pscan_chan_list + chan_list_idx)
+					->chan_scan_mode.hidden_ssid_report =
+					MTRUE;
+			} else {
+				(pscan_chan_list + chan_list_idx)
+					->chan_scan_mode.passive_scan = MFALSE;
+			}
+
+			if (puser_scan_in->chan_list[chan_idx].scan_time) {
+				scan_dur =
+					(t_u16)puser_scan_in->
+					chan_list[chan_idx]
+					.scan_time;
+			} else {
+				if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
+				    scan_type ==
+				    MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
+					scan_dur = pmadapter->passive_scan_time;
+				} else if (*pfiltered_scan) {
+					scan_dur =
+						pmadapter->specific_scan_time;
+				} else {
+					scan_dur = pmadapter->active_scan_time;
+				}
+			}
+
+			if (pmadapter->coex_scan &&
+			    pmadapter->coex_min_scan_time &&
+			    (pmadapter->coex_min_scan_time > scan_dur))
+				scan_dur = pmadapter->coex_min_scan_time;
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
+			    pmadapter->passive_to_active_scan ==
+			    MLAN_PASS_TO_ACT_SCAN_EN) {
+				(pscan_chan_list + chan_list_idx)
+					->chan_scan_mode.
+					passive_to_active_scan = MTRUE;
+				scan_dur =
+					MAX(MIN_PASSIVE_TO_ACTIVE_SCAN_TIME,
+					    scan_dur);
+			}
+			PRINTM(MINFO,
+			       "chan=%d, mode=%d, passive_to_active=%d\n",
+			       (pscan_chan_list + chan_list_idx)->chan_number,
+			       (pscan_chan_list + chan_list_idx)
+			       ->chan_scan_mode.passive_scan,
+			       (pscan_chan_list + chan_list_idx)
+			       ->chan_scan_mode.passive_to_active_scan);
+
+			(pscan_chan_list + chan_list_idx)->min_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			(pscan_chan_list + chan_list_idx)->max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			chan_list_idx++;
+		}
+
+		/* Check if we are only scanning the current channel */
+		if ((chan_idx == 1) &&
+		    (puser_scan_in->chan_list[0].chan_number ==
+		     pmpriv->curr_bss_params.bss_descriptor.channel)) {
+			*pscan_current_only = MTRUE;
+			PRINTM(MINFO, "Scan: Scanning current channel only\n");
+		}
+
+	} else {
+		num_of_channel =
+			wlan_scan_create_channel_list(pmpriv, puser_scan_in,
+						      pscan_chan_list,
+						      *pfiltered_scan);
+		PRINTM(MCMND, "Scan: Creating full region channel list %d\n",
+		       num_of_channel);
+		if (num_of_channel > MRVDRV_MAX_CHANNELS_PER_SCAN)
+			pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Inspect the scan response buffer for pointers to expected TLVs
+ *
+ *  TLVs can be included at the end of the scan response BSS information.
+ *    Parse the data in the buffer for pointers to TLVs that can potentially
+ *    be passed back in the response
+ *
+ *  @param pmadapter        Pointer to the mlan_adapter structure
+ *  @param ptlv             Pointer to the start of the TLV buffer to parse
+ *  @param tlv_buf_size     Size of the TLV buffer
+ *  @param req_tlv_type     Request TLV's type
+ *  @param pptlv            Output parameter: Pointer to the request TLV if
+ * found
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_ret_802_11_scan_get_tlv_ptrs(pmlan_adapter pmadapter,
+				  MrvlIEtypes_Data_t *ptlv,
+				  t_u32 tlv_buf_size,
+				  t_u32 req_tlv_type,
+				  MrvlIEtypes_Data_t **pptlv)
+{
+	MrvlIEtypes_Data_t *pcurrent_tlv;
+	t_u32 tlv_buf_left;
+	t_u32 tlv_type;
+	t_u32 tlv_len;
+
+	ENTER();
+
+	pcurrent_tlv = ptlv;
+	tlv_buf_left = tlv_buf_size;
+	*pptlv = MNULL;
+
+	PRINTM(MINFO, "SCAN_RESP: tlv_buf_size = %d\n", tlv_buf_size);
+
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(pcurrent_tlv->header.type);
+		tlv_len = wlan_le16_to_cpu(pcurrent_tlv->header.len);
+
+		if (sizeof(ptlv->header) + tlv_len > tlv_buf_left) {
+			PRINTM(MERROR, "SCAN_RESP: TLV buffer corrupt\n");
+			break;
+		}
+
+		if (req_tlv_type == tlv_type) {
+			switch (tlv_type) {
+			case TLV_TYPE_TSFTIMESTAMP:
+				PRINTM(MINFO,
+				       "SCAN_RESP: TSF Timestamp TLV, len = %d\n",
+				       tlv_len);
+				*pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
+				break;
+			case TLV_TYPE_CHANNELBANDLIST:
+				PRINTM(MINFO,
+				       "SCAN_RESP: CHANNEL BAND LIST TLV, len = %d\n",
+				       tlv_len);
+				*pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
+				break;
+			case TLV_TYPE_CHANNEL_STATS:
+				PRINTM(MINFO,
+				       "SCAN_RESP: CHANNEL STATS TLV, len = %d\n",
+				       tlv_len);
+				*pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
+				break;
+			default:
+				PRINTM(MERROR,
+				       "SCAN_RESP: Unhandled TLV = %d\n",
+				       tlv_type);
+				/* Give up, this seems corrupted */
+				LEAVE();
+				return;
+			}
+		}
+
+		if (*pptlv) {
+			/* HEXDUMP("SCAN_RESP: TLV Buf", (t_u8 *)*pptlv+4,
+			 * tlv_len); */
+			break;
+		}
+
+		tlv_buf_left -= (sizeof(ptlv->header) + tlv_len);
+		pcurrent_tlv =
+			(MrvlIEtypes_Data_t *)(pcurrent_tlv->data + tlv_len);
+
+	}			/* while */
+
+	LEAVE();
+}
+
+/**
+ *  @brief Interpret a BSS scan response returned from the firmware
+ *
+ *  Parse the various fixed fields and IEs passed back for a BSS probe
+ *   response or beacon from the scan command.  Record information as needed
+ *   in the scan table BSSDescriptor_t for that entry.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pbss_entry   Output parameter: Pointer to the BSS Entry
+ *  @param pbeacon_info Pointer to the Beacon information
+ *  @param bytes_left   Number of bytes left to parse
+ *  @param ext_scan     extended scan
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,
+				BSSDescriptor_t *pbss_entry,
+				t_u8 **pbeacon_info, t_u32 *bytes_left,
+				t_u8 ext_scan)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	IEEEtypes_ElementId_e element_id;
+	IEEEtypes_FhParamSet_t *pfh_param_set;
+	IEEEtypes_DsParamSet_t *pds_param_set;
+	IEEEtypes_CfParamSet_t *pcf_param_set;
+	IEEEtypes_IbssParamSet_t *pibss_param_set;
+	IEEEtypes_CapInfo_t *pcap_info;
+	WLAN_802_11_FIXED_IEs fixed_ie;
+	t_u8 *pcurrent_ptr;
+	t_u8 *prate;
+	t_u8 element_len;
+	t_u16 total_ie_len;
+	t_u8 bytes_to_copy;
+	t_u8 rate_size;
+	t_u16 beacon_size;
+	t_u8 found_data_rate_ie;
+	t_u32 bytes_left_for_current_beacon;
+	IEEEtypes_ERPInfo_t *perp_info;
+
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	const t_u8 osen_oui[] = { 0x50, 0x6f, 0x9a, 0x12 };
+
+	IEEEtypes_CountryInfoSet_t *pcountry_info;
+	IEEEtypes_Extension_t *pext_tlv;
+
+	ENTER();
+
+	found_data_rate_ie = MFALSE;
+	rate_size = 0;
+	beacon_size = 0;
+
+	if (*bytes_left >= sizeof(beacon_size)) {
+		/* Extract & convert beacon size from the command buffer */
+		memcpy_ext(pmadapter, &beacon_size, *pbeacon_info,
+			   sizeof(beacon_size), sizeof(beacon_size));
+		beacon_size = wlan_le16_to_cpu(beacon_size);
+		*bytes_left -= sizeof(beacon_size);
+		*pbeacon_info += sizeof(beacon_size);
+	}
+
+	if (!beacon_size || beacon_size > *bytes_left) {
+		*pbeacon_info += *bytes_left;
+		*bytes_left = 0;
+
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize the current working beacon pointer for this BSS iteration
+	 */
+	pcurrent_ptr = *pbeacon_info;
+
+	/* Advance the return beacon pointer past the current beacon */
+	*pbeacon_info += beacon_size;
+	*bytes_left -= beacon_size;
+
+	bytes_left_for_current_beacon = beacon_size;
+
+	if (bytes_left_for_current_beacon <
+	    (MLAN_MAC_ADDR_LENGTH + sizeof(t_u8) +
+	     sizeof(WLAN_802_11_FIXED_IEs))) {
+		PRINTM(MERROR, "InterpretIE: Not enough bytes left\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memcpy_ext(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	PRINTM(MINFO, "InterpretIE: AP MAC Addr-" MACSTR "\n",
+	       MAC2STR(pbss_entry->mac_address));
+
+	pcurrent_ptr += MLAN_MAC_ADDR_LENGTH;
+	bytes_left_for_current_beacon -= MLAN_MAC_ADDR_LENGTH;
+
+	/*
+	 * Next 4 fields are RSSI (for legacy scan only), time stamp,
+	 *   beacon interval, and capability information
+	 */
+	if (!ext_scan) {
+		/* RSSI is 1 byte long */
+		pbss_entry->rssi = (t_s32)(*pcurrent_ptr);
+		PRINTM(MINFO, "InterpretIE: RSSI=%02X\n", *pcurrent_ptr);
+		pcurrent_ptr += 1;
+		bytes_left_for_current_beacon -= 1;
+	}
+
+	/*
+	 *  The RSSI is not part of the beacon/probe response.  After we have
+	 *    advanced pcurrent_ptr past the RSSI field, save the remaining
+	 *    data for use at the application layer
+	 */
+	pbss_entry->pbeacon_buf = pcurrent_ptr;
+	pbss_entry->beacon_buf_size = bytes_left_for_current_beacon;
+
+	/* Time stamp is 8 bytes long */
+	memcpy_ext(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8,
+		   sizeof(fixed_ie.time_stamp));
+	memcpy_ext(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8,
+		   sizeof(pbss_entry->time_stamp));
+	pcurrent_ptr += 8;
+	bytes_left_for_current_beacon -= 8;
+
+	/* Beacon interval is 2 bytes long */
+	memcpy_ext(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2,
+		   sizeof(fixed_ie.beacon_interval));
+	pbss_entry->beacon_period = wlan_le16_to_cpu(fixed_ie.beacon_interval);
+	pcurrent_ptr += 2;
+	bytes_left_for_current_beacon -= 2;
+
+	/* Capability information is 2 bytes long */
+	memcpy_ext(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2,
+		   sizeof(fixed_ie.capabilities));
+	PRINTM(MINFO, "InterpretIE: fixed_ie.capabilities=0x%X\n",
+	       fixed_ie.capabilities);
+	fixed_ie.capabilities = wlan_le16_to_cpu(fixed_ie.capabilities);
+	pcap_info = (IEEEtypes_CapInfo_t *)&fixed_ie.capabilities;
+	memcpy_ext(pmadapter, &pbss_entry->cap_info, pcap_info,
+		   sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
+	pcurrent_ptr += 2;
+	bytes_left_for_current_beacon -= 2;
+
+	/* Rest of the current buffer are IE's */
+	PRINTM(MINFO, "InterpretIE: IELength for this AP = %d\n",
+	       bytes_left_for_current_beacon);
+
+	HEXDUMP("InterpretIE: IE info", (t_u8 *)pcurrent_ptr,
+		bytes_left_for_current_beacon);
+
+	if (pcap_info->privacy) {
+		PRINTM(MINFO, "InterpretIE: AP WEP enabled\n");
+		pbss_entry->privacy = Wlan802_11PrivFilter8021xWEP;
+	} else {
+		pbss_entry->privacy = Wlan802_11PrivFilterAcceptAll;
+	}
+
+	if (pcap_info->ibss == 1)
+		pbss_entry->bss_mode = MLAN_BSS_MODE_IBSS;
+	else
+		pbss_entry->bss_mode = MLAN_BSS_MODE_INFRA;
+
+	if (pcap_info->spectrum_mgmt == 1) {
+		PRINTM(MINFO, "InterpretIE: 11h- Spectrum Management "
+		       "capability bit found\n");
+		pbss_entry->wlan_11h_bss_info.sensed_11h = 1;
+	}
+
+	/* Process variable IE */
+	while (bytes_left_for_current_beacon >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+
+		if (bytes_left_for_current_beacon < total_ie_len) {
+			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+			       "bytes left < IE length\n");
+			bytes_left_for_current_beacon = 0;
+			ret = MLAN_STATUS_FAILURE;
+			continue;
+		}
+
+		switch (element_id) {
+		case SSID:
+			if (element_len > MRVDRV_MAX_SSID_LENGTH) {
+				bytes_left_for_current_beacon = 0;
+				ret = MLAN_STATUS_FAILURE;
+				continue;
+			}
+			if (!pbss_entry->ssid.ssid_len) {
+				pbss_entry->ssid.ssid_len = element_len;
+				memcpy_ext(pmadapter, pbss_entry->ssid.ssid,
+					   (pcurrent_ptr + 2), element_len,
+					   sizeof(pbss_entry->ssid.ssid));
+			}
+			PRINTM(MINFO, "InterpretIE: ssid: %-32s\n",
+			       pbss_entry->ssid.ssid);
+			break;
+
+		case SUPPORTED_RATES:
+			if (element_len > WLAN_SUPPORTED_RATES) {
+				bytes_left_for_current_beacon = 0;
+				ret = MLAN_STATUS_FAILURE;
+				continue;
+			}
+			memcpy_ext(pmadapter, pbss_entry->data_rates,
+				   pcurrent_ptr + 2, element_len,
+				   sizeof(pbss_entry->data_rates));
+			memcpy_ext(pmadapter, pbss_entry->supported_rates,
+				   pcurrent_ptr + 2, element_len,
+				   sizeof(pbss_entry->supported_rates));
+			HEXDUMP("InterpretIE: SupportedRates:",
+				pbss_entry->supported_rates, element_len);
+			rate_size = element_len;
+			found_data_rate_ie = MTRUE;
+			break;
+
+		case FH_PARAM_SET:
+			pfh_param_set = (IEEEtypes_FhParamSet_t *)pcurrent_ptr;
+			pbss_entry->network_type_use = Wlan802_11FH;
+			memcpy_ext(pmadapter,
+				   &pbss_entry->phy_param_set.fh_param_set,
+				   pfh_param_set, total_ie_len,
+				   sizeof(IEEEtypes_FhParamSet_t));
+			pbss_entry->phy_param_set.fh_param_set.len =
+				MIN(element_len,
+				    (sizeof(IEEEtypes_FhParamSet_t) -
+				     sizeof(IEEEtypes_Header_t)));
+			pbss_entry->phy_param_set.fh_param_set.dwell_time =
+				wlan_le16_to_cpu(pbss_entry->phy_param_set.
+						 fh_param_set.dwell_time);
+			break;
+
+		case DS_PARAM_SET:
+			pds_param_set = (IEEEtypes_DsParamSet_t *)pcurrent_ptr;
+
+			pbss_entry->network_type_use = Wlan802_11DS;
+			pbss_entry->channel = pds_param_set->current_chan;
+
+			memcpy_ext(pmadapter,
+				   &pbss_entry->phy_param_set.ds_param_set,
+				   pds_param_set, total_ie_len,
+				   sizeof(IEEEtypes_DsParamSet_t));
+			pbss_entry->phy_param_set.ds_param_set.len =
+				MIN(element_len,
+				    (sizeof(IEEEtypes_DsParamSet_t) -
+				     sizeof(IEEEtypes_Header_t)));
+			break;
+
+		case CF_PARAM_SET:
+			pcf_param_set = (IEEEtypes_CfParamSet_t *)pcurrent_ptr;
+			memcpy_ext(pmadapter,
+				   &pbss_entry->ss_param_set.cf_param_set,
+				   pcf_param_set, total_ie_len,
+				   sizeof(IEEEtypes_CfParamSet_t));
+			pbss_entry->ss_param_set.cf_param_set.len =
+				MIN(element_len,
+				    (sizeof(IEEEtypes_CfParamSet_t) -
+				     sizeof(IEEEtypes_Header_t)));
+			break;
+
+		case IBSS_PARAM_SET:
+			pibss_param_set =
+				(IEEEtypes_IbssParamSet_t *)pcurrent_ptr;
+			pbss_entry->atim_window =
+				wlan_le16_to_cpu(pibss_param_set->atim_window);
+			memcpy_ext(pmadapter,
+				   &pbss_entry->ss_param_set.ibss_param_set,
+				   pibss_param_set, total_ie_len,
+				   sizeof(IEEEtypes_IbssParamSet_t));
+			pbss_entry->ss_param_set.ibss_param_set.len =
+				MIN(element_len,
+				    (sizeof(IEEEtypes_IbssParamSet_t) -
+				     sizeof(IEEEtypes_Header_t)));
+			break;
+
+			/* Handle Country Info IE */
+		case COUNTRY_INFO:
+			pcountry_info =
+				(IEEEtypes_CountryInfoSet_t *)pcurrent_ptr;
+
+			if (pcountry_info->len <
+			    sizeof(pcountry_info->country_code) ||
+			    (unsigned)(pcountry_info->len + 2) >
+			    sizeof(IEEEtypes_CountryInfoFullSet_t)) {
+				PRINTM(MERROR,
+				       "InterpretIE: 11D- Err "
+				       "country_info len =%d min=%d max=%d\n",
+				       pcountry_info->len,
+				       sizeof(pcountry_info->country_code),
+				       sizeof(IEEEtypes_CountryInfoFullSet_t));
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+
+			memcpy_ext(pmadapter, &pbss_entry->country_info,
+				   pcountry_info, pcountry_info->len + 2,
+				   sizeof(pbss_entry->country_info));
+			HEXDUMP("InterpretIE: 11D- country_info:",
+				(t_u8 *)pcountry_info,
+				(t_u32)(pcountry_info->len + 2));
+			break;
+
+		case ERP_INFO:
+			perp_info = (IEEEtypes_ERPInfo_t *)pcurrent_ptr;
+			pbss_entry->erp_flags = perp_info->erp_flags;
+			break;
+
+		case POWER_CONSTRAINT:
+		case POWER_CAPABILITY:
+		case TPC_REPORT:
+		case CHANNEL_SWITCH_ANN:
+		case QUIET:
+		case IBSS_DFS:
+		case SUPPORTED_CHANNELS:
+		case TPC_REQUEST:
+			wlan_11h_process_bss_elem(pmadapter,
+						  &pbss_entry->
+						  wlan_11h_bss_info,
+						  pcurrent_ptr);
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+			/*
+			 * Only process extended supported rate
+			 * if data rate is already found.
+			 * Data rate IE should come before
+			 * extended supported rate IE
+			 */
+			if (found_data_rate_ie) {
+				if ((element_len + rate_size) >
+				    WLAN_SUPPORTED_RATES) {
+					bytes_to_copy = (WLAN_SUPPORTED_RATES -
+							 rate_size);
+				} else {
+					bytes_to_copy = element_len;
+				}
+
+				prate = (t_u8 *)pbss_entry->data_rates;
+				prate += rate_size;
+				memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
+					   bytes_to_copy, bytes_to_copy);
+
+				prate = (t_u8 *)pbss_entry->supported_rates;
+				prate += rate_size;
+				memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
+					   bytes_to_copy, bytes_to_copy);
+			}
+			HEXDUMP("InterpretIE: ExtSupportedRates:",
+				pbss_entry->supported_rates,
+				element_len + rate_size);
+			break;
+
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+
+			if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+				    wpa_oui, sizeof(wpa_oui))) {
+				pbss_entry->pwpa_ie =
+					(IEEEtypes_VendorSpecific_t *)
+					pcurrent_ptr;
+				pbss_entry->wpa_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				HEXDUMP("InterpretIE: Resp WPA_IE",
+					(t_u8 *)pbss_entry->pwpa_ie,
+					((*(pbss_entry->pwpa_ie)).vend_hdr.len +
+					 sizeof(IEEEtypes_Header_t)));
+			} else if (!memcmp
+				   (pmadapter, pvendor_ie->vend_hdr.oui,
+				    wmm_oui, sizeof(wmm_oui))) {
+				if (total_ie_len ==
+				    sizeof(IEEEtypes_WmmParameter_t) ||
+				    total_ie_len ==
+				    sizeof(IEEEtypes_WmmInfo_t)) {
+					/*
+					 * Only accept and copy the WMM IE if
+					 * it matches the size expected for the
+					 * WMM Info IE or the WMM Parameter IE.
+					 */
+					memcpy_ext(pmadapter,
+						   (t_u8 *)&pbss_entry->wmm_ie,
+						   pcurrent_ptr, total_ie_len,
+						   sizeof(pbss_entry->wmm_ie));
+					HEXDUMP("InterpretIE: Resp WMM_IE",
+						(t_u8 *)&pbss_entry->wmm_ie,
+						total_ie_len);
+				}
+			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					   osen_oui, sizeof(osen_oui))) {
+				pbss_entry->posen_ie =
+					(IEEEtypes_Generic_t *)pcurrent_ptr;
+				pbss_entry->osen_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				HEXDUMP("InterpretIE: Resp OSEN_IE",
+					(t_u8 *)pbss_entry->posen_ie,
+					(*(pbss_entry->posen_ie)).ieee_hdr.len +
+					sizeof(IEEEtypes_Header_t));
+			}
+			break;
+		case RSN_IE:
+			pbss_entry->prsn_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->rsn_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp RSN_IE",
+				(t_u8 *)pbss_entry->prsn_ie,
+				(*(pbss_entry->prsn_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case RSNX_IE:
+			pbss_entry->prsnx_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->rsnx_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp RSNX_IE",
+				(t_u8 *)pbss_entry->prsnx_ie,
+				(*(pbss_entry->prsnx_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case WAPI_IE:
+			pbss_entry->pwapi_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pbss_entry->wapi_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp WAPI_IE",
+				(t_u8 *)pbss_entry->pwapi_ie,
+				(*(pbss_entry->pwapi_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case MULTI_BSSID:
+			if (IS_FW_SUPPORT_MULTIBSSID(pmadapter)) {
+				pbss_entry->multi_bssid_ap = MULTI_BSSID_AP;
+				HEXDUMP("InterpretIE: Multi BSSID IE",
+					(t_u8 *)pcurrent_ptr, total_ie_len);
+			}
+			break;
+		case HT_CAPABILITY:
+			pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
+			pbss_entry->ht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTCAP_IE",
+				(t_u8 *)pbss_entry->pht_cap,
+				(*(pbss_entry->pht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_OPERATION:
+			pbss_entry->pht_info =
+				(IEEEtypes_HTInfo_t *)pcurrent_ptr;
+			pbss_entry->ht_info_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp HTINFO_IE",
+				(t_u8 *)pbss_entry->pht_info,
+				(*(pbss_entry->pht_info)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BSSCO_2040:
+			pbss_entry->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
+			pbss_entry->bss_co_2040_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
+				(t_u8 *)pbss_entry->pbss_co_2040,
+				(*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_CAPABILITY:
+			pbss_entry->pext_cap =
+				(IEEEtypes_ExtCap_t *)pcurrent_ptr;
+			pbss_entry->ext_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTCAP_IE",
+				(t_u8 *)pbss_entry->pext_cap,
+				(*(pbss_entry->pext_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case OVERLAPBSSSCANPARAM:
+			pbss_entry->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
+			pbss_entry->overlap_bss_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OBSS_IE",
+				(t_u8 *)pbss_entry->poverlap_bss_scan_param,
+				(*(pbss_entry->poverlap_bss_scan_param))
+				.ieee_hdr.len + sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_CAPABILITY:
+			pbss_entry->pvht_cap =
+				(IEEEtypes_VHTCap_t *)pcurrent_ptr;
+			pbss_entry->vht_cap_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTCAP_IE",
+				(t_u8 *)pbss_entry->pvht_cap,
+				(*(pbss_entry->pvht_cap)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_OPERATION:
+			pbss_entry->pvht_oprat =
+				(IEEEtypes_VHTOprat_t *)pcurrent_ptr;
+			pbss_entry->vht_oprat_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp VHTOPER_IE",
+				(t_u8 *)pbss_entry->pvht_oprat,
+				(*(pbss_entry->pvht_oprat)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_BSS_LOAD:
+			pbss_entry->pext_bssload =
+				(IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
+			pbss_entry->ext_bssload_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
+				(t_u8 *)pbss_entry->pext_bssload,
+				(*(pbss_entry->pext_bssload)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_TX_POWER_ENV:
+			pbss_entry->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
+			pbss_entry->vht_txpower_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp TXPOW_IE",
+				(t_u8 *)pbss_entry->pvht_txpower,
+				(*(pbss_entry->pvht_txpower)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXT_POWER_CONSTR:
+			pbss_entry->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
+			pbss_entry->ext_pwer_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp EXTPOW_IE",
+				(t_u8 *)pbss_entry->pext_pwer,
+				(*(pbss_entry->pext_pwer)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case QUIET_CHAN:
+			pbss_entry->pquiet_chan =
+				(IEEEtypes_QuietChan_t *)pcurrent_ptr;
+			pbss_entry->quiet_chan_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
+				(t_u8 *)pbss_entry->pquiet_chan,
+				(*(pbss_entry->pquiet_chan)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case BW_CHANNEL_SWITCH:
+			/* RANDYTODO */
+			break;
+		case AID_INFO:
+			break;
+		case OPER_MODE_NTF:
+			pbss_entry->poper_mode =
+				(IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
+			pbss_entry->oper_mode_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
+				(t_u8 *)pbss_entry->poper_mode,
+				(*(pbss_entry->poper_mode)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		case EXTENSION:
+			pext_tlv = (IEEEtypes_Extension_t *) pcurrent_ptr;
+			switch (pext_tlv->ext_id) {
+			case HE_CAPABILITY:
+				pbss_entry->phe_cap =
+					(IEEEtypes_HECap_t *) pcurrent_ptr;
+				pbss_entry->he_cap_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				break;
+			case HE_OPERATION:
+				pbss_entry->phe_oprat = pext_tlv;
+				pbss_entry->he_oprat_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				break;
+			default:
+				break;
+			}
+			break;
+		case MOBILITY_DOMAIN:
+			PRINTM(MCMND, "Mobility Domain IE received in Scan\n");
+			pbss_entry->pmd_ie =
+				(IEEEtypes_MobilityDomain_t *)pcurrent_ptr;
+			pbss_entry->md_offset =
+				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
+			HEXDUMP("InterpretIE: Resp Mobility Domain IE",
+				(t_u8 *)pbss_entry->pmd_ie,
+				(*(pbss_entry->pmd_ie)).ieee_hdr.len +
+				sizeof(IEEEtypes_Header_t));
+			break;
+		default:
+			break;
+		}
+
+		pcurrent_ptr += element_len + 2;
+
+		/* Need to account for IE ID and IE Len */
+		bytes_left_for_current_beacon -= (element_len + 2);
+
+	}			/* while (bytes_left_for_current_beacon > 2) */
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Adjust ie's position in BSSDescriptor_t
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pbss_entry   A pointer to BSSDescriptor_t structure
+ *
+ *  @return           N/A
+ */
+static t_void
+wlan_adjust_ie_in_bss_entry(mlan_private *pmpriv, BSSDescriptor_t *pbss_entry)
+{
+	ENTER();
+	if (pbss_entry->pbeacon_buf) {
+		if (pbss_entry->pwpa_ie) {
+			pbss_entry->pwpa_ie =
+				(IEEEtypes_VendorSpecific_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->wpa_offset);
+		}
+		if (pbss_entry->prsn_ie) {
+			pbss_entry->prsn_ie =
+				(IEEEtypes_Generic_t *)(pbss_entry->
+							pbeacon_buf +
+							pbss_entry->rsn_offset);
+		}
+		if (pbss_entry->pwapi_ie) {
+			pbss_entry->pwapi_ie =
+				(IEEEtypes_Generic_t *)(pbss_entry->
+							pbeacon_buf +
+							pbss_entry->
+							wapi_offset);
+		}
+
+		if (pbss_entry->posen_ie) {
+			pbss_entry->posen_ie =
+				(IEEEtypes_Generic_t *)(pbss_entry->
+							pbeacon_buf +
+							pbss_entry->
+							osen_offset);
+		}
+		if (pbss_entry->pmd_ie) {
+			pbss_entry->pmd_ie =
+				(IEEEtypes_MobilityDomain_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->md_offset);
+		}
+		if (pbss_entry->pht_cap) {
+			pbss_entry->pht_cap =
+				(IEEEtypes_HTCap_t *)(pbss_entry->pbeacon_buf +
+						      pbss_entry->
+						      ht_cap_offset);
+		}
+		if (pbss_entry->pht_info) {
+			pbss_entry->pht_info =
+				(IEEEtypes_HTInfo_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->ht_info_offset);
+		}
+		if (pbss_entry->pbss_co_2040) {
+			pbss_entry->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->bss_co_2040_offset);
+		}
+		if (pbss_entry->pext_cap) {
+			pbss_entry->pext_cap =
+				(IEEEtypes_ExtCap_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->ext_cap_offset);
+		}
+		if (pbss_entry->poverlap_bss_scan_param) {
+			pbss_entry->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->overlap_bss_offset);
+		}
+		if (pbss_entry->pvht_cap) {
+			pbss_entry->pvht_cap =
+				(IEEEtypes_VHTCap_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->vht_cap_offset);
+		}
+		if (pbss_entry->pvht_oprat) {
+			pbss_entry->pvht_oprat =
+				(IEEEtypes_VHTOprat_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->vht_oprat_offset);
+		}
+		if (pbss_entry->pvht_txpower) {
+			pbss_entry->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->vht_txpower_offset);
+		}
+		if (pbss_entry->pext_pwer) {
+			pbss_entry->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->ext_pwer_offset);
+		}
+		if (pbss_entry->pext_bssload) {
+			pbss_entry->pext_bssload =
+				(IEEEtypes_ExtBSSload_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->ext_bssload_offset);
+		}
+		if (pbss_entry->pquiet_chan) {
+			pbss_entry->pquiet_chan =
+				(IEEEtypes_QuietChan_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->quiet_chan_offset);
+		}
+		if (pbss_entry->poper_mode) {
+			pbss_entry->poper_mode =
+				(IEEEtypes_OperModeNtf_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->oper_mode_offset);
+		}
+		if (pbss_entry->phe_cap) {
+			pbss_entry->phe_cap =
+				(IEEEtypes_HECap_t *) (pbss_entry->pbeacon_buf +
+						       pbss_entry->
+						       he_cap_offset);
+		}
+
+		if (pbss_entry->phe_oprat) {
+			pbss_entry->phe_oprat =
+				(IEEEtypes_Extension_t
+				 *) (pbss_entry->pbeacon_buf +
+				     pbss_entry->he_oprat_offset);
+		}
+		if (pbss_entry->prsnx_ie) {
+			pbss_entry->prsnx_ie =
+				(IEEEtypes_Generic_t
+				 *)(pbss_entry->pbeacon_buf +
+				    pbss_entry->rsnx_offset);
+		}
+	} else {
+		pbss_entry->pwpa_ie = MNULL;
+		pbss_entry->wpa_offset = 0;
+		pbss_entry->prsn_ie = MNULL;
+		pbss_entry->rsn_offset = 0;
+		pbss_entry->pwapi_ie = MNULL;
+		pbss_entry->wapi_offset = 0;
+
+		pbss_entry->posen_ie = MNULL;
+		pbss_entry->osen_offset = 0;
+		pbss_entry->pmd_ie = MNULL;
+		pbss_entry->md_offset = 0;
+		pbss_entry->pht_cap = MNULL;
+		pbss_entry->ht_cap_offset = 0;
+		pbss_entry->pht_info = MNULL;
+		pbss_entry->ht_info_offset = 0;
+		pbss_entry->pbss_co_2040 = MNULL;
+		pbss_entry->bss_co_2040_offset = 0;
+		pbss_entry->pext_cap = MNULL;
+		pbss_entry->ext_cap_offset = 0;
+		pbss_entry->poverlap_bss_scan_param = MNULL;
+		pbss_entry->overlap_bss_offset = 0;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Store a beacon or probe response for a BSS returned in the scan
+ *
+ *  Store a new scan response or an update for a previous scan response.  New
+ *    entries need to verify that they do not exceed the total amount of
+ *    memory allocated for the table.
+
+ *  Replacement entries need to take into consideration the amount of space
+ *    currently allocated for the beacon/probe response and adjust the entry
+ *    as needed.
+ *
+ *  A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
+ *    for an entry in case it is a beacon since a probe response for the
+ *    network will by larger per the standard.  This helps to reduce the
+ *    amount of memory copying to fit a new probe response into an entry
+ *    already occupied by a network's previously stored beacon.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param beacon_idx   Index in the scan table to store this entry; may be
+ *                      replacing an older duplicate entry for this BSS
+ *  @param num_of_ent   Number of entries currently in the table
+ *  @param pnew_beacon  Pointer to the new beacon/probe response to save
+ *
+ *  @return           N/A
+ */
+static t_void
+wlan_ret_802_11_scan_store_beacon(mlan_private *pmpriv,
+				  t_u32 beacon_idx,
+				  t_u32 num_of_ent,
+				  BSSDescriptor_t *pnew_beacon)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 *pbcn_store;
+	t_u32 new_bcn_size;
+	t_u32 old_bcn_size;
+	t_u32 bcn_space;
+	t_u32 adj_idx;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *tmp_buf;
+	t_u32 bcn_size = 0;
+	t_u32 bcn_offset = 0;
+
+	ENTER();
+
+	if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
+		new_bcn_size = pnew_beacon->beacon_buf_size;
+		old_bcn_size =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size;
+		bcn_space =
+			pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
+		pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
+
+		/* Set the max to be the same as current entry unless changed
+		 * below */
+		pnew_beacon->beacon_buf_size_max = bcn_space;
+
+		if (new_bcn_size == old_bcn_size) {
+			/*
+			 * Beacon is the same size as the previous entry.
+			 *   Replace the previous contents with the scan result
+			 */
+			memcpy_ext(pmadapter, pbcn_store,
+				   pnew_beacon->pbeacon_buf,
+				   pnew_beacon->beacon_buf_size,
+				   pnew_beacon->beacon_buf_size);
+
+		} else if (new_bcn_size <= bcn_space) {
+			/*
+			 * New beacon size will fit in the amount of space
+			 *   we have previously allocated for it
+			 */
+
+			/* Copy the new beacon buffer entry over the old one */
+			memcpy_ext(pmadapter, pbcn_store,
+				   pnew_beacon->pbeacon_buf, new_bcn_size,
+				   new_bcn_size);
+
+			/*
+			 *  If the old beacon size was less than the
+			 *  maximum we had allotted for the entry, and
+			 *  the new entry is even smaller, reset the
+			 *  max size to the old beacon entry and compress
+			 *  the storage space (leaving a new pad space of
+			 *  (old_bcn_size - new_bcn_size).
+			 */
+			if (old_bcn_size < bcn_space &&
+			    new_bcn_size <= old_bcn_size) {
+				/*
+				 * Old Beacon size is smaller than the
+				 * allotted storage size. Shrink the
+				 * allotted storage space.
+				 */
+				PRINTM(MINFO,
+				       "AppControl: Smaller Duplicate Beacon (%d), "
+				       "old = %d, new = %d, space = %d, left = %d\n",
+				       beacon_idx, old_bcn_size, new_bcn_size,
+				       bcn_space,
+				       (pmadapter->bcn_buf_size -
+					(pmadapter->pbcn_buf_end -
+					 pmadapter->bcn_buf)));
+
+				/*
+				 * memmove (since the memory overlaps) the data
+				 * after the beacon we just stored to the end
+				 * of the current beacon.  This cleans up any
+				 * unused space the old larger beacon was using
+				 * in the buffer
+				 */
+				memmove(pmadapter,
+					(void *)((t_ptr)pbcn_store +
+						 (t_ptr)old_bcn_size),
+					(void *)((t_ptr)pbcn_store +
+						 (t_ptr)bcn_space),
+					(t_u32)((t_ptr)pmadapter->pbcn_buf_end -
+						((t_ptr)pbcn_store +
+						 (t_ptr)bcn_space)));
+
+				/*
+				 * Decrement the end pointer by the difference
+				 * between the old larger size and the new
+				 * smaller size since we are using less space
+				 * due to the new beacon being smaller
+				 */
+				pmadapter->pbcn_buf_end -=
+					(bcn_space - old_bcn_size);
+
+				/*
+				 * Set the maximum storage size to the old
+				 * beacon size
+				 */
+				pnew_beacon->beacon_buf_size_max = old_bcn_size;
+
+				/* Adjust beacon buffer pointers that are past
+				 * the current */
+				for (adj_idx = 0; adj_idx < num_of_ent;
+				     adj_idx++) {
+					if (pmadapter->pscan_table[adj_idx]
+					    .pbeacon_buf > pbcn_store) {
+						pmadapter->pscan_table[adj_idx]
+							.pbeacon_buf -=
+							(bcn_space -
+							 old_bcn_size);
+						wlan_adjust_ie_in_bss_entry
+							(pmpriv,
+							 &pmadapter->
+							 pscan_table[adj_idx]);
+					}
+				}
+			}
+		} else if (pmadapter->pbcn_buf_end +
+			   (new_bcn_size - bcn_space) <
+			   (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
+			/*
+			 * Beacon is larger than space previously allocated
+			 * (bcn_space) and there is enough space left in the
+			 * beaconBuffer to store the additional data
+			 */
+			PRINTM(MINFO,
+			       "AppControl: Larger Duplicate Beacon (%d), "
+			       "old = %d, new = %d, space = %d, left = %d\n",
+			       beacon_idx, old_bcn_size, new_bcn_size,
+			       bcn_space,
+			       (pmadapter->bcn_buf_size -
+				(pmadapter->pbcn_buf_end -
+				 pmadapter->bcn_buf)));
+
+			/*
+			 * memmove (since the memory overlaps) the data
+			 *  after the beacon we just stored to the end of
+			 *  the current beacon.  This moves the data for
+			 *  the beacons after this further in memory to
+			 *  make space for the new larger beacon we are
+			 *  about to copy in.
+			 */
+			memmove(pmadapter,
+				(void *)((t_ptr)pbcn_store +
+					 (t_ptr)new_bcn_size),
+				(void *)((t_ptr)pbcn_store + (t_ptr)bcn_space),
+				(t_u32)((t_ptr)pmadapter->pbcn_buf_end -
+					((t_ptr)pbcn_store +
+					 (t_ptr)bcn_space)));
+
+			/* Copy the new beacon buffer entry over the old one */
+			memcpy_ext(pmadapter, pbcn_store,
+				   pnew_beacon->pbeacon_buf, new_bcn_size,
+				   new_bcn_size);
+
+			/*
+			 * Move the beacon end pointer by the amount of new
+			 * beacon data we are adding
+			 */
+			pmadapter->pbcn_buf_end += (new_bcn_size - bcn_space);
+
+			/*
+			 * This entry is bigger than the allotted max space
+			 *  previously reserved.  Increase the max space to
+			 *  be equal to the new beacon size
+			 */
+			pnew_beacon->beacon_buf_size_max = new_bcn_size;
+
+			/* Adjust beacon buffer pointers that are past the
+			 * current */
+			for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
+				if (pmadapter->pscan_table[adj_idx].
+				    pbeacon_buf > pbcn_store) {
+					pmadapter->pscan_table[adj_idx]
+						.pbeacon_buf +=
+						(new_bcn_size - bcn_space);
+					wlan_adjust_ie_in_bss_entry(pmpriv,
+								    &pmadapter->
+								    pscan_table
+								    [adj_idx]);
+				}
+			}
+		} else {
+			/*
+			 * Beacon is larger than the previously allocated
+			 * space, but there is not enough free space to
+			 * store the additional data
+			 */
+			PRINTM(MERROR,
+			       "AppControl: Failed: Larger Duplicate Beacon (%d),"
+			       " old = %d, new = %d, space = %d, left = %d\n",
+			       beacon_idx, old_bcn_size, new_bcn_size,
+			       bcn_space,
+			       (pmadapter->bcn_buf_size -
+				(pmadapter->pbcn_buf_end -
+				 pmadapter->bcn_buf)));
+
+			/* Storage failure, keep old beacon intact */
+			pnew_beacon->beacon_buf_size = old_bcn_size;
+			if (pnew_beacon->pwpa_ie)
+				pnew_beacon->wpa_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.wpa_offset;
+			if (pnew_beacon->prsn_ie)
+				pnew_beacon->rsn_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.rsn_offset;
+			if (pnew_beacon->pwapi_ie)
+				pnew_beacon->wapi_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.wapi_offset;
+
+			if (pnew_beacon->posen_ie)
+				pnew_beacon->osen_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.osen_offset;
+			if (pnew_beacon->pmd_ie)
+				pnew_beacon->md_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.md_offset;
+			if (pnew_beacon->pht_cap)
+				pnew_beacon->ht_cap_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.ht_cap_offset;
+			if (pnew_beacon->pht_info)
+				pnew_beacon->ht_info_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.ht_info_offset;
+			if (pnew_beacon->pbss_co_2040)
+				pnew_beacon->bss_co_2040_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.bss_co_2040_offset;
+			if (pnew_beacon->pext_cap)
+				pnew_beacon->ext_cap_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.ext_cap_offset;
+			if (pnew_beacon->poverlap_bss_scan_param)
+				pnew_beacon->overlap_bss_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.overlap_bss_offset;
+			if (pnew_beacon->pvht_cap)
+				pnew_beacon->vht_cap_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.vht_cap_offset;
+			if (pnew_beacon->pvht_oprat)
+				pnew_beacon->vht_oprat_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.vht_oprat_offset;
+			if (pnew_beacon->pvht_txpower)
+				pnew_beacon->vht_txpower_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.vht_txpower_offset;
+			if (pnew_beacon->pext_pwer)
+				pnew_beacon->ext_pwer_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.ext_pwer_offset;
+			if (pnew_beacon->pext_bssload)
+				pnew_beacon->ext_bssload_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.ext_bssload_offset;
+			if (pnew_beacon->pquiet_chan)
+				pnew_beacon->quiet_chan_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.quiet_chan_offset;
+			if (pnew_beacon->poper_mode)
+				pnew_beacon->oper_mode_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.oper_mode_offset;
+			if (pnew_beacon->phe_cap)
+				pnew_beacon->he_cap_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.he_cap_offset;
+			if (pnew_beacon->phe_oprat)
+				pnew_beacon->he_oprat_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.he_oprat_offset;
+			if (pnew_beacon->prsnx_ie)
+				pnew_beacon->rsnx_offset =
+					pmadapter->pscan_table[beacon_idx]
+					.rsnx_offset;
+		}
+		/* Point the new entry to its permanent storage space */
+		pnew_beacon->pbeacon_buf = pbcn_store;
+		wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+	} else {
+		if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		     SCAN_BEACON_ENTRY_PAD >
+		     (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) &&
+		    (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
+			/* no space for this entry, realloc bcn buffer */
+			if (pmadapter->callbacks.moal_vmalloc &&
+			    pmadapter->callbacks.moal_vfree)
+				ret = pmadapter->callbacks.
+					moal_vmalloc(pmadapter->pmoal_handle,
+						     pmadapter->bcn_buf_size +
+						     DEFAULT_SCAN_BEACON_BUFFER,
+						     (t_u8 **)&tmp_buf);
+			else
+				ret = pmadapter->callbacks.
+					moal_malloc(pmadapter->pmoal_handle,
+						    pmadapter->bcn_buf_size +
+						    DEFAULT_SCAN_BEACON_BUFFER,
+						    MLAN_MEM_DEF,
+						    (t_u8 **)&tmp_buf);
+
+			if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
+				PRINTM(MCMND,
+				       "Realloc Beacon buffer, old size=%d, new_size=%d\n",
+				       pmadapter->bcn_buf_size,
+				       pmadapter->bcn_buf_size +
+				       DEFAULT_SCAN_BEACON_BUFFER);
+				bcn_size = pmadapter->pbcn_buf_end -
+					pmadapter->bcn_buf;
+				memcpy_ext(pmadapter, tmp_buf,
+					   pmadapter->bcn_buf, bcn_size,
+					   bcn_size);
+				/* Adjust beacon buffer pointers that are past
+				 * the current */
+				for (adj_idx = 0; adj_idx < num_of_ent;
+				     adj_idx++) {
+					bcn_offset =
+						pmadapter->pscan_table[adj_idx]
+						.pbeacon_buf -
+						pmadapter->bcn_buf;
+					pmadapter->pscan_table[adj_idx]
+						.pbeacon_buf =
+						tmp_buf + bcn_offset;
+					wlan_adjust_ie_in_bss_entry(pmpriv,
+								    &pmadapter->
+								    pscan_table
+								    [adj_idx]);
+				}
+				pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
+				if (pmadapter->callbacks.moal_vmalloc &&
+				    pmadapter->callbacks.moal_vfree)
+					pmadapter->callbacks.
+						moal_vfree(pmadapter->
+							   pmoal_handle,
+							   (t_u8 *)pmadapter->
+							   bcn_buf);
+				else
+					pmadapter->callbacks.
+						moal_mfree(pmadapter->
+							   pmoal_handle,
+							   (t_u8 *)pmadapter->
+							   bcn_buf);
+				pmadapter->bcn_buf = tmp_buf;
+				pmadapter->bcn_buf_size +=
+					DEFAULT_SCAN_BEACON_BUFFER;
+			}
+		}
+		/*
+		 * No existing beacon data exists for this entry, check to see
+		 *   if we can fit it in the remaining space
+		 */
+		if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
+		    SCAN_BEACON_ENTRY_PAD <
+		    (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
+			/*
+			 * Copy the beacon buffer data from the local entry
+			 * to the adapter dev struct buffer space used to
+			 * store the raw beacon data for each entry in the
+			 * scan table
+			 */
+			memcpy_ext(pmadapter, pmadapter->pbcn_buf_end,
+				   pnew_beacon->pbeacon_buf,
+				   pnew_beacon->beacon_buf_size,
+				   pnew_beacon->beacon_buf_size);
+
+			/*
+			 * Update the beacon ptr to point to the table
+			 * save area
+			 */
+			pnew_beacon->pbeacon_buf = pmadapter->pbcn_buf_end;
+			pnew_beacon->beacon_buf_size_max =
+				(pnew_beacon->beacon_buf_size +
+				 SCAN_BEACON_ENTRY_PAD);
+			wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+
+			/* Increment the end pointer by the size reserved */
+			pmadapter->pbcn_buf_end +=
+				pnew_beacon->beacon_buf_size_max;
+
+			PRINTM(MINFO,
+			       "AppControl: Beacon[%02d] sz=%03d,"
+			       " used = %04d, left = %04d\n",
+			       beacon_idx, pnew_beacon->beacon_buf_size,
+			       (pmadapter->pbcn_buf_end - pmadapter->bcn_buf),
+			       (pmadapter->bcn_buf_size -
+				(pmadapter->pbcn_buf_end -
+				 pmadapter->bcn_buf)));
+		} else {
+			/*
+			 * No space for new beacon
+			 */
+			PRINTM(MCMND,
+			       "AppControl: No space beacon (%d): " MACSTR
+			       "; sz=%03d, left=%03d\n",
+			       beacon_idx, MAC2STR(pnew_beacon->mac_address),
+			       pnew_beacon->beacon_buf_size,
+			       (pmadapter->bcn_buf_size -
+				(pmadapter->pbcn_buf_end -
+				 pmadapter->bcn_buf)));
+
+			/*
+			 * Storage failure; clear storage records
+			 * for this bcn
+			 */
+			pnew_beacon->pbeacon_buf = MNULL;
+			pnew_beacon->beacon_buf_size = 0;
+			pnew_beacon->beacon_buf_size_max = 0;
+			wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief update beacon buffer of the current bss descriptor
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS, otherwise failure
+ */
+static mlan_status
+wlan_update_curr_bcn(mlan_private *pmpriv)
+{
+	BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
+		pcurr_bss->pbeacon_buf = pmpriv->pcurr_bcn_buf;
+		pcurr_bss->beacon_buf_size = pmpriv->curr_bcn_size;
+		pcurr_bss->beacon_buf_size_max = pmpriv->curr_bcn_size;
+
+		/* adjust the pointers in the current bss descriptor */
+		if (pcurr_bss->pwpa_ie) {
+			pcurr_bss->pwpa_ie =
+				(IEEEtypes_VendorSpecific_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->wpa_offset);
+		}
+		if (pcurr_bss->prsn_ie) {
+			pcurr_bss->prsn_ie =
+				(IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
+							pcurr_bss->rsn_offset);
+		}
+		if (pcurr_bss->pmd_ie) {
+			pcurr_bss->pmd_ie = (IEEEtypes_MobilityDomain_t
+					     *)(pcurr_bss->pbeacon_buf +
+						pcurr_bss->md_offset);
+		}
+		if (pcurr_bss->pht_cap) {
+			pcurr_bss->pht_cap =
+				(IEEEtypes_HTCap_t *)(pcurr_bss->pbeacon_buf +
+						      pcurr_bss->ht_cap_offset);
+		}
+
+		if (pcurr_bss->pht_info) {
+			pcurr_bss->pht_info =
+				(IEEEtypes_HTInfo_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->ht_info_offset);
+		}
+
+		if (pcurr_bss->pbss_co_2040) {
+			pcurr_bss->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->bss_co_2040_offset);
+		}
+
+		if (pcurr_bss->pext_cap) {
+			pcurr_bss->pext_cap =
+				(IEEEtypes_ExtCap_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->ext_cap_offset);
+		}
+
+		if (pcurr_bss->poverlap_bss_scan_param) {
+			pcurr_bss->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->overlap_bss_offset);
+		}
+
+		if (pcurr_bss->pvht_cap) {
+			pcurr_bss->pvht_cap =
+				(IEEEtypes_VHTCap_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->vht_cap_offset);
+		}
+
+		if (pcurr_bss->pvht_oprat) {
+			pcurr_bss->pvht_oprat =
+				(IEEEtypes_VHTOprat_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->vht_oprat_offset);
+		}
+
+		if (pcurr_bss->pvht_txpower) {
+			pcurr_bss->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->vht_txpower_offset);
+		}
+
+		if (pcurr_bss->pext_pwer) {
+			pcurr_bss->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->ext_pwer_offset);
+		}
+
+		if (pcurr_bss->pext_bssload) {
+			pcurr_bss->pext_bssload =
+				(IEEEtypes_ExtBSSload_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->ext_bssload_offset);
+		}
+
+		if (pcurr_bss->pquiet_chan) {
+			pcurr_bss->pquiet_chan =
+				(IEEEtypes_QuietChan_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->quiet_chan_offset);
+		}
+
+		if (pcurr_bss->poper_mode) {
+			pcurr_bss->poper_mode =
+				(IEEEtypes_OperModeNtf_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->oper_mode_offset);
+		}
+		if (pcurr_bss->phe_cap) {
+			pcurr_bss->phe_cap =
+				(IEEEtypes_HECap_t *) (pcurr_bss->pbeacon_buf +
+						       pcurr_bss->
+						       he_cap_offset);
+		}
+
+		if (pcurr_bss->phe_oprat) {
+			pcurr_bss->phe_oprat =
+				(IEEEtypes_Extension_t
+				 *) (pcurr_bss->pbeacon_buf +
+				     pcurr_bss->he_oprat_offset);
+		}
+		if (pcurr_bss->prsnx_ie) {
+			pcurr_bss->prsnx_ie =
+				(IEEEtypes_Generic_t
+				 *)(pcurr_bss->pbeacon_buf +
+				    pcurr_bss->rsnx_offset);
+		}
+
+		PRINTM(MINFO, "current beacon restored %d\n",
+		       pmpriv->curr_bcn_size);
+	} else {
+		PRINTM(MERROR, "curr_bcn_buf not saved\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief get the chan load from chan stats.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param channel      channel  *
+ *
+ *  @return             channel load
+ */
+static t_u16
+wlan_get_chan_load(mlan_adapter *pmadapter, t_u8 channel)
+{
+	t_u16 chan_load = 0;
+	int i;
+	for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++) {
+		if ((pmadapter->pchan_stats[i].chan_num == channel) &&
+		    pmadapter->pchan_stats[i].cca_scan_duration) {
+			chan_load =
+				(pmadapter->pchan_stats[i].cca_busy_duration *
+				 100) /
+				pmadapter->pchan_stats[i].cca_scan_duration;
+			break;
+		}
+	}
+	return chan_load;
+}
+
+/**
+ *  @brief get the chan min/max rssi
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param channel      channel  *
+ *  @param min_flag     flag to get min rssi
+ *  @return             rssi
+ */
+static t_u8
+wlan_get_chan_rssi(mlan_adapter *pmadapter, t_u8 channel, t_u8 min_flag)
+{
+	t_u8 rssi = 0;
+	int i;
+	for (i = 0; i < (int)pmadapter->num_in_scan_table; i++) {
+		if (pmadapter->pscan_table[i].channel == channel) {
+			if (rssi == 0)
+				rssi = (t_s32)pmadapter->pscan_table[i].rssi;
+			else {
+				if (min_flag)
+					rssi = MIN(rssi,
+						   pmadapter->pscan_table[i].
+						   rssi);
+				else
+					rssi = MAX(rssi,
+						   pmadapter->pscan_table[i].
+						   rssi);
+			}
+		}
+	}
+	return rssi;
+}
+
+/**
+ *  @brief update the min/max rssi for channel statistics.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *	@return             N/A
+ */
+static t_void
+wlan_update_chan_rssi(mlan_adapter *pmadapter)
+{
+	int i;
+	t_s8 min_rssi = 0;
+	t_s8 max_rssi = 0;
+	t_s8 rss = 0;
+	for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++) {
+		if (pmadapter->pchan_stats[i].chan_num &&
+		    pmadapter->pchan_stats[i].cca_scan_duration) {
+			min_rssi =
+				-wlan_get_chan_rssi(pmadapter,
+						    pmadapter->pchan_stats[i].
+						    chan_num, MFALSE);
+			max_rssi =
+				-wlan_get_chan_rssi(pmadapter,
+						    pmadapter->pchan_stats[i].
+						    chan_num, MTRUE);
+			rss = min_rssi - pmadapter->pchan_stats[i].noise;
+			// rss should always > 0, FW need fix the wrong
+			// rssi/noise in scantable
+			if (rss > 0)
+				pmadapter->pchan_stats[i].min_rss = rss;
+			else
+				pmadapter->pchan_stats[i].min_rss = 0;
+
+			rss = max_rssi - pmadapter->pchan_stats[i].noise;
+			if (rss > 0)
+				pmadapter->pchan_stats[i].max_rss = rss;
+			else
+				pmadapter->pchan_stats[i].max_rss = 0;
+			PRINTM(MCMND,
+			       "chan=%d, min_rssi=%d, max_rssi=%d noise=%d min_rss=%d, max_rss=%d\n",
+			       pmadapter->pchan_stats[i].chan_num, min_rssi,
+			       max_rssi, pmadapter->pchan_stats[i].noise,
+			       pmadapter->pchan_stats[i].min_rss,
+			       pmadapter->pchan_stats[i].max_rss);
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief Post process the scan table after a new scan command has completed
+ *
+ *  Inspect each entry of the scan table and try to find an entry that
+ *    matches our current associated/joined network from the scan.  If
+ *    one is found, update the stored copy of the BSSDescriptor for our
+ *    current network.
+ *
+ *  Debug dump the current scan table contents if compiled accordingly.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_scan_process_results(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_s32 j;
+	t_u32 i;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pmpriv->media_connected == MTRUE) {
+		j = wlan_find_bssid_in_list(pmpriv,
+					    pmpriv->curr_bss_params.
+					    bss_descriptor.mac_address,
+					    pmpriv->bss_mode);
+
+		if (j >= 0) {
+			memcpy_ext(pmadapter, &pmadapter->pscan_table[j].ssid,
+				   &pmpriv->curr_bss_params.bss_descriptor.ssid,
+				   sizeof(mlan_802_11_ssid),
+				   sizeof(mlan_802_11_ssid));
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    pmpriv->
+							    curr_bcn_buf_lock);
+			pmpriv->curr_bss_params.bss_descriptor.pwpa_ie = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.wpa_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.prsn_ie = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.rsn_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pwapi_ie = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.wapi_offset = 0;
+
+			pmpriv->curr_bss_params.bss_descriptor.posen_ie = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.osen_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pmd_ie = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.md_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pht_cap = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.ht_cap_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.pht_info = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.ht_info_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.pbss_co_2040 =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				bss_co_2040_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pext_cap = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.ext_cap_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.
+				poverlap_bss_scan_param = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				overlap_bss_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pvht_cap = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.vht_cap_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.pvht_oprat =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				vht_oprat_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pvht_txpower =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				vht_txpower_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pext_pwer =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.ext_pwer_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.pext_bssload =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				ext_bssload_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pquiet_chan =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				quiet_chan_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.poper_mode =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.
+				oper_mode_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.phe_cap = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.he_cap_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.phe_oprat =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.he_oprat_offset =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.prsnx_ie = MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.rsnx_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pbeacon_buf =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.beacon_buf_size =
+				0;
+			pmpriv->curr_bss_params.bss_descriptor.
+				beacon_buf_size_max = 0;
+
+			PRINTM(MINFO,
+			       "Found current ssid/bssid in list @ index #%d\n",
+			       j);
+			/* Make a copy of current BSSID descriptor */
+			memcpy_ext(pmadapter,
+				   &pmpriv->curr_bss_params.bss_descriptor,
+				   &pmadapter->pscan_table[j],
+				   sizeof(pmpriv->curr_bss_params.
+					  bss_descriptor),
+				   sizeof(pmpriv->curr_bss_params.
+					  bss_descriptor));
+
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      pmpriv->
+							      curr_bcn_buf_lock);
+			wlan_save_curr_bcn(pmpriv);
+		} else {
+			// Apend to the end of scan table
+			if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
+				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+						       sizeof(BSSDescriptor_t),
+						       MLAN_MEM_DEF,
+						       (t_u8 **)&bss_new_entry);
+				if (ret == MLAN_STATUS_SUCCESS && bss_new_entry) {
+					memcpy_ext(pmadapter, bss_new_entry,
+						   &pmpriv->curr_bss_params.
+						   bss_descriptor,
+						   sizeof(pmpriv->
+							  curr_bss_params.
+							  bss_descriptor),
+						   sizeof(BSSDescriptor_t));
+					if (pmadapter->num_in_scan_table <
+					    MRVDRV_MAX_BSSID_LIST)
+						pmadapter->num_in_scan_table++;
+					pmadapter->pscan_table
+						[pmadapter->num_in_scan_table -
+						 1]
+						.pbeacon_buf = MNULL;
+					wlan_ret_802_11_scan_store_beacon
+						(pmpriv,
+						 pmadapter->num_in_scan_table -
+						 1,
+						 pmadapter->num_in_scan_table,
+						 bss_new_entry);
+					if (bss_new_entry->pbeacon_buf == MNULL)
+						pmadapter->num_in_scan_table--;
+					else
+						memcpy_ext(pmadapter,
+							   &pmadapter->
+							   pscan_table
+							   [pmadapter->
+							    num_in_scan_table -
+							    1], bss_new_entry,
+							   sizeof
+							   (BSSDescriptor_t),
+							   sizeof
+							   (BSSDescriptor_t));
+					pcb->moal_mfree(pmadapter->pmoal_handle,
+							(t_u8 *)bss_new_entry);
+				}
+			}
+		}
+	}
+
+	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+		PRINTM(MINFO,
+		       "Scan:(%02d) " MACSTR ", "
+		       "RSSI[%03d], SSID[%s]\n",
+		       i, MAC2STR(pmadapter->pscan_table[i].mac_address),
+		       (t_s32)pmadapter->pscan_table[i].rssi,
+		       pmadapter->pscan_table[i].ssid.ssid);
+		pmadapter->pscan_table[i].chan_load =
+			wlan_get_chan_load(pmadapter,
+					   pmadapter->pscan_table[i].channel);
+	}
+	wlan_update_chan_rssi(pmadapter);
+
+	/*
+	 * Prepares domain info from scan table and downloads the
+	 *   domain info command to the FW.
+	 */
+	wlan_11d_prepare_dnld_domain_info_cmd(pmpriv);
+	PRINTM(MMSG, "wlan: SCAN COMPLETED: scanned AP count=%d\n",
+	       pmadapter->num_in_scan_table);
+	LEAVE();
+}
+
+/**
+ *  @brief Delete a specific indexed entry from the scan table.
+ *
+ *  Delete the scan table entry indexed by table_idx.  Compact the remaining
+ *    entries and adjust any buffering of beacon/probe response data
+ *    if needed.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param table_idx    Scan table entry index to delete from the table
+ *
+ *  @return             N/A
+ *
+ *  @pre                table_idx must be an index to a valid entry
+ */
+static t_void
+wlan_scan_delete_table_entry(mlan_private *pmpriv, t_s32 table_idx)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 del_idx;
+	t_u32 beacon_buf_adj;
+	t_u8 *pbeacon_buf;
+
+	ENTER();
+
+	/*
+	 * Shift the saved beacon buffer data for the scan table back over the
+	 *   entry being removed.  Update the end of buffer pointer.  Save the
+	 *   deleted buffer allocation size for pointer adjustments for entries
+	 *   compacted after the deleted index.
+	 */
+	beacon_buf_adj = pmadapter->pscan_table[table_idx].beacon_buf_size_max;
+
+	PRINTM(MINFO,
+	       "Scan: Delete Entry %d, beacon buffer removal = %d bytes\n",
+	       table_idx, beacon_buf_adj);
+
+	/* Check if the table entry had storage allocated for its beacon */
+	if (beacon_buf_adj) {
+		pbeacon_buf = pmadapter->pscan_table[table_idx].pbeacon_buf;
+
+		/*
+		 * Remove the entry's buffer space, decrement the table
+		 * end pointer by the amount we are removing
+		 */
+		pmadapter->pbcn_buf_end -= beacon_buf_adj;
+
+		PRINTM(MINFO,
+		       "Scan: Delete Entry %d, compact data: %p <- %p (sz = %d)\n",
+		       table_idx, pbeacon_buf, pbeacon_buf + beacon_buf_adj,
+		       pmadapter->pbcn_buf_end - pbeacon_buf);
+
+		/*
+		 * Compact data storage.  Copy all data after the deleted
+		 * entry's end address (pbeacon_buf + beacon_buf_adj) back to
+		 * the original start address (pbeacon_buf).
+		 *
+		 * Scan table entries affected by the move will have their entry
+		 *   pointer adjusted below.
+		 *
+		 * Use memmove since the dest/src memory regions overlap.
+		 */
+		memmove(pmadapter, pbeacon_buf,
+			(void *)((t_ptr)pbeacon_buf + (t_ptr)beacon_buf_adj),
+			(t_u32)((t_ptr)pmadapter->pbcn_buf_end -
+				(t_ptr)pbeacon_buf));
+	}
+
+	PRINTM(MINFO, "Scan: Delete Entry %d, num_in_scan_table = %d\n",
+	       table_idx, pmadapter->num_in_scan_table);
+
+	/*
+	 * Shift all of the entries after the table_idx back by one, compacting
+	 * the table and removing the requested entry
+	 */
+	for (del_idx = table_idx; (del_idx + 1) < pmadapter->num_in_scan_table;
+	     del_idx++) {
+		/* Copy the next entry over this one */
+		memcpy_ext(pmadapter, pmadapter->pscan_table + del_idx,
+			   pmadapter->pscan_table + del_idx + 1,
+			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
+		/*
+		 * Adjust this entry's pointer to its beacon buffer based on the
+		 *   removed/compacted entry from the deleted index.  Don't
+		 * decrement if the buffer pointer is MNULL (no data stored for
+		 * this entry).
+		 */
+		if (pmadapter->pscan_table[del_idx].pbeacon_buf) {
+			pmadapter->pscan_table[del_idx].pbeacon_buf -=
+				beacon_buf_adj;
+			if (pmadapter->pscan_table[del_idx].pwpa_ie) {
+				pmadapter->pscan_table[del_idx].pwpa_ie =
+					(IEEEtypes_VendorSpecific_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .wpa_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].prsn_ie) {
+				pmadapter->pscan_table[del_idx].prsn_ie =
+					(IEEEtypes_Generic_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .rsn_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pwapi_ie) {
+				pmadapter->pscan_table[del_idx].pwapi_ie =
+					(IEEEtypes_Generic_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .wapi_offset);
+			}
+
+			if (pmadapter->pscan_table[del_idx].posen_ie) {
+				pmadapter->pscan_table[del_idx].posen_ie =
+					(IEEEtypes_Generic_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .osen_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pmd_ie) {
+				pmadapter->pscan_table[del_idx].pmd_ie =
+					(IEEEtypes_MobilityDomain_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .md_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pht_cap) {
+				pmadapter->pscan_table[del_idx].pht_cap =
+					(IEEEtypes_HTCap_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .ht_cap_offset);
+			}
+
+			if (pmadapter->pscan_table[del_idx].pht_info) {
+				pmadapter->pscan_table[del_idx].pht_info =
+					(IEEEtypes_HTInfo_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .ht_info_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pbss_co_2040) {
+				pmadapter->pscan_table[del_idx].pbss_co_2040 =
+					(IEEEtypes_2040BSSCo_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .bss_co_2040_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pext_cap) {
+				pmadapter->pscan_table[del_idx].pext_cap =
+					(IEEEtypes_ExtCap_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .ext_cap_offset);
+			}
+			if (pmadapter->pscan_table[del_idx]
+			    .poverlap_bss_scan_param) {
+				pmadapter->pscan_table[del_idx]
+					.poverlap_bss_scan_param =
+					(IEEEtypes_OverlapBSSScanParam_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .overlap_bss_offset);
+			}
+
+			if (pmadapter->pscan_table[del_idx].pvht_cap) {
+				pmadapter->pscan_table[del_idx].pvht_cap =
+					(IEEEtypes_VHTCap_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .vht_cap_offset);
+			}
+
+			if (pmadapter->pscan_table[del_idx].pvht_oprat) {
+				pmadapter->pscan_table[del_idx].pvht_oprat =
+					(IEEEtypes_VHTOprat_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .vht_oprat_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pvht_txpower) {
+				pmadapter->pscan_table[del_idx].pvht_txpower =
+					(IEEEtypes_VHTtxpower_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .vht_txpower_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pext_pwer) {
+				pmadapter->pscan_table[del_idx].pext_pwer =
+					(IEEEtypes_ExtPwerCons_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .ext_pwer_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pext_bssload) {
+				pmadapter->pscan_table[del_idx].pext_bssload =
+					(IEEEtypes_ExtBSSload_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .ext_bssload_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pquiet_chan) {
+				pmadapter->pscan_table[del_idx].pquiet_chan =
+					(IEEEtypes_QuietChan_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .quiet_chan_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].poper_mode) {
+				pmadapter->pscan_table[del_idx].poper_mode =
+					(IEEEtypes_OperModeNtf_t
+					 *)(pmadapter->pscan_table[del_idx]
+					    .pbeacon_buf +
+					    pmadapter->pscan_table[del_idx]
+					    .oper_mode_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].phe_cap) {
+				pmadapter->pscan_table[del_idx].phe_cap =
+					(IEEEtypes_HECap_t
+					 *) (pmadapter->pscan_table[del_idx]
+					     .pbeacon_buf +
+					     pmadapter->pscan_table[del_idx]
+					     .he_cap_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].phe_oprat) {
+				pmadapter->pscan_table[del_idx].phe_oprat =
+					(IEEEtypes_Extension_t
+					 *) (pmadapter->pscan_table[del_idx]
+					     .pbeacon_buf +
+					     pmadapter->pscan_table[del_idx]
+					     .he_oprat_offset);
+			}
+		}
+	}
+
+	/* The last entry is invalid now that it has been deleted or moved back
+	 */
+	memset(pmadapter,
+	       pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
+	       sizeof(BSSDescriptor_t));
+
+	pmadapter->num_in_scan_table--;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Delete all entry's age out
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+static void
+wlan_scan_delete_ageout_entry(mlan_private *pmpriv)
+{
+	BSSDescriptor_t *pbss_entry;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_s32 table_idx = pmadapter->num_in_scan_table - 1;
+	t_u32 i = 0;
+	t_u32 age_in_secs = 0;
+	t_u32 age_ts_usec = 0;
+
+	ENTER();
+#define SCAN_RESULT_AGEOUT 10
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &age_in_secs, &age_ts_usec);
+
+	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
+		pbss_entry = &pmadapter->pscan_table[table_idx];
+		if (age_in_secs >
+		    (pbss_entry->age_in_secs + SCAN_RESULT_AGEOUT)) {
+			PRINTM(MCMND,
+			       "SCAN: ageout AP MAC Addr-" MACSTR
+			       " ssid: %-32s\n",
+			       MAC2STR(pbss_entry->mac_address),
+			       pbss_entry->ssid.ssid);
+			wlan_scan_delete_table_entry(pmpriv, table_idx);
+		}
+		table_idx--;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Delete all occurrences of a given SSID from the scan table
+ *
+ *  Iterate through the scan table and delete all entries that match a given
+ *    SSID.  Compact the remaining scan table entries.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pdel_ssid    Pointer to an SSID to be used in deleting all
+ *                        matching SSIDs from the scan table
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_scan_delete_ssid_table_entry(mlan_private *pmpriv,
+				  mlan_802_11_ssid *pdel_ssid)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_s32 table_idx;
+
+	ENTER();
+
+	PRINTM(MINFO, "Scan: Delete Ssid Entry: %-32s\n", pdel_ssid->ssid);
+
+	/*
+	 * If the requested SSID is found in the table, delete it.  Then keep
+	 * searching the table for multiple entries for the SSID until no
+	 * more are found
+	 */
+	while ((table_idx = wlan_find_ssid_in_list(pmpriv, pdel_ssid, MNULL,
+						   MLAN_BSS_MODE_AUTO)) >= 0) {
+		PRINTM(MINFO, "Scan: Delete SSID Entry: Found Idx = %d\n",
+		       table_idx);
+		ret = MLAN_STATUS_SUCCESS;
+		wlan_scan_delete_table_entry(pmpriv, table_idx);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Check if a scanned network compatible with the driver settings
+ *
+ *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
+ * enabled enabled  enabled   AES     mode   Privacy  WPA  WPA2  Compatible
+ *    0       0        0       0      NONE      0      0    0   yes No security
+ *    0       1        0       0       x        1x     1    x   yes WPA (disable
+ * HT if no AES) 0       0        1       0       x        1x     x    1   yes
+ * WPA2 (disable HT if no AES) 0       0        0       1      NONE      1 0 0
+ * yes Ad-hoc AES 1       0        0       0      NONE      1      0    0   yes
+ * Static WEP (disable HT) 0       0        0       0     !=NONE     1      0 0
+ * yes Dynamic WEP
+ *
+ *  @param pmpriv  A pointer to mlan_private
+ *  @param index   Index in scan table to check against current driver settings
+ *  @param mode    Network mode: Infrastructure or IBSS
+ *
+ *  @return        Index in ScanTable, or negative value if error
+ */
+t_s32
+wlan_is_network_compatible(mlan_private *pmpriv, t_u32 index, t_u32 mode)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	BSSDescriptor_t *pbss_desc;
+
+	ENTER();
+
+	pbss_desc = &pmadapter->pscan_table[index];
+	/* Don't check for compatibility if roaming */
+	if ((pmpriv->media_connected == MTRUE) &&
+	    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+	    (pbss_desc->bss_mode == MLAN_BSS_MODE_INFRA)) {
+		LEAVE();
+		return index;
+	}
+
+	pbss_desc->disable_11n = MFALSE;
+
+	/* if the HE CAP IE exists, HT CAP IE should exist too */
+	/* 2.4G AX AP, don't have VHT CAP */
+	if (pbss_desc->phe_cap && !pbss_desc->pht_cap) {
+		PRINTM(MINFO,
+		       "Disable 11n if VHT CAP/HT CAP IE is not found from the 11AX AP\n");
+		pbss_desc->disable_11n = MTRUE;
+	}
+
+	/* if the VHT CAP IE exists, the HT CAP IE should exist too */
+	if (pbss_desc->pvht_cap && !pbss_desc->pht_cap) {
+		PRINTM(MINFO,
+		       "Disable 11n if HT CAP IE is not found from the 11AC AP\n");
+		pbss_desc->disable_11n = MTRUE;
+	}
+
+	if (pbss_desc->wlan_11h_bss_info.chan_switch_ann.element_id ==
+	    CHANNEL_SWITCH_ANN) {
+		PRINTM(MINFO,
+		       "Don't connect to AP with CHANNEL_SWITCH_ANN IE.\n");
+		LEAVE();
+		return -1;
+	}
+
+	if (pmpriv->wps.session_enable == MTRUE) {
+		PRINTM(MINFO, "Return success directly in WPS period\n");
+		LEAVE();
+		return index;
+	}
+
+	if (pmpriv->sec_info.osen_enabled && pbss_desc->posen_ie &&
+	    ((*(pbss_desc->posen_ie)).ieee_hdr.element_id ==
+	     VENDOR_SPECIFIC_221)) {
+		/* Hotspot 2.0 OSEN AKM */
+		PRINTM(MMSG,
+		       "Return success directly in Hotspot OSEN: index=%d "
+		       "encryption_mode=%#x\n",
+		       index, pmpriv->sec_info.encryption_mode);
+		LEAVE();
+		return index;
+	}
+
+	if ((pbss_desc->bss_mode == mode) &&
+	    (pmpriv->sec_info.ewpa_enabled == MTRUE
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	     || supplicantIsEnabled(pmpriv->psapriv)
+#endif
+	    )) {
+		if (((pbss_desc->pwpa_ie) &&
+		     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)) ||
+		    ((pbss_desc->prsn_ie) &&
+		     ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE))) {
+			if (((pmpriv->adapter->config_bands & BAND_GN
+			      || pmpriv->adapter->config_bands & BAND_AN) &&
+			     pbss_desc->pht_cap) &&
+			    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+			    !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
+						CIPHER_SUITE_CCMP) &&
+			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						CIPHER_SUITE_CCMP)
+			    && !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						   CIPHER_SUITE_GCMP) &&
+			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						CIPHER_SUITE_GCMP_256)
+			    && !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						   CIPHER_SUITE_CCMP_256)) {
+
+				if (is_wpa_oui_present(pmpriv->adapter,
+						       pbss_desc,
+						       CIPHER_SUITE_TKIP) ||
+				    is_rsn_oui_present(pmpriv->adapter,
+						       pbss_desc,
+						       CIPHER_SUITE_TKIP)) {
+					PRINTM(MINFO,
+					       "Disable 11n if AES is not supported by AP\n");
+					pbss_desc->disable_11n = MTRUE;
+				} else {
+					LEAVE();
+					return -1;
+				}
+			}
+			LEAVE();
+			return index;
+		} else {
+			PRINTM(MINFO,
+			       "ewpa_enabled: Ignore none WPA/WPA2 AP\n");
+			LEAVE();
+			return -1;
+		}
+	}
+
+	if (pmpriv->sec_info.wapi_enabled &&
+	    (pbss_desc->pwapi_ie &&
+	     ((*(pbss_desc->pwapi_ie)).ieee_hdr.element_id == WAPI_IE))) {
+		PRINTM(MINFO, "Return success for WAPI AP\n");
+		LEAVE();
+		return index;
+	}
+
+	if (pbss_desc->bss_mode == mode) {
+		if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled &&
+		    !pmpriv->sec_info.wpa_enabled &&
+		    !pmpriv->sec_info.wpa2_enabled &&
+		    ((!pbss_desc->pwpa_ie) ||
+		     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
+		    ((!pbss_desc->prsn_ie) ||
+		     ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE))
+		    && pmpriv->sec_info.encryption_mode ==
+		    MLAN_ENCRYPTION_MODE_NONE && !pbss_desc->privacy) {
+			/* No security */
+			LEAVE();
+			return index;
+		} else if (pmpriv->sec_info.wep_status ==
+			   Wlan802_11WEPEnabled &&
+			   !pmpriv->sec_info.wpa_enabled &&
+			   !pmpriv->sec_info.wpa2_enabled
+			   && pbss_desc->privacy) {
+			/* Static WEP enabled */
+			PRINTM(MINFO, "Disable 11n in WEP mode\n");
+			pbss_desc->disable_11n = MTRUE;
+			/* Reject the following cases: */
+			/*
+			 * case 1: RSN IE w/o WEP OUI and WPA IE w/o WEP OUI
+			 * case 2: RSN IE w/o WEP OUI and No WPA IE
+			 * case 3: WPA IE w/o WEP OUI and No RSN IE
+			 */
+			if (((pbss_desc->prsn_ie) &&
+			     ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
+			      RSN_IE)) ||
+			    ((pbss_desc->pwpa_ie) &&
+			     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
+			      WPA_IE))) {
+				if (!is_rsn_oui_present(pmpriv->adapter,
+							pbss_desc,
+							CIPHER_SUITE_WEP40) &&
+				    !is_rsn_oui_present(pmpriv->adapter,
+							pbss_desc,
+							CIPHER_SUITE_WEP104) &&
+				    !is_wpa_oui_present(pmpriv->adapter,
+							pbss_desc,
+							CIPHER_SUITE_WEP40) &&
+				    !is_wpa_oui_present(pmpriv->adapter,
+							pbss_desc,
+							CIPHER_SUITE_WEP104))
+					index = -1;
+			}
+
+			LEAVE();
+			return index;
+		} else if (pmpriv->sec_info.wep_status ==
+			   Wlan802_11WEPDisabled &&
+			   pmpriv->sec_info.wpa_enabled &&
+			   !pmpriv->sec_info.wpa2_enabled &&
+			   ((pbss_desc->pwpa_ie) &&
+			    ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
+			     WPA_IE))
+			   /*
+			    * Privacy bit may NOT be set in some APs like
+			    * LinkSys WRT54G && pbss_desc->privacy
+			    */
+			) {
+			PRINTM(MINFO,
+			       "wlan_is_network_compatible() WPA: index=%d wpa_ie=%#x "
+			       "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
+			       "privacy=%#x\n",
+			       index,
+			       (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie))
+			       .vend_hdr.element_id :
+			       0, (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie))
+			       .ieee_hdr.element_id :
+			       0,
+			       (pmpriv->sec_info.wep_status ==
+				Wlan802_11WEPEnabled) ?
+			       "e" :
+			       "d",
+			       (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
+			       (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
+			       pmpriv->sec_info.encryption_mode,
+			       pbss_desc->privacy);
+			if (((pmpriv->adapter->config_bands & BAND_GN
+			      || pmpriv->adapter->config_bands & BAND_AN) &&
+			     pbss_desc->pht_cap) &&
+			    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+			    !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
+						CIPHER_SUITE_CCMP)) {
+				if (is_wpa_oui_present(pmpriv->adapter,
+						       pbss_desc,
+						       CIPHER_SUITE_TKIP)) {
+					PRINTM(MINFO,
+					       "Disable 11n if AES is not supported by AP\n");
+					pbss_desc->disable_11n = MTRUE;
+				} else {
+					LEAVE();
+					return -1;
+				}
+			}
+			LEAVE();
+			return index;
+		} else if (pmpriv->sec_info.wep_status ==
+			   Wlan802_11WEPDisabled &&
+			   !pmpriv->sec_info.wpa_enabled &&
+			   pmpriv->sec_info.wpa2_enabled &&
+			   ((pbss_desc->prsn_ie) &&
+			    ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
+			     RSN_IE))
+			   /*
+			    * Privacy bit may NOT be set in some APs like
+			    * LinkSys WRT54G && pbss_desc->privacy
+			    */
+			) {
+			/* WPA2 enabled */
+			PRINTM(MINFO,
+			       "wlan_is_network_compatible() WPA2: index=%d wpa_ie=%#x "
+			       "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
+			       "privacy=%#x\n",
+			       index,
+			       (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie))
+			       .vend_hdr.element_id :
+			       0, (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie))
+			       .ieee_hdr.element_id :
+			       0,
+			       (pmpriv->sec_info.wep_status ==
+				Wlan802_11WEPEnabled) ?
+			       "e" :
+			       "d",
+			       (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
+			       (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
+			       pmpriv->sec_info.encryption_mode,
+			       pbss_desc->privacy);
+			if (((pmpriv->adapter->config_bands & BAND_GN
+			      || pmpriv->adapter->config_bands & BAND_AN) &&
+			     pbss_desc->pht_cap) &&
+			    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
+			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						CIPHER_SUITE_CCMP)
+			    && !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						   CIPHER_SUITE_GCMP) &&
+			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						CIPHER_SUITE_GCMP_256)
+			    && !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
+						   CIPHER_SUITE_CCMP_256)) {
+				if (is_rsn_oui_present(pmpriv->adapter,
+						       pbss_desc,
+						       CIPHER_SUITE_TKIP)) {
+					PRINTM(MINFO,
+					       "Disable 11n if AES is not supported by AP\n");
+					pbss_desc->disable_11n = MTRUE;
+				} else if (is_rsn_oui_present_in_wpa_ie
+					   (pmpriv, CIPHER_SUITE_CCMP) ||
+					   is_rsn_oui_present_in_wpa_ie(pmpriv,
+									CIPHER_SUITE_GCMP)
+					   ||
+					   is_rsn_oui_present_in_wpa_ie(pmpriv,
+									CIPHER_SUITE_GCMP_256)
+					   ||
+					   is_rsn_oui_present_in_wpa_ie(pmpriv,
+									CIPHER_SUITE_CCMP_256))
+				{
+					LEAVE();
+					return index;
+				} else {
+					LEAVE();
+					return -1;
+				}
+			}
+			LEAVE();
+			return index;
+		} else if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled
+			   && !pmpriv->sec_info.wpa_enabled &&
+			   !pmpriv->sec_info.wpa2_enabled &&
+			   ((!pbss_desc->pwpa_ie) ||
+			    ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id !=
+			     WPA_IE)) && ((!pbss_desc->prsn_ie) ||
+					  ((*(pbss_desc->prsn_ie)).ieee_hdr.
+					   element_id != RSN_IE))
+			   && pmpriv->sec_info.encryption_mode !=
+			   MLAN_ENCRYPTION_MODE_NONE && pbss_desc->privacy) {
+			/* Dynamic WEP enabled */
+			pbss_desc->disable_11n = MTRUE;
+			PRINTM(MINFO,
+			       "wlan_is_network_compatible() dynamic WEP: index=%d "
+			       "wpa_ie=%#x rsn_ie=%#x EncMode=%#x privacy=%#x\n",
+			       index,
+			       (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie))
+			       .vend_hdr.element_id :
+			       0, (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie))
+			       .ieee_hdr.element_id :
+			       0,
+			       pmpriv->sec_info.encryption_mode,
+			       pbss_desc->privacy);
+			LEAVE();
+			return index;
+		}
+		/* Security doesn't match */
+		PRINTM(MINFO,
+		       "wlan_is_network_compatible() FAILED: index=%d wpa_ie=%#x "
+		       "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
+		       index,
+		       (pbss_desc->pwpa_ie) ?
+		       (*(pbss_desc->pwpa_ie)).vend_hdr.element_id :
+		       0,
+		       (pbss_desc->prsn_ie) ?
+		       (*(pbss_desc->prsn_ie)).ieee_hdr.element_id :
+		       0,
+		       (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ?
+		       "e" :
+		       "d",
+		       (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
+		       (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
+		       pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
+		LEAVE();
+		return -1;
+	}
+	/* Mode doesn't match */
+	LEAVE();
+	return -1;
+}
+
+/**
+ *  @brief Internal function used to flush the scan list
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_flush_scan_table(pmlan_adapter pmadapter)
+{
+	t_u8 i = 0;
+	ENTER();
+
+	PRINTM(MINFO, "Flushing scan table\n");
+
+	memset(pmadapter, pmadapter->pscan_table, 0,
+	       (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
+	pmadapter->num_in_scan_table = 0;
+
+	memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
+	pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+
+	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+		pmadapter->pchan_stats[i].cca_scan_duration = 0;
+	pmadapter->idx_chan_stats = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Internal function used to start a scan based on an input config
+ *
+ *  Use the input user scan configuration information when provided in
+ *    order to send the appropriate scan commands to firmware to populate or
+ *    update the internal driver scan table
+ *
+ *  @param pmpriv          A pointer to mlan_private structure
+ *  @param pioctl_buf      A pointer to MLAN IOCTL Request buffer
+ *  @param puser_scan_in   Pointer to the input configuration for the requested
+ *                         scan.
+ *
+ *  @return              MLAN_STATUS_SUCCESS or < 0 if error
+ */
+mlan_status
+wlan_scan_networks(mlan_private *pmpriv, t_void *pioctl_buf,
+		   wlan_user_scan_cfg *puser_scan_in)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
+	t_u32 buf_size;
+	ChanScanParamSet_t *pscan_chan_list;
+
+	t_u8 keep_previous_scan;
+	t_u8 filtered_scan;
+	t_u8 scan_current_chan_only;
+	t_u8 max_chan_per_scan;
+	t_u8 i;
+
+	ENTER();
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(wlan_scan_cmd_config_tlv), MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_cfg_out);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
+		PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_chan_list);
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
+		PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
+	memset(pmadapter, pscan_cfg_out, 0x00,
+	       sizeof(wlan_scan_cmd_config_tlv));
+
+	keep_previous_scan = MFALSE;
+
+	ret = wlan_scan_setup_scan_config(pmpriv, puser_scan_in,
+					  &pscan_cfg_out->config,
+					  &pchan_list_out, pscan_chan_list,
+					  &max_chan_per_scan, &filtered_scan,
+					  &scan_current_chan_only);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to setup scan config\n");
+		if (pscan_cfg_out)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_cfg_out);
+		if (pscan_chan_list)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pscan_chan_list);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (puser_scan_in)
+		keep_previous_scan = puser_scan_in->keep_previous_scan;
+
+	if (keep_previous_scan == MFALSE) {
+		memset(pmadapter, pmadapter->pscan_table, 0x00,
+		       sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
+		pmadapter->num_in_scan_table = 0;
+		pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+	} else {
+		wlan_scan_delete_ageout_entry(pmpriv);
+	}
+	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+		pmadapter->pchan_stats[i].cca_scan_duration = 0;
+	pmadapter->idx_chan_stats = 0;
+
+	ret = wlan_scan_channel_list(pmpriv, pioctl_buf, max_chan_per_scan,
+				     filtered_scan, &pscan_cfg_out->config,
+				     pchan_list_out, pscan_chan_list);
+
+	/* Get scan command from scan_pending_q and put to cmd_pending_q */
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
+		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
+			wlan_request_cmd_lock(pmadapter);
+			pmadapter->pscan_ioctl_req = pioctl_req;
+			pmadapter->scan_processing = MTRUE;
+			wlan_release_cmd_lock(pmadapter);
+		} else {
+			wlan_request_cmd_lock(pmadapter);
+			if (util_peek_list(pmadapter->pmoal_handle,
+					   &pmadapter->scan_pending_q, MNULL,
+					   MNULL)) {
+				pcmd_node =
+					(cmd_ctrl_node *)
+					util_dequeue_list(pmadapter->
+							  pmoal_handle,
+							  &pmadapter->
+							  scan_pending_q, MNULL,
+							  MNULL);
+				pmadapter->pscan_ioctl_req = pioctl_req;
+				pmadapter->scan_processing = MTRUE;
+				wlan_insert_cmd_to_pending_q(pmadapter,
+							     pcmd_node, MTRUE);
+			}
+			wlan_release_cmd_lock(pmadapter);
+		}
+	}
+	if (pscan_cfg_out)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
+
+	if (pscan_chan_list)
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pscan_chan_list);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Prepare a scan command to be sent to the firmware
+ *
+ *  Use the wlan_scan_cmd_config sent to the command processing module in
+ *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN command
+ *   struct to send to firmware.
+ *
+ *  The fixed fields specifying the BSS type and BSSID filters as well as a
+ *   variable number/length of TLVs are sent in the command to firmware.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
+ *                    firmware with the HostCmd_DS_801_11_SCAN structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_scan(mlan_private *pmpriv,
+		     HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SCAN *pscan_cmd = &pcmd->params.scan;
+	wlan_scan_cmd_config *pscan_cfg;
+
+	ENTER();
+
+	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+	/* Set fixed field variables in scan command */
+	pscan_cmd->bss_mode = pscan_cfg->bss_mode;
+	memcpy_ext(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
+		   sizeof(pscan_cmd->bssid), sizeof(pscan_cmd->bssid));
+	memcpy_ext(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
+		   pscan_cfg->tlv_buf_len, pscan_cfg->tlv_buf_len);
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
+
+	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+	pcmd->size = (t_u16)wlan_cpu_to_le16((t_u16)
+					     (sizeof(pscan_cmd->bss_mode) +
+					      sizeof(pscan_cmd->bssid) +
+					      pscan_cfg->tlv_buf_len +
+					      S_DS_GEN));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Check if any hidden SSID found in passive scan channels
+ *          and do specific SSID active scan for those channels
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MTRUE/MFALSE
+ */
+
+static t_bool
+wlan_active_scan_req_for_passive_chan(mlan_private *pmpriv,
+				      mlan_ioctl_req *pioctl_buf)
+{
+	t_bool ret = MFALSE;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_bool scan_reqd = MFALSE;
+	t_bool chan_listed = MFALSE;
+	t_u8 id = 0;
+	t_u32 bss_idx, i;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	wlan_user_scan_cfg *user_scan_cfg;
+	mlan_ds_scan *pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+	mlan_scan_req *pscan_req = MNULL;
+	wlan_user_scan_cfg *puser_scan_in = MNULL;
+
+	ENTER();
+
+	if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+		puser_scan_in = (wlan_user_scan_cfg *)
+			pscan->param.user_scan.scan_cfg_buf;
+		if (!puser_scan_in->ssid_filter)
+			goto done;
+	}
+
+	if (pmadapter->active_scan_triggered) {
+		pmadapter->active_scan_triggered = MFALSE;
+		goto done;
+	}
+
+	if ((pcb->moal_malloc(pmadapter->pmoal_handle,
+			      sizeof(wlan_user_scan_cfg), MLAN_MEM_DEF,
+			      (t_u8 **)&user_scan_cfg) !=
+	     MLAN_STATUS_SUCCESS) || !user_scan_cfg) {
+		PRINTM(MERROR, "Memory allocation for user_scan_cfg failed\n");
+		goto done;
+	}
+	memset(pmadapter, user_scan_cfg, 0, sizeof(wlan_user_scan_cfg));
+	for (bss_idx = 0; bss_idx < pmadapter->num_in_scan_table; bss_idx++) {
+		scan_reqd = MFALSE;
+		if (!memcmp(pmadapter,
+			    pmadapter->pscan_table[bss_idx].ssid.ssid,
+			    null_ssid,
+			    pmadapter->pscan_table[bss_idx].ssid.ssid_len)) {
+			if (puser_scan_in &&
+			    puser_scan_in->chan_list[0].chan_number) {
+				for (i = 0;
+				     i < WLAN_USER_SCAN_CHAN_MAX &&
+				     puser_scan_in->chan_list[i].chan_number;
+				     i++) {
+					if (puser_scan_in->chan_list[i]
+					    .chan_number ==
+					    pmadapter->pscan_table[bss_idx]
+					    .channel) {
+						if (puser_scan_in->chan_list[i]
+						    .scan_type ==
+						    MLAN_SCAN_TYPE_PASSIVE)
+							scan_reqd = MTRUE;
+						break;
+					}
+				}
+			} else if (pmadapter->scan_type ==
+				   MLAN_SCAN_TYPE_PASSIVE) {
+				scan_reqd = MTRUE;
+			} else {
+				if ((pmadapter->pscan_table[bss_idx].bss_band &
+				     BAND_A) &&
+				    wlan_11h_radar_detect_required(pmpriv,
+								   pmadapter->
+								   pscan_table
+								   [bss_idx]
+								   .channel))
+					scan_reqd = MTRUE;
+				if (pmadapter->pscan_table[bss_idx].bss_band &
+				    (BAND_B | BAND_G) &&
+				    wlan_bg_scan_type_is_passive(pmpriv,
+								 pmadapter->
+								 pscan_table
+								 [bss_idx]
+								 .channel))
+					scan_reqd = MTRUE;
+			}
+
+			if (scan_reqd) {
+				chan_listed = MFALSE;
+				for (i = 0; i < id; i++) {
+					if ((user_scan_cfg->chan_list[i]
+					     .chan_number ==
+					     pmadapter->pscan_table[bss_idx]
+					     .channel) &&
+					    (user_scan_cfg->chan_list[i]
+					     .radio_type &
+					     pmadapter->pscan_table[bss_idx]
+					     .bss_band)) {
+						chan_listed = MTRUE;
+						break;
+					}
+				}
+				if (chan_listed == MTRUE)
+					continue;
+				user_scan_cfg->chan_list[id].chan_number =
+					pmadapter->pscan_table[bss_idx].channel;
+				if (pmadapter->pscan_table[bss_idx].bss_band &
+				    (BAND_B | BAND_G))
+					user_scan_cfg->chan_list[id].
+						radio_type = BAND_2GHZ;
+				if (pmadapter->pscan_table[bss_idx].
+				    bss_band & BAND_A)
+					user_scan_cfg->chan_list[id].
+						radio_type = BAND_5GHZ;
+				user_scan_cfg->chan_list[id].scan_type =
+					MLAN_SCAN_TYPE_ACTIVE;
+				id++;
+			}
+		}
+	}
+	if (id) {
+		pmadapter->active_scan_triggered = MTRUE;
+		if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+			memcpy_ext(pmpriv->adapter, user_scan_cfg->ssid_list,
+				   puser_scan_in->ssid_list,
+				   sizeof(user_scan_cfg->ssid_list),
+				   sizeof(user_scan_cfg->ssid_list));
+		} else {
+			pscan_req = &pscan->param.scan_req;
+			memcpy_ext(pmpriv->adapter,
+				   user_scan_cfg->ssid_list[0].ssid,
+				   pscan_req->scan_ssid.ssid,
+				   pscan_req->scan_ssid.ssid_len,
+				   MLAN_MAX_SSID_LENGTH);
+		}
+		user_scan_cfg->keep_previous_scan = MTRUE;
+		if (MLAN_STATUS_SUCCESS !=
+		    wlan_scan_networks(pmpriv, pioctl_buf, user_scan_cfg)) {
+			goto done;
+		}
+		ret = MTRUE;
+	}
+	if (user_scan_cfg)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)user_scan_cfg);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of scan
+ *
+ *   The response buffer for the scan command has the following
+ *      memory layout:
+ *
+ *     .-------------------------------------------------------------.
+ *     |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
+ *     .-------------------------------------------------------------.
+ *     |  BufSize (t_u16) : sizeof the BSS Description data          |
+ *     .-------------------------------------------------------------.
+ *     |  NumOfSet (t_u8) : Number of BSS Descs returned             |
+ *     .-------------------------------------------------------------.
+ *     |  BSSDescription data (variable, size given in BufSize)      |
+ *     .-------------------------------------------------------------.
+ *     |  TLV data (variable, size calculated using Header->Size,    |
+ *     |            BufSize and sizeof the fixed fields above)       |
+ *     .-------------------------------------------------------------.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11_scan(mlan_private *pmpriv,
+		     HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	MrvlIEtypes_Data_t *ptlv;
+	MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
+	MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
+	t_u8 *pbss_info;
+	t_u32 scan_resp_size;
+	t_u32 bytes_left;
+	t_u32 num_in_table;
+	t_u32 bss_idx;
+	t_u32 idx;
+	t_u32 tlv_buf_size;
+	t_u64 tsf_val;
+	chan_freq_power_t *cfp;
+	MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
+	ChanBandParamSet_t *pchan_band;
+	t_u8 band;
+	t_u8 is_bgscan_resp;
+	t_u32 age_ts_usec;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+	t_u32 status_code = 0;
+	pmlan_ioctl_req pscan_ioctl_req = MNULL;
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
+	if (is_bgscan_resp)
+		pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
+	else
+		pscan_rsp = &resp->params.scan_resp;
+
+	if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
+		       pscan_rsp->number_of_sets);
+		status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
+	PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
+
+	scan_resp_size = resp->size;
+
+	PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
+	       pscan_rsp->number_of_sets);
+
+	/* Update the age_in_second */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->age_in_secs,
+						  &age_ts_usec);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	pbss_info = pscan_rsp->bss_desc_and_tlv_buffer;
+
+	/*
+	 * The size of the TLV buffer is equal to the entire command response
+	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
+	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
+	 *   response header (S_DS_GEN)
+	 */
+	tlv_buf_size = scan_resp_size -
+		(bytes_left + sizeof(pscan_rsp->bss_descript_size) +
+		 sizeof(pscan_rsp->number_of_sets) + S_DS_GEN);
+	if (is_bgscan_resp)
+		tlv_buf_size -=
+			sizeof(resp->params.bg_scan_query_resp.
+			       report_condition);
+
+	ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
+				      bytes_left);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+					  TLV_TYPE_TSFTIMESTAMP,
+					  (MrvlIEtypes_Data_t **)&ptsf_tlv);
+
+	/*
+	 * Search the TLV buffer space in the scan response
+	 * for any valid TLVs
+	 */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+					  TLV_TYPE_CHANNELBANDLIST,
+					  (MrvlIEtypes_Data_t **)
+					  &pchan_band_tlv);
+	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
+					  TLV_TYPE_CHANNEL_STATS,
+					  (MrvlIEtypes_Data_t **)
+					  &pchanstats_tlv);
+
+	if (pchanstats_tlv)
+		wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
+
+	/*
+	 * Process each scan response returned (pscan_rsp->number_of_sets).
+	 * Save the information in the bss_new_entry and then insert into
+	 * the driver scan table either as an update to an existing entry
+	 * or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie
+		    (pmadapter, bss_new_entry, &pbss_info, &bytes_left,
+		     MFALSE) == MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			if (pchan_band_tlv) {
+				pchan_band =
+					&pchan_band_tlv->chan_band_param[idx];
+				band = radio_type_to_band(pchan_band->bandcfg.
+							  chanBand);
+				if (!bss_new_entry->channel)
+					bss_new_entry->channel =
+						pchan_band->chan_number;
+			}
+			/*
+			 * Save the band designation for this entry
+			 * for use in join
+			 */
+			bss_new_entry->bss_band = band;
+			bss_new_entry->age_in_secs = pmadapter->age_in_secs;
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "SCAN_RESP: dropping entry on blacklist channel.\n");
+				continue;
+			}
+
+			/*
+			 * Search the scan table for the same bssid
+			 */
+			for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+				if (!memcmp(pmadapter,
+					    bss_new_entry->mac_address,
+					    pmadapter->pscan_table[bss_idx]
+					    .mac_address,
+					    sizeof(bss_new_entry->
+						   mac_address))) {
+					/*
+					 * If the SSID matches as well, it is a
+					 * duplicate of this entry.  Keep the
+					 * bss_idx set to this entry so we
+					 * replace the old contents in the table
+					 */
+					if ((bss_new_entry->ssid.ssid_len ==
+					     pmadapter->pscan_table[bss_idx]
+					     .ssid.ssid_len) &&
+					    (!memcmp(pmadapter,
+						     bss_new_entry->ssid.ssid,
+						     pmadapter->
+						     pscan_table[bss_idx]
+						     .ssid.ssid,
+						     bss_new_entry->ssid.
+						     ssid_len))) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+
+						break;
+					}
+					/*
+					 * If the SSID is NULL for same BSSID
+					 * keep the bss_idx set to this entry
+					 * so we replace the old contents in
+					 * the table
+					 */
+					if (!memcmp(pmadapter,
+						    pmadapter->
+						    pscan_table[bss_idx]
+						    .ssid.ssid, null_ssid,
+						    pmadapter->
+						    pscan_table[bss_idx]
+						    .ssid.ssid_len)) {
+						PRINTM(MINFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bss_idx);
+						break;
+					}
+				}
+			}
+			/*
+			 * If the bss_idx is equal to the number of entries
+			 * in the table, the new entry was not a duplicate;
+			 * append it to the scan table
+			 */
+			if (bss_idx == num_in_table) {
+				/*
+				 * Range check the bss_idx, keep it limited
+				 * to the last entry
+				 */
+				if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+					bss_idx--;
+				else
+					num_in_table++;
+			} else {
+				if ((bss_new_entry->channel !=
+				     pmadapter->pscan_table[bss_idx].channel) &&
+				    (bss_new_entry->rssi >
+				     pmadapter->pscan_table[bss_idx].rssi)) {
+					PRINTM(MCMND,
+					       "skip update the duplicate entry with low rssi\n");
+					continue;
+				}
+			}
+			/*
+			 * Save the beacon/probe response returned for later
+			 * application retrieval. Duplicate beacon/probe
+			 * responses are updated if possible
+			 */
+			wlan_ret_802_11_scan_store_beacon(pmpriv, bss_idx,
+							  num_in_table,
+							  bss_new_entry);
+			if (bss_new_entry->pbeacon_buf == MNULL) {
+				PRINTM(MCMND,
+				       "No space for beacon, drop this entry\n");
+				num_in_table--;
+				continue;
+			}
+			/*
+			 * If the TSF TLV was appended to the scan results, save
+			 * this entry's TSF value in the networkTSF field.  The
+			 * networkTSF is the firmware's TSF value at the time
+			 * the beacon or probe response was received.
+			 */
+			if (ptsf_tlv) {
+				memcpy_ext(pmpriv->adapter, &tsf_val,
+					   &ptsf_tlv->tsf_data[idx *
+							       TSF_DATA_SIZE],
+					   sizeof(tsf_val), sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy_ext(pmpriv->adapter,
+					   &bss_new_entry->network_tsf,
+					   &tsf_val,
+					   sizeof(bss_new_entry->network_tsf),
+					   sizeof(bss_new_entry->network_tsf));
+			}
+
+			/* Copy the locally created bss_new_entry to the scan
+			 * table */
+			memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
+				   bss_new_entry,
+				   sizeof(pmadapter->pscan_table[bss_idx]),
+				   sizeof(pmadapter->pscan_table[bss_idx]));
+
+		} else {
+			/* Error parsing/interpreting the scan response, skipped
+			 */
+			PRINTM(MERROR,
+			       "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
+	       pscan_rsp->number_of_sets,
+	       num_in_table - pmadapter->num_in_scan_table, num_in_table);
+
+	/* Update the total number of BSSIDs in the scan table */
+	pmadapter->num_in_scan_table = num_in_table;
+	if (is_bgscan_resp)
+		goto done;
+	wlan_request_cmd_lock(pmadapter);
+	if (!util_peek_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
+			    MNULL, MNULL)) {
+		wlan_release_cmd_lock(pmadapter);
+		if (pmadapter->pscan_ioctl_req) {
+			if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+			    ->sub_command ==
+			    MLAN_OID_SCAN_SPECIFIC_SSID ||
+			    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+			    ->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+				if (wlan_active_scan_req_for_passive_chan
+				    (pmpriv, pmadapter->pscan_ioctl_req)) {
+					goto done;
+				}
+			}
+		}
+		/*
+		 * Process the resulting scan table:
+		 *   - Remove any bad ssids
+		 *   - Update our current BSS information from scan data
+		 */
+		wlan_scan_process_results(pmpriv);
+
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		/* Need to indicate IOCTL complete */
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 (pmlan_ioctl_req)
+						 pscan_ioctl_req,
+						 MLAN_STATUS_SUCCESS);
+		}
+		wlan_release_cmd_lock(pmadapter);
+		pmadapter->bgscan_reported = MFALSE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+	} else {
+		/* If firmware not ready, do not issue any more scan commands */
+		if (pmadapter->hw_status != WlanHardwareStatusReady) {
+			wlan_release_cmd_lock(pmadapter);
+			status_code = MLAN_ERROR_FW_NOT_READY;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		} else {
+			/* Get scan command from scan_pending_q and put to
+			 * cmd_pending_q */
+			pcmd_node =
+				(cmd_ctrl_node *)util_dequeue_list(pmadapter->
+								   pmoal_handle,
+								   &pmadapter->
+								   scan_pending_q,
+								   MNULL,
+								   MNULL);
+			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
+						     MTRUE);
+			wlan_release_cmd_lock(pmadapter);
+		}
+	}
+
+done:
+	if (bss_new_entry)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+	if (ret) {
+		/* Flush all pending scan commands */
+		wlan_flush_scan_queue(pmadapter);
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = status_code;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pscan_ioctl_req,
+						 MLAN_STATUS_FAILURE);
+		}
+		wlan_release_cmd_lock(pmadapter);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Prepare an extended scan command to be sent to the firmware
+ *
+ *  Use the wlan_scan_cmd_config sent to the command processing module in
+ *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
+ *   struct to send to firmware.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
+ *                    firmware with the HostCmd_DS_802_11_SCAN_EXT structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_scan_ext(mlan_private *pmpriv,
+			 HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
+	wlan_scan_cmd_config *pscan_cfg = MNULL;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
+
+	if (pmpriv->adapter->ext_scan_enh == MTRUE) {
+		if (pdata_buf) {
+			if (pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE)
+				pext_scan_cmd->ext_scan_type = EXT_SCAN_ENHANCE;
+			else
+				pext_scan_cmd->ext_scan_type = EXT_SCAN_DEFAULT;
+		} else {
+			pcmd->size =
+				wlan_cpu_to_le16((t_u16)
+						 (sizeof
+						  (pext_scan_cmd->
+						   ext_scan_type) +
+						  (t_u16)(sizeof
+							  (pext_scan_cmd->
+							   reserved)) +
+						  S_DS_GEN));
+			pext_scan_cmd->ext_scan_type = EXT_SCAN_CANCEL;
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+	if (!pdata_buf) {
+		PRINTM(MERROR, "wlan_cmd_802_11_scan_ext: pdata_buf is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
+
+	memcpy_ext(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
+		   pscan_cfg->tlv_buf, pscan_cfg->tlv_buf_len,
+		   pscan_cfg->tlv_buf_len);
+
+	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+	pcmd->size = wlan_cpu_to_le16((t_u16)
+				      (sizeof(pext_scan_cmd->ext_scan_type) +
+				       (t_u16)sizeof(pext_scan_cmd->reserved) +
+				       pscan_cfg->tlv_buf_len + S_DS_GEN));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of extended scan
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11_scan_ext(mlan_private *pmpriv,
+			 HostCmd_DS_COMMAND *resp, t_void *pioctl_buf)
+{
+	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &(resp->params.ext_scan);
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	MrvlIEtypes_ChannelStats_t *tlv_chanstats = MNULL;
+	t_u16 tlv_buf_left = 0;
+	t_u16 tlv_type = 0;
+	t_u16 tlv_len = 0;
+	t_u32 ext_scan_type;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	pmlan_ioctl_req pioctl_req = (pmlan_ioctl_req)pioctl_buf;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	ENTER();
+
+	PRINTM(MINFO, "EXT scan returns successfully\n");
+	ext_scan_type = pext_scan_cmd->ext_scan_type;
+	if (ext_scan_type == EXT_SCAN_CANCEL) {
+		PRINTM(MCMND, "Cancel scan command completed!\n");
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
+		wlan_release_cmd_lock(pmadapter);
+		/* Need to indicate IOCTL complete */
+		if (pioctl_req != MNULL) {
+			pioctl_req->status_code = MLAN_STATUS_SUCCESS;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 (pmlan_ioctl_req)pioctl_req,
+						 MLAN_STATUS_SUCCESS);
+		}
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	} else if (ext_scan_type == EXT_SCAN_ENHANCE) {
+		/* Setup the timer after scan command response */
+		pcb->moal_start_timer(pmpriv->adapter->pmoal_handle,
+				      pmpriv->adapter->pmlan_cmd_timer, MFALSE,
+				      MRVDRV_TIMER_10S * 2);
+		pmpriv->adapter->cmd_timer_is_set = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	tlv = (MrvlIEtypesHeader_t *)pext_scan_cmd->tlv_buffer;
+	tlv_buf_left = resp->size -
+		(sizeof(HostCmd_DS_802_11_SCAN_EXT) - 1 + S_DS_GEN);
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+			PRINTM(MERROR, "Error processing scan gap TLV\n");
+			break;
+		}
+		switch (tlv_type) {
+		case TLV_TYPE_CHANNEL_STATS:
+			tlv_chanstats = (MrvlIEtypes_ChannelStats_t *)tlv;
+			wlan_update_chan_statistics(pmpriv, tlv_chanstats);
+			break;
+		default:
+			break;
+		}
+		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function add a new entry to scan_table
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param bss_new_entry    A pointer to the bss_new_entry
+ *  @param num_in_tbl		number of scan entry in scan_table
+ *
+ *  @return             N/A
+ */
+static t_void
+wlan_add_new_entry_to_scan_table(mlan_private *pmpriv,
+				 BSSDescriptor_t *bss_new_entry,
+				 t_u32 *num_in_tbl)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 bss_idx;
+	t_u32 num_in_table = *num_in_tbl;
+	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = { 0 };
+
+	/*
+	 * Search the scan table for the same bssid
+	 */
+	for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
+		if (!memcmp(pmadapter, bss_new_entry->mac_address,
+			    pmadapter->pscan_table[bss_idx].mac_address,
+			    sizeof(bss_new_entry->mac_address))) {
+			/*
+			 * If the SSID matches as well, it is a
+			 * duplicate of this entry.  Keep the
+			 * bss_idx set to this entry so we
+			 * replace the old contents in the table
+			 */
+			if ((bss_new_entry->ssid.ssid_len ==
+			     pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
+			    (!memcmp(pmadapter, bss_new_entry->ssid.ssid,
+				     pmadapter->pscan_table[bss_idx].ssid.ssid,
+				     bss_new_entry->ssid.ssid_len))) {
+				PRINTM(MINFO,
+				       "EXT_SCAN: Duplicate of index: %d\n",
+				       bss_idx);
+				break;
+			}
+			/*
+			 * If the SSID is NULL for same BSSID
+			 * keep the bss_idx set to this entry
+			 * so we replace the old contents in
+			 * the table
+			 */
+			if (!memcmp(pmadapter,
+				    pmadapter->pscan_table[bss_idx].ssid.ssid,
+				    null_ssid, pmadapter->pscan_table[bss_idx]
+				    .ssid.ssid_len)) {
+				PRINTM(MINFO,
+				       "EXT_SCAN: Duplicate of index: %d\n",
+				       bss_idx);
+				break;
+			}
+		}
+	}
+	/* If the bss_idx is equal to the number of entries
+	 * in the table, the new entry was not a duplicate;
+	 * append it to the scan table
+	 */
+	if (bss_idx == num_in_table) {
+		/* Range check the bss_idx, keep it limited to the last entry */
+		if (bss_idx == MRVDRV_MAX_BSSID_LIST)
+			bss_idx--;
+		else
+			num_in_table++;
+	} else {
+		if ((bss_new_entry->channel !=
+		     pmadapter->pscan_table[bss_idx].channel) &&
+		    (bss_new_entry->rssi >
+		     pmadapter->pscan_table[bss_idx].rssi)) {
+			PRINTM(MCMND,
+			       "skip update the duplicate entry with low rssi\n");
+			return;
+		}
+	}
+	/*
+	 * Save the beacon/probe response returned for later
+	 * application retrieval. Duplicate beacon/probe
+	 * responses are updated if possible
+	 */
+	wlan_ret_802_11_scan_store_beacon(pmpriv, bss_idx, num_in_table,
+					  bss_new_entry);
+	if (bss_new_entry->pbeacon_buf == MNULL) {
+		PRINTM(MCMND, "No space for beacon, drop this entry\n");
+		num_in_table--;
+		goto done;
+	} else {
+		/* Copy the locally created bss_new_entry to the scan table */
+		memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
+			   bss_new_entry,
+			   sizeof(pmadapter->pscan_table[bss_idx]),
+			   sizeof(pmadapter->pscan_table[bss_idx]));
+	}
+done:
+	*num_in_tbl = num_in_table;
+	return;
+}
+
+/** 8 bytes timestamp, 2 bytest interval, 2 bytes capability */
+#define BEACON_FIX_SIZE 12
+
+/**
+ *  @brief This function realloc the beacon buffer and update ssid for new entry
+ *
+ *  @param pmadpater        A pointer to mlan_adapter structure
+ *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
+ *  @param pnew_entry       A pinter to new entry
+ *  @param pssid            A pointer to ssid IE
+ *
+ *  @return                MLAN_STATUS_FAILURE/MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_update_ssid_in_beacon_buf(mlan_adapter *pmadapter,
+			       BSSDescriptor_t *pbss_entry,
+			       BSSDescriptor_t *pnew_entry,
+			       IEEEtypes_Ssid_t * pssid,
+			       IEEEtypes_ExtCap_t *pnew_extcap,
+			       IEEEtypes_Generic_t *pnew_rsnx)
+{
+	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+	t_u8 *pbeacon_buf = MNULL;
+	t_u32 beacon_buf_size = 0;
+	t_s8 offset = pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len;
+	IEEEtypes_ExtCap_t *pextcap;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u32 rsnx_offset = 0;
+
+	if (pnew_entry->ssid.ssid_len >= pbss_entry->ssid.ssid_len)
+		beacon_buf_size =
+			pbss_entry->beacon_buf_size +
+			(pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len);
+	else
+		beacon_buf_size =
+			pbss_entry->beacon_buf_size -
+			(pbss_entry->ssid.ssid_len - pnew_entry->ssid.ssid_len);
+
+	rsnx_offset = beacon_buf_size;
+	if (pnew_rsnx)
+		beacon_buf_size +=
+			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, beacon_buf_size,
+			       MLAN_MEM_DEF, (t_u8 **)&pbeacon_buf);
+	if (ret != MLAN_STATUS_SUCCESS || !pbeacon_buf) {
+		PRINTM(MERROR,
+		       "Memory allocation for beacon buf for bss_new_entry\n");
+		goto done;
+	}
+	pnew_entry->beacon_buf_size = beacon_buf_size;
+	pnew_entry->pbeacon_buf = pbeacon_buf;
+	/** copy fixed IE */
+	memcpy_ext(pmadapter, pbeacon_buf, pbss_entry->pbeacon_buf,
+		   BEACON_FIX_SIZE, BEACON_FIX_SIZE);
+	/** copy new ssid ie */
+	memcpy_ext(pmadapter, pbeacon_buf + BEACON_FIX_SIZE, (t_u8 *)pssid,
+		   pssid->len + sizeof(IEEEtypes_Header_t),
+		   pssid->len + sizeof(IEEEtypes_Header_t));
+	/** copy left IE to new beacon buffer */
+	memcpy_ext(pmadapter,
+		   pbeacon_buf + BEACON_FIX_SIZE + pssid->len +
+		   sizeof(IEEEtypes_Header_t),
+		   pbss_entry->pbeacon_buf + BEACON_FIX_SIZE +
+		   pbss_entry->ssid.ssid_len +
+		   sizeof(IEEEtypes_Header_t),
+		   pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
+		   (pbss_entry->ssid.ssid_len +
+		    sizeof(IEEEtypes_Header_t)),
+		   pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
+		   (pbss_entry->ssid.ssid_len + sizeof(IEEEtypes_Header_t)));
+
+	/* adjust the ie pointer */
+	if (pnew_entry->pwpa_ie)
+		pnew_entry->wpa_offset += offset;
+	if (pnew_entry->prsn_ie)
+		pnew_entry->rsn_offset += offset;
+	if (pnew_entry->pwapi_ie)
+		pnew_entry->wapi_offset += offset;
+
+	if (pnew_entry->posen_ie)
+		pnew_entry->osen_offset += offset;
+	if (pnew_entry->pmd_ie)
+		pnew_entry->md_offset += offset;
+	if (pnew_entry->pht_cap)
+		pnew_entry->ht_cap_offset += offset;
+	if (pnew_entry->pht_info)
+		pnew_entry->ht_info_offset += offset;
+	if (pnew_entry->pbss_co_2040)
+		pnew_entry->bss_co_2040_offset += offset;
+	if (pnew_entry->pext_cap) {
+		pnew_entry->ext_cap_offset += offset;
+		if (pnew_extcap) {
+			pextcap =
+				(IEEEtypes_ExtCap_t *)(pnew_entry->pbeacon_buf +
+						       pnew_entry->
+						       ext_cap_offset);
+			memcpy_ext(pmadapter,
+				   pbeacon_buf + pnew_entry->ext_cap_offset,
+				   (t_u8 *)pnew_extcap,
+				   pnew_extcap->ieee_hdr.len +
+				   sizeof(IEEEtypes_Header_t),
+				   pextcap->ieee_hdr.len +
+				   sizeof(IEEEtypes_Header_t));
+		}
+	}
+	if (pnew_entry->poverlap_bss_scan_param)
+		pnew_entry->overlap_bss_offset += offset;
+	if (pnew_entry->pvht_cap)
+		pnew_entry->vht_cap_offset += offset;
+	if (pnew_entry->pvht_oprat)
+		pnew_entry->vht_oprat_offset += offset;
+	if (pnew_entry->pvht_txpower)
+		pnew_entry->vht_txpower_offset += offset;
+	if (pnew_entry->pext_pwer)
+		pnew_entry->ext_pwer_offset += offset;
+	if (pnew_entry->pext_bssload)
+		pnew_entry->ext_bssload_offset += offset;
+	if (pnew_entry->pquiet_chan)
+		pnew_entry->quiet_chan_offset += offset;
+	if (pnew_entry->poper_mode)
+		pnew_entry->oper_mode_offset += offset;
+	if (pnew_entry->phe_cap)
+		pnew_entry->he_cap_offset += offset;
+	if (pnew_entry->phe_oprat)
+		pnew_entry->he_oprat_offset += offset;
+	if (pnew_rsnx)
+		memcpy_ext(pmadapter, pbeacon_buf + rsnx_offset,
+			   (t_u8 *)pnew_rsnx,
+			   pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
+			   pnew_rsnx->ieee_hdr.len +
+			   sizeof(IEEEtypes_Header_t));
+	DBG_HEXDUMP(MCMD_D, "MBSSID beacon buf", pbeacon_buf, beacon_buf_size);
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	return ret;
+}
+
+/**
+ *  @brief This function generate the bssid from bssid_idx
+ *
+ *  @param pmadpater        A pointer to mlan_adapter structure
+ *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
+ *  @param pnew_entry       A pinter to new entry
+ *  @param bssid_index      bssid_index from BSSID_IDX IE
+ *
+ *  @return                N/A
+ */
+static void
+wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,
+				    BSSDescriptor_t *pbss_entry,
+				    BSSDescriptor_t *pnew_entry,
+				    t_u8 bssid_index, t_u8 max_bssid_indicator)
+{
+	t_u8 mask = 0xff;
+	t_u8 new_bssid[6];
+	t_u8 bssid_a;
+	t_u8 src_bssid[6];
+
+	memcpy_ext(pmadapter, (t_u8 *)src_bssid,
+		   pbss_entry->mac_address,
+		   sizeof(mlan_802_11_mac_addr), sizeof(src_bssid));
+	memcpy_ext(pmadapter, (t_u8 *)new_bssid,
+		   (t_u8 *)&pbss_entry->mac_address,
+		   sizeof(mlan_802_11_mac_addr), sizeof(new_bssid));
+
+	mask = (mask >> (8 - max_bssid_indicator));
+	bssid_a = src_bssid[5] & (~mask);
+	src_bssid[5] = (src_bssid[5] + bssid_index) & mask;
+	new_bssid[5] = bssid_a | src_bssid[5];
+
+	memcpy_ext(pmadapter, (t_u8 *)&pnew_entry->mac_address, new_bssid,
+		   sizeof(new_bssid), sizeof(mlan_802_11_mac_addr));
+	memcpy_ext(pmadapter, (t_u8 *)&pnew_entry->multi_bssid_ap_addr,
+		   (t_u8 *)&pbss_entry->mac_address,
+		   sizeof(mlan_802_11_mac_addr), sizeof(mlan_802_11_mac_addr));
+}
+
+/**
+ *  @brief This function parse the non_trans_bssid_profile
+ *
+ *  @param pmadapter        A pointer to mlan_adapter structure
+ *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
+ * IE
+ *  @param pbss_profile     A pointer to IEEEtypes_NonTransBSSIDprofile_t
+ *  @param num_in_table     A pointer to buffer to save num of entry in scan
+ * table.
+ *  @param  max_bssid_indicator max bssid indicator
+ *
+ *  @return                 N/A
+ */
+static t_void
+wlan_parse_non_trans_bssid_profile(mlan_private *pmpriv,
+				   BSSDescriptor_t *pbss_entry,
+				   IEEEtypes_NonTransBSSIDProfile_t *
+				   pbss_profile, t_u32 *num_in_table,
+				   t_u8 max_bssid_indicator)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	IEEEtypes_Header_t *pheader =
+		(IEEEtypes_Header_t *)pbss_profile->profile_data;
+	IEEEtypes_MultiBSSIDIndex_t *pbssid_index = MNULL;
+	IEEEtypes_Ssid_t *pssid = MNULL;
+	IEEEtypes_NotxBssCap_t *pcap =
+		(IEEEtypes_NotxBssCap_t *) pbss_profile->profile_data;
+	t_u8 *pos = pbss_profile->profile_data;
+	t_s8 left_len = pbss_profile->ieee_hdr.len;
+	t_u8 ret = MFALSE;
+	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	t_u8 *pbeacon_buf = MNULL;
+	IEEEtypes_ExtCap_t *pextcap = MNULL;
+	IEEEtypes_Generic_t *prsnx = MNULL;
+
+	ENTER();
+
+	/* The first element within the Nontransmitted
+	 * BSSID Profile is not the Nontransmitted
+	 * BSSID Capability element.
+	 */
+	if (pcap->element_id != NONTX_BSSID_CAP || pcap->len != 2) {
+		PRINTM(MERROR,
+		       "The first element within the Nontransmitted BSSID Profile is not the NontransmittedBSSID Capability element\n");
+		LEAVE();
+		return;
+	}
+
+	while (left_len >= 2) {
+		pheader = (IEEEtypes_Header_t *)pos;
+		if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) >
+		    left_len) {
+			PRINTM(MMSG, "invalid IE length = %d left len %d\n",
+			       pheader->len, left_len);
+			break;
+		}
+		switch (pheader->element_id) {
+		case MBSSID_INDEX:
+			pbssid_index = (IEEEtypes_MultiBSSIDIndex_t *) pos;
+			if (pbssid_index->bssid_index == 0 ||
+			    pbssid_index->bssid_index > 46) {
+				PRINTM(MERROR,
+				       " No valid Multiple BSSID-Index element\n");
+				goto done;
+			}
+			PRINTM(MCMND, "MBSSID: Find mbssid_index=%d\n",
+			       pbssid_index->bssid_index);
+			ret = MTRUE;
+			break;
+		case EXT_CAPABILITY:
+			pextcap = (IEEEtypes_ExtCap_t *)pos;
+			DBG_HEXDUMP(MCMD_D, "MBSSID extcap", pos,
+				    pextcap->ieee_hdr.len +
+				    sizeof(IEEEtypes_Header_t));
+			break;
+		case RSNX_IE:
+			prsnx = (IEEEtypes_Generic_t *)pos;
+			DBG_HEXDUMP(MCMD_D, "MBSSID RSNX", pos,
+				    prsnx->ieee_hdr.len +
+				    sizeof(IEEEtypes_Header_t));
+			break;
+		case SSID:
+			pssid = (IEEEtypes_Ssid_t *) pos;
+			PRINTM(MCMND, "MBSSID: Find mbssid ssid=%s\n",
+			       pssid->ssid);
+			break;
+		default:
+			break;
+		}
+		left_len -= pheader->len + sizeof(IEEEtypes_Header_t);
+		pos += pheader->len + sizeof(IEEEtypes_Header_t);
+	}
+	if (ret == MTRUE) {
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       sizeof(BSSDescriptor_t), MLAN_MEM_DEF,
+				       (t_u8 **)&bss_new_entry);
+		if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+			PRINTM(MERROR,
+			       "Memory allocation for bss_new_entry failed!\n");
+			goto done;
+		}
+		memcpy_ext(pmadapter, bss_new_entry, pbss_entry,
+			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+		wlan_gen_multi_bssid_by_bssid_index(pmadapter, pbss_entry,
+						    bss_new_entry,
+						    pbssid_index->bssid_index,
+						    max_bssid_indicator);
+		if (pssid) {
+			memset(pmadapter, (t_u8 *)&bss_new_entry->ssid, 0,
+			       sizeof(mlan_802_11_ssid));
+			bss_new_entry->ssid.ssid_len = pssid->len;
+			memcpy_ext(pmadapter, bss_new_entry->ssid.ssid,
+				   pssid->ssid, pssid->len,
+				   MLAN_MAX_SSID_LENGTH);
+			if (MLAN_STATUS_SUCCESS !=
+			    wlan_update_ssid_in_beacon_buf(pmadapter,
+							   pbss_entry,
+							   bss_new_entry, pssid,
+							   pextcap, prsnx)) {
+				PRINTM(MERROR,
+				       "Fail to update MBSSID beacon buf\n");
+				pcb->moal_mfree(pmadapter->pmoal_handle,
+						(t_u8 *)bss_new_entry);
+				goto done;
+			}
+			pbeacon_buf = bss_new_entry->pbeacon_buf;
+		}
+		memcpy_ext(pmadapter, &bss_new_entry->cap_info, &pcap->cap,
+			   sizeof(IEEEtypes_CapInfo_t),
+			   sizeof(IEEEtypes_CapInfo_t));
+		bss_new_entry->multi_bssid_ap = MULTI_BSSID_SUB_AP;
+		wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
+						 num_in_table);
+		if (pssid && pbeacon_buf)
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pbeacon_buf);
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function parse the multi_bssid IE from pbss_entry
+ *
+ *  @param pmpriv        A pointer to mlan_private structure
+ *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
+ * IE
+ *  @param num_in_table     A pointer to buffer to save num of entry in scan
+ * table.
+ *
+ *  @return                 number entry in scan table
+ */
+static t_void
+wlan_parse_multi_bssid_ie(mlan_private *pmpriv,
+			  BSSDescriptor_t *pbss_entry,
+			  IEEEtypes_MultiBSSID_t * pmulti_bssid,
+			  t_u32 *num_in_table)
+{
+	t_u32 bytes_left = 0;
+	t_u8 *pcurrent_ptr = MNULL;
+	IEEEtypes_NonTransBSSIDProfile_t *pbssid_profile = MNULL;
+
+	if (!pmulti_bssid)
+		return;
+	bytes_left = pmulti_bssid->ieee_hdr.len - 1;
+	pcurrent_ptr = pmulti_bssid->sub_elem_data;
+	while (bytes_left >= 2) {
+		pbssid_profile =
+			(IEEEtypes_NonTransBSSIDProfile_t *) pcurrent_ptr;
+		if (pbssid_profile->ieee_hdr.element_id !=
+		    NONTRANS_BSSID_PROFILE_SUBELEM_ID) {
+			PRINTM(MERROR, "Invalid multi-bssid IE\n");
+			break;
+		}
+		if (bytes_left < (t_u32)(pbssid_profile->ieee_hdr.len + 2)) {
+			PRINTM(MERROR, "Invalid multi-bssid IE\n");
+			break;
+		}
+		wlan_parse_non_trans_bssid_profile(pmpriv, pbss_entry,
+						   pbssid_profile, num_in_table,
+						   pmulti_bssid->
+						   max_bssid_indicator);
+		pcurrent_ptr += pbssid_profile->ieee_hdr.len + 2;
+		bytes_left -= pbssid_profile->ieee_hdr.len + 2;
+	}
+	return;
+}
+
+/**
+ *  @brief This function search all the mbssid IE in the beacon buffer
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
+ * IE
+ *  @param num_in_table     A pointer to buffer to save num of entry in scan
+ * table.
+ *
+ *  @return                 N/A
+ */
+static void
+wlan_parse_multi_bssid_ap(mlan_private *pmpriv,
+			  BSSDescriptor_t *pbss_entry, t_u32 *num_in_table)
+{
+	IEEEtypes_ElementId_e element_id;
+	t_u8 element_len;
+	t_u16 total_ie_len;
+	t_u32 bytes_left = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
+	t_u8 *pcurrent_ptr = pbss_entry->pbeacon_buf + BEACON_FIX_SIZE;
+	IEEEtypes_Ssid_t *pssid = (IEEEtypes_Ssid_t *) pcurrent_ptr;
+
+	if (pssid->element_id != SSID) {
+		PRINTM(MERROR,
+		       "Invalid beacon ie, ssid should be in the first element\n");
+		return;
+	}
+	/* Process variable IE */
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+			       "bytes left < IE length\n");
+			bytes_left = 0;
+			continue;
+		}
+		if (element_id == MULTI_BSSID)
+			wlan_parse_multi_bssid_ie(pmpriv, pbss_entry,
+						  (IEEEtypes_MultiBSSID_t *)
+						  pcurrent_ptr, num_in_table);
+		pcurrent_ptr += total_ie_len;
+		bytes_left -= total_ie_len;
+	}
+	return;
+}
+
+/**
+ *  @brief This function parse and store the extended scan results
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param number_of_sets   Number of BSS
+ *  @param pscan_resp       A pointer to scan response buffer
+ *  @param scan_resp_size   Size of scan response buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_parse_ext_scan_result(mlan_private *pmpriv,
+			   t_u8 number_of_sets,
+			   t_u8 *pscan_resp, t_u16 scan_resp_size)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = MNULL;
+	BSSDescriptor_t *bss_new_entry = MNULL;
+	t_u8 *pbss_info;
+	t_u32 bytes_left;
+	t_u32 bytes_left_for_tlv;
+	t_u32 num_in_table;
+	t_u32 idx;
+	t_u64 tsf_val;
+	chan_freq_power_t *cfp;
+	t_u16 tlv_type, tlv_len;
+	MrvlIEtypes_Data_t *ptlv = MNULL;
+	MrvlIEtypes_Bss_Scan_Rsp_t *pscan_rsp_tlv = MNULL;
+	MrvlIEtypes_Bss_Scan_Info_t *pscan_info_tlv = MNULL;
+	t_u8 band;
+	t_u32 age_ts_usec;
+
+	ENTER();
+	pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(MERROR,
+		       "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
+		       number_of_sets);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bytes_left = scan_resp_size;
+	PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
+	PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
+	       number_of_sets);
+	/* Update the age_in_second */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->age_in_secs,
+						  &age_ts_usec);
+
+	num_in_table = pmadapter->num_in_scan_table;
+	ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
+
+	/*
+	 *  Process each scan response returned number_of_sets. Save
+	 *    the information in the bss_new_entry and then insert into the
+	 *    driver scan table either as an update to an existing entry
+	 *    or as an addition at the end of the table
+	 */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
+			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
+
+	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
+		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	for (idx = 0;
+	     idx < number_of_sets && bytes_left > sizeof(MrvlIEtypesHeader_t);
+	     idx++) {
+		tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+		tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+		if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+			PRINTM(MERROR,
+			       "EXT_SCAN: Error bytes left < TLV length\n");
+			break;
+		}
+		pscan_rsp_tlv = MNULL;
+		pscan_info_tlv = MNULL;
+		bytes_left_for_tlv = bytes_left;
+		/*
+		 * BSS response TLV with beacon or probe response buffer
+		 * at the initial position of each descriptor
+		 */
+		if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
+			pbss_info = (t_u8 *)ptlv;
+			pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		} else
+			break;
+
+		/* Process variable TLV */
+		while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
+		       wlan_le16_to_cpu(ptlv->header.type) !=
+		       TLV_TYPE_BSS_SCAN_RSP) {
+			tlv_type = wlan_le16_to_cpu(ptlv->header.type);
+			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
+			if (bytes_left_for_tlv <
+			    sizeof(MrvlIEtypesHeader_t) + tlv_len) {
+				PRINTM(MERROR,
+				       "EXT_SCAN: Error in processing TLV, "
+				       "bytes left < TLV length\n");
+				pscan_rsp_tlv = MNULL;
+				bytes_left_for_tlv = 0;
+				continue;
+			}
+			switch (tlv_type) {
+			case TLV_TYPE_BSS_SCAN_INFO:
+				pscan_info_tlv =
+					(MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
+				if (tlv_len !=
+				    sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
+				    sizeof(MrvlIEtypesHeader_t)) {
+					bytes_left_for_tlv = 0;
+					continue;
+				}
+				break;
+			default:
+				break;
+			}
+			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
+			bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
+			bytes_left_for_tlv -=
+				(tlv_len + sizeof(MrvlIEtypesHeader_t));
+		}
+		/* No BSS response TLV */
+		if (pscan_rsp_tlv == MNULL)
+			break;
+
+		/*
+		 * Advance pointer to the beacon buffer length and
+		 * update the bytes count so that the function
+		 * wlan_interpret_bss_desc_with_ie() can handle the
+		 * scan buffer withut any change
+		 */
+		pbss_info += sizeof(t_u16);
+		bytes_left -= sizeof(t_u16);
+
+		/* Zero out the bss_new_entry we are about to store info in */
+		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if (wlan_interpret_bss_desc_with_ie
+		    (pmadapter, bss_new_entry, &pbss_info, &bytes_left,
+		     MTRUE) == MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
+			       MAC2STR(bss_new_entry->mac_address));
+
+			band = BAND_G;
+			/*
+			 * If the BSS info TLV was appended to the scan results,
+			 * save this entry's TSF value in the networkTSF field.
+			 * The networkTSF is the firmware's TSF value at the
+			 * time the beacon or probe response was received.
+			 */
+			if (pscan_info_tlv) {
+				/* RSSI is 2 byte long */
+				bss_new_entry->rssi =
+					-(t_s32)(wlan_le16_to_cpu
+						 (pscan_info_tlv->rssi));
+				PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
+				       bss_new_entry->rssi);
+				memcpy_ext(pmpriv->adapter, &tsf_val,
+					   &pscan_info_tlv->tsf,
+					   sizeof(tsf_val), sizeof(tsf_val));
+				tsf_val = wlan_le64_to_cpu(tsf_val);
+				memcpy_ext(pmpriv->adapter,
+					   &bss_new_entry->network_tsf,
+					   &tsf_val,
+					   sizeof(bss_new_entry->network_tsf),
+					   sizeof(bss_new_entry->network_tsf));
+				band = radio_type_to_band(pscan_info_tlv->
+							  bandcfg.chanBand);
+				if (!bss_new_entry->channel)
+					bss_new_entry->channel =
+						pscan_info_tlv->channel;
+			}
+			/* Save the band designation for this entry for use in
+			 * join */
+			bss_new_entry->bss_band = band;
+			bss_new_entry->age_in_secs = pmadapter->age_in_secs;
+
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								(t_u8)
+								bss_new_entry->
+								bss_band,
+								(t_u16)
+								bss_new_entry->
+								channel);
+			if (cfp)
+				bss_new_entry->freq = cfp->freq;
+			else
+				bss_new_entry->freq = 0;
+
+			/* Skip entry if on blacklisted channel */
+			if (cfp && cfp->dynamic.blacklist) {
+				PRINTM(MINFO,
+				       "EXT_SCAN: dropping entry on blacklist channel.\n");
+				continue;
+			}
+			if (IS_FW_SUPPORT_MULTIBSSID(pmadapter)) {
+				if (bss_new_entry->multi_bssid_ap ==
+				    MULTI_BSSID_AP)
+					wlan_parse_multi_bssid_ap(pmpriv,
+								  bss_new_entry,
+								  &num_in_table);
+			}
+			wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
+							 &num_in_table);
+
+		} else {
+			/* Error parsing/interpreting the scan response, skipped
+			 */
+			PRINTM(MERROR,
+			       "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
+		}
+	}
+
+	PRINTM(MCMND, "EXT_SCAN: Scanned %2d APs, %d valid, %d total\n",
+	       number_of_sets, num_in_table - pmadapter->num_in_scan_table,
+	       num_in_table);
+
+	/* Update the total number of BSSIDs in the scan table */
+	pmadapter->num_in_scan_table = num_in_table;
+	/* Update the age_in_second */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->age_in_secs,
+						  &age_ts_usec);
+
+done:
+	if (bss_new_entry)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the event extended scan report
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pmbuf        A pointer to mlan_buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_handle_event_ext_scan_report(mlan_private *pmpriv, mlan_buffer *pmbuf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = &pmadapter->callbacks;
+	mlan_ioctl_req *pioctl_req = MNULL;
+	cmd_ctrl_node *pcmd_node = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	mlan_event_scan_result *pevent_scan =
+		(pmlan_event_scan_result)(pmbuf->pbuf + pmbuf->data_offset);
+	t_u8 *ptlv = (pmbuf->pbuf + pmbuf->data_offset +
+		      sizeof(mlan_event_scan_result));
+	t_u16 tlv_buf_left = wlan_le16_to_cpu(pevent_scan->buf_size);
+
+	DBG_HEXDUMP(MCMD_D, "EVENT EXT_SCAN", pmbuf->pbuf + pmbuf->data_offset,
+		    pmbuf->data_len);
+	wlan_parse_ext_scan_result(pmpriv, pevent_scan->num_of_set, ptlv,
+				   tlv_buf_left);
+	if (!pevent_scan->more_event
+	    && (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)
+		) {
+		wlan_request_cmd_lock(pmadapter);
+		if (!util_peek_list(pmadapter->pmoal_handle,
+				    &pmadapter->scan_pending_q, MNULL, MNULL)) {
+			wlan_release_cmd_lock(pmadapter);
+			if (pmadapter->pscan_ioctl_req) {
+				if (((mlan_ds_scan *)
+				     pmadapter->pscan_ioctl_req->pbuf)
+				    ->sub_command ==
+				    MLAN_OID_SCAN_SPECIFIC_SSID ||
+				    ((mlan_ds_scan *)
+				     pmadapter->pscan_ioctl_req->pbuf)
+				    ->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+					if (wlan_active_scan_req_for_passive_chan(pmpriv, pmadapter->pscan_ioctl_req)) {
+						LEAVE();
+						return ret;
+					}
+				}
+			}
+			/*
+			 * Process the resulting scan table:
+			 *   - Remove any bad ssids
+			 *   - Update our current BSS information from scan data
+			 */
+			wlan_scan_process_results(pmpriv);
+			wlan_request_cmd_lock(pmadapter);
+			pmadapter->scan_processing = MFALSE;
+			pioctl_req = pmadapter->pscan_ioctl_req;
+			pmadapter->pscan_ioctl_req = MNULL;
+			/* Need to indicate IOCTL complete */
+			if (pioctl_req != MNULL) {
+				pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+				/* Indicate ioctl complete */
+				pcb->moal_ioctl_complete(pmadapter->
+							 pmoal_handle,
+							 (pmlan_ioctl_req)
+							 pioctl_req,
+							 MLAN_STATUS_SUCCESS);
+			}
+			wlan_release_cmd_lock(pmadapter);
+
+			pmadapter->bgscan_reported = MFALSE;
+			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT,
+					MNULL);
+		} else {
+			/* If firmware not ready, do not issue any more scan
+			 * commands */
+			if (pmadapter->hw_status != WlanHardwareStatusReady) {
+				wlan_release_cmd_lock(pmadapter);
+				/* Flush all pending scan commands */
+				wlan_flush_scan_queue(pmadapter);
+				wlan_request_cmd_lock(pmadapter);
+				pmadapter->scan_processing = MFALSE;
+				pioctl_req = pmadapter->pscan_ioctl_req;
+				pmadapter->pscan_ioctl_req = MNULL;
+				/* Indicate IOCTL complete */
+				if (pioctl_req != MNULL) {
+					pioctl_req->status_code =
+						MLAN_ERROR_FW_NOT_READY;
+
+					/* Indicate ioctl complete */
+					pcb->moal_ioctl_complete(pmadapter->
+								 pmoal_handle,
+								 (pmlan_ioctl_req)
+								 pioctl_req,
+								 MLAN_STATUS_FAILURE);
+				}
+				wlan_release_cmd_lock(pmadapter);
+			} else {
+				/* Get scan command from scan_pending_q and put
+				 * to cmd_pending_q */
+				pcmd_node =
+					(cmd_ctrl_node *)
+					util_dequeue_list(pmadapter->
+							  pmoal_handle,
+							  &pmadapter->
+							  scan_pending_q, MNULL,
+							  MNULL);
+				wlan_insert_cmd_to_pending_q(pmadapter,
+							     pcmd_node, MTRUE);
+				wlan_release_cmd_lock(pmadapter);
+			}
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the event extended scan status
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pmbuf        A pointer to mlan_buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_handle_event_ext_scan_status(mlan_private *pmpriv, mlan_buffer *pmbuf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_event_scan_status *scan_event;
+	mlan_ioctl_req *pioctl_req;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+	t_u16 tlv_buf_left, tlv_len, tlv_type;
+	MrvlIEtypesHeader_t *tlv;
+	MrvlIEtypes_ChannelStats_t *tlv_chan_stats;
+	t_u8 status;
+
+	ENTER();
+
+	if (pmbuf->data_len < sizeof(mlan_event_scan_status)) {
+		PRINTM(MERROR, "Wrong ext scan status event data length\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	scan_event =
+		(pmlan_event_scan_status) (pmbuf->pbuf + pmbuf->data_offset);
+	DBG_HEXDUMP(MCMD_D, "EVENT: Ext_Scan_Status", scan_event,
+		    pmbuf->data_len);
+	status = scan_event->scan_status;
+	PRINTM(MEVENT, "ext_scan_status: status %d (scan %s), buf_len %d\n",
+	       status, status ? "cancelled" : "success", scan_event->buf_len);
+
+	tlv = (MrvlIEtypesHeader_t *)scan_event->event_buf;
+	tlv_buf_left = pmbuf->data_len - sizeof(mlan_event_scan_status);
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+			PRINTM(MERROR,
+			       "Error process scan gap tlv: length %d type 0x%x\n",
+			       tlv_len, tlv_type);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		switch (tlv_type) {
+		case TLV_TYPE_CHANNEL_STATS:
+			tlv_chan_stats = (MrvlIEtypes_ChannelStats_t *)tlv;
+			wlan_update_chan_statistics(pmpriv, tlv_chan_stats);
+			break;
+		default:
+			break;
+		}
+		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+done:
+	/* Now we got response from FW, cancel the command timer */
+	if (!pmadapter->curr_cmd && pmadapter->cmd_timer_is_set) {
+		/* Cancel command timeout timer */
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pmadapter->pmlan_cmd_timer);
+		/* Cancel command timeout timer */
+		pmadapter->cmd_timer_is_set = MFALSE;
+	}
+	if (pmadapter->pscan_ioctl_req) {
+		if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+		    ->sub_command ==
+		    MLAN_OID_SCAN_SPECIFIC_SSID ||
+		    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
+		    ->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
+			if (wlan_active_scan_req_for_passive_chan
+			    (pmpriv, pmadapter->pscan_ioctl_req)) {
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+	/*
+	 * Process the resulting scan table:
+	 *   - Remove any bad ssids
+	 *   - Update our current BSS information from scan data
+	 */
+	wlan_scan_process_results(pmpriv);
+	/** Complete scan ioctl */
+	wlan_request_cmd_lock(pmadapter);
+	pmadapter->scan_processing = MFALSE;
+	pioctl_req = pmadapter->pscan_ioctl_req;
+	pmadapter->pscan_ioctl_req = MNULL;
+	/* Need to indicate IOCTL complete */
+	if (pioctl_req != MNULL) {
+		pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
+		/* Indicate ioctl complete */
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
+					 MLAN_STATUS_SUCCESS);
+	}
+	wlan_release_cmd_lock(pmadapter);
+	wlan_move_cmd_to_cmd_pending_q(pmadapter);
+	pmadapter->bgscan_reported = MFALSE;
+	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of bg_scan_query.
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_802_11_bg_scan_query(mlan_private *pmpriv,
+			      HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_BG_SCAN_QUERY *bg_query = &pcmd->params.bg_scan_query;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
+	pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) +
+				      S_DS_GEN);
+
+	bg_query->flush = MTRUE;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Create a channel list for the driver to scan based on region info
+ *
+ *  Use the driver region/band information to construct a comprehensive list
+ *    of channels to scan.  This routine is used for any scan that is not
+ *    provided a specific channel list to scan.
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pbg_scan_in      pointer to scan configuration parameters
+ *  @param tlv_chan_list    A pointer to structure
+ * MrvlIEtypes_ChanListParamSet_t
+ *
+ *  @return                 channel number
+ */
+static t_u8
+wlan_bgscan_create_channel_list(mlan_private *pmpriv,
+				const wlan_bgscan_cfg *pbg_scan_in,
+				MrvlIEtypes_ChanListParamSet_t *tlv_chan_list)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	region_chan_t *pscan_region;
+	chan_freq_power_t *cfp;
+	t_u32 region_idx;
+	t_u32 chan_idx = 0;
+	t_u32 next_chan;
+	t_u8 scan_type;
+	t_u8 radio_type;
+	t_u8 band;
+
+	ENTER();
+
+	for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
+	     region_idx++) {
+		if (wlan_11d_is_enabled(pmpriv) &&
+		    pmpriv->media_connected != MTRUE) {
+			/* Scan all the supported chan for the first scan */
+			if (!pmadapter->universal_channel[region_idx].valid)
+				continue;
+			pscan_region =
+				&pmadapter->universal_channel[region_idx];
+		} else {
+			if (!pmadapter->region_channel[region_idx].valid)
+				continue;
+			pscan_region = &pmadapter->region_channel[region_idx];
+		}
+
+		if (pbg_scan_in && !pbg_scan_in->chan_list[0].chan_number &&
+		    pbg_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
+			radio_type = pbg_scan_in->chan_list[0].radio_type &
+				~BAND_SPECIFIED;
+			if (!radio_type && (pscan_region->band != BAND_B) &&
+			    (pscan_region->band != BAND_G))
+				continue;
+			if (radio_type && (pscan_region->band != BAND_A))
+				continue;
+		}
+		if ((pbg_scan_in &&
+		     (pbg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS)) ||
+		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			band = pmadapter->adhoc_start_band;
+		else
+			band = pmpriv->config_bands;
+		if (!wlan_is_band_compatible(band, pscan_region->band))
+			continue;
+		for (next_chan = 0; next_chan < pscan_region->num_cfp;
+		     next_chan++, chan_idx++) {
+			if (chan_idx >= WLAN_BG_SCAN_CHAN_MAX)
+				break;
+			/*
+			 * Set the default scan type to ACTIVE SCAN type, will
+			 * later be changed to passive on a per channel basis
+			 * if restricted by regulatory requirements (11d or 11h)
+			 */
+			scan_type = MLAN_SCAN_TYPE_ACTIVE;
+			cfp = pscan_region->pcfp + next_chan;
+
+			switch (pscan_region->band) {
+			case BAND_A:
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.bandcfg.chanBand = BAND_5GHZ;
+				/* Passive scan on DFS channels */
+				if (wlan_11h_radar_detect_required
+				    (pmpriv, (t_u8)cfp->channel))
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+				break;
+			case BAND_B:
+			case BAND_G:
+				if (wlan_bg_scan_type_is_passive
+				    (pmpriv, (t_u8)cfp->channel))
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.bandcfg.chanBand = BAND_2GHZ;
+				break;
+			default:
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.bandcfg.chanBand = BAND_2GHZ;
+				break;
+			}
+
+			if (pbg_scan_in && pbg_scan_in->chan_list[0].scan_time) {
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.max_scan_time = wlan_cpu_to_le16((t_u16)pbg_scan_in->chan_list[0]
+									  .
+									  scan_time);
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.min_scan_time = wlan_cpu_to_le16((t_u16)pbg_scan_in->chan_list[0]
+									  .
+									  scan_time);
+			} else if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 passive_scan_time);
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.min_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 passive_scan_time);
+			} else {
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.max_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 specific_scan_time);
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.min_scan_time =
+					wlan_cpu_to_le16(pmadapter->
+							 specific_scan_time);
+			}
+
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.chan_scan_mode.passive_scan = MTRUE;
+			} else {
+				tlv_chan_list->chan_scan_param[chan_idx]
+					.chan_scan_mode.passive_scan = MFALSE;
+			}
+
+			tlv_chan_list->chan_scan_param[chan_idx].chan_number =
+				(t_u8)cfp->channel;
+		}
+	}
+
+	LEAVE();
+	return chan_idx;
+}
+
+/**
+ *  @brief This function prepares command of bg_scan_config
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_bgscan_config(mlan_private *pmpriv,
+		       HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
+		&pcmd->params.bg_scan_config;
+	wlan_bgscan_cfg *bg_scan_in = (wlan_bgscan_cfg *)pdata_buf;
+	t_u16 cmd_size = 0;
+	MrvlIEtypes_NumProbes_t *pnum_probes_tlv = MNULL;
+	MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_tlv = MNULL;
+	MrvlIEtypes_BeaconLowSnrThreshold_t *snr_tlv = MNULL;
+	MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	MrvlIEtypes_StartLater_t *tlv_start_later = MNULL;
+	MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL;
+	MrvlIEtypes_EESParamSet_t *tlv_ees_cfg = MNULL;
+	MrvlIEtype_EESNetworkCfg_t *tlv_ees_net_cfg = MNULL;
+	MrvlIEtypes_Cipher_t *tlv_ees_cipher = MNULL;
+	MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
+	MrvlIETypes_HTCap_t *pht_cap = MNULL;
+	MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
+	MrvlIEtypes_Extension_t *phe_cap = MNULL;
+	t_u16 len = 0;
+
+	t_u8 index;
+	t_u8 *tlv = MNULL;
+	t_u16 num_probes = 0;
+	t_u32 ssid_idx;
+	t_u32 ssid_len = 0;
+	t_u32 chan_idx;
+	t_u32 chan_num;
+	t_u8 radio_type;
+	t_u16 scan_dur;
+	t_u8 scan_type;
+	t_u8 band;
+	const t_u8 zero_mac[6] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
+	bg_scan->action = wlan_cpu_to_le16(bg_scan_in->action);
+	bg_scan->enable = bg_scan_in->enable;
+	bg_scan->bss_type = bg_scan_in->bss_type;
+	cmd_size = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG) + S_DS_GEN;
+	if (bg_scan_in->scan_interval)
+		bg_scan->scan_interval =
+			wlan_cpu_to_le32(bg_scan_in->scan_interval);
+	else
+		bg_scan->scan_interval =
+			wlan_cpu_to_le32(DEFAULT_BGSCAN_INTERVAL);
+	bg_scan->report_condition =
+		wlan_cpu_to_le32(bg_scan_in->report_condition);
+
+	if ((bg_scan_in->action == BG_SCAN_ACT_GET) ||
+	    (bg_scan_in->action == BG_SCAN_ACT_GET_PPS_UAPSD) ||
+	    (!bg_scan->enable))
+		goto done;
+
+	tlv = (t_u8 *)bg_scan + sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG);
+	num_probes = (bg_scan_in->num_probes ? bg_scan_in->num_probes :
+		      pmadapter->scan_probes);
+	if (num_probes) {
+		pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)tlv;
+		pnum_probes_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
+		pnum_probes_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(pnum_probes_tlv->num_probes));
+		pnum_probes_tlv->num_probes =
+			wlan_cpu_to_le16((t_u16)num_probes);
+		tlv += sizeof(MrvlIEtypes_NumProbes_t);
+		cmd_size += sizeof(MrvlIEtypes_NumProbes_t);
+	}
+	if (bg_scan_in->rssi_threshold) {
+		rssi_tlv = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
+		rssi_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
+		rssi_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (MrvlIEtypes_BeaconLowRssiThreshold_t)
+					 - sizeof(MrvlIEtypesHeader_t));
+		rssi_tlv->value = bg_scan_in->rssi_threshold;
+		rssi_tlv->frequency = 0;
+		tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+		cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+	}
+	if (bg_scan_in->snr_threshold) {
+		snr_tlv = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
+		snr_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
+		snr_tlv->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (MrvlIEtypes_BeaconLowSnrThreshold_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		snr_tlv->value = bg_scan_in->snr_threshold;
+		snr_tlv->frequency = 0;
+		tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+		cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
+	}
+	if (bg_scan_in->repeat_count) {
+		tlv_repeat = (MrvlIEtypes_RepeatCount_t *)tlv;
+		tlv_repeat->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
+		tlv_repeat->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		tlv_repeat->repeat_count =
+			wlan_cpu_to_le16(bg_scan_in->repeat_count);
+		tlv += sizeof(MrvlIEtypes_RepeatCount_t);
+		cmd_size += sizeof(MrvlIEtypes_RepeatCount_t);
+	}
+	for (ssid_idx = 0; ((ssid_idx < NELEMENTS(bg_scan_in->ssid_list)) &&
+			    (*bg_scan_in->ssid_list[ssid_idx].ssid ||
+			     bg_scan_in->ssid_list[ssid_idx].max_len));
+	     ssid_idx++) {
+		ssid_len = wlan_strlen((char *)bg_scan_in->ssid_list[ssid_idx].
+				       ssid);
+		pwildcard_ssid_tlv = (MrvlIEtypes_WildCardSsIdParamSet_t *)tlv;
+		pwildcard_ssid_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
+		pwildcard_ssid_tlv->header.len =
+			(t_u16)(ssid_len +
+				sizeof(pwildcard_ssid_tlv->max_ssid_length));
+		pwildcard_ssid_tlv->max_ssid_length =
+			bg_scan_in->ssid_list[ssid_idx].max_len;
+		memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
+			   bg_scan_in->ssid_list[ssid_idx].ssid, ssid_len,
+			   MLAN_MAX_SSID_LENGTH);
+		tlv += sizeof(pwildcard_ssid_tlv->header) +
+			pwildcard_ssid_tlv->header.len;
+		cmd_size +=
+			sizeof(pwildcard_ssid_tlv->header) +
+			pwildcard_ssid_tlv->header.len;
+		pwildcard_ssid_tlv->header.len =
+			wlan_cpu_to_le16(pwildcard_ssid_tlv->header.len);
+		PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
+		       pwildcard_ssid_tlv->ssid,
+		       pwildcard_ssid_tlv->max_ssid_length);
+	}
+	if (bg_scan_in->chan_list[0].chan_number) {
+		tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+		PRINTM(MINFO, "Scan: Using supplied channel list\n");
+		chan_num = 0;
+		for (chan_idx = 0; chan_idx < WLAN_BG_SCAN_CHAN_MAX &&
+		     bg_scan_in->chan_list[chan_idx].chan_number; chan_idx++) {
+			radio_type = bg_scan_in->chan_list[chan_idx].radio_type;
+			if (bg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS ||
+			    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+				band = pmadapter->adhoc_start_band;
+			else
+				band = pmpriv->config_bands;
+			if (!wlan_is_band_compatible
+			    (band, radio_type_to_band(radio_type)))
+				continue;
+			scan_type = bg_scan_in->chan_list[chan_idx].scan_type;
+			/* Prevent active scanning on a radar controlled channel
+			 */
+			if (radio_type == BAND_5GHZ) {
+				if (wlan_11h_radar_detect_required(pmpriv,
+								   bg_scan_in->
+								   chan_list
+								   [chan_idx]
+								   .
+								   chan_number))
+				{
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+				}
+			}
+			if (radio_type == BAND_2GHZ) {
+				if (wlan_bg_scan_type_is_passive(pmpriv,
+								 bg_scan_in->
+								 chan_list
+								 [chan_idx]
+								 .chan_number)) {
+					scan_type = MLAN_SCAN_TYPE_PASSIVE;
+				}
+			}
+			tlv_chan_list->chan_scan_param[chan_num].chan_number =
+				bg_scan_in->chan_list[chan_idx].chan_number;
+			tlv_chan_list->chan_scan_param[chan_num]
+				.bandcfg.chanBand =
+				bg_scan_in->chan_list[chan_idx].radio_type;
+
+			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+				tlv_chan_list->chan_scan_param[chan_num]
+					.chan_scan_mode.passive_scan = MTRUE;
+			} else {
+				tlv_chan_list->chan_scan_param[chan_num]
+					.chan_scan_mode.passive_scan = MFALSE;
+			}
+			if (bg_scan_in->chan_list[chan_idx].scan_time) {
+				scan_dur =
+					(t_u16)bg_scan_in->chan_list[chan_idx]
+					.scan_time;
+			} else {
+				if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
+					scan_dur = pmadapter->passive_scan_time;
+				} else {
+					scan_dur =
+						pmadapter->specific_scan_time;
+				}
+			}
+			tlv_chan_list->chan_scan_param[chan_num].min_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			tlv_chan_list->chan_scan_param[chan_num].max_scan_time =
+				wlan_cpu_to_le16(scan_dur);
+			chan_num++;
+		}
+		tlv_chan_list->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		tlv_chan_list->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
+		tlv += sizeof(MrvlIEtypesHeader_t) +
+			sizeof(ChanScanParamSet_t) * chan_num;
+		cmd_size += sizeof(MrvlIEtypesHeader_t) +
+			sizeof(ChanScanParamSet_t) * chan_num;
+	} else {
+		tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+		chan_num = wlan_bgscan_create_channel_list(pmpriv, bg_scan_in,
+							   tlv_chan_list);
+		tlv_chan_list->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		tlv_chan_list->header.len =
+			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
+		tlv += sizeof(MrvlIEtypesHeader_t) +
+			sizeof(ChanScanParamSet_t) * chan_num;
+		cmd_size += sizeof(MrvlIEtypesHeader_t) +
+			sizeof(ChanScanParamSet_t) * chan_num;
+	}
+	if (bg_scan_in->chan_per_scan) {
+		bg_scan->chan_per_scan = bg_scan_in->chan_per_scan;
+	} else {
+		if (bg_scan_in->report_condition & BG_SCAN_WAIT_ALL_CHAN_DONE)
+			bg_scan->chan_per_scan = chan_num;
+		else
+			bg_scan->chan_per_scan =
+				MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
+	}
+	if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
+	    (pmpriv->config_bands & BAND_GN
+	     || pmpriv->config_bands & BAND_AN)) {
+		pht_cap = (MrvlIETypes_HTCap_t *)tlv;
+		memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
+		pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+		pht_cap->header.len = sizeof(HTCap_t);
+		wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands,
+				     MTRUE);
+		DBG_HEXDUMP(MCMD_D, "BGSCAN: HT_CAPABILITIES IE",
+			    (t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
+		tlv += sizeof(MrvlIETypes_HTCap_t);
+		cmd_size += sizeof(MrvlIETypes_HTCap_t);
+		pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
+	}
+	if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
+	    (pmpriv->config_bands & BAND_AAC)) {
+		pvht_cap = (MrvlIETypes_VHTCap_t *)tlv;
+		memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
+		pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
+		pvht_cap->header.len = sizeof(VHT_capa_t);
+		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands,
+				      MFALSE, MFALSE);
+		DBG_HEXDUMP(MCMD_D, "BGSCAN: VHT_CAPABILITIES IE",
+			    (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
+		tlv += sizeof(MrvlIETypes_VHTCap_t);
+		cmd_size += sizeof(MrvlIETypes_VHTCap_t);
+		pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
+	}
+
+	if (IS_FW_SUPPORT_11AX(pmadapter) && (pmpriv->config_bands & BAND_AAX)) {
+		phe_cap = (MrvlIEtypes_Extension_t *) tlv;
+		len = wlan_fill_he_cap_tlv(pmpriv, BAND_A, phe_cap, MFALSE);
+		DBG_HEXDUMP(MCMD_D, "BGSCAN: HE_CAPABILITIES IE",
+			    (t_u8 *)phe_cap, len);
+		tlv += len;
+		cmd_size += len;
+	}
+	if (wlan_is_ext_capa_support(pmpriv)) {
+		wlan_add_ext_capa_info_ie(pmpriv, MNULL, &tlv);
+		cmd_size += sizeof(MrvlIETypes_ExtCap_t);
+	}
+	if (pmpriv->adapter->ecsa_enable) {
+		t_u8 bandwidth = BW_20MHZ;
+		t_u8 oper_class = 1;
+		t_u32 usr_dot_11n_dev_cap;
+		if (pmpriv->media_connected) {
+			if (pmpriv->config_bands & BAND_A)
+				usr_dot_11n_dev_cap =
+					pmpriv->usr_dot_11n_dev_cap_a;
+			else
+				usr_dot_11n_dev_cap =
+					pmpriv->usr_dot_11n_dev_cap_bg;
+			if (usr_dot_11n_dev_cap & MBIT(17)) {
+				bandwidth = BW_40MHZ;
+				if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info)
+				    && (pmpriv->config_bands & BAND_AAC))
+					bandwidth = BW_80MHZ;
+			}
+			wlan_get_curr_oper_class(pmpriv,
+						 pmpriv->curr_bss_params.
+						 bss_descriptor.channel,
+						 bandwidth, &oper_class);
+		}
+		len = wlan_add_supported_oper_class_ie(pmpriv, &tlv,
+						       oper_class);
+		cmd_size += len;
+	}
+
+	tlv_start_later = (MrvlIEtypes_StartLater_t *)tlv;
+	tlv_start_later->header.type =
+		wlan_cpu_to_le16(TLV_TYPE_STARTBGSCANLATER);
+	tlv_start_later->header.len =
+		wlan_cpu_to_le16(sizeof(MrvlIEtypes_StartLater_t) -
+				 sizeof(MrvlIEtypesHeader_t));
+	tlv_start_later->value = wlan_cpu_to_le16(bg_scan_in->start_later);
+	tlv += sizeof(MrvlIEtypes_StartLater_t);
+	cmd_size += sizeof(MrvlIEtypes_StartLater_t);
+
+	if (bg_scan_in->config_ees) {
+		/* Fill EES configuration */
+		tlv_ees_cfg = (MrvlIEtypes_EESParamSet_t *) tlv;
+		tlv_ees_cfg->header.type = wlan_cpu_to_le16(TLV_TYPE_EES_CFG);
+		tlv_ees_cfg->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_EESParamSet_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		tlv_ees_cfg->ees_mode = wlan_cpu_to_le16(bg_scan_in->ees_mode);
+		tlv_ees_cfg->report_cond =
+			wlan_cpu_to_le16(bg_scan_in->report_cond);
+		tlv_ees_cfg->high_period =
+			wlan_cpu_to_le16(bg_scan_in->high_period);
+		tlv_ees_cfg->high_period_count =
+			wlan_cpu_to_le16(bg_scan_in->high_period_count);
+		tlv_ees_cfg->mid_period =
+			wlan_cpu_to_le16(bg_scan_in->mid_period);
+		tlv_ees_cfg->mid_period_count =
+			wlan_cpu_to_le16(bg_scan_in->mid_period_count);
+		tlv_ees_cfg->low_period =
+			wlan_cpu_to_le16(bg_scan_in->low_period);
+		tlv_ees_cfg->low_period_count =
+			wlan_cpu_to_le16(bg_scan_in->low_period_count);
+		tlv += sizeof(MrvlIEtypes_EESParamSet_t);
+		cmd_size += sizeof(MrvlIEtypes_EESParamSet_t);
+
+		if (bg_scan_in->network_count) {
+			/* Fill EES network configuration */
+			tlv_ees_net_cfg = (MrvlIEtype_EESNetworkCfg_t *) tlv;
+			tlv_ees_net_cfg->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_EES_NET_CFG);
+			tlv_ees_net_cfg->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtype_EESNetworkCfg_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			tlv_ees_net_cfg->network_count =
+				bg_scan_in->network_count;
+			tlv_ees_net_cfg->max_conn_count =
+				bg_scan_in->max_conn_count;
+			tlv_ees_net_cfg->black_list_exp =
+				bg_scan_in->black_list_exp;
+			tlv += sizeof(MrvlIEtype_EESNetworkCfg_t);
+			cmd_size += sizeof(MrvlIEtype_EESNetworkCfg_t);
+			for (index = 0; index < bg_scan_in->network_count;
+			     index++) {
+				if (wlan_strlen
+				    ((char *)bg_scan_in->ees_ssid_cfg[index]
+				     .ssid)) {
+					/* Fill SSID settings */
+					tlv_ssid =
+						(MrvlIEtypes_SsIdParamSet_t *)
+						tlv;
+					tlv_ssid->header.type =
+						wlan_cpu_to_le16(TLV_TYPE_SSID);
+					tlv_ssid->header.len = wlan_cpu_to_le16((t_u16)bg_scan_in->ees_ssid_cfg[index]
+										.
+										max_len);
+					memcpy_ext(pmadapter, tlv_ssid->ssid,
+						   bg_scan_in->
+						   ees_ssid_cfg[index]
+						   .ssid,
+						   bg_scan_in->
+						   ees_ssid_cfg[index]
+						   .max_len,
+						   MLAN_MAX_SSID_LENGTH);
+					tlv += sizeof(MrvlIEtypesHeader_t) +
+						tlv_ssid->header.len;
+					cmd_size +=
+						sizeof(MrvlIEtypesHeader_t) +
+						tlv_ssid->header.len;
+				} else {
+					/* Fill Wildcard SSID settings */
+					pwildcard_ssid_tlv =
+						(MrvlIEtypes_WildCardSsIdParamSet_t
+						 *)tlv;
+					pwildcard_ssid_tlv->header.type =
+						wlan_cpu_to_le16
+						(TLV_TYPE_WILDCARDSSID);
+					pwildcard_ssid_tlv->header.len =
+						wlan_cpu_to_le16(sizeof
+								 (MrvlIEtypes_WildCardSsIdParamSet_t)
+								 -
+								 sizeof
+								 (MrvlIEtypesHeader_t));
+					pwildcard_ssid_tlv->max_ssid_length =
+						MLAN_MAX_SSID_LENGTH;
+					tlv += sizeof(MrvlIEtypesHeader_t) +
+						sizeof(pwildcard_ssid_tlv->
+						       max_ssid_length);
+					cmd_size +=
+						sizeof(MrvlIEtypesHeader_t) +
+						sizeof(pwildcard_ssid_tlv->
+						       max_ssid_length);
+				}
+				/* Fill Cipher settings */
+				tlv_ees_cipher = (MrvlIEtypes_Cipher_t *)tlv;
+				tlv_ees_cipher->header.type =
+					wlan_cpu_to_le16(TLV_TYPE_CIPHER);
+				tlv_ees_cipher->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_Cipher_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				tlv_ees_cipher->pair_cipher =
+					bg_scan_in->ees_ssid_cfg[index]
+					.pair_cipher;
+				tlv_ees_cipher->group_cipher =
+					bg_scan_in->ees_ssid_cfg[index]
+					.group_cipher;
+				tlv += sizeof(MrvlIEtypes_Cipher_t);
+				cmd_size += sizeof(MrvlIEtypes_Cipher_t);
+			}
+		}
+	}
+
+	if (memcmp(pmadapter, bg_scan_in->random_mac, zero_mac,
+		   MLAN_MAC_ADDR_LENGTH)) {
+		MrvlIEtypes_MacAddr_t *randomMacParam =
+			(MrvlIEtypes_MacAddr_t *)tlv;
+		memset(pmadapter, randomMacParam, 0,
+		       sizeof(MrvlIEtypes_MacAddr_t));
+		randomMacParam->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
+		randomMacParam->header.len =
+			wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+		memcpy_ext(pmadapter, randomMacParam->mac,
+			   bg_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		tlv += sizeof(MrvlIEtypes_MacAddr_t);
+		cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
+	}
+done:
+	pcmd->size = wlan_cpu_to_le16(cmd_size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of extended scan
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_bgscan_config(mlan_private *pmpriv,
+		       HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_scan *pscan = MNULL;
+	HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
+		&resp->params.bg_scan_config;
+	wlan_bgscan_cfg *bg_scan_out = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+		bg_scan_out =
+			(wlan_bgscan_cfg *)pscan->param.user_scan.scan_cfg_buf;
+		bg_scan_out->action = wlan_le16_to_cpu(bg_scan->action);
+		if ((bg_scan_out->action == BG_SCAN_ACT_GET) ||
+		    (bg_scan_out->action == BG_SCAN_ACT_GET_PPS_UAPSD)) {
+			bg_scan_out->enable = bg_scan->enable;
+			bg_scan_out->bss_type = bg_scan->bss_type;
+			bg_scan_out->chan_per_scan = bg_scan->chan_per_scan;
+			bg_scan_out->scan_interval =
+				wlan_le32_to_cpu(bg_scan->scan_interval);
+			bg_scan_out->report_condition =
+				wlan_le32_to_cpu(bg_scan->report_condition);
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_scan) + MLAN_SUB_COMMAND_SIZE;
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of bgscan_query
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ret_802_11_bgscan_query(mlan_private *pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_scan *pscan = MNULL;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 i;
+	ENTER();
+	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
+		pmadapter->pchan_stats[i].cca_scan_duration = 0;
+	pmadapter->idx_chan_stats = 0;
+
+	wlan_ret_802_11_scan(pmpriv, resp, MNULL);
+	if (pioctl_buf) {
+		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
+		pscan->param.scan_resp.pscan_table =
+			(t_u8 *)pmadapter->pscan_table;
+		pscan->param.scan_resp.num_in_scan_table =
+			pmadapter->num_in_scan_table;
+		pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
+		pscan->param.scan_resp.pchan_stats =
+			(t_u8 *)pmadapter->pchan_stats;
+		pscan->param.scan_resp.num_in_chan_stats =
+			pmadapter->num_in_chan_stats;
+
+		pioctl_buf->data_read_written =
+			sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function finds ssid in ssid list.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param ssid         SSID to find in the list
+ *  @param bssid        BSSID to qualify the SSID selection (if provided)
+ *  @param mode         Network mode: Infrastructure or IBSS
+ *
+ *  @return             index in BSSID list or < 0 if error
+ */
+t_s32
+wlan_find_ssid_in_list(mlan_private *pmpriv,
+		       mlan_802_11_ssid *ssid, t_u8 *bssid, t_u32 mode)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_s32 net = -1, j;
+	t_u8 best_rssi = 0;
+	t_u32 i;
+
+	ENTER();
+	PRINTM(MINFO, "Num of entries in scan table = %d\n",
+	       pmadapter->num_in_scan_table);
+
+	/*
+	 * Loop through the table until the maximum is reached or until a match
+	 *   is found based on the bssid field comparison
+	 */
+	for (i = 0;
+	     i < pmadapter->num_in_scan_table && (!bssid || (bssid && net < 0));
+	     i++) {
+		if (!wlan_ssid_cmp(pmadapter, &pmadapter->pscan_table[i].ssid,
+				   ssid) &&
+		    (!bssid ||
+		     !memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
+			     bssid, MLAN_MAC_ADDR_LENGTH))) {
+			if ((mode == MLAN_BSS_MODE_INFRA) &&
+			    !wlan_is_band_compatible(pmpriv->config_bands,
+						     pmadapter->pscan_table[i].
+						     bss_band))
+				continue;
+
+			switch (mode) {
+			case MLAN_BSS_MODE_INFRA:
+			case MLAN_BSS_MODE_IBSS:
+				j = wlan_is_network_compatible(pmpriv, i, mode);
+
+				if (j >= 0) {
+					if (SCAN_RSSI(pmadapter->pscan_table[i]
+						      .rssi) > best_rssi) {
+						best_rssi =
+							SCAN_RSSI(pmadapter->
+								  pscan_table[i]
+								  .rssi);
+						net = i;
+					}
+				} else {
+					if (net == -1)
+						net = j;
+				}
+				break;
+			case MLAN_BSS_MODE_AUTO:
+			default:
+				/*
+				 * Do not check compatibility if the mode
+				 * requested is Auto/Unknown.  Allows generic
+				 * find to work without verifying against the
+				 * Adapter security settings
+				 */
+				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
+				    best_rssi) {
+					best_rssi =
+						SCAN_RSSI(pmadapter->
+							  pscan_table[i].rssi);
+					net = i;
+				}
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return net;
+}
+
+/**
+ *  @brief This function finds a specific compatible BSSID in the scan list
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param bssid        BSSID to find in the scan list
+ *  @param mode         Network mode: Infrastructure or IBSS
+ *
+ *  @return             index in BSSID list or < 0 if error
+ */
+t_s32
+wlan_find_bssid_in_list(mlan_private *pmpriv, t_u8 *bssid, t_u32 mode)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_s32 net = -1;
+	t_u32 i;
+
+	ENTER();
+
+	if (!bssid) {
+		LEAVE();
+		return -1;
+	}
+
+	PRINTM(MINFO, "FindBSSID: Num of BSSIDs = %d\n",
+	       pmadapter->num_in_scan_table);
+
+	/*
+	 * Look through the scan table for a compatible match. The ret return
+	 *   variable will be equal to the index in the scan table (greater
+	 *   than zero) if the network is compatible.  The loop will continue
+	 *   past a matched bssid that is not compatible in case there is an
+	 *   AP with multiple SSIDs assigned to the same BSSID
+	 */
+	for (i = 0; net < 0 && i < pmadapter->num_in_scan_table; i++) {
+		if (!memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
+			    bssid, MLAN_MAC_ADDR_LENGTH)) {
+			if ((mode == MLAN_BSS_MODE_INFRA) &&
+			    !wlan_is_band_compatible(pmpriv->config_bands,
+						     pmadapter->pscan_table[i].
+						     bss_band))
+				continue;
+			switch (mode) {
+			case MLAN_BSS_MODE_INFRA:
+			case MLAN_BSS_MODE_IBSS:
+				net = wlan_is_network_compatible(pmpriv, i,
+								 mode);
+				break;
+			default:
+				net = i;
+				break;
+			}
+		}
+	}
+
+	LEAVE();
+	return net;
+}
+
+/**
+ *  @brief Compare two SSIDs
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param ssid1     A pointer to ssid to compare
+ *  @param ssid2     A pointer to ssid to compare
+ *
+ *  @return         0--ssid is same, otherwise is different
+ */
+t_s32
+wlan_ssid_cmp(pmlan_adapter pmadapter, mlan_802_11_ssid *ssid1,
+	      mlan_802_11_ssid *ssid2)
+{
+	ENTER();
+
+	if (!ssid1 || !ssid2) {
+		LEAVE();
+		return -1;
+	}
+
+	if (ssid1->ssid_len != ssid2->ssid_len) {
+		LEAVE();
+		return -1;
+	}
+
+	LEAVE();
+	return memcmp(pmadapter, ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
+}
+
+/**
+ *  @brief Find the AP with specific ssid in the scan list
+ *
+ *  @param pmpriv               A pointer to mlan_private structure
+ *  @param preq_ssid_bssid      A pointer to AP's ssid returned
+ *
+ *  @return                     MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+mlan_status
+wlan_find_best_network(mlan_private *pmpriv, mlan_ssid_bssid *preq_ssid_bssid)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	BSSDescriptor_t *preq_bss;
+	t_s32 i;
+
+	ENTER();
+
+	memset(pmadapter, preq_ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+	i = wlan_find_best_network_in_list(pmpriv);
+
+	if (i >= 0) {
+		preq_bss = &pmadapter->pscan_table[i];
+		memcpy_ext(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
+			   sizeof(mlan_802_11_ssid),
+			   sizeof(preq_ssid_bssid->ssid));
+		memcpy_ext(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
+			   (t_u8 *)&preq_bss->mac_address, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+
+		/* Make sure we are in the right mode */
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_AUTO)
+			pmpriv->bss_mode = preq_bss->bss_mode;
+		preq_ssid_bssid->channel = (t_u16)preq_bss->channel;
+		if (preq_bss->pmd_ie
+		    && wlan_ft_akm_is_used(pmpriv, (t_u8 *)preq_bss->prsn_ie)
+			) {
+
+			preq_ssid_bssid->ft_md = preq_bss->pmd_ie->mdid;
+			preq_ssid_bssid->ft_cap = preq_bss->pmd_ie->ft_cap;
+		}
+		preq_ssid_bssid->bss_band = preq_bss->bss_band;
+		preq_ssid_bssid->idx = i + 1;
+	}
+
+	if (!preq_ssid_bssid->ssid.ssid_len) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MINFO,
+	       "Best network found = [%s], "
+	       "[" MACSTR "]\n",
+	       preq_ssid_bssid->ssid.ssid, MAC2STR(preq_ssid_bssid->bssid));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Send a scan command for all available channels filtered on a spec
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param preq_ssid    A pointer to AP's ssid returned
+ *
+ *  @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+mlan_status
+wlan_scan_specific_ssid(mlan_private *pmpriv,
+			t_void *pioctl_buf, mlan_802_11_ssid *preq_ssid)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	wlan_user_scan_cfg *pscan_cfg;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	ENTER();
+
+	if (!preq_ssid) {
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	wlan_scan_delete_ssid_table_entry(pmpriv, preq_ssid);
+
+	ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle,
+			       sizeof(wlan_user_scan_cfg), MLAN_MEM_DEF,
+			       (t_u8 **)&pscan_cfg);
+
+	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg) {
+		PRINTM(MERROR, "Memory allocation for pscan_cfg failed!\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(pmpriv->adapter, pscan_cfg, 0x00, sizeof(wlan_user_scan_cfg));
+
+	memcpy_ext(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
+		   preq_ssid->ssid, preq_ssid->ssid_len, MLAN_MAX_SSID_LENGTH);
+	pscan_cfg->keep_previous_scan = MFALSE;
+
+	ret = wlan_scan_networks(pmpriv, pioctl_buf, pscan_cfg);
+
+	if (pscan_cfg)
+		pcb->moal_mfree(pmpriv->adapter->pmoal_handle,
+				(t_u8 *)pscan_cfg);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Save a beacon buffer of the current bss descriptor
+ *  Save the current beacon buffer to restore in the following cases that
+ *  makes the bcn_buf not to contain the current ssid's beacon buffer.
+ *    - the current ssid was not found somehow in the last scan.
+ *    - the current ssid was the last entry of the scan table and overloaded.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_save_curr_bcn(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+	BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmpriv->curr_bcn_buf_lock);
+	/* save the beacon buffer if it is not saved or updated */
+	if ((pmpriv->pcurr_bcn_buf == MNULL) ||
+	    (pmpriv->curr_bcn_size != pcurr_bss->beacon_buf_size) ||
+	    (memcmp(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
+		    pcurr_bss->pbeacon_buf, pcurr_bss->beacon_buf_size))) {
+		if (pmpriv->pcurr_bcn_buf) {
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					pmpriv->pcurr_bcn_buf);
+			pmpriv->pcurr_bcn_buf = MNULL;
+		}
+		pmpriv->curr_bcn_size = pcurr_bss->beacon_buf_size;
+
+		if (pmpriv->curr_bcn_size) {
+			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+					       pcurr_bss->beacon_buf_size,
+					       MLAN_MEM_DEF,
+					       &pmpriv->pcurr_bcn_buf);
+
+			if ((ret == MLAN_STATUS_SUCCESS) &&
+			    pmpriv->pcurr_bcn_buf) {
+				memcpy_ext(pmpriv->adapter,
+					   pmpriv->pcurr_bcn_buf,
+					   pcurr_bss->pbeacon_buf,
+					   pcurr_bss->beacon_buf_size,
+					   pcurr_bss->beacon_buf_size);
+				PRINTM(MINFO, "current beacon saved %d\n",
+				       pmpriv->curr_bcn_size);
+			} else {
+				PRINTM(MERROR,
+				       "Fail to allocate curr_bcn_buf\n");
+			}
+		}
+	}
+	wlan_update_curr_bcn(pmpriv);
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pmpriv->curr_bcn_buf_lock);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Free a beacon buffer of the current bss descriptor
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+t_void
+wlan_free_curr_bcn(mlan_private *pmpriv)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+	ENTER();
+	if (pmpriv->pcurr_bcn_buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle, pmpriv->pcurr_bcn_buf);
+		pmpriv->pcurr_bcn_buf = MNULL;
+	}
+	LEAVE();
+}
diff --git a/wlan_sd8987/mlan/mlan_sdio.c b/wlan_sd8987/mlan/mlan_sdio.c
new file mode 100755
index 0000000..6cabdd5
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sdio.c
@@ -0,0 +1,3708 @@
+/** @file mlan_sdio.c
+ *
+ *  @brief This file contains SDIO specific code
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/27/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_init.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_sdio.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef SD8887
+static const struct _mlan_sdio_card_reg mlan_reg_sd8887 = {
+	.start_rd_port = 0,
+	.start_wr_port = 0,
+	.base_0_reg = 0x6C,
+	.base_1_reg = 0x6D,
+	.poll_reg = 0x5C,
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+	.host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
+		DN_LD_CMD_PORT_HOST_INT_STATUS | UP_LD_CMD_PORT_HOST_INT_STATUS,
+	.status_reg_0 = 0x90,
+	.status_reg_1 = 0x91,
+	.sdio_int_mask = 0xff,
+	.data_port_mask = 0xffffffff,
+	.max_mp_regs = 196,
+	.rd_bitmap_l = 0x10,
+	.rd_bitmap_u = 0x11,
+	.rd_bitmap_1l = 0x12,
+	.rd_bitmap_1u = 0x13,
+	.wr_bitmap_l = 0x14,
+	.wr_bitmap_u = 0x15,
+	.wr_bitmap_1l = 0x16,
+	.wr_bitmap_1u = 0x17,
+	.rd_len_p0_l = 0x18,
+	.rd_len_p0_u = 0x19,
+	.card_config_2_1_reg = 0xD9,
+	.cmd_config_0 = 0xC4,
+	.cmd_config_1 = 0xC5,
+	.cmd_config_2 = 0xC6,
+	.cmd_config_3 = 0xC7,
+	.cmd_rd_len_0 = 0xC0,
+	.cmd_rd_len_1 = 0xC1,
+	.cmd_rd_len_2 = 0xC2,
+	.cmd_rd_len_3 = 0xC3,
+	.io_port_0_reg = 0xE4,
+	.io_port_1_reg = 0xE5,
+	.io_port_2_reg = 0xE6,
+	.host_int_rsr_reg = 0x04,
+	.host_int_mask_reg = 0x08,
+	.host_int_status_reg = 0x0C,
+	.host_restart_reg = 0x58,
+	.card_to_host_event_reg = 0x5C,
+	.host_interrupt_mask_reg = 0x60,
+	.card_interrupt_status_reg = 0x64,
+	.card_interrupt_rsr_reg = 0x68,
+	.card_revision_reg = 0xC8,
+	.card_ocr_0_reg = 0xD4,
+	.card_ocr_1_reg = 0xD5,
+	.card_ocr_3_reg = 0xD6,
+	.card_config_reg = 0xD7,
+	.card_misc_cfg_reg = 0xD8,
+	.debug_0_reg = 0xDC,
+	.debug_1_reg = 0xDD,
+	.debug_2_reg = 0xDE,
+	.debug_3_reg = 0xDF,
+	.fw_reset_reg = 0x0B6,
+	.fw_reset_val = 1,
+	.winner_check_reg = 0x90,
+};
+
+static const struct _mlan_card_info mlan_card_info_sd8887 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+	.v16_fw_api = 0,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+#ifdef SD8801
+static const struct _mlan_sdio_card_reg mlan_reg_sd8801 = {
+	.start_rd_port = 1,
+	.start_wr_port = 1,
+	.base_0_reg = 0x40,
+	.base_1_reg = 0x41,
+	.poll_reg = 0x30,
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK,
+	.host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS,
+	.status_reg_0 = 0x60,
+	.status_reg_1 = 0x61,
+	.sdio_int_mask = 0x3f,
+	.data_port_mask = 0x0000fffe,
+	.max_mp_regs = 64,
+	.rd_bitmap_l = 0x4,
+	.rd_bitmap_u = 0x5,
+	.wr_bitmap_l = 0x6,
+	.wr_bitmap_u = 0x7,
+	.rd_len_p0_l = 0x8,
+	.rd_len_p0_u = 0x9,
+	.io_port_0_reg = 0x78,
+	.io_port_1_reg = 0x79,
+	.io_port_2_reg = 0x7A,
+	.host_int_rsr_reg = 0x01,
+	.host_int_mask_reg = 0x02,
+	.host_int_status_reg = 0x03,
+	.card_misc_cfg_reg = 0x6c,
+	.fw_reset_reg = 0x64,
+	.fw_reset_val = 0,
+};
+
+static const struct _mlan_card_info mlan_card_info_sd8801 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+	.v14_fw_api = 1,
+	.v16_fw_api = 0,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+#ifdef SD8897
+static const struct _mlan_sdio_card_reg mlan_reg_sd8897 = {
+	.start_rd_port = 0,
+	.start_wr_port = 0,
+	.base_0_reg = 0x60,
+	.base_1_reg = 0x61,
+	.poll_reg = 0x50,
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+	.host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
+		DN_LD_CMD_PORT_HOST_INT_STATUS | UP_LD_CMD_PORT_HOST_INT_STATUS,
+	.status_reg_0 = 0xC0,
+	.status_reg_1 = 0xC1,
+	.sdio_int_mask = 0xff,
+	.data_port_mask = 0xffffffff,
+	.max_mp_regs = 184,
+	.rd_bitmap_l = 0x04,
+	.rd_bitmap_u = 0x05,
+	.rd_bitmap_1l = 0x06,
+	.rd_bitmap_1u = 0x07,
+	.wr_bitmap_l = 0x08,
+	.wr_bitmap_u = 0x09,
+	.wr_bitmap_1l = 0x0A,
+	.wr_bitmap_1u = 0x0B,
+	.rd_len_p0_l = 0x0C,
+	.rd_len_p0_u = 0x0D,
+	.card_config_2_1_reg = 0xCD,
+	.cmd_config_0 = 0xB8,
+	.cmd_config_1 = 0xB9,
+	.cmd_config_2 = 0xBA,
+	.cmd_config_3 = 0xBB,
+	.cmd_rd_len_0 = 0xB4,
+	.cmd_rd_len_1 = 0xB5,
+	.cmd_rd_len_2 = 0xB6,
+	.cmd_rd_len_3 = 0xB7,
+	.io_port_0_reg = 0xD8,
+	.io_port_1_reg = 0xD9,
+	.io_port_2_reg = 0xDA,
+	.host_int_rsr_reg = 0x01,
+	.host_int_mask_reg = 0x02,
+	.host_int_status_reg = 0x03,
+	.host_restart_reg = 0x4C,
+	.card_to_host_event_reg = 0x50,
+	.host_interrupt_mask_reg = 0x54,
+	.card_interrupt_status_reg = 0x58,
+	.card_interrupt_rsr_reg = 0x5C,
+	.card_revision_reg = 0xBC,
+	.card_ocr_0_reg = 0xC8,
+	.card_ocr_1_reg = 0xC9,
+	.card_ocr_3_reg = 0xCA,
+	.card_config_reg = 0xCB,
+	.card_misc_cfg_reg = 0xCC,
+	.debug_0_reg = 0xD0,
+	.debug_1_reg = 0xD1,
+	.debug_2_reg = 0xD2,
+	.debug_3_reg = 0xD3,
+	.fw_reset_reg = 0x0E8,
+	.fw_reset_val = 1,
+	.winner_check_reg = 0xC0,
+};
+
+static const struct _mlan_card_info mlan_card_info_sd8897 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 0,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#if defined(SD8977) || defined(SD8997) || defined(SD8987) || defined(SD9098) || defined(SD9097) || defined(SD8978) || defined(SD9177)
+static const struct _mlan_sdio_card_reg mlan_reg_sd8977_sd8997 = {
+	.start_rd_port = 0,
+	.start_wr_port = 0,
+	.base_0_reg = 0xf8,
+	.base_1_reg = 0xf9,
+	.poll_reg = 0x5C,
+	.host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK |
+		CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK,
+	.host_int_status = DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS |
+		DN_LD_CMD_PORT_HOST_INT_STATUS | UP_LD_CMD_PORT_HOST_INT_STATUS,
+	.status_reg_0 = 0xe8,
+	.status_reg_1 = 0xe9,
+	.sdio_int_mask = 0xff,
+	.data_port_mask = 0xffffffff,
+	.max_mp_regs = 196,
+	.rd_bitmap_l = 0x10,
+	.rd_bitmap_u = 0x11,
+	.rd_bitmap_1l = 0x12,
+	.rd_bitmap_1u = 0x13,
+	.wr_bitmap_l = 0x14,
+	.wr_bitmap_u = 0x15,
+	.wr_bitmap_1l = 0x16,
+	.wr_bitmap_1u = 0x17,
+	.rd_len_p0_l = 0x18,
+	.rd_len_p0_u = 0x19,
+	.card_config_2_1_reg = 0xD9,
+	.cmd_config_0 = 0xC4,
+	.cmd_config_1 = 0xC5,
+	.cmd_config_2 = 0xC6,
+	.cmd_config_3 = 0xC7,
+	.cmd_rd_len_0 = 0xC0,
+	.cmd_rd_len_1 = 0xC1,
+	.cmd_rd_len_2 = 0xC2,
+	.cmd_rd_len_3 = 0xC3,
+	.io_port_0_reg = 0xE4,
+	.io_port_1_reg = 0xE5,
+	.io_port_2_reg = 0xE6,
+	.host_int_rsr_reg = 0x04,
+	.host_int_mask_reg = 0x08,
+	.host_int_status_reg = 0x0C,
+	.host_restart_reg = 0x58,
+	.card_to_host_event_reg = 0x5C,
+	.host_interrupt_mask_reg = 0x60,
+	.card_interrupt_status_reg = 0x64,
+	.card_interrupt_rsr_reg = 0x68,
+	.card_revision_reg = 0xC8,
+	.card_ocr_0_reg = 0xD4,
+	.card_ocr_1_reg = 0xD5,
+	.card_ocr_3_reg = 0xD6,
+	.card_config_reg = 0xD7,
+	.card_misc_cfg_reg = 0xD8,
+	.debug_0_reg = 0xDC,
+	.debug_1_reg = 0xDD,
+	.debug_2_reg = 0xDE,
+	.debug_3_reg = 0xDF,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.fw_dnld_offset_0_reg = 0xEC,
+	.fw_dnld_offset_1_reg = 0xED,
+	.fw_dnld_offset_2_reg = 0xEE,
+	.fw_dnld_offset_3_reg = 0xEF,
+	.fw_dnld_status_0_reg = 0xE8,
+	.fw_dnld_status_1_reg = 0xE9,
+	.winner_check_reg = 0xFC,
+};
+#endif
+
+#ifdef SD8997
+static const struct _mlan_card_info mlan_card_info_sd8997 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef SD9097
+static const struct _mlan_card_info mlan_card_info_sd9097 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+#ifdef SD9098
+static const struct _mlan_card_info mlan_card_info_sd9098 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+#ifdef SD9177
+static const struct _mlan_card_info mlan_card_info_sd9177 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+#if defined(SD8977) || defined(SD8978)
+static const struct _mlan_card_info mlan_card_info_sd8977 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+	.v16_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+#ifdef SD8987
+static const struct _mlan_card_info mlan_card_info_sd8987 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+	.v16_fw_api = 1,
+	.supp_ps_handshake = 0,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/**
+ *  @brief This function initialize the SDIO port
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_init_ioport(mlan_adapter *pmadapter)
+{
+	t_u32 reg;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 host_int_rsr_reg = pmadapter->pcard_sd->reg->host_int_rsr_reg;
+	t_u8 host_int_rsr_mask = pmadapter->pcard_sd->reg->sdio_int_mask;
+	t_u8 card_misc_cfg_reg = pmadapter->pcard_sd->reg->card_misc_cfg_reg;
+	t_u8 card_config_2_1_reg =
+		pmadapter->pcard_sd->reg->card_config_2_1_reg;
+	t_u8 cmd_config_0 = pmadapter->pcard_sd->reg->cmd_config_0;
+	t_u8 cmd_config_1 = pmadapter->pcard_sd->reg->cmd_config_1;
+
+	ENTER();
+	if (pmadapter->pcard_sd->supports_sdio_new_mode) {
+		pmadapter->pcard_sd->ioport = MEM_PORT;
+	} else {
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_sd->reg->io_port_0_reg,
+				       &reg))
+			pmadapter->pcard_sd->ioport |= (reg & 0xff);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_sd->reg->io_port_1_reg,
+				       &reg))
+			pmadapter->pcard_sd->ioport |= ((reg & 0xff) << 8);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_sd->reg->io_port_2_reg,
+				       &reg))
+			pmadapter->pcard_sd->ioport |= ((reg & 0xff) << 16);
+		else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	PRINTM(MINFO, "SDIO FUNC1 IO port: 0x%x\n",
+	       pmadapter->pcard_sd->ioport);
+
+	if (pmadapter->pcard_sd->supports_sdio_new_mode) {
+		/* enable sdio cmd53 new mode */
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       card_config_2_1_reg, &reg)) {
+			pcb->moal_write_reg(pmadapter->pmoal_handle,
+					    card_config_2_1_reg,
+					    reg | CMD53_NEW_MODE);
+		} else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		/* configure cmd port  */
+		/* enable reading rx length from the register  */
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle, cmd_config_0,
+				       &reg)) {
+			pcb->moal_write_reg(pmadapter->pmoal_handle,
+					    cmd_config_0,
+					    reg | CMD_PORT_RD_LEN_EN);
+		} else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		/* enable Dnld/Upld ready auto reset for cmd port
+		 * after cmd53 is completed */
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_read_reg(pmadapter->pmoal_handle, cmd_config_1,
+				       &reg)) {
+			pcb->moal_write_reg(pmadapter->pmoal_handle,
+					    cmd_config_1,
+					    reg | CMD_PORT_AUTO_EN);
+		} else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+#if defined(SD8977) || defined(SD8978)
+	if (IS_SD8977(pmadapter->card_type) || IS_SD8978(pmadapter->card_type)) {
+		if ((pmadapter->init_para.int_mode == INT_MODE_GPIO) &&
+		    (pmadapter->init_para.gpio_pin == GPIO_INT_NEW_MODE)) {
+			PRINTM(MMSG, "Enable GPIO-1 int mode\n");
+			pcb->moal_write_reg(pmadapter->pmoal_handle,
+					    SCRATCH_REG_32,
+					    ENABLE_GPIO_1_INT_MODE);
+		}
+	}
+#endif
+	/* Set Host interrupt reset to read to clear */
+	if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      host_int_rsr_reg, &reg)) {
+		pcb->moal_write_reg(pmadapter->pmoal_handle, host_int_rsr_reg,
+				    reg | host_int_rsr_mask);
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Dnld/Upld ready set to auto reset */
+	if (MLAN_STATUS_SUCCESS == pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      card_misc_cfg_reg,
+						      &reg)) {
+		pcb->moal_write_reg(pmadapter->pmoal_handle, card_misc_cfg_reg,
+				    reg | AUTO_RE_ENABLE_INT);
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ *  @param port      Port
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_write_data_sync(mlan_adapter *pmadapter, mlan_buffer *pmbuf, t_u32 port)
+{
+	t_u32 i = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	do {
+		ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, pmbuf,
+						port, 0);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			i++;
+			PRINTM(MERROR,
+			       "host_to_card, write iomem (%d) failed: %d\n", i,
+			       ret);
+			if (MLAN_STATUS_SUCCESS !=
+			    pcb->moal_write_reg(pmadapter->pmoal_handle,
+						HOST_TO_CARD_EVENT_REG,
+						HOST_TERM_CMD53)) {
+				PRINTM(MERROR, "write CFG reg failed\n");
+			}
+			ret = MLAN_STATUS_FAILURE;
+			if (i > MAX_WRITE_IOMEM_RETRY) {
+				pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
+				goto exit;
+			}
+		}
+	} while (ret == MLAN_STATUS_FAILURE);
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function gets available SDIO port for reading cmd/data
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pport      A pointer to port number
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_get_rd_port(mlan_adapter *pmadapter, t_u8 *pport)
+{
+	t_u32 rd_bitmap = pmadapter->pcard_sd->mp_rd_bitmap;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	t_u8 max_ports = pmadapter->pcard_sd->max_ports;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+
+	PRINTM(MIF_D, "wlan_get_rd_port: mp_rd_bitmap=0x%08x\n", rd_bitmap);
+	if (new_mode) {
+		if (!(rd_bitmap & reg->data_port_mask)) {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	} else {
+		if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask))) {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+	if (!new_mode && (pmadapter->pcard_sd->mp_rd_bitmap & CTRL_PORT_MASK)) {
+		pmadapter->pcard_sd->mp_rd_bitmap &= (t_u32)(~CTRL_PORT_MASK);
+		*pport = CTRL_PORT;
+		PRINTM(MIF_D, "wlan_get_rd_port: port=%d mp_rd_bitmap=0x%08x\n",
+		       *pport, pmadapter->pcard_sd->mp_rd_bitmap);
+	} else {
+		if (pmadapter->pcard_sd->mp_rd_bitmap &
+		    (1 << pmadapter->pcard_sd->curr_rd_port)) {
+			pmadapter->pcard_sd->mp_rd_bitmap &=
+				(t_u32)(~
+					(1 << pmadapter->pcard_sd->
+					 curr_rd_port));
+			*pport = pmadapter->pcard_sd->curr_rd_port;
+
+			/* hw rx wraps round only after port (MAX_PORT-1) */
+			if (++pmadapter->pcard_sd->curr_rd_port == max_ports)
+				pmadapter->pcard_sd->curr_rd_port =
+					reg->start_rd_port;
+		} else {
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+
+		PRINTM(MIF_D, "port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", *pport,
+		       rd_bitmap, pmadapter->pcard_sd->mp_rd_bitmap);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function gets available SDIO port for writing data
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pport      A pointer to port number
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_get_wr_port_data(mlan_adapter *pmadapter, t_u8 *pport)
+{
+	t_u32 wr_bitmap = pmadapter->pcard_sd->mp_wr_bitmap;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+
+	PRINTM(MIF_D, "wlan_get_wr_port_data: mp_wr_bitmap=0x%08x\n",
+	       wr_bitmap);
+
+	if (!(wr_bitmap & pmadapter->pcard_sd->mp_data_port_mask)) {
+		pmadapter->data_sent = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if (pmadapter->pcard_sd->mp_wr_bitmap &
+	    (1 << pmadapter->pcard_sd->curr_wr_port)) {
+		pmadapter->pcard_sd->mp_wr_bitmap &=
+			(t_u32)(~(1 << pmadapter->pcard_sd->curr_wr_port));
+		*pport = pmadapter->pcard_sd->curr_wr_port;
+		if (++pmadapter->pcard_sd->curr_wr_port ==
+		    pmadapter->pcard_sd->mp_end_port)
+			pmadapter->pcard_sd->curr_wr_port = reg->start_wr_port;
+	} else {
+		pmadapter->data_sent = MTRUE;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	if ((!new_mode) && (*pport == CTRL_PORT)) {
+		PRINTM(MERROR,
+		       "Invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+		       *pport, pmadapter->pcard_sd->curr_wr_port, wr_bitmap,
+		       pmadapter->pcard_sd->mp_wr_bitmap);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	PRINTM(MIF_D, "port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *pport,
+	       wr_bitmap, pmadapter->pcard_sd->mp_wr_bitmap);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function polls the card status register.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param bits       the bit mask
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_poll_card_status(mlan_adapter *pmadapter, t_u8 bits)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 tries;
+	t_u32 cs = 0;
+
+	ENTER();
+
+	for (tries = 0; tries < 10000; tries++) {
+		if (pcb->moal_read_reg(pmadapter->pmoal_handle,
+				       pmadapter->pcard_sd->reg->poll_reg,
+				       &cs) != MLAN_STATUS_SUCCESS)
+			break;
+		else if ((cs & bits) == bits) {
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+		wlan_udelay(pmadapter, 10);
+	}
+
+	PRINTM(MERROR,
+	       "wlan_sdio_poll_card_status failed, tries = %d, cs = 0x%x\n",
+	       tries, cs);
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function reads firmware status registers
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param dat          A pointer to keep returned data
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_read_fw_status(mlan_adapter *pmadapter, t_u16 *dat)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 fws0 = 0, fws1 = 0;
+
+	ENTER();
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_sd->reg->status_reg_0, &fws0)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_sd->reg->status_reg_1, &fws1)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	*dat = (t_u16)((fws1 << 8) | fws0);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads firmware dnld offset registers
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param dat          A pointer to keep returned data
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_read_fw_dnld_offset(mlan_adapter *pmadapter, t_u32 *dat)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 fw_dnld_offset_0 = 0;
+	t_u32 fw_dnld_offset_1 = 0;
+	t_u32 fw_dnld_offset_2 = 0;
+	t_u32 fw_dnld_offset_3 = 0;
+
+	ENTER();
+
+	ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+				 reg->fw_dnld_offset_0_reg, &fw_dnld_offset_0);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Dev fw_dnld_offset_0 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+		       reg->fw_dnld_offset_0_reg, fw_dnld_offset_0);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+				 reg->fw_dnld_offset_1_reg, &fw_dnld_offset_1);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Dev fw_dnld_offset_1 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+		       reg->fw_dnld_offset_1_reg, fw_dnld_offset_1);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+				 reg->fw_dnld_offset_2_reg, &fw_dnld_offset_2);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Dev fw_dnld_offset_2 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+		       reg->fw_dnld_offset_2_reg, fw_dnld_offset_2);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+				 reg->fw_dnld_offset_3_reg, &fw_dnld_offset_3);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Dev fw_dnld_offset_3 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+		       reg->fw_dnld_offset_3_reg, fw_dnld_offset_3);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dat = (t_u32)(((fw_dnld_offset_3 & 0xff) << 24) |
+		       ((fw_dnld_offset_2 & 0xff) << 16) |
+		       ((fw_dnld_offset_1 & 0xff) << 8) |
+		       (fw_dnld_offset_0 & 0xff));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function reads firmware dnld status registers
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param dat          A pointer to keep returned data
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_read_fw_dnld_status(mlan_adapter *pmadapter, t_u16 *dat)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 fw_dnld_status_0 = 0;
+	t_u32 fw_dnld_status_1 = 0;
+
+	ENTER();
+
+	ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+				 reg->fw_dnld_status_0_reg, &fw_dnld_status_0);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Dev fw_dnld_status_0 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+		       reg->fw_dnld_status_0_reg, fw_dnld_status_0);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+				 reg->fw_dnld_status_1_reg, &fw_dnld_status_1);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Dev fw_dnld_status_1 reg read failed: reg(0x%04X)=0x%x. Terminating download\n",
+		       reg->fw_dnld_status_1_reg, fw_dnld_status_1);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	*dat = (t_u16)(((fw_dnld_status_1 & 0xff) << 8) |
+		       (fw_dnld_status_0 & 0xff));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**  @brief This function disables the host interrupts mask.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param mask         the interrupt mask
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_disable_host_int_mask(pmlan_adapter pmadapter, t_u8 mask)
+{
+	t_u32 host_int_mask = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	/* Read back the host_int_mask register */
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_read_reg(pmadapter->pmoal_handle,
+			       pmadapter->pcard_sd->reg->host_int_mask_reg,
+			       &host_int_mask)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Update with the mask and write back to the register */
+	host_int_mask &= ~mask;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_sd->reg->host_int_mask_reg,
+				host_int_mask)) {
+		PRINTM(MWARN, "Disable host interrupt failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enables the host interrupts mask
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param mask    the interrupt mask
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_enable_host_int_mask(pmlan_adapter pmadapter, t_u8 mask)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	/* Simply write the mask to the register */
+	if (MLAN_STATUS_SUCCESS !=
+	    pcb->moal_write_reg(pmadapter->pmoal_handle,
+				pmadapter->pcard_sd->reg->host_int_mask_reg,
+				mask)) {
+		PRINTM(MWARN, "Enable host interrupt failed\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads data from the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param type     A pointer to keep type as data or command
+ *  @param nb       A pointer to keep the data/cmd length returned in buffer
+ *  @param pmbuf    A pointer to the SDIO data/cmd buffer
+ *  @param npayload the length of data/cmd buffer
+ *  @param ioport   the SDIO ioport
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_card_to_host(mlan_adapter *pmadapter, t_u32 *type,
+		       t_u32 *nb, pmlan_buffer pmbuf,
+		       t_u32 npayload, t_u32 ioport)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u32 i = 0;
+
+	ENTER();
+
+	if (!pmbuf) {
+		PRINTM(MWARN, "pmbuf is NULL!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	do {
+		ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, pmbuf,
+					       ioport, 0);
+
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "wlan: cmd53 read failed: %d ioport=0x%x retry=%d\n",
+			       ret, ioport, i);
+			i++;
+			if (MLAN_STATUS_SUCCESS !=
+			    pcb->moal_write_reg(pmadapter->pmoal_handle,
+						HOST_TO_CARD_EVENT_REG,
+						HOST_TERM_CMD53)) {
+				PRINTM(MERROR, "Set Term cmd53 failed\n");
+			}
+			if (i > MAX_WRITE_IOMEM_RETRY) {
+				pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+				ret = MLAN_STATUS_FAILURE;
+				goto exit;
+			}
+		}
+	} while (ret == MLAN_STATUS_FAILURE);
+	*nb = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset));
+	if (*nb > npayload) {
+		PRINTM(MERROR, "invalid packet, *nb=%d, npayload=%d\n", *nb,
+		       npayload);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	DBG_HEXDUMP(MIF_D, "SDIO Blk Rd", pmbuf->pbuf + pmbuf->data_offset,
+		    MIN(*nb, MAX_DATA_DUMP_LEN));
+
+	*type = wlan_le16_to_cpu(*(t_u16 *)
+				 (pmbuf->pbuf + pmbuf->data_offset + 2));
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function downloads FW blocks to device
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param firmware     A pointer to firmware image
+ *  @param firmwarelen  firmware len
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_prog_fw_w_helper(pmlan_adapter pmadapter, t_u8 *fw, t_u32 fw_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *firmware = fw;
+	t_u32 firmwarelen = fw_len;
+	t_u32 offset = 0;
+	t_u32 base0, base1;
+	t_void *tmpfwbuf = MNULL;
+	t_u32 tmpfwbufsz;
+	t_u8 *fwbuf;
+	mlan_buffer mbuf;
+	t_u16 len = 0;
+	t_u32 txlen = 0, tx_blocks = 0, tries = 0;
+	t_u32 i = 0;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	t_u32 read_base_0_reg = reg->base_0_reg;
+	t_u32 read_base_1_reg = reg->base_1_reg;
+#if defined(SD9098)
+	t_u32 rev_id_reg = 0;
+	t_u32 revision_id = 0;
+#endif
+	t_u8 check_fw_status = MFALSE;
+	t_u16 fw_dnld_status = 0;
+	t_u32 fw_dnld_offset = 0;
+	t_u8 mic_retry = 0;
+
+	ENTER();
+
+	if (!firmware && !pcb->moal_get_fw_data) {
+		PRINTM(MMSG, "No firmware image found! Terminating download\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	PRINTM(MINFO, "WLAN: Downloading FW image (%d bytes)\n", firmwarelen);
+
+	tmpfwbufsz = ALIGN_SZ(WLAN_UPLD_SIZE, DMA_ALIGNMENT);
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, tmpfwbufsz,
+			       MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&tmpfwbuf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !tmpfwbuf) {
+		PRINTM(MERROR,
+		       "Unable to allocate buffer for firmware. Terminating download\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(pmadapter, tmpfwbuf, 0, tmpfwbufsz);
+	/* Ensure 8-byte aligned firmware buffer */
+	fwbuf = (t_u8 *)ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT);
+#if defined(SD9098)
+	if (IS_SD9098(pmadapter->card_type)) {
+		rev_id_reg = pmadapter->pcard_sd->reg->card_revision_reg;
+		ret = pcb->moal_read_reg(pmadapter->pmoal_handle, rev_id_reg,
+					 &revision_id);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "Card Revision register read failed:"
+			       "card_revision_reg=0x%x\n", rev_id_reg);
+			goto done;
+		}
+		/* Skyhawk A0, need to check both CRC and MIC error */
+		if (revision_id >= CHIP_9098_REV_A0)
+			check_fw_status = MTRUE;
+	}
+#endif
+#if defined(SD9097)
+	if (IS_SD9097(pmadapter->card_type))
+		check_fw_status = MTRUE;
+#endif
+#if defined(SD9177)
+	if (IS_SD9177(pmadapter->card_type))
+		check_fw_status = MTRUE;
+#endif
+	/* Perform firmware data transfer */
+	do {
+		/* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits
+		 */
+		ret = wlan_sdio_poll_card_status(pmadapter,
+						 CARD_IO_READY |
+						 DN_LD_CARD_RDY);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MFATAL,
+			       "WLAN: FW download with helper poll status timeout @ %d\n",
+			       offset);
+			goto done;
+		}
+
+		/* More data */
+		if (firmwarelen && offset >= firmwarelen)
+			break;
+
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+						 read_base_0_reg, &base0);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "Dev BASE0 register read failed:"
+				       " base0=0x%04X(%d). Terminating download\n",
+				       base0, base0);
+				goto done;
+			}
+			ret = pcb->moal_read_reg(pmadapter->pmoal_handle,
+						 read_base_1_reg, &base1);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "Dev BASE1 register read failed:"
+				       " base1=0x%04X(%d). Terminating download\n",
+				       base1, base1);
+				goto done;
+			}
+			len = (t_u16)(((base1 & 0xff) << 8) | (base0 & 0xff));
+
+			if (len)
+				break;
+			wlan_udelay(pmadapter, 10);
+		}
+
+		if (!len)
+			break;
+		else if (len > WLAN_UPLD_SIZE) {
+			PRINTM(MFATAL,
+			       "WLAN: FW download failure @ %d, invalid length %d\n",
+			       offset, len);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		/* Ignore CRC check before download the 1st packet */
+		if (offset == 0 && (len & MBIT(0)))
+			len &= ~MBIT(0);
+
+		txlen = len;
+
+		if (len & MBIT(0)) {
+			/* New fw download process, check CRC and MIC error */
+			if (check_fw_status) {
+				/* Get offset from fw dnld offset Register */
+				ret = wlan_sdio_read_fw_dnld_offset(pmadapter,
+								    &fw_dnld_offset);
+				if (ret != MLAN_STATUS_SUCCESS) {
+					PRINTM(MFATAL,
+					       "WLAN: FW download with helper read fw dnld offset failed @ %d\n",
+					       offset);
+					goto done;
+				}
+				/* Get CRC MIC error from fw dnld status
+				 * Register */
+				ret = wlan_sdio_read_fw_dnld_status(pmadapter,
+								    &fw_dnld_status);
+				if (ret != MLAN_STATUS_SUCCESS) {
+					PRINTM(MFATAL,
+					       "WLAN: FW download with helper read fw dnld status failed @ %d\n",
+					       offset);
+					goto done;
+				}
+				PRINTM(MERROR,
+				       "WLAN: FW download error: status=0x%x offset = 0x%x fw offset = 0x%x\n",
+				       fw_dnld_status, offset, fw_dnld_offset);
+			}
+			i++;
+			if (i > MAX_WRITE_IOMEM_RETRY) {
+				PRINTM(MFATAL,
+				       "WLAN: FW download failure @ %d, over max retry count\n",
+				       offset);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+
+			PRINTM(MERROR,
+			       "WLAN: FW CRC error indicated by the helper:"
+			       " len = 0x%04X, txlen = %d\n", len, txlen);
+			len &= ~MBIT(0);
+			if (fw_dnld_status & (MBIT(6) | MBIT(7))) {
+				offset = 0;
+				mic_retry++;
+				if (mic_retry > MAX_FW_RETRY) {
+					PRINTM(MFATAL,
+					       "WLAN: FW download failure @ %d, over max mic retry count\n",
+					       offset);
+					ret = MLAN_STATUS_FAILURE;
+					goto done;
+				}
+			}
+			PRINTM(MERROR, "WLAN: retry: %d, offset %d\n", i,
+			       offset);
+			DBG_HEXDUMP(MERROR, "WLAN: FW block:", fwbuf, len);
+			/* Setting this to 0 to resend from same offset */
+			txlen = 0;
+		} else {
+			i = 0;
+
+			/* Set blocksize to transfer - checking
+			 * for last block */
+			if (firmwarelen && firmwarelen - offset < txlen)
+				txlen = firmwarelen - offset;
+			PRINTM(MINFO, ".");
+
+			tx_blocks = (txlen + MLAN_SDIO_BLOCK_SIZE_FW_DNLD - 1) /
+				MLAN_SDIO_BLOCK_SIZE_FW_DNLD;
+
+			/* Copy payload to buffer */
+			if (firmware)
+				memmove(pmadapter, fwbuf, &firmware[offset],
+					txlen);
+			else
+				pcb->moal_get_fw_data(pmadapter->pmoal_handle,
+						      offset, txlen, fwbuf);
+		}
+
+		/* Send data */
+		memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+		mbuf.pbuf = (t_u8 *)fwbuf;
+		mbuf.data_len = tx_blocks * MLAN_SDIO_BLOCK_SIZE_FW_DNLD;
+
+		ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf,
+						pmadapter->pcard_sd->ioport, 0);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "WLAN: FW download, write iomem (%d) failed @ %d\n",
+			       i, offset);
+			if (pcb->moal_write_reg(pmadapter->pmoal_handle,
+						HOST_TO_CARD_EVENT_REG,
+						HOST_TERM_CMD53) !=
+			    MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "write CFG reg failed\n");
+			}
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		offset += txlen;
+	} while (MTRUE);
+
+	PRINTM(MMSG, "Wlan: FW download over, firmwarelen=%d downloaded %d\n",
+	       firmwarelen, offset);
+
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	if (tmpfwbuf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tmpfwbuf);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function disables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_disable_sdio_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+
+	ENTER();
+	ret = wlan_sdio_disable_host_int_mask(pmadapter, HIM_DISABLE);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function decodes the rx packet &
+ *  calls corresponding handlers according to the packet type
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf      A pointer to the SDIO data/cmd buffer
+ *  @param upld_typ  Type of rx packet
+ *  @param lock_flag  flag for spin_lock.
+ *  @return          MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_decode_rx_packet(mlan_adapter *pmadapter,
+		      mlan_buffer *pmbuf, t_u32 upld_typ, t_u8 lock_flag)
+{
+	t_u8 *cmd_buf;
+	t_u32 event;
+	t_u32 in_ts_sec, in_ts_usec;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	switch (upld_typ) {
+	case MLAN_TYPE_SPA_DATA:
+		PRINTM(MINFO, "--- Rx: SPA Data packet ---\n");
+		pmbuf->data_len = pmadapter->upld_len;
+		if (pmadapter->rx_work_flag) {
+			pmbuf->buf_type = MLAN_BUF_TYPE_SPA_DATA;
+			if (lock_flag)
+				pmadapter->callbacks.moal_spin_lock(pmadapter->
+								    pmoal_handle,
+								    pmadapter->
+								    rx_data_queue.
+								    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			if (lock_flag)
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 pmadapter->
+							 rx_data_queue.plock);
+		} else {
+			wlan_decode_spa_buffer(pmadapter,
+					       pmbuf->pbuf + pmbuf->data_offset,
+					       pmbuf->data_len);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+	case MLAN_TYPE_DATA:
+		PRINTM(MINFO, "--- Rx: Data packet ---\n");
+		if (pmadapter->upld_len > pmbuf->data_len) {
+			PRINTM(MERROR,
+			       "SDIO: Drop packet upld_len=%d data_len=%d \n",
+			       pmadapter->upld_len, pmbuf->data_len);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+			break;
+		}
+		pmbuf->data_len = (pmadapter->upld_len - SDIO_INTF_HEADER_LEN);
+		pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
+		if (pmadapter->rx_work_flag) {
+			//rx_trace 5
+			if (pmadapter->tp_state_on) {
+				pmadapter->callbacks.
+					moal_tp_accounting(pmadapter->
+							   pmoal_handle, pmbuf,
+							   5 /*RX_DROP_P1 */ );
+				pcb->moal_get_system_time(pmadapter->
+							  pmoal_handle,
+							  &in_ts_sec,
+							  &in_ts_usec);
+				pmbuf->in_ts_sec = in_ts_sec;
+				pmbuf->in_ts_usec = in_ts_usec;
+			}
+			if (pmadapter->tp_state_drop_point ==
+			    5 /*RX_DROP_P1 */ ) {
+				pmadapter->ops.data_complete(pmadapter, pmbuf,
+							     MLAN_STATUS_SUCCESS);
+			} else {
+				if (lock_flag)
+					pmadapter->callbacks.
+						moal_spin_lock(pmadapter->
+							       pmoal_handle,
+							       pmadapter->
+							       rx_data_queue.
+							       plock);
+				util_enqueue_list_tail(pmadapter->pmoal_handle,
+						       &pmadapter->
+						       rx_data_queue,
+						       (pmlan_linked_list)pmbuf,
+						       MNULL, MNULL);
+				pmadapter->rx_pkts_queued++;
+				if (pmadapter->tp_state_on)
+					pmadapter->callbacks.
+						moal_tp_accounting_rx_param
+						(pmadapter->pmoal_handle, 1,
+						 pmadapter->rx_pkts_queued);
+				if (lock_flag)
+					pmadapter->callbacks.
+						moal_spin_unlock(pmadapter->
+								 pmoal_handle,
+								 pmadapter->
+								 rx_data_queue.
+								 plock);
+			}
+		} else {
+			wlan_handle_rx_packet(pmadapter, pmbuf);
+		}
+		pmadapter->data_received = MTRUE;
+		break;
+
+	case MLAN_TYPE_CMD:
+		PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
+		if (pmadapter->cmd_sent)
+			pmadapter->cmd_sent = MFALSE;
+		/* take care of curr_cmd = NULL case */
+		if (!pmadapter->curr_cmd) {
+			cmd_buf = pmadapter->upld_buf;
+			if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) {
+				wlan_process_sleep_confirm_resp(pmadapter,
+								pmbuf->pbuf +
+								pmbuf->
+								data_offset +
+								SDIO_INTF_HEADER_LEN,
+								pmadapter->
+								upld_len -
+								SDIO_INTF_HEADER_LEN);
+			}
+			pmadapter->upld_len -= SDIO_INTF_HEADER_LEN;
+			memcpy_ext(pmadapter, cmd_buf,
+				   pmbuf->pbuf + pmbuf->data_offset +
+				   SDIO_INTF_HEADER_LEN,
+				   pmadapter->upld_len - SDIO_INTF_HEADER_LEN,
+				   MRVDRV_SIZE_OF_CMD_BUFFER);
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		} else {
+			pmadapter->cmd_resp_received = MTRUE;
+			pmadapter->upld_len -= SDIO_INTF_HEADER_LEN;
+			pmbuf->data_len = pmadapter->upld_len;
+			pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
+			pmadapter->curr_cmd->respbuf = pmbuf;
+			if (pmadapter->upld_len >= MRVDRV_SIZE_OF_CMD_BUFFER) {
+				PRINTM(MMSG, "Invalid CmdResp len=%d\n",
+				       pmadapter->upld_len);
+				DBG_HEXDUMP(MERROR, "Invalid CmdResp",
+					    pmbuf->pbuf + pmbuf->data_offset,
+					    MAX_DATA_DUMP_LEN);
+			}
+		}
+		break;
+
+	case MLAN_TYPE_EVENT:
+		PRINTM(MINFO, "--- Rx: Event ---\n");
+		event = *(t_u32 *)&pmbuf->pbuf[pmbuf->data_offset +
+					       SDIO_INTF_HEADER_LEN];
+		pmadapter->event_cause = wlan_le32_to_cpu(event);
+		if ((pmadapter->upld_len > MLAN_EVENT_HEADER_LEN) &&
+		    ((pmadapter->upld_len - MLAN_EVENT_HEADER_LEN) <
+		     MAX_EVENT_SIZE)) {
+			memcpy_ext(pmadapter, pmadapter->event_body,
+				   pmbuf->pbuf + pmbuf->data_offset +
+				   MLAN_EVENT_HEADER_LEN,
+				   pmadapter->upld_len - MLAN_EVENT_HEADER_LEN,
+				   MAX_EVENT_SIZE);
+		}
+
+		/* event cause has been saved to adapter->event_cause */
+		pmadapter->event_received = MTRUE;
+		pmbuf->data_len = pmadapter->upld_len;
+		pmadapter->pmlan_buffer_event = pmbuf;
+
+		/* remove SDIO header */
+		pmbuf->data_offset += SDIO_INTF_HEADER_LEN;
+		pmbuf->data_len -= SDIO_INTF_HEADER_LEN;
+		break;
+
+	default:
+		PRINTM(MERROR, "SDIO unknown upload type = 0x%x\n", upld_typ);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		break;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function receives single packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_receive_single_packet(mlan_adapter *pmadapter)
+{
+	mlan_buffer *pmbuf;
+	t_u8 port;
+	t_u16 rx_len;
+	t_u32 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	pmbuf = pmadapter->pcard_sd->mpa_rx.mbuf_arr[0];
+	port = pmadapter->pcard_sd->mpa_rx.start_port;
+	rx_len = pmadapter->pcard_sd->mpa_rx.len_arr[0];
+	if (MLAN_STATUS_SUCCESS !=
+	    wlan_sdio_card_to_host(pmadapter, &pkt_type,
+				   (t_u32 *)&pmadapter->upld_len, pmbuf, rx_len,
+				   pmadapter->pcard_sd->ioport + port)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (pkt_type != MLAN_TYPE_DATA && pkt_type != MLAN_TYPE_SPA_DATA) {
+		PRINTM(MERROR,
+		       "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
+		       pkt_type, pmbuf->data_len);
+		pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pmadapter->pcard_sd->mpa_rx_count[0]++;
+	wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+done:
+	if (ret != MLAN_STATUS_SUCCESS)
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	MP_RX_AGGR_BUF_RESET(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function receives data from the card in aggregate mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_receive_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf_aggr;
+	mlan_buffer *mbuf_deaggr;
+	t_u32 pind = 0;
+	t_u32 pkt_len, pkt_type = 0;
+	t_u8 *curr_ptr;
+	t_u32 cmd53_port = 0;
+	t_u32 i = 0;
+	t_u32 port_count = 0;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	/* do aggr RX now */
+	PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n",
+	       pmadapter->pcard_sd->mpa_rx.pkt_cnt);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (pmadapter->pcard_sd->mpa_rx.pkt_cnt == 1)
+		return wlan_receive_single_packet(pmadapter);
+	if (!pmadapter->pcard_sd->mpa_rx.buf) {
+		mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_rx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+		     pind++) {
+			pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind]->data_len =
+				pmadapter->pcard_sd->mpa_rx.len_arr[pind];
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->pcard_sd->mpa_rx.
+					      mbuf_arr[pind]);
+		}
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->pcard_sd->mpa_rx.buf;
+		mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_rx.buf_len;
+	}
+
+	if (new_mode) {
+		port_count = bitcount(pmadapter->pcard_sd->mpa_rx.ports) - 1;
+		/* port_count = pmadapter->mpa_rx.pkt_cnt - 1; */
+		cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
+			      (port_count << 8)) +
+			pmadapter->pcard_sd->mpa_rx.start_port;
+	} else {
+		cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
+			      (pmadapter->pcard_sd->mpa_rx.ports << 4)) +
+			pmadapter->pcard_sd->mpa_rx.start_port;
+	}
+	do {
+		ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle,
+					       &mbuf_aggr, cmd53_port, 0);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "wlan: sdio mp cmd53 read failed: %d ioport=0x%x retry=%d\n",
+			       ret, cmd53_port, i);
+			i++;
+			if (MLAN_STATUS_SUCCESS !=
+			    pcb->moal_write_reg(pmadapter->pmoal_handle,
+						HOST_TO_CARD_EVENT_REG,
+						HOST_TERM_CMD53)) {
+				PRINTM(MERROR, "Set Term cmd53 failed\n");
+			}
+			if (i > MAX_WRITE_IOMEM_RETRY) {
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+	} while (ret == MLAN_STATUS_FAILURE);
+	if (pmadapter->rx_work_flag)
+		pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+						    pmadapter->rx_data_queue.
+						    plock);
+	if (!pmadapter->pcard_sd->mpa_rx.buf &&
+	    pmadapter->pcard_sd->mpa_rx.pkt_cnt > 1) {
+		for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+		     pind++) {
+			mbuf_deaggr =
+				pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind];
+			pkt_len =
+				wlan_le16_to_cpu(*(t_u16 *)
+						 (mbuf_deaggr->pbuf +
+						  mbuf_deaggr->data_offset));
+			pkt_type =
+				wlan_le16_to_cpu(*(t_u16 *)
+						 (mbuf_deaggr->pbuf +
+						  mbuf_deaggr->data_offset +
+						  2));
+			pmadapter->upld_len = pkt_len;
+			wlan_decode_rx_packet(pmadapter, mbuf_deaggr, pkt_type,
+					      MFALSE);
+		}
+	} else {
+		DBG_HEXDUMP(MIF_D, "SDIO MP-A Blk Rd",
+			    pmadapter->pcard_sd->mpa_rx.buf,
+			    MIN(pmadapter->pcard_sd->mpa_rx.buf_len,
+				MAX_DATA_DUMP_LEN));
+
+		curr_ptr = pmadapter->pcard_sd->mpa_rx.buf;
+
+		for (pind = 0; pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+		     pind++) {
+			/* get curr PKT len & type */
+			pkt_len = wlan_le16_to_cpu(*(t_u16 *)&curr_ptr[0]);
+			pkt_type = wlan_le16_to_cpu(*(t_u16 *)&curr_ptr[2]);
+
+			PRINTM(MINFO, "RX: [%d] pktlen: %d pkt_type: 0x%x\n",
+			       pind, pkt_len, pkt_type);
+
+			/* copy pkt to deaggr buf */
+			mbuf_deaggr =
+				pmadapter->pcard_sd->mpa_rx.mbuf_arr[pind];
+			if ((pkt_type == MLAN_TYPE_DATA
+			     || pkt_type == MLAN_TYPE_SPA_DATA) &&
+			    (pkt_len <=
+			     pmadapter->pcard_sd->mpa_rx.len_arr[pind])) {
+				memcpy_ext(pmadapter,
+					   mbuf_deaggr->pbuf +
+					   mbuf_deaggr->data_offset,
+					   curr_ptr, pkt_len, pkt_len);
+				pmadapter->upld_len = pkt_len;
+				/* Process de-aggr packet */
+				wlan_decode_rx_packet(pmadapter, mbuf_deaggr,
+						      pkt_type, MFALSE);
+			} else {
+				PRINTM(MERROR,
+				       "Wrong aggr packet: type=%d, len=%d, max_len=%d\n",
+				       pkt_type, pkt_len,
+				       pmadapter->pcard_sd->mpa_rx.
+				       len_arr[pind]);
+				wlan_free_mlan_buffer(pmadapter, mbuf_deaggr);
+			}
+			curr_ptr += pmadapter->pcard_sd->mpa_rx.len_arr[pind];
+		}
+	}
+	if (pmadapter->rx_work_flag)
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      pmadapter->rx_data_queue.
+						      plock);
+	pmadapter->pcard_sd->mpa_rx_count[pmadapter->pcard_sd->mpa_rx.pkt_cnt -
+					  1]++;
+	MP_RX_AGGR_BUF_RESET(pmadapter);
+done:
+	return ret;
+}
+
+/**
+ *  @brief This function receives data from the card in aggregate mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf      A pointer to the SDIO data/cmd buffer
+ *  @param port      Current port on which packet needs to be rxed
+ *  @param rx_len    Length of received packet
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_card_to_host_mp_aggr(mlan_adapter *pmadapter,
+			       mlan_buffer *pmbuf, t_u8 port, t_u16 rx_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_s32 f_do_rx_aggr = 0;
+	t_s32 f_do_rx_cur = 0;
+	t_s32 f_aggr_cur = 0;
+	t_s32 f_post_aggr_cur = 0;
+	t_u32 pind = 0;
+	t_u32 pkt_type = 0;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+	if (!new_mode && (port == CTRL_PORT)) {
+		/* Read the command response or event without aggr */
+		PRINTM(MINFO,
+		       "card_2_host_mp_aggr: No aggr for control port\n");
+
+		f_do_rx_cur = 1;
+		goto rx_curr_single;
+	}
+
+	if (!pmadapter->pcard_sd->mpa_rx.enabled) {
+		PRINTM(MINFO,
+		       "card_2_host_mp_aggr: rx aggregation disabled !\n");
+
+		f_do_rx_cur = 1;
+		goto rx_curr_single;
+	}
+	if ((new_mode &&
+	     (pmadapter->pcard_sd->mp_rd_bitmap & reg->data_port_mask))
+	    || (!new_mode &&
+		(pmadapter->pcard_sd->
+		 mp_rd_bitmap & (~((t_u32)CTRL_PORT_MASK))))
+		) {
+		/* Some more data RX pending */
+		PRINTM(MINFO, "card_2_host_mp_aggr: Not last packet\n");
+
+		if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+			if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) {
+				f_aggr_cur = 1;
+			} else {
+				/* No room in Aggr buf, do rx aggr now */
+				f_do_rx_aggr = 1;
+				f_post_aggr_cur = 1;
+			}
+		} else {
+			/* Rx aggr not in progress */
+			f_aggr_cur = 1;
+		}
+
+	} else {
+		/* No more data RX pending */
+		PRINTM(MINFO, "card_2_host_mp_aggr: Last packet\n");
+
+		if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+			f_do_rx_aggr = 1;
+			if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) {
+				f_aggr_cur = 1;
+			} else {
+				/* No room in Aggr buf, do rx aggr now */
+				f_do_rx_cur = 1;
+			}
+		} else {
+			f_do_rx_cur = 1;
+		}
+	}
+
+	if (f_aggr_cur) {
+		PRINTM(MINFO, "Current packet aggregation.\n");
+		/* Curr pkt can be aggregated */
+		if (new_mode)
+			MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
+		else
+			MP_RX_AGGR_SETUP_NONEWMODE(pmadapter, pmbuf, port,
+						   rx_len);
+		if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
+		    ((new_mode && MP_RX_AGGR_PORT_LIMIT_REACHED(pmadapter))
+		     || (!new_mode &&
+			 MP_RX_AGGR_PORT_LIMIT_REACHED_NONEWMODE(pmadapter))
+		    )) {
+			PRINTM(MINFO,
+			       "card_2_host_mp_aggr: Aggregation Packet limit reached\n");
+			/* No more pkts allowed in Aggr buf, rx it */
+			f_do_rx_aggr = 1;
+		}
+	}
+
+	if (f_do_rx_aggr) {
+		/* do aggr RX now */
+		if (MLAN_STATUS_SUCCESS != wlan_receive_mp_aggr_buf(pmadapter)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+rx_curr_single:
+	if (f_do_rx_cur) {
+		PRINTM(MINFO, "RX: f_do_rx_cur: port: %d rx_len: %d\n", port,
+		       rx_len);
+
+		if (MLAN_STATUS_SUCCESS !=
+		    wlan_sdio_card_to_host(pmadapter, &pkt_type,
+					   (t_u32 *)&pmadapter->upld_len, pmbuf,
+					   rx_len,
+					   pmadapter->pcard_sd->ioport +
+					   port)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if (!new_mode &&
+		    ((port == CTRL_PORT) &&
+		     ((pkt_type != MLAN_TYPE_EVENT) &&
+		      (pkt_type != MLAN_TYPE_CMD)))) {
+			PRINTM(MERROR,
+			       "Wrong pkt from CTRL PORT: type=%d, len=%dd\n",
+			       pkt_type, pmbuf->data_len);
+			pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		if (new_mode || (port != CTRL_PORT)
+			) {
+			if (pkt_type != MLAN_TYPE_DATA
+			    && pkt_type != MLAN_TYPE_SPA_DATA) {
+				PRINTM(MERROR,
+				       "receive a wrong pkt from DATA PORT: type=%d, len=%dd\n",
+				       pkt_type, pmbuf->data_len);
+				pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL;
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+
+		if (new_mode || (port != CTRL_PORT)
+			)
+			pmadapter->pcard_sd->mpa_rx_count[0]++;
+
+		wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type, MTRUE);
+	}
+	if (f_post_aggr_cur) {
+		PRINTM(MINFO, "Current packet aggregation.\n");
+		/* Curr pkt can be aggregated */
+		if (new_mode)
+			MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len);
+		else
+			MP_RX_AGGR_SETUP_NONEWMODE(pmadapter, pmbuf, port,
+						   rx_len);
+	}
+done:
+	if (ret == MLAN_STATUS_FAILURE) {
+		if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+			/* MP-A transfer failed - cleanup */
+			for (pind = 0;
+			     pind < pmadapter->pcard_sd->mpa_rx.pkt_cnt;
+			     pind++) {
+				wlan_free_mlan_buffer(pmadapter,
+						      pmadapter->pcard_sd->
+						      mpa_rx.mbuf_arr[pind]);
+			}
+			MP_RX_AGGR_BUF_RESET(pmadapter);
+		}
+
+		if (f_do_rx_cur) {
+			/* Single Transfer pending */
+			/* Free curr buff also */
+			wlan_free_mlan_buffer(pmadapter, pmbuf);
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends aggr buf
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_send_mp_aggr_buf(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 cmd53_port = 0;
+	t_u32 port_count = 0;
+	mlan_buffer mbuf_aggr;
+	t_u8 i = 0;
+	t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+
+	if (!pmadapter->pcard_sd->mpa_tx.pkt_cnt) {
+		LEAVE();
+		return ret;
+	}
+	PRINTM(MINFO,
+	       "host_2_card_mp_aggr: Send aggregation buffer."
+	       "%d %d\n",
+	       pmadapter->pcard_sd->mpa_tx.start_port,
+	       pmadapter->pcard_sd->mpa_tx.ports);
+
+	memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));
+
+	if (!pmadapter->pcard_sd->mpa_tx.buf &&
+	    pmadapter->pcard_sd->mpa_tx.pkt_cnt > 1) {
+		mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_tx.buf_len;
+		mbuf_aggr.pnext = mbuf_aggr.pprev = &mbuf_aggr;
+		mbuf_aggr.use_count = 0;
+		for (i = 0; i < pmadapter->pcard_sd->mpa_tx.pkt_cnt; i++)
+			wlan_link_buf_to_aggr(&mbuf_aggr,
+					      pmadapter->pcard_sd->mpa_tx.
+					      mbuf_arr[i]);
+	} else {
+		mbuf_aggr.pbuf = (t_u8 *)pmadapter->pcard_sd->mpa_tx.buf;
+		mbuf_aggr.data_len = pmadapter->pcard_sd->mpa_tx.buf_len;
+	}
+
+	if (new_mode) {
+		port_count = bitcount(pmadapter->pcard_sd->mpa_tx.ports) - 1;
+		cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
+			      (port_count << 8)) +
+			pmadapter->pcard_sd->mpa_tx.start_port;
+	} else {
+		cmd53_port = (pmadapter->pcard_sd->ioport | SDIO_MPA_ADDR_BASE |
+			      (pmadapter->pcard_sd->mpa_tx.ports << 4)) +
+			pmadapter->pcard_sd->mpa_tx.start_port;
+	}
+	if (pmadapter->pcard_sd->mpa_tx.pkt_cnt == 1)
+		cmd53_port = pmadapter->pcard_sd->ioport +
+			pmadapter->pcard_sd->mpa_tx.start_port;
+	/** only one packet */
+	if (!pmadapter->pcard_sd->mpa_tx.buf &&
+	    pmadapter->pcard_sd->mpa_tx.pkt_cnt == 1)
+		ret = wlan_write_data_sync(pmadapter,
+					   pmadapter->pcard_sd->mpa_tx.
+					   mbuf_arr[0], cmd53_port);
+	else
+		ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
+	if (!pmadapter->pcard_sd->mpa_tx.buf) {
+		/** free mlan buffer */
+		for (i = 0; i < pmadapter->pcard_sd->mpa_tx.pkt_cnt; i++) {
+			wlan_write_data_complete(pmadapter,
+						 pmadapter->pcard_sd->mpa_tx.
+						 mbuf_arr[i],
+						 MLAN_STATUS_SUCCESS);
+		}
+	}
+	if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+	      (1 << pmadapter->pcard_sd->curr_wr_port)) &&
+	    (pmadapter->pcard_sd->mpa_tx.pkt_cnt < mp_aggr_pkt_limit))
+		pmadapter->pcard_sd->mpa_sent_no_ports++;
+	pmadapter->pcard_sd->mpa_tx_count[pmadapter->pcard_sd->mpa_tx.pkt_cnt -
+					  1]++;
+	pmadapter->pcard_sd->last_mp_wr_bitmap[pmadapter->pcard_sd->
+					       last_mp_index] =
+		pmadapter->pcard_sd->mp_wr_bitmap;
+	pmadapter->pcard_sd->last_mp_wr_ports[pmadapter->pcard_sd->
+					      last_mp_index] = cmd53_port;
+	pmadapter->pcard_sd->last_mp_wr_len[pmadapter->pcard_sd->
+					    last_mp_index] =
+		pmadapter->pcard_sd->mpa_tx.buf_len;
+	pmadapter->pcard_sd->last_curr_wr_port[pmadapter->pcard_sd->
+					       last_mp_index] =
+		pmadapter->pcard_sd->curr_wr_port;
+	memcpy_ext(pmadapter,
+		   (t_u8 *)&pmadapter->pcard_sd->last_mp_wr_info[pmadapter->
+								 pcard_sd->
+								 last_mp_index *
+								 mp_aggr_pkt_limit],
+		   (t_u8 *)pmadapter->pcard_sd->mpa_tx.mp_wr_info,
+		   mp_aggr_pkt_limit * sizeof(t_u16),
+		   mp_aggr_pkt_limit * sizeof(t_u16));
+	pmadapter->pcard_sd->last_mp_index++;
+	if (pmadapter->pcard_sd->last_mp_index >= SDIO_MP_DBG_NUM)
+		pmadapter->pcard_sd->last_mp_index = 0;
+	MP_TX_AGGR_BUF_RESET(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card in SDIO aggregated mode.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param mbuf      A pointer to the SDIO data/cmd buffer
+ *  @param port	     current port for aggregation
+ *  @param next_pkt_len Length of next packet used for multiport aggregation
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_host_to_card_mp_aggr(mlan_adapter *pmadapter,
+			  mlan_buffer *mbuf, t_u8 port, t_u32 next_pkt_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_s32 f_send_aggr_buf = 0;
+	t_s32 f_send_cur_buf = 0;
+	t_s32 f_precopy_cur_buf = 0;
+	t_s32 f_postcopy_cur_buf = 0;
+	t_u8 aggr_sg = 0;
+	t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+
+	PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
+	       next_pkt_len, port);
+
+	if (!pmadapter->pcard_sd->mpa_tx.enabled) {
+		PRINTM(MINFO,
+		       "host_2_card_mp_aggr: tx aggregation disabled !\n");
+		f_send_cur_buf = 1;
+		goto tx_curr_single;
+	}
+
+	if (next_pkt_len) {
+		/* More pkt in TX queue */
+		PRINTM(MINFO, "host_2_card_mp_aggr: More packets in Queue.\n");
+
+		if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
+			if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+						    mbuf->data_len)) {
+				f_precopy_cur_buf = 1;
+
+				if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+				      (1
+				       << pmadapter->pcard_sd->curr_wr_port)) ||
+				    !MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+							     mbuf->data_len +
+							     next_pkt_len)) {
+					f_send_aggr_buf = 1;
+				}
+			} else {
+				/* No room in Aggr buf, send it */
+				f_send_aggr_buf = 1;
+
+				if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+				      (1
+				       << pmadapter->pcard_sd->curr_wr_port))) {
+					f_send_cur_buf = 1;
+				} else {
+					f_postcopy_cur_buf = 1;
+				}
+			}
+		} else {
+			if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+						    mbuf->data_len) &&
+			    (pmadapter->pcard_sd->mp_wr_bitmap &
+			     (1 << pmadapter->pcard_sd->curr_wr_port)))
+				f_precopy_cur_buf = 1;
+			else
+				f_send_cur_buf = 1;
+		}
+	} else {
+		/* Last pkt in TX queue */
+		PRINTM(MINFO,
+		       "host_2_card_mp_aggr: Last packet in Tx Queue.\n");
+
+		if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
+			/* some packs in Aggr buf already */
+			f_send_aggr_buf = 1;
+
+			if (MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
+						    mbuf->data_len)) {
+				f_precopy_cur_buf = 1;
+			} else {
+				/* No room in Aggr buf, send it */
+				f_send_cur_buf = 1;
+			}
+		} else {
+			f_send_cur_buf = 1;
+		}
+		pmadapter->pcard_sd->mpa_sent_last_pkt++;
+	}
+
+	if (f_precopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
+		if (pmadapter->pcard_sd->mpa_buf)
+			memcpy_ext(pmadapter,
+				   pmadapter->pcard_sd->mpa_buf +
+				   (pmadapter->pcard_sd->last_mp_index *
+				    mp_aggr_pkt_limit +
+				    pmadapter->pcard_sd->mpa_tx.pkt_cnt) *
+				   MLAN_SDIO_BLOCK_SIZE,
+				   mbuf->pbuf + mbuf->data_offset,
+				   MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->pcard_sd->mpa_tx.buf) {
+			if (new_mode)
+				MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
+			else
+				MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
+								port);
+			aggr_sg = MTRUE;
+		} else {
+			if (new_mode)
+				MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
+			else
+				MP_TX_AGGR_BUF_PUT_NONEWMODE(pmadapter, mbuf,
+							     port);
+		}
+		if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter)
+		    || (!new_mode && MP_TX_AGGR_PORT_LIMIT_REACHED(pmadapter))
+			) {
+			PRINTM(MIF_D,
+			       "host_2_card_mp_aggr: Aggregation Pkt limit reached\n");
+			/* No more pkts allowed in Aggr buf, send it */
+			f_send_aggr_buf = 1;
+		}
+	}
+
+	if (f_send_aggr_buf)
+		ret = wlan_send_mp_aggr_buf(pmadapter);
+
+tx_curr_single:
+	if (f_send_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: writing to port #%d\n",
+		       port);
+		ret = wlan_write_data_sync(pmadapter, mbuf,
+					   pmadapter->pcard_sd->ioport + port);
+		if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+		      (1 << pmadapter->pcard_sd->curr_wr_port)))
+			pmadapter->pcard_sd->mpa_sent_no_ports++;
+		pmadapter->pcard_sd->last_mp_wr_bitmap[pmadapter->pcard_sd->
+						       last_mp_index] =
+			pmadapter->pcard_sd->mp_wr_bitmap;
+		pmadapter->pcard_sd->last_mp_wr_ports[pmadapter->pcard_sd->
+						      last_mp_index] =
+			pmadapter->pcard_sd->ioport + port;
+		pmadapter->pcard_sd->last_mp_wr_len[pmadapter->pcard_sd->
+						    last_mp_index] =
+			mbuf->data_len;
+		memset(pmadapter,
+		       (t_u8 *)&pmadapter->pcard_sd->last_mp_wr_info[pmadapter->
+								     pcard_sd->
+								     last_mp_index
+								     *
+								     mp_aggr_pkt_limit],
+		       0, sizeof(t_u16) * mp_aggr_pkt_limit);
+		pmadapter->pcard_sd->last_mp_wr_info[pmadapter->pcard_sd->
+						     last_mp_index *
+						     mp_aggr_pkt_limit] =
+			*(t_u16 *)(mbuf->pbuf + mbuf->data_offset);
+		pmadapter->pcard_sd->last_curr_wr_port[pmadapter->pcard_sd->
+						       last_mp_index] =
+			pmadapter->pcard_sd->curr_wr_port;
+		if (pmadapter->pcard_sd->mpa_buf)
+			memcpy_ext(pmadapter,
+				   pmadapter->pcard_sd->mpa_buf +
+				   (pmadapter->pcard_sd->last_mp_index *
+				    mp_aggr_pkt_limit *
+				    MLAN_SDIO_BLOCK_SIZE),
+				   mbuf->pbuf + mbuf->data_offset,
+				   MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
+		pmadapter->pcard_sd->last_mp_index++;
+		if (pmadapter->pcard_sd->last_mp_index >= SDIO_MP_DBG_NUM)
+			pmadapter->pcard_sd->last_mp_index = 0;
+		pmadapter->pcard_sd->mpa_tx_count[0]++;
+	}
+	if (f_postcopy_cur_buf) {
+		PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
+		if (pmadapter->pcard_sd->mpa_buf)
+			memcpy_ext(pmadapter,
+				   pmadapter->pcard_sd->mpa_buf +
+				   (pmadapter->pcard_sd->last_mp_index *
+				    mp_aggr_pkt_limit +
+				    pmadapter->pcard_sd->mpa_tx.pkt_cnt) *
+				   MLAN_SDIO_BLOCK_SIZE,
+				   mbuf->pbuf + mbuf->data_offset,
+				   MLAN_SDIO_BLOCK_SIZE, MLAN_SDIO_BLOCK_SIZE);
+		if (!pmadapter->pcard_sd->mpa_tx.buf) {
+			if (new_mode)
+				MP_TX_AGGR_BUF_PUT_SG(pmadapter, mbuf, port);
+			else
+				MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(pmadapter, mbuf,
+								port);
+			aggr_sg = MTRUE;
+		} else {
+			if (new_mode)
+				MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
+			else
+				MP_TX_AGGR_BUF_PUT_NONEWMODE(pmadapter, mbuf,
+							     port);
+		}
+	}
+	/* Always return PENDING in SG mode */
+	if (aggr_sg)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+		Global functions
+********************************************************/
+
+/**
+ *  @brief This function checks if the interface is ready to download
+ *  or not while other download interface is present
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param val        Winner status (0: winner)
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ *
+ */
+static mlan_status
+wlan_sdio_check_winner_status(mlan_adapter *pmadapter, t_u32 *val)
+{
+	t_u32 winner = 0;
+	pmlan_callbacks pcb;
+	t_u8 card_winner_check_reg = pmadapter->pcard_sd->reg->winner_check_reg;
+
+	ENTER();
+
+#ifdef SD8801
+	if (IS_SD8801(pmadapter->card_type)) {
+		*val = 0;
+		return MLAN_STATUS_SUCCESS;
+	}
+#endif
+	pcb = &pmadapter->callbacks;
+
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      card_winner_check_reg,
+						      &winner)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	*val = winner;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function checks if the firmware is ready to accept
+ *  command or not.
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param pollnum    Maximum polling number
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_check_fw_status(mlan_adapter *pmadapter, t_u32 pollnum)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 firmwarestat = 0;
+	t_u32 tries;
+
+	ENTER();
+
+	/* Wait for firmware initialization event */
+	for (tries = 0; tries < pollnum; tries++) {
+		ret = wlan_sdio_read_fw_status(pmadapter, &firmwarestat);
+		if (MLAN_STATUS_SUCCESS != ret)
+			continue;
+		if (firmwarestat == SDIO_FIRMWARE_READY) {
+			ret = MLAN_STATUS_SUCCESS;
+			break;
+		} else {
+			wlan_mdelay(pmadapter, 100);
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+
+	if (ret != MLAN_STATUS_SUCCESS) {
+		if (pollnum > 1)
+			PRINTM(MERROR,
+			       "Fail to poll firmware status: firmwarestat=0x%x\n",
+			       firmwarestat);
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function enables the host interrupts.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_enable_sdio_host_int(pmlan_adapter pmadapter)
+{
+	mlan_status ret;
+	t_u8 mask = pmadapter->pcard_sd->reg->host_int_enable;
+
+	ENTER();
+	ret = wlan_sdio_enable_host_int_mask(pmadapter, mask);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function downloads firmware to card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_dnld_fw(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 poll_num = 1;
+	t_u32 winner = 0;
+
+	ENTER();
+
+/*when using GPIO wakeup, don't run the below code.
+ *if using GPIO wakeup, host will do handshake with FW
+ *to check if FW wake up and pull up SDIO line, then reload driver.
+ *So when using GPIO wakeup, don't need driver to do check wakeup status again.
+ *when using SDIO interface wakeup, run the below code;
+ *if using SDIO interface wakeup, driver need to do check wakeup status with FW.
+ */
+
+	/* Card specific probing */
+	ret = wlan_sdio_probe(pmadapter);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR, "WLAN SDIO probe failed\n", ret);
+		LEAVE();
+		return ret;
+	}
+
+	/* Check if firmware is already running */
+	ret = wlan_sdio_check_fw_status(pmadapter, poll_num);
+	if (ret == MLAN_STATUS_SUCCESS) {
+#if defined(SDIO)
+		if (pmfw->fw_reload == FW_RELOAD_SDIO_INBAND_RESET) {
+			PRINTM(MMSG, "Try reset fw in mlan\n");
+			ret = wlan_reset_fw(pmadapter);
+			if (ret == MLAN_STATUS_FAILURE) {
+				PRINTM(MERROR, "FW reset failure!");
+				LEAVE();
+				return ret;
+			}
+		} else {
+#endif
+			PRINTM(MMSG,
+			       "WLAN FW already running! Skip FW download\n");
+#if defined(SDIO)
+			pmadapter->ops.wakeup_card(pmadapter, MFALSE);
+#endif
+			goto done;
+#if defined(SDIO)
+		}
+#endif
+	}
+	poll_num = MAX_FIRMWARE_POLL_TRIES;
+	/* Check if other interface is downloading */
+	ret = wlan_sdio_check_winner_status(pmadapter, &winner);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MFATAL, "WLAN read winner status failed!\n");
+		goto done;
+	}
+	if (winner) {
+		PRINTM(MMSG,
+		       "WLAN is not the winner (0x%x). Skip FW download\n",
+		       winner);
+		poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
+		goto poll_fw;
+	}
+
+	/* Download the firmware image via helper */
+	ret = wlan_sdio_prog_fw_w_helper(pmadapter, pmfw->pfw_buf,
+					 pmfw->fw_len);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
+		LEAVE();
+		return ret;
+	}
+
+poll_fw:
+	/* Check if the firmware is downloaded successfully or not */
+	ret = wlan_sdio_check_fw_status(pmadapter, poll_num);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "FW failed to be active in time!\n");
+		ret = MLAN_STATUS_FAILURE;
+		LEAVE();
+		return ret;
+	}
+#ifdef SD9177
+	if (IS_SD9177(pmadapter->card_type))
+		wlan_mdelay(pmadapter, 1000);
+#endif
+done:
+
+	/* re-enable host interrupt for mlan after fw dnld is successful */
+	wlan_enable_sdio_host_int(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function probes the driver
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_sdio_probe(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 sdio_ireg = 0;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+	/*
+	 * Read the HOST_INT_STATUS_REG for ACK the first interrupt got
+	 * from the bootloader. If we don't do this we get a interrupt
+	 * as soon as we register the irq.
+	 */
+	pcb->moal_read_reg(pmadapter->pmoal_handle,
+			   pmadapter->pcard_sd->reg->host_int_status_reg,
+			   &sdio_ireg);
+
+	/* Disable host interrupt mask register for SDIO */
+	ret = wlan_disable_sdio_host_int(pmadapter);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Get SDIO ioport */
+	ret = wlan_sdio_init_ioport(pmadapter);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function get sdio device from card type
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_get_sdio_device(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 card_type = pmadapter->card_type;
+
+	ENTER();
+
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_sdio_card),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->pcard_sd);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_sd) {
+		PRINTM(MERROR, "Failed to allocate pcard_sd\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter->pcard_sd->max_ports = MAX_PORT;
+	pmadapter->pcard_sd->mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
+	pmadapter->pcard_sd->supports_sdio_new_mode = MTRUE;
+	pmadapter->pcard_sd->mp_tx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
+	pmadapter->pcard_sd->mp_rx_aggr_buf_size = SDIO_MP_AGGR_BUF_SIZE_MAX;
+
+	switch (card_type) {
+#ifdef SD8801
+	case CARD_TYPE_SD8801:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8801;
+		pmadapter->pcard_info = &mlan_card_info_sd8801;
+		pmadapter->pcard_sd->max_ports = MAX_PORT_16;
+		pmadapter->pcard_sd->mp_aggr_pkt_limit =
+			SDIO_MP_AGGR_DEF_PKT_LIMIT_8;
+		pmadapter->pcard_sd->supports_sdio_new_mode = MFALSE;
+		pmadapter->pcard_sd->mp_tx_aggr_buf_size =
+			SDIO_MP_AGGR_BUF_SIZE_32K;
+		pmadapter->pcard_sd->mp_rx_aggr_buf_size =
+			SDIO_MP_AGGR_BUF_SIZE_32K;
+		break;
+#endif
+#ifdef SD8887
+	case CARD_TYPE_SD8887:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8887;
+		pmadapter->pcard_info = &mlan_card_info_sd8887;
+		break;
+#endif
+#ifdef SD8897
+	case CARD_TYPE_SD8897:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8897;
+		pmadapter->pcard_info = &mlan_card_info_sd8897;
+		break;
+#endif
+#if defined(SD8977) || defined(SD8978)
+	case CARD_TYPE_SD8977:
+	case CARD_TYPE_SD8978:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+		pmadapter->pcard_info = &mlan_card_info_sd8977;
+		break;
+#endif
+#ifdef SD8997
+	case CARD_TYPE_SD8997:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+		pmadapter->pcard_info = &mlan_card_info_sd8997;
+		break;
+#endif
+#ifdef SD8987
+	case CARD_TYPE_SD8987:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+		pmadapter->pcard_info = &mlan_card_info_sd8987;
+		break;
+#endif
+#ifdef SD9098
+	case CARD_TYPE_SD9098:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+		pmadapter->pcard_info = &mlan_card_info_sd9098;
+		break;
+#endif
+#ifdef SD9097
+	case CARD_TYPE_SD9097:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+		pmadapter->pcard_info = &mlan_card_info_sd9097;
+		break;
+#endif
+#ifdef SD9177
+	case CARD_TYPE_SD9177:
+		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
+		pmadapter->pcard_info = &mlan_card_info_sd9177;
+		break;
+#endif
+	default:
+		PRINTM(MERROR, "can't get right card type \n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function dump the mp registers when issue happened
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             N/A
+ */
+void
+wlan_dump_mp_registers(pmlan_adapter pmadapter)
+{
+	t_u32 mp_wr_bitmap;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+	t_u32 mp_rd_bitmap;
+	t_u16 rx_len = 0;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	t_u8 cmd_rd_len_0 = reg->cmd_rd_len_0;
+	t_u8 cmd_rd_len_1 = reg->cmd_rd_len_1;
+	t_u8 host_int_status_reg = reg->host_int_status_reg;
+	t_u32 sdio_ireg = 0;
+
+	mp_wr_bitmap = (t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l];
+	mp_wr_bitmap |= ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_u])
+		<< 8;
+	if (new_mode) {
+		mp_wr_bitmap |=
+			((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1l])
+			<< 16;
+		mp_wr_bitmap |=
+			((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1u])
+			<< 24;
+	}
+	PRINTM(MMSG, "wlan: mp_data_port_mask = 0x%x\n",
+	       pmadapter->pcard_sd->mp_data_port_mask);
+	PRINTM(MMSG, "wlan: HW wr_bitmap=0x%08x Host: wr_bitmap=0x%08x\n",
+	       mp_wr_bitmap, pmadapter->pcard_sd->mp_wr_bitmap);
+	mp_rd_bitmap = (t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_l];
+	mp_rd_bitmap |= ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_u])
+		<< 8;
+	if (new_mode) {
+		mp_rd_bitmap |=
+			((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1l])
+			<< 16;
+		mp_rd_bitmap |=
+			((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1u])
+			<< 24;
+	}
+	PRINTM(MMSG, "wlan: HW rd_bitmap=0x%08x Host: rd_bitmap=0x%08x\n",
+	       mp_rd_bitmap, pmadapter->pcard_sd->mp_rd_bitmap);
+
+	if (new_mode) {
+		rx_len = ((t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_1])
+			<< 8;
+		rx_len |= (t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_0];
+		PRINTM(MMSG, "wlan: cmd rx buffer rx_len = %d\n", rx_len);
+	}
+	PRINTM(MMSG, "wlan: HW sdio_ireg = 0x%x\n",
+	       pmadapter->pcard_sd->mp_regs[host_int_status_reg]);
+	sdio_ireg = pmadapter->pcard_sd->mp_regs[host_int_status_reg];
+
+	if (new_mode && rx_len)
+		sdio_ireg |= UP_LD_CMD_PORT_HOST_INT_STATUS;
+
+	if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+	      pmadapter->pcard_sd->mp_data_port_mask)) {
+		if (mp_wr_bitmap & pmadapter->pcard_sd->mp_data_port_mask)
+			sdio_ireg |= DN_LD_HOST_INT_STATUS;
+	}
+
+	if ((!pmadapter->pcard_sd->mp_rd_bitmap) && mp_rd_bitmap)
+		sdio_ireg |= UP_LD_HOST_INT_STATUS;
+
+	pmadapter->pcard_sd->mp_regs[host_int_status_reg] = sdio_ireg;
+	PRINTM(MMSG, "wlan: recovered sdio_ireg=0x%x\n", sdio_ireg);
+	return;
+}
+
+/**
+ *  @brief This function gets interrupt status.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_sdio_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf;
+	t_u32 sdio_ireg = 0;
+	t_u8 offset = 0;
+	t_u8 i = 0;
+	int max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs;
+	t_u8 host_int_status_reg =
+		pmadapter->pcard_sd->reg->host_int_status_reg;
+
+	ENTER();
+
+	while (max_mp_regs) {
+		memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+		mbuf.pbuf = pmadapter->pcard_sd->mp_regs + offset;
+		mbuf.data_len = MIN(max_mp_regs, MLAN_SDIO_BLOCK_SIZE);
+		do {
+			ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle,
+						       &mbuf,
+						       (REG_PORT +
+							offset) |
+						       MLAN_SDIO_BYTE_MODE_MASK,
+						       0);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "wlan: cmd53 read regs failed: %d port=%x retry=%d\n",
+				       ret, REG_PORT + offset, i);
+				i++;
+				pcb->moal_write_reg(pmadapter->pmoal_handle,
+						    HOST_TO_CARD_EVENT_REG,
+						    HOST_TERM_CMD53);
+				if (i > MAX_WRITE_IOMEM_RETRY) {
+					PRINTM(MERROR,
+					       "wlan: Fail to read mp_regs\n");
+					pmadapter->dbg.num_int_read_failure++;
+					goto done;
+				}
+			}
+		} while (ret == MLAN_STATUS_FAILURE);
+		offset += mbuf.data_len;
+		max_mp_regs -= mbuf.data_len;
+	}
+	if (i > 0)
+		wlan_dump_mp_registers(pmadapter);
+
+	DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->pcard_sd->mp_regs,
+		    max_mp_regs);
+	sdio_ireg = pmadapter->pcard_sd->mp_regs[host_int_status_reg];
+	pmadapter->dbg.last_int_status = pmadapter->ireg | sdio_ireg;
+	if (sdio_ireg) {
+		/*
+		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+		 * DN_LD_CMD_PORT_HOST_INT_STATUS and/or
+		 * UP_LD_CMD_PORT_HOST_INT_STATUS
+		 * Clear the interrupt status register
+		 */
+		PRINTM(MINTR, "wlan_interrupt: sdio_ireg = 0x%x\n", sdio_ireg);
+		pmadapter->pcard_sd->num_of_irq++;
+		pcb->moal_spin_lock(pmadapter->pmoal_handle,
+				    pmadapter->pint_lock);
+		pmadapter->ireg |= sdio_ireg;
+		pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+				      pmadapter->pint_lock);
+		if (!pmadapter->pps_uapsd_mode &&
+		    pmadapter->ps_state == PS_STATE_SLEEP) {
+			pmadapter->pm_wakeup_fw_try = MFALSE;
+			pmadapter->ps_state = PS_STATE_AWAKE;
+			pmadapter->pm_wakeup_card_req = MFALSE;
+		}
+	} else {
+		PRINTM(MMSG, "wlan_interrupt: sdio_ireg = 0x%x\n", sdio_ireg);
+	}
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function try to read the packet when fail to alloc rx buffer
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param port      Current port on which packet needs to be rxed
+ *  @param rx_len    Length of received packet
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_card_to_host_recovery(mlan_adapter *pmadapter,
+				t_u8 port, t_u16 rx_len)
+{
+	mlan_buffer mbuf;
+	t_u32 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	ENTER();
+	if (!pmadapter->pcard_sd->supports_sdio_new_mode)
+		goto done;
+	if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) {
+		PRINTM(MDATA, "Recovery:do Rx Aggr\n");
+		/* do aggr RX now */
+		wlan_receive_mp_aggr_buf(pmadapter);
+	}
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = pmadapter->pcard_sd->rx_buf;
+	mbuf.data_len = rx_len;
+
+	PRINTM(MDATA, "Recovery: Try read port=%d rx_len=%d\n", port, rx_len);
+	if (MLAN_STATUS_SUCCESS !=
+	    wlan_sdio_card_to_host(pmadapter, &pkt_type,
+				   (t_u32 *)&pmadapter->upld_len, &mbuf, rx_len,
+				   pmadapter->pcard_sd->ioport + port)) {
+		PRINTM(MERROR, "Recovery: Fail to do cmd53\n");
+	}
+	if (pkt_type != MLAN_TYPE_DATA && pkt_type != MLAN_TYPE_SPA_DATA) {
+		PRINTM(MERROR,
+		       "Recovery: Receive a wrong pkt: type=%d, len=%d\n",
+		       pkt_type, pmadapter->upld_len);
+		goto done;
+	}
+	if (pkt_type == MLAN_TYPE_DATA) {
+		// TODO fill the hole in Rx reorder table
+		PRINTM(MDATA, "Recovery: Drop Data packet\n");
+		pmadapter->dbg.num_pkt_dropped++;
+	} else if (pkt_type == MLAN_TYPE_SPA_DATA) {
+		PRINTM(MDATA, "Recovery: SPA Data packet len=%d\n",
+		       pmadapter->upld_len);
+		wlan_decode_spa_buffer(pmadapter, pmadapter->pcard_sd->rx_buf,
+				       pmadapter->upld_len);
+		pmadapter->data_received = MTRUE;
+	}
+	PRINTM(MMSG, "wlan: Success handle rx port=%d, rx_len=%d \n", port,
+	       rx_len);
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the interrupt status and handle it accordingly.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_process_sdio_int_status(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 sdio_ireg;
+	mlan_buffer *pmbuf = MNULL;
+
+	t_u8 port = 0;
+	t_u32 len_reg_l, len_reg_u;
+	t_u32 rx_blocks;
+	t_u8 bit_count = 0;
+	t_u32 ps_state = pmadapter->ps_state;
+	t_u16 rx_len;
+	t_u32 upld_typ = 0;
+	t_u32 cr = 0;
+	const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg;
+	t_u8 rd_len_p0_l = reg->rd_len_p0_l;
+	t_u8 rd_len_p0_u = reg->rd_len_p0_u;
+	t_u8 cmd_rd_len_0 = reg->cmd_rd_len_0;
+	t_u8 cmd_rd_len_1 = reg->cmd_rd_len_1;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+	sdio_ireg = (t_u8)pmadapter->ireg;
+	pmadapter->ireg = 0;
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock);
+
+	if (!sdio_ireg)
+		goto done;
+
+	if (new_mode) {
+		/* check the command port */
+		if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS) {
+			if (pmadapter->cmd_sent)
+				pmadapter->cmd_sent = MFALSE;
+
+			PRINTM(MINFO, "cmd_sent=%d\n", pmadapter->cmd_sent);
+		}
+
+		if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) {
+			/* read the len of control packet */
+			rx_len = ((t_u16)pmadapter->pcard_sd->
+				  mp_regs[cmd_rd_len_1])
+				<< 8;
+			rx_len |=
+				(t_u16)pmadapter->pcard_sd->
+				mp_regs[cmd_rd_len_0];
+			PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
+			rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) /
+				MLAN_SDIO_BLOCK_SIZE;
+			if (rx_len <= SDIO_INTF_HEADER_LEN ||
+			    (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+			    ALLOC_BUF_SIZE) {
+				PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
+			pmbuf = wlan_alloc_mlan_buffer(pmadapter, rx_len, 0,
+						       MOAL_MALLOC_BUFFER);
+			if (pmbuf == MNULL) {
+				PRINTM(MERROR,
+				       "Failed to allocate 'mlan_buffer'\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(MINFO, "cmd rx buffer rx_len = %d\n", rx_len);
+
+			/* Transfer data from card */
+			if (MLAN_STATUS_SUCCESS !=
+			    wlan_sdio_card_to_host(pmadapter, &upld_typ,
+						   (t_u32 *)&pmadapter->
+						   upld_len, pmbuf, rx_len,
+						   pmadapter->pcard_sd->
+						   ioport | CMD_PORT_SLCT)) {
+				pmadapter->dbg.
+					num_cmdevt_card_to_host_failure++;
+				PRINTM(MERROR,
+				       "Card-to-host cmd failed: int status=0x%x\n",
+				       sdio_ireg);
+				wlan_free_mlan_buffer(pmadapter, pmbuf);
+				ret = MLAN_STATUS_FAILURE;
+				goto term_cmd53;
+			}
+
+			if ((upld_typ != MLAN_TYPE_CMD) &&
+			    (upld_typ != MLAN_TYPE_EVENT))
+				PRINTM(MERROR,
+				       "receive a wrong packet from CMD PORT. type =0x%x\n",
+				       upld_typ);
+
+			wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ,
+					      MFALSE);
+
+			/* We might receive data/sleep_cfm at the same time */
+			/* reset data_receive flag to avoid ps_state change */
+			if ((ps_state == PS_STATE_SLEEP_CFM) &&
+			    (pmadapter->ps_state == PS_STATE_SLEEP))
+				pmadapter->data_received = MFALSE;
+		}
+	}
+
+	if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
+		if (pmadapter->pcard_sd->mp_wr_bitmap &
+		    pmadapter->pcard_sd->mp_data_port_mask)
+			pmadapter->pcard_sd->mp_invalid_update++;
+		pmadapter->pcard_sd->mp_wr_bitmap =
+			(t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l];
+		pmadapter->pcard_sd->mp_wr_bitmap |=
+			((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_u])
+			<< 8;
+		if (new_mode) {
+			pmadapter->pcard_sd->mp_wr_bitmap |=
+				((t_u32)pmadapter->pcard_sd->
+				 mp_regs[reg->wr_bitmap_1l])
+				<< 16;
+			pmadapter->pcard_sd->mp_wr_bitmap |=
+				((t_u32)pmadapter->pcard_sd->
+				 mp_regs[reg->wr_bitmap_1u])
+				<< 24;
+		}
+		bit_count = bitcount(pmadapter->pcard_sd->mp_wr_bitmap &
+				     pmadapter->pcard_sd->mp_data_port_mask);
+		if (bit_count) {
+			pmadapter->pcard_sd->mp_update[bit_count - 1]++;
+			if (pmadapter->pcard_sd->mp_update[bit_count - 1] ==
+			    0xffffffff)
+				memset(pmadapter,
+				       pmadapter->pcard_sd->mp_update, 0,
+				       sizeof(pmadapter->pcard_sd->mp_update));
+		}
+
+		pmadapter->pcard_sd->last_recv_wr_bitmap =
+			pmadapter->pcard_sd->mp_wr_bitmap;
+		PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n",
+		       pmadapter->pcard_sd->mp_wr_bitmap);
+		if (pmadapter->data_sent &&
+		    (pmadapter->pcard_sd->mp_wr_bitmap &
+		     (1 << pmadapter->pcard_sd->curr_wr_port))) {
+			pmadapter->callbacks.
+				moal_tp_accounting_rx_param(pmadapter->
+							    pmoal_handle, 3, 0);
+			PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n");
+			pmadapter->data_sent = MFALSE;
+		}
+	}
+	if ((!new_mode) && (pmadapter->cmd_sent == MTRUE)) {
+		/* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */
+		pmadapter->pcard_sd->mp_wr_bitmap |=
+			(t_u32)pmadapter->pcard_sd->
+			mp_regs[reg->wr_bitmap_l] & CTRL_PORT_MASK;
+		if (pmadapter->pcard_sd->mp_wr_bitmap & CTRL_PORT_MASK)
+			pmadapter->cmd_sent = MFALSE;
+	}
+
+	if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
+		pmadapter->pcard_sd->mp_rd_bitmap =
+			(t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_l];
+		pmadapter->pcard_sd->mp_rd_bitmap |=
+			((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_u])
+			<< 8;
+		if (new_mode) {
+			pmadapter->pcard_sd->mp_rd_bitmap |=
+				((t_u32)pmadapter->pcard_sd->
+				 mp_regs[reg->rd_bitmap_1l])
+				<< 16;
+			pmadapter->pcard_sd->mp_rd_bitmap |=
+				((t_u32)pmadapter->pcard_sd->
+				 mp_regs[reg->rd_bitmap_1u])
+				<< 24;
+		}
+		pmadapter->pcard_sd->last_recv_rd_bitmap =
+			pmadapter->pcard_sd->mp_rd_bitmap;
+
+		PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n",
+		       pmadapter->pcard_sd->mp_rd_bitmap);
+		pmadapter->callbacks.moal_tp_accounting_rx_param(pmadapter->
+								 pmoal_handle,
+								 0, 0);
+
+		while (MTRUE) {
+			ret = wlan_get_rd_port(pmadapter, &port);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MINFO,
+				       "no more rd_port to be handled\n");
+				break;
+			}
+			len_reg_l = rd_len_p0_l + (port << 1);
+			len_reg_u = rd_len_p0_u + (port << 1);
+			rx_len = ((t_u16)pmadapter->pcard_sd->
+				  mp_regs[len_reg_u])
+				<< 8;
+			rx_len |=
+				(t_u16)pmadapter->pcard_sd->mp_regs[len_reg_l];
+			PRINTM(MINFO, "RX: port=%d rx_len=%u\n", port, rx_len);
+			rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) /
+				MLAN_SDIO_BLOCK_SIZE;
+			if (rx_len <= SDIO_INTF_HEADER_LEN ||
+			    (rx_blocks * MLAN_SDIO_BLOCK_SIZE) >
+			    pmadapter->pcard_sd->mpa_rx.buf_size) {
+				PRINTM(MERROR, "invalid rx_len=%d\n", rx_len);
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
+
+			if (!new_mode && (port == CTRL_PORT))
+				pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+							       rx_len, 0,
+							       MOAL_MALLOC_BUFFER);
+			else
+				pmbuf = wlan_alloc_mlan_buffer(pmadapter,
+							       rx_len,
+							       MLAN_RX_HEADER_LEN,
+							       MOAL_ALLOC_MLAN_BUFFER);
+			if (pmbuf == MNULL) {
+				PRINTM(MERROR,
+				       "Failed to allocate 'mlan_buffer'\n");
+				pmadapter->dbg.num_alloc_buffer_failure++;
+				if (MLAN_STATUS_SUCCESS ==
+				    wlan_sdio_card_to_host_recovery(pmadapter,
+								    port,
+								    rx_len))
+					continue;
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(MINFO, "rx_len = %d\n", rx_len);
+			if (MLAN_STATUS_SUCCESS !=
+			    wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf,
+							   port, rx_len)) {
+				if ((!new_mode) && (port == CTRL_PORT))
+					pmadapter->dbg.
+						num_cmdevt_card_to_host_failure++;
+				else
+					pmadapter->dbg.
+						num_rx_card_to_host_failure++;
+
+				PRINTM(MERROR,
+				       "Card to host failed: int status=0x%x\n",
+				       sdio_ireg);
+				ret = MLAN_STATUS_FAILURE;
+				goto term_cmd53;
+			}
+		}
+		/* We might receive data/sleep_cfm at the same time */
+		/* reset data_receive flag to avoid ps_state change */
+		if ((ps_state == PS_STATE_SLEEP_CFM) &&
+		    (pmadapter->ps_state == PS_STATE_SLEEP))
+			pmadapter->data_received = MFALSE;
+	}
+
+	ret = MLAN_STATUS_SUCCESS;
+	goto done;
+
+term_cmd53:
+	/* terminate cmd53 */
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config Reg val = %d\n", cr);
+	if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle,
+						       HOST_TO_CARD_EVENT_REG,
+						       (cr | HOST_TERM_CMD53)))
+		PRINTM(MERROR, "write CFG reg failed\n");
+	PRINTM(MINFO, "write success\n");
+	if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle,
+						      HOST_TO_CARD_EVENT_REG,
+						      &cr))
+		PRINTM(MERROR, "read CFG reg failed\n");
+	PRINTM(MINFO, "Config reg val =%x\n", cr);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param type      data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ *  @param tx_param  A pointer to mlan_tx_param
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type,
+		       mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 buf_block_len;
+	t_u32 blksz;
+	t_u8 port = 0;
+	t_u32 cmd53_port = 0;
+	t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
+
+	ENTER();
+
+	/* Allocate buffer and copy payload */
+	blksz = MLAN_SDIO_BLOCK_SIZE;
+	buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(type);
+
+	/*
+	 * This is SDIO specific header
+	 *  t_u16 length,
+	 *  t_u16 type (MLAN_TYPE_DATA = 0,
+	 *    MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3)
+	 */
+	if (type == MLAN_TYPE_DATA) {
+		ret = wlan_get_wr_port_data(pmadapter, &port);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR,
+			       "no wr_port available: wr_bitmap=0x%08x curr_wr_port=%d\n",
+			       pmadapter->pcard_sd->mp_wr_bitmap,
+			       pmadapter->pcard_sd->curr_wr_port);
+			goto exit;
+		}
+		/* Transfer data to card */
+		pmbuf->data_len = buf_block_len * blksz;
+
+		if (tx_param)
+			ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port,
+							tx_param->next_pkt_len);
+		else
+			ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port,
+							0);
+	} else {
+		/*Type must be MLAN_TYPE_CMD */
+		pmadapter->cmd_sent = MTRUE;
+		if (!new_mode)
+			pmadapter->pcard_sd->mp_wr_bitmap &=
+				(t_u32)(~(1 << CTRL_PORT));
+		if (pmbuf->data_len <= SDIO_INTF_HEADER_LEN ||
+		    pmbuf->data_len > WLAN_UPLD_SIZE)
+			PRINTM(MWARN,
+			       "wlan_sdio_host_to_card(): Error: payload=%p, nb=%d\n",
+			       payload, pmbuf->data_len);
+		/* Transfer data to card */
+		pmbuf->data_len = buf_block_len * blksz;
+		if (new_mode)
+			cmd53_port =
+				(pmadapter->pcard_sd->ioport) | CMD_PORT_SLCT;
+		else
+			cmd53_port = pmadapter->pcard_sd->ioport + CTRL_PORT;
+		ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+	}
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
+		if (type == MLAN_TYPE_CMD)
+			pmadapter->cmd_sent = MFALSE;
+		if (type == MLAN_TYPE_DATA)
+			pmadapter->data_sent = MFALSE;
+	} else {
+		if (type == MLAN_TYPE_DATA) {
+			if (!(pmadapter->pcard_sd->mp_wr_bitmap &
+			      (1 << pmadapter->pcard_sd->curr_wr_port)))
+				pmadapter->data_sent = MTRUE;
+			else
+				pmadapter->data_sent = MFALSE;
+		}
+		DBG_HEXDUMP(MIF_D, "SDIO Blk Wr",
+			    pmbuf->pbuf + pmbuf->data_offset,
+			    MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+#if (defined(SD9098) || defined(SD9097) || defined(SD9177))
+/**
+ *  @brief This function sends vdll data to the card.
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_send_vdll(mlan_adapter *pmadapter, mlan_buffer *pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 buf_block_len;
+	t_u32 blksz;
+	t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset;
+	t_u32 cmd53_port = 0;
+	ENTER();
+	blksz = MLAN_SDIO_BLOCK_SIZE;
+	buf_block_len = (pmbuf->data_len + blksz - 1) / blksz;
+
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16((t_u16)pmbuf->data_len);
+	*(t_u16 *)&payload[2] = wlan_cpu_to_le16(MLAN_TYPE_VDLL);
+
+	pmbuf->data_len = buf_block_len * blksz;
+
+	if (pmbuf->data_len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+		PRINTM(MERROR, "VDLL block is too big: %d\n", pmbuf->data_len);
+		return MLAN_STATUS_FAILURE;
+	}
+	cmd53_port = (pmadapter->pcard_sd->ioport) | CMD_PORT_SLCT;
+	pmadapter->cmd_sent = MTRUE;
+	ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port);
+	if (ret == MLAN_STATUS_FAILURE)
+		PRINTM(MERROR, "Send Vdll: host_to_card failed: 0x%X\n", ret);
+	else
+		DBG_HEXDUMP(MIF_D, "SDIO Blk Wr",
+			    pmbuf->pbuf + pmbuf->data_offset,
+			    MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function sends data to the card.
+ *
+ *  @param pmpriv    A pointer to mlan_private structure
+ *  @param type      data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * SDIO header)
+ *  @param tx_param  A pointer to mlan_tx_param
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_sdio_host_to_card_ext(pmlan_private pmpriv, t_u8 type,
+			   mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+
+#if (defined(SD9098) || defined(SD9097) || defined(SD9177))
+	if (type == MLAN_TYPE_VDLL)
+		return wlan_sdio_send_vdll(pmadapter, pmbuf);
+#endif
+	ret = wlan_sdio_host_to_card(pmadapter, type, pmbuf, tx_param);
+
+	if (type == MLAN_TYPE_DATA && ret == MLAN_STATUS_FAILURE)
+		pmadapter->data_sent = MFALSE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Deaggregate single port aggregation packet
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param buf	A pointer to aggregated data packet
+ *  @param len
+ *
+ *  @return		N/A
+ */
+void
+wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len)
+{
+	int total_pkt_len;
+	t_u8 block_num = 0;
+	t_u16 block_size = 0;
+	t_u8 *data;
+	t_u32 pkt_len;
+	mlan_buffer *mbuf_deaggr = MNULL;
+
+	ENTER();
+
+	data = (t_u8 *)buf;
+	total_pkt_len = len;
+	if (total_pkt_len < pmadapter->pcard_sd->sdio_rx_block_size) {
+		PRINTM(MERROR, "Invalid sp aggr packet size=%d\n",
+		       total_pkt_len);
+		goto done;
+	}
+	while (total_pkt_len >= (OFFSET_OF_SDIO_HEADER + SDIO_INTF_HEADER_LEN)) {
+		block_num = *(data + OFFSET_OF_BLOCK_NUMBER);
+		block_size =
+			pmadapter->pcard_sd->sdio_rx_block_size * block_num;
+		if (block_size > total_pkt_len) {
+			PRINTM(MERROR,
+			       "Error in pkt, block_num=%d, pkt_len=%d\n",
+			       block_num, total_pkt_len);
+			break;
+		}
+		pkt_len =
+			wlan_le16_to_cpu(*(t_u16 *)
+					 (data + OFFSET_OF_SDIO_HEADER));
+		if ((pkt_len + OFFSET_OF_SDIO_HEADER) > block_size) {
+			PRINTM(MERROR,
+			       "Error in pkt, pkt_len=%d, block_size=%d\n",
+			       pkt_len, block_size);
+			break;
+		}
+		mbuf_deaggr =
+			wlan_alloc_mlan_buffer(pmadapter,
+					       pkt_len - SDIO_INTF_HEADER_LEN,
+					       MLAN_RX_HEADER_LEN,
+					       MOAL_ALLOC_MLAN_BUFFER);
+		if (mbuf_deaggr == MNULL) {
+			PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
+			break;
+		}
+		memcpy_ext(pmadapter,
+			   mbuf_deaggr->pbuf + mbuf_deaggr->data_offset,
+			   data + OFFSET_OF_SDIO_HEADER + SDIO_INTF_HEADER_LEN,
+			   pkt_len - SDIO_INTF_HEADER_LEN,
+			   pkt_len - SDIO_INTF_HEADER_LEN);
+		mbuf_deaggr->data_len = pkt_len - SDIO_INTF_HEADER_LEN;
+		wlan_handle_rx_packet(pmadapter, mbuf_deaggr);
+		data += block_size;
+		total_pkt_len -= block_size;
+		if (total_pkt_len < pmadapter->pcard_sd->sdio_rx_block_size)
+			break;
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function deaggr rx pkt
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the SDIO mpa data
+ *  @return          N/A
+ */
+t_void
+wlan_sdio_deaggr_rx_pkt(pmlan_adapter pmadapter, mlan_buffer *pmbuf)
+{
+	if (pmbuf->buf_type == MLAN_BUF_TYPE_SPA_DATA) {
+		wlan_decode_spa_buffer(pmadapter,
+				       pmbuf->pbuf + pmbuf->data_offset,
+				       pmbuf->data_len);
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	} else
+		wlan_handle_rx_packet(pmadapter, pmbuf);
+}
+
+/**
+ *  @brief This function allocates buffer for the SDIO aggregation buffer
+ *          related members of adapter structure
+ *
+ *  @param pmadapter       A pointer to mlan_adapter structure
+ *  @param mpa_tx_buf_size Tx buffer size to allocate
+ *  @param mpa_rx_buf_size Rx buffer size to allocate
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_alloc_sdio_mpa_buffers(mlan_adapter *pmadapter,
+			    t_u32 mpa_tx_buf_size, t_u32 mpa_rx_buf_size)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
+
+	ENTER();
+
+	if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->pcard_sd->max_seg_size <
+	     pmadapter->pcard_sd->max_sp_tx_size)) {
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       mpa_tx_buf_size + DMA_ALIGNMENT,
+				       MLAN_MEM_DEF | MLAN_MEM_DMA,
+				       (t_u8 **)&pmadapter->pcard_sd->mpa_tx.
+				       head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS ||
+		    !pmadapter->pcard_sd->mpa_tx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP TX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->pcard_sd->mpa_tx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->pcard_sd->mpa_tx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable TX SG mode\n");
+		pmadapter->pcard_sd->mpa_tx.head_ptr = MNULL;
+		pmadapter->pcard_sd->mpa_tx.buf = MNULL;
+	}
+	pmadapter->pcard_sd->mpa_tx.buf_size = mpa_tx_buf_size;
+
+	if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->pcard_sd->max_seg_size <
+	     pmadapter->pcard_sd->max_sp_rx_size)) {
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       mpa_rx_buf_size + DMA_ALIGNMENT,
+				       MLAN_MEM_DEF | MLAN_MEM_DMA,
+				       (t_u8 **)&pmadapter->pcard_sd->mpa_rx.
+				       head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS ||
+		    !pmadapter->pcard_sd->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->pcard_sd->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->pcard_sd->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+		pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+	}
+	pmadapter->pcard_sd->mpa_rx.buf_size = mpa_rx_buf_size;
+error:
+	if (ret != MLAN_STATUS_SUCCESS)
+		wlan_free_sdio_mpa_buffers(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees buffers for the SDIO aggregation
+ *
+ *  @param pmadapter       A pointer to mlan_adapter structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_free_sdio_mpa_buffers(mlan_adapter *pmadapter)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	if (pmadapter->pcard_sd->mpa_tx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->pcard_sd->mpa_tx.head_ptr);
+		pmadapter->pcard_sd->mpa_tx.head_ptr = MNULL;
+		pmadapter->pcard_sd->mpa_tx.buf = MNULL;
+		pmadapter->pcard_sd->mpa_tx.buf_size = 0;
+	}
+
+	if (pmadapter->pcard_sd->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->pcard_sd->mpa_rx.head_ptr);
+		pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+		pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+		pmadapter->pcard_sd->mpa_rx.buf_size = 0;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function re-allocate rx mpa buffer
+ *
+ *  @param pmadapter       A pointer to mlan_adapter structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_re_alloc_sdio_rx_mpa_buffer(mlan_adapter *pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
+	t_u32 mpa_rx_buf_size = pmadapter->pcard_sd->mp_tx_aggr_buf_size;
+
+	if (pmadapter->pcard_sd->mpa_rx.buf) {
+		pcb->moal_mfree(pmadapter->pmoal_handle,
+				(t_u8 *)pmadapter->pcard_sd->mpa_rx.head_ptr);
+		pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+		pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+		pmadapter->pcard_sd->mpa_rx.buf_size = 0;
+	}
+	if (pmadapter->pcard_sd->sdio_rx_aggr_enable) {
+		mpa_rx_buf_size = MAX(mpa_rx_buf_size, SDIO_CMD53_MAX_SIZE);
+		/** reallocate rx buffer for recover when single port rx
+		 * aggregation enabled */
+		if (pmadapter->pcard_sd->rx_buffer) {
+			pcb->moal_mfree(pmadapter->pmoal_handle,
+					(t_u8 *)pmadapter->pcard_sd->rx_buffer);
+			pmadapter->pcard_sd->rx_buffer = MNULL;
+			pmadapter->pcard_sd->rx_buf = MNULL;
+		}
+		ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+						       SDIO_CMD53_MAX_SIZE +
+						       DMA_ALIGNMENT,
+						       MLAN_MEM_DEF |
+						       MLAN_MEM_DMA,
+						       (t_u8 **)&pmadapter->
+						       pcard_sd->rx_buffer);
+
+		if (ret != MLAN_STATUS_SUCCESS ||
+		    !pmadapter->pcard_sd->rx_buffer) {
+			PRINTM(MERROR, "Failed to allocate receive buffer\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->pcard_sd->rx_buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->pcard_sd->rx_buffer,
+					   DMA_ALIGNMENT);
+	}
+	if ((pmadapter->pcard_sd->max_segs < mp_aggr_pkt_limit) ||
+	    (pmadapter->pcard_sd->max_seg_size <
+	     pmadapter->pcard_sd->max_sp_rx_size)) {
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       mpa_rx_buf_size + DMA_ALIGNMENT,
+				       MLAN_MEM_DEF | MLAN_MEM_DMA,
+				       (t_u8 **)&pmadapter->pcard_sd->mpa_rx.
+				       head_ptr);
+		if (ret != MLAN_STATUS_SUCCESS ||
+		    !pmadapter->pcard_sd->mpa_rx.head_ptr) {
+			PRINTM(MERROR,
+			       "Could not allocate buffer for SDIO MP RX aggr\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+		pmadapter->pcard_sd->mpa_rx.buf =
+			(t_u8 *)ALIGN_ADDR(pmadapter->pcard_sd->mpa_rx.head_ptr,
+					   DMA_ALIGNMENT);
+	} else {
+		PRINTM(MMSG, "wlan: Enable RX SG mode\n");
+		pmadapter->pcard_sd->mpa_rx.head_ptr = MNULL;
+		pmadapter->pcard_sd->mpa_rx.buf = MNULL;
+	}
+	pmadapter->pcard_sd->mpa_rx.buf_size = mpa_rx_buf_size;
+	PRINTM(MMSG, "mpa_rx_buf_size=%d\n", mpa_rx_buf_size);
+error:
+	return ret;
+}
+
+/**
+ *  @brief This function wakes up the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *  @param timeout          set timeout flag
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pm_sdio_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 age_ts_usec;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+	PRINTM(MEVENT, "Wakeup device...\n");
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->pm_wakeup_in_secs,
+						  &age_ts_usec);
+
+	if (timeout) {
+		pmadapter->callbacks.moal_start_timer(pmadapter->pmoal_handle,
+						      pmadapter->
+						      pwakeup_fw_timer, MFALSE,
+						      MRVDRV_TIMER_3S);
+		pmadapter->wakeup_fw_timer_is_set = MTRUE;
+	}
+
+	ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+				  HOST_TO_CARD_EVENT_REG, HOST_POWER_UP);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function resets the PM setting of the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pm_sdio_reset_card(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+
+	ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+				  HOST_TO_CARD_EVENT_REG, 0);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues commands to initialize firmware
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_set_sdio_gpio_int(pmlan_private priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_adapter pmadapter = MNULL;
+	HostCmd_DS_SDIO_GPIO_INT_CONFIG sdio_int_cfg;
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter = priv->adapter;
+
+	ENTER();
+
+	if (pmadapter->pcard_sd->int_mode == INT_MODE_GPIO) {
+		if (pmadapter->pcard_sd->gpio_pin != GPIO_INT_NEW_MODE) {
+			PRINTM(MINFO,
+			       "SDIO_GPIO_INT_CONFIG: interrupt mode is GPIO\n");
+			sdio_int_cfg.action = HostCmd_ACT_GEN_SET;
+			sdio_int_cfg.gpio_pin = pmadapter->pcard_sd->gpio_pin;
+			sdio_int_cfg.gpio_int_edge = INT_FALLING_EDGE;
+			sdio_int_cfg.gpio_pulse_width = DELAY_1_US;
+			ret = wlan_prepare_cmd(priv,
+					       HostCmd_CMD_SDIO_GPIO_INT_CONFIG,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       &sdio_int_cfg);
+
+			if (ret) {
+				PRINTM(MERROR,
+				       "SDIO_GPIO_INT_CONFIG: send command fail\n");
+				ret = MLAN_STATUS_FAILURE;
+			}
+		}
+	} else {
+		PRINTM(MINFO, "SDIO_GPIO_INT_CONFIG: interrupt mode is SDIO\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of SDIO GPIO interrupt
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd,
+		       t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_SDIO_GPIO_INT_CONFIG *psdio_gpio_int =
+		&cmd->params.sdio_gpio_int;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_GPIO_INT_CONFIG);
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG)) +
+				     S_DS_GEN);
+
+	memset(pmpriv->adapter, psdio_gpio_int, 0,
+	       sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG));
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		memcpy_ext(pmpriv->adapter, psdio_gpio_int, pdata_buf,
+			   sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG),
+			   sizeof(HostCmd_DS_SDIO_GPIO_INT_CONFIG));
+		psdio_gpio_int->action =
+			wlan_cpu_to_le16(psdio_gpio_int->action);
+		psdio_gpio_int->gpio_pin =
+			wlan_cpu_to_le16(psdio_gpio_int->gpio_pin);
+		psdio_gpio_int->gpio_int_edge =
+			wlan_cpu_to_le16(psdio_gpio_int->gpio_int_edge);
+		psdio_gpio_int->gpio_pulse_width =
+			wlan_cpu_to_le16(psdio_gpio_int->gpio_pulse_width);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+mlan_status
+wlan_reset_fw(pmlan_adapter pmadapter)
+{
+	t_u32 tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = pmadapter->pcard_sd->reg->fw_reset_reg;
+	t_u8 reset_val = pmadapter->pcard_sd->reg->fw_reset_val;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	wlan_pm_sdio_wakeup_card(pmadapter, MFALSE);
+
+	/** wait SOC fully wake up */
+	for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
+		if (MLAN_STATUS_SUCCESS ==
+		    pcb->moal_write_reg(pmadapter->pmoal_handle, reset_reg,
+					0xba)) {
+			pcb->moal_read_reg(pmadapter->pmoal_handle, reset_reg,
+					   &value);
+			if (value == 0xba) {
+				PRINTM(MMSG, "FW wake up\n");
+				break;
+			}
+		}
+		pcb->moal_udelay(pmadapter->pmoal_handle, 1000);
+	}
+	/* Write register to notify FW */
+	if (MLAN_STATUS_FAILURE == pcb->moal_write_reg(pmadapter->pmoal_handle,
+						       reset_reg, reset_val)) {
+		PRINTM(MERROR, "Failed to write register.\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#if defined(SD8997) || defined(SD8977) || defined(SD8987) || defined(SD9098) || defined(SD9097) || defined(SD8978) || defined(SD9177)
+	if (MFALSE
+#ifdef SD8997
+	    || IS_SD8997(pmadapter->card_type)
+#endif
+#ifdef SD8977
+	    || IS_SD8977(pmadapter->card_type)
+#endif
+#ifdef SD8978
+	    || IS_SD8978(pmadapter->card_type)
+#endif
+#ifdef SD8987
+	    || IS_SD8987(pmadapter->card_type)
+#endif
+#ifdef SD9098
+	    || IS_SD9098(pmadapter->card_type)
+#endif
+#ifdef SD9097
+	    || IS_SD9097(pmadapter->card_type)
+#endif
+#ifdef SD9177
+	    || IS_SD9177(pmadapter->card_type)
+#endif
+		) {
+		pcb->moal_read_reg(pmadapter->pmoal_handle,
+				   HOST_TO_CARD_EVENT_REG, &value);
+		pcb->moal_write_reg(pmadapter->pmoal_handle,
+				    HOST_TO_CARD_EVENT_REG,
+				    value | HOST_POWER_UP);
+	}
+#endif
+	/* Poll register around 100 ms */
+	for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
+		pcb->moal_read_reg(pmadapter->pmoal_handle, reset_reg, &value);
+		if (value == 0)
+			/* FW is ready */
+			break;
+		pcb->moal_udelay(pmadapter->pmoal_handle, 1000);
+	}
+
+	if (value) {
+		PRINTM(MERROR, "Failed to poll FW reset register %X=0x%x\n",
+		       reset_reg, value);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	PRINTM(MMSG, "FW Reset success\n");
+	ret = wlan_sdio_probe(pmadapter);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle event/data/cmd complete
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the mlan_buffer
+ *  @return          N/A
+ */
+static mlan_status
+wlan_sdio_data_evt_complete(pmlan_adapter pmadapter,
+			    mlan_buffer *pmbuf, mlan_status status)
+{
+	ENTER();
+
+	wlan_free_mlan_buffer(pmadapter, pmbuf);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle receive packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the mlan_buffer
+ *  @return
+ */
+static mlan_status
+wlan_sdio_handle_rx_packet(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
+{
+	ENTER();
+
+	wlan_sdio_deaggr_rx_pkt(pmadapter, pmbuf);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+mlan_adapter_operations mlan_sdio_ops = {
+	.dnld_fw = wlan_sdio_dnld_fw,
+	.interrupt = wlan_sdio_interrupt,
+	.process_int_status = wlan_process_sdio_int_status,
+	.host_to_card = wlan_sdio_host_to_card_ext,
+	.wakeup_card = wlan_pm_sdio_wakeup_card,
+	.reset_card = wlan_pm_sdio_reset_card,
+	.event_complete = wlan_sdio_data_evt_complete,
+	.data_complete = wlan_sdio_data_evt_complete,
+	.cmdrsp_complete = wlan_sdio_data_evt_complete,
+	.handle_rx_packet = wlan_sdio_handle_rx_packet,
+	.disable_host_int = wlan_disable_sdio_host_int,
+	.enable_host_int = wlan_enable_sdio_host_int,
+
+	.intf_header_len = SDIO_INTF_HEADER_LEN,
+};
diff --git a/wlan_sd8987/mlan/mlan_sdio.h b/wlan_sd8987/mlan/mlan_sdio.h
new file mode 100755
index 0000000..f62b1d9
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sdio.h
@@ -0,0 +1,357 @@
+/** @file mlan_sdio.h
+ *
+ * @brief This file contains definitions for SDIO interface.
+ * driver.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+/****************************************************
+Change log:
+****************************************************/
+
+#ifndef _MLAN_SDIO_H
+#define _MLAN_SDIO_H
+
+/** Block mode */
+#ifndef BLOCK_MODE
+#define BLOCK_MODE 1
+#endif
+
+/** Fixed address mode */
+#ifndef FIXED_ADDRESS
+#define FIXED_ADDRESS 0
+#endif
+
+/* Host Control Registers */
+/** Host Control Registers : Host to Card Event */
+#define HOST_TO_CARD_EVENT_REG 0x00
+/** Host Control Registers : Host terminates Command 53 */
+#define HOST_TERM_CMD53 (0x1U << 2)
+/** Host Control Registers : Host without Command 53 finish host */
+#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2)
+/** Host Control Registers : Host power up */
+#define HOST_POWER_UP (0x1U << 1)
+/** Host Control Registers : Host power down */
+#define HOST_POWER_DOWN (0x1U << 0)
+
+/** Host Control Registers : Upload host interrupt RSR */
+#define UP_LD_HOST_INT_RSR (0x1U)
+#define HOST_INT_RSR_MASK 0xFF
+
+/** Host Control Registers : Upload command port host interrupt status */
+#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U)
+/** Host Control Registers : Download command port host interrupt status */
+#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U)
+
+/** Host Control Registers : Upload host interrupt mask */
+#define UP_LD_HOST_INT_MASK (0x1U)
+/** Host Control Registers : Download host interrupt mask */
+#define DN_LD_HOST_INT_MASK (0x2U)
+/** Host Control Registers : Cmd port upload interrupt mask */
+#define CMD_PORT_UPLD_INT_MASK (0x1U << 6)
+/** Host Control Registers : Cmd port download interrupt mask */
+#define CMD_PORT_DNLD_INT_MASK (0x1U << 7)
+/** Enable Host interrupt mask */
+#define HIM_ENABLE                                                             \
+	(UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | CMD_PORT_UPLD_INT_MASK |  \
+	 CMD_PORT_DNLD_INT_MASK)
+/** Disable Host interrupt mask */
+#define HIM_DISABLE 0xff
+
+/** Host Control Registers : Upload host interrupt status */
+#define UP_LD_HOST_INT_STATUS (0x1U)
+/** Host Control Registers : Download host interrupt status */
+#define DN_LD_HOST_INT_STATUS (0x2U)
+
+/** Host Control Registers : Download CRC error */
+#define DN_LD_CRC_ERR (0x1U << 2)
+/** Host Control Registers : Upload restart */
+#define UP_LD_RESTART (0x1U << 1)
+/** Host Control Registers : Download restart */
+#define DN_LD_RESTART (0x1U << 0)
+
+/** Card Control Registers : Command port upload ready */
+#define UP_LD_CP_RDY (0x1U << 6)
+/** Card Control Registers : Command port download ready */
+#define DN_LD_CP_RDY (0x1U << 7)
+/** Card Control Registers : Card I/O ready */
+#define CARD_IO_READY (0x1U << 3)
+/** Card Control Registers : CIS card ready */
+#define CIS_CARD_RDY (0x1U << 2)
+/** Card Control Registers : Upload card ready */
+#define UP_LD_CARD_RDY (0x1U << 1)
+/** Card Control Registers : Download card ready */
+#define DN_LD_CARD_RDY (0x1U << 0)
+
+/** Card Control Registers : Host power interrupt mask */
+#define HOST_POWER_INT_MASK (0x1U << 3)
+/** Card Control Registers : Abort card interrupt mask */
+#define ABORT_CARD_INT_MASK (0x1U << 2)
+/** Card Control Registers : Upload card interrupt mask */
+#define UP_LD_CARD_INT_MASK (0x1U << 1)
+/** Card Control Registers : Download card interrupt mask */
+#define DN_LD_CARD_INT_MASK (0x1U << 0)
+
+/** Card Control Registers : Power up interrupt */
+#define POWER_UP_INT (0x1U << 4)
+/** Card Control Registers : Power down interrupt */
+#define POWER_DOWN_INT (0x1U << 3)
+
+/** Card Control Registers : Power up RSR */
+#define POWER_UP_RSR (0x1U << 4)
+/** Card Control Registers : Power down RSR */
+#define POWER_DOWN_RSR (0x1U << 3)
+
+/** Card Control Registers : SD test BUS 0 */
+#define SD_TESTBUS0 (0x1U)
+/** Card Control Registers : SD test BUS 1 */
+#define SD_TESTBUS1 (0x1U)
+/** Card Control Registers : SD test BUS 2 */
+#define SD_TESTBUS2 (0x1U)
+/** Card Control Registers : SD test BUS 3 */
+#define SD_TESTBUS3 (0x1U)
+
+/** Port for registers */
+#define REG_PORT 0
+/** Port for memory */
+#define MEM_PORT 0x10000
+/** Ctrl port */
+#define CTRL_PORT			0
+/** Ctrl port mask */
+#define CTRL_PORT_MASK			0x0001
+/** Card Control Registers : cmd53 new mode */
+#define CMD53_NEW_MODE (0x1U << 0)
+/** Card Control Registers : cmd53 tx len format 1 (0x10) */
+#define CMD53_TX_LEN_FORMAT_1 (0x1U << 4)
+/** Card Control Registers : cmd53 tx len format 2 (0x20)*/
+#define CMD53_TX_LEN_FORMAT_2 (0x1U << 5)
+/** Card Control Registers : cmd53 rx len format 1 (0x40) */
+#define CMD53_RX_LEN_FORMAT_1 (0x1U << 6)
+/** Card Control Registers : cmd53 rx len format 2 (0x80)*/
+#define CMD53_RX_LEN_FORMAT_2 (0x1U << 7)
+
+#define CMD_PORT_RD_LEN_EN (0x1U << 2)
+/* Card Control Registers : cmd port auto enable */
+#define CMD_PORT_AUTO_EN (0x1U << 0)
+
+/* Command port */
+#define CMD_PORT_SLCT 0x8000
+
+/** Misc. Config Register : Auto Re-enable interrupts */
+#define AUTO_RE_ENABLE_INT MBIT(4)
+
+/** Enable GPIO-1 as a duplicated signal of interrupt as appear of SDIO_DAT1*/
+#define ENABLE_GPIO_1_INT_MODE 0x88
+/** Scratch reg 3 2  :     Configure GPIO-1 INT*/
+#define SCRATCH_REG_32 0xEE
+
+/** Event header Len*/
+#define MLAN_EVENT_HEADER_LEN 8
+
+/** SDIO byte mode size */
+#define MAX_BYTE_MODE_SIZE 512
+
+/** The base address for packet with multiple ports aggregation */
+#define SDIO_MPA_ADDR_BASE 0x1000
+
+/** SDIO Tx aggregation in progress ? */
+#define MP_TX_AGGR_IN_PROGRESS(a) (a->pcard_sd->mpa_tx.pkt_cnt > 0)
+
+/** SDIO Tx aggregation buffer room for next packet ? */
+#define MP_TX_AGGR_BUF_HAS_ROOM(a, mbuf, len)                                  \
+	(((a->pcard_sd->mpa_tx.buf_len) + len) <=                              \
+	 (a->pcard_sd->mpa_tx.buf_size))
+
+/** Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
+#define MP_TX_AGGR_BUF_PUT(a, mbuf, port)                                      \
+	do {                                                                   \
+		pmadapter->callbacks.moal_memmove(                             \
+			a->pmoal_handle,                                       \
+			&a->pcard_sd->mpa_tx.buf[a->pcard_sd->mpa_tx.buf_len], \
+			mbuf->pbuf + mbuf->data_offset, mbuf->data_len);       \
+		a->pcard_sd->mpa_tx.buf_len += mbuf->data_len;                 \
+		a->pcard_sd->mpa_tx.mp_wr_info[a->pcard_sd->mpa_tx.pkt_cnt] =  \
+			*(t_u16 *)(mbuf->pbuf + mbuf->data_offset);            \
+		if (!a->pcard_sd->mpa_tx.pkt_cnt) {                            \
+			a->pcard_sd->mpa_tx.start_port = port;                 \
+		}                                                              \
+		a->pcard_sd->mpa_tx.ports |= (1 << port);                      \
+		a->pcard_sd->mpa_tx.pkt_cnt++;                                 \
+	} while (0)
+
+#define MP_TX_AGGR_BUF_PUT_NONEWMODE(a, mbuf, port) do {                  \
+	pmadapter->callbacks.moal_memmove(a->pmoal_handle, \
+		&a->pcard_sd->mpa_tx.buf[a->pcard_sd->mpa_tx.buf_len], \
+		mbuf->pbuf+mbuf->data_offset, mbuf->data_len);\
+	a->pcard_sd->mpa_tx.buf_len += mbuf->data_len;                        \
+	a->pcard_sd->mpa_tx.mp_wr_info[a->pcard_sd->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+	if (!a->pcard_sd->mpa_tx.pkt_cnt) {                                   \
+	    a->pcard_sd->mpa_tx.start_port = port;                            \
+	}                                                           \
+	if (a->pcard_sd->mpa_tx.start_port <= port) {                         \
+	    a->pcard_sd->mpa_tx.ports |= (1 << (a->pcard_sd->mpa_tx.pkt_cnt));			\
+	} else {                                                    \
+	      a->pcard_sd->mpa_tx.ports |= (1 << (a->pcard_sd->mpa_tx.pkt_cnt \
+			+ 1 + (a->pcard_sd->max_ports - a->pcard_sd->mp_end_port)));  \
+	}                                                           \
+	a->pcard_sd->mpa_tx.pkt_cnt++;                                       \
+} while (0)
+#define MP_TX_AGGR_BUF_PUT_SG(a, mbuf, port)                                   \
+	do {                                                                   \
+		a->pcard_sd->mpa_tx.buf_len += mbuf->data_len;                 \
+		a->pcard_sd->mpa_tx.mp_wr_info[a->pcard_sd->mpa_tx.pkt_cnt] =  \
+			*(t_u16 *)(mbuf->pbuf + mbuf->data_offset);            \
+		a->pcard_sd->mpa_tx.mbuf_arr[a->pcard_sd->mpa_tx.pkt_cnt] =    \
+			mbuf;                                                  \
+		if (!a->pcard_sd->mpa_tx.pkt_cnt) {                            \
+			a->pcard_sd->mpa_tx.start_port = port;                 \
+		}                                                              \
+		a->pcard_sd->mpa_tx.ports |= (1 << port);                      \
+		a->pcard_sd->mpa_tx.pkt_cnt++;                                 \
+	} while (0)
+#define MP_TX_AGGR_BUF_PUT_SG_NONEWMODE(a, mbuf, port) do {                  \
+	a->pcard_sd->mpa_tx.buf_len += mbuf->data_len;                        \
+    a->pcard_sd->mpa_tx.mp_wr_info[a->pcard_sd->mpa_tx.pkt_cnt] = *(t_u16 *)(mbuf->pbuf+mbuf->data_offset); \
+    a->pcard_sd->mpa_tx.mbuf_arr[a->pcard_sd->mpa_tx.pkt_cnt] = mbuf;               \
+	if (!a->pcard_sd->mpa_tx.pkt_cnt) {                                   \
+	    a->pcard_sd->mpa_tx.start_port = port;                            \
+	}                                                           \
+	if (a->pcard_sd->mpa_tx.start_port <= port) {                         \
+	    a->pcard_sd->mpa_tx.ports |= (1 << (a->pcard_sd->mpa_tx.pkt_cnt));			\
+	} else {                                                    \
+	      a->pcard_sd->mpa_tx.ports |= (1 << (a->pcard_sd->mpa_tx.pkt_cnt \
+			+ 1 + (a->pcard_sd->max_ports - a->pcard_sd->mp_end_port)));  \
+	}                                                           \
+	a->pcard_sd->mpa_tx.pkt_cnt++;                                       \
+} while (0)
+
+/** SDIO Tx aggregation limit ? */
+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a)                                        \
+	((a->pcard_sd->mpa_tx.pkt_cnt) == (a->pcard_sd->mpa_tx.pkt_aggr_limit))
+
+#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->pcard_sd->curr_wr_port < \
+                a->pcard_sd->mpa_tx.start_port) && (((a->pcard_sd->max_ports - \
+                a->pcard_sd->mpa_tx.start_port) + a->pcard_sd->curr_wr_port) >= \
+                    a->pcard_sd->mp_aggr_pkt_limit))
+
+/** Reset SDIO Tx aggregation buffer parameters */
+#define MP_TX_AGGR_BUF_RESET(a)                                                \
+	do {                                                                   \
+		memset(a, a->pcard_sd->mpa_tx.mp_wr_info, 0,                   \
+		       sizeof(a->pcard_sd->mpa_tx.mp_wr_info));                \
+		a->pcard_sd->mpa_tx.pkt_cnt = 0;                               \
+		a->pcard_sd->mpa_tx.buf_len = 0;                               \
+		a->pcard_sd->mpa_tx.ports = 0;                                 \
+		a->pcard_sd->mpa_tx.start_port = 0;                            \
+	} while (0)
+
+/** SDIO Rx aggregation limit ? */
+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a)                                        \
+	(a->pcard_sd->mpa_rx.pkt_cnt == a->pcard_sd->mpa_rx.pkt_aggr_limit)
+
+/** SDIO Rx aggregation port limit ? */
+/** this is for test only, because port 0 is reserved for control port */
+/* #define MP_RX_AGGR_PORT_LIMIT_REACHED(a) (a->curr_rd_port == 1) */
+
+/* receive packets aggregated up to a half of mp_end_port */
+/* note: hw rx wraps round only after port (MAX_PORT-1) */
+#define MP_RX_AGGR_PORT_LIMIT_REACHED(a)                                       \
+	(((a->pcard_sd->curr_rd_port < a->pcard_sd->mpa_rx.start_port) &&      \
+	  (((a->pcard_sd->max_ports - a->pcard_sd->mpa_rx.start_port) +                      \
+	    a->pcard_sd->curr_rd_port) >= (a->pcard_sd->mp_end_port >> 1))) || \
+	 ((a->pcard_sd->curr_rd_port - a->pcard_sd->mpa_rx.start_port) >=      \
+	  (a->pcard_sd->mp_end_port >> 1)))
+
+#define MP_RX_AGGR_PORT_LIMIT_REACHED_NONEWMODE(a) ((a->pcard_sd->curr_rd_port < \
+                a->pcard_sd->mpa_rx.start_port) && (((a->pcard_sd->max_ports - \
+                a->pcard_sd->mpa_rx.start_port) + a->pcard_sd->curr_rd_port) >= \
+                a->pcard_sd->mp_aggr_pkt_limit))
+
+/** SDIO Rx aggregation in progress ? */
+#define MP_RX_AGGR_IN_PROGRESS(a) (a->pcard_sd->mpa_rx.pkt_cnt > 0)
+
+/** SDIO Rx aggregation buffer room for next packet ? */
+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)                                     \
+	((a->pcard_sd->mpa_rx.buf_len + rx_len) <= a->pcard_sd->mpa_rx.buf_size)
+
+/** Prepare to copy current packet from card to SDIO Rx aggregation buffer */
+#define MP_RX_AGGR_SETUP(a, mbuf, port, rx_len)                                \
+	do {                                                                   \
+		a->pcard_sd->mpa_rx.buf_len += rx_len;                         \
+		if (!a->pcard_sd->mpa_rx.pkt_cnt) {                            \
+			a->pcard_sd->mpa_rx.start_port = port;                 \
+		}                                                              \
+		a->pcard_sd->mpa_rx.ports |= (1 << port);                      \
+		a->pcard_sd->mpa_rx.mbuf_arr[a->pcard_sd->mpa_rx.pkt_cnt] =    \
+			mbuf;                                                  \
+		a->pcard_sd->mpa_rx.len_arr[a->pcard_sd->mpa_rx.pkt_cnt] =     \
+			rx_len;                                                \
+		a->pcard_sd->mpa_rx.pkt_cnt++;                                 \
+	} while (0)
+
+#define MP_RX_AGGR_SETUP_NONEWMODE(a, mbuf, port, rx_len) do {   \
+	a->pcard_sd->mpa_rx.buf_len += rx_len;                       \
+	if (!a->pcard_sd->mpa_rx.pkt_cnt) {                          \
+	    a->pcard_sd->mpa_rx.start_port = port;                   \
+	}                                                  \
+	if (a->pcard_sd->mpa_rx.start_port <= port) {                  \
+	    a->pcard_sd->mpa_rx.ports |= (1 << (a->pcard_sd->mpa_rx.pkt_cnt)); \
+	} else {                                           \
+	    a->pcard_sd->mpa_rx.ports |= (1 << (a->pcard_sd->mpa_rx.pkt_cnt + 1)); \
+	}                                                  \
+	a->pcard_sd->mpa_rx.mbuf_arr[a->pcard_sd->mpa_rx.pkt_cnt] = mbuf;      \
+	a->pcard_sd->mpa_rx.len_arr[a->pcard_sd->mpa_rx.pkt_cnt] = rx_len;     \
+	a->pcard_sd->mpa_rx.pkt_cnt++;                               \
+} while (0);
+
+/** Reset SDIO Rx aggregation buffer parameters */
+#define MP_RX_AGGR_BUF_RESET(a)                                                \
+	do {                                                                   \
+		a->pcard_sd->mpa_rx.pkt_cnt = 0;                               \
+		a->pcard_sd->mpa_rx.buf_len = 0;                               \
+		a->pcard_sd->mpa_rx.ports = 0;                                 \
+		a->pcard_sd->mpa_rx.start_port = 0;                            \
+	} while (0)
+
+/** aggr buf size 32k  */
+#define SDIO_MP_AGGR_BUF_SIZE_32K (32768)
+/** max aggr buf size 64k-256 */
+#define SDIO_MP_AGGR_BUF_SIZE_MAX (65280)
+
+extern mlan_adapter_operations mlan_sdio_ops;
+
+/** Probe and initialization function */
+mlan_status wlan_sdio_probe(pmlan_adapter pmadapter);
+mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter);
+
+mlan_status wlan_send_mp_aggr_buf(mlan_adapter *pmadapter);
+
+mlan_status wlan_re_alloc_sdio_rx_mpa_buffer(mlan_adapter *pmadapter);
+
+void wlan_decode_spa_buffer(mlan_adapter *pmadapter, t_u8 *buf, t_u32 len);
+t_void wlan_sdio_deaggr_rx_pkt(pmlan_adapter pmadapter, mlan_buffer *pmbuf);
+/** Transfer data to card */
+mlan_status wlan_sdio_host_to_card(mlan_adapter *pmadapter, t_u8 type,
+				   mlan_buffer *mbuf, mlan_tx_param *tx_param);
+mlan_status wlan_set_sdio_gpio_int(pmlan_private priv);
+mlan_status wlan_cmd_sdio_gpio_int(pmlan_private pmpriv,
+				   HostCmd_DS_COMMAND *cmd,
+				   t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_reset_fw(pmlan_adapter pmadapter);
+
+#endif /* _MLAN_SDIO_H */
diff --git a/wlan_sd8987/mlan/mlan_shim.c b/wlan_sd8987/mlan/mlan_shim.c
new file mode 100755
index 0000000..28d04f8
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_shim.c
@@ -0,0 +1,1893 @@
+/** @file mlan_shim.c
+ *
+ *  @brief This file contains APIs to MOAL module.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+#ifdef UAP_SUPPORT
+#include "mlan_uap.h"
+#endif
+#include "mlan_11h.h"
+#include "mlan_11n_rxreorder.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+#ifdef STA_SUPPORT
+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
+#ifdef STA_SUPPORT
+		case MLAN_IOCTL_MISC_CFG:
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			if (misc->sub_command == MLAN_OID_MISC_WARM_RESET) {
+				PRINTM(MCMND, "Warm Reset ioctl\n");
+				status = wlan_misc_ioctl_warm_reset(pmadapter,
+								    pioctl_buf);
+			}
+			break;
+#endif
+		default:
+			break;
+		}
+		if (status != MLAN_STATUS_PENDING)
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 pioctl_buf, status);
+	}
+	LEAVE();
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @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;
+
+#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->hs_wake_interval = pmdevice->hs_wake_interval;
+	if (pmdevice->indication_gpio != 0xff) {
+		pmadapter->ind_gpio = pmdevice->indication_gpio & 0x0f;
+		pmadapter->level = (pmdevice->indication_gpio & 0xf0) >> 4;
+		if (pmadapter->level != 0 && pmadapter->level != 1) {
+			PRINTM(MERROR,
+			       "Indication GPIO level is wrong and will use default value 0.\n");
+			pmadapter->level = 0;
+		}
+	}
+	pmadapter->hs_mimo_switch = pmdevice->hs_mimo_switch;
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		pmadapter->tx_cmd_ep = pmdevice->tx_cmd_ep;
+		pmadapter->rx_cmd_ep = pmdevice->rx_cmd_ep;
+		pmadapter->tx_data_ep = pmdevice->tx_data_ep;
+		pmadapter->rx_data_ep = pmdevice->rx_data_ep;
+	}
+#endif
+	pmadapter->init_para.dfs53cfg = pmdevice->dfs53cfg;
+	pmadapter->priv_num = 0;
+	pmadapter->priv[0] = MNULL;
+
+	if (pcb->moal_vmalloc && pcb->moal_vfree)
+		ret = pcb->moal_vmalloc(pmadapter->pmoal_handle,
+					sizeof(mlan_private),
+					(t_u8 **)&pmadapter->priv[0]);
+	else
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+				       sizeof(mlan_private), MLAN_MEM_DEF,
+				       (t_u8 **)&pmadapter->priv[0]);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[0]) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+
+	pmadapter->priv_num++;
+	memset(pmadapter, pmadapter->priv[0], 0, sizeof(mlan_private));
+
+	pmadapter->priv[0]->adapter = pmadapter;
+	pmadapter->priv[0]->bss_type = (t_u8)pmdevice->bss_attr[0].bss_type;
+	pmadapter->priv[0]->frame_type = (t_u8)pmdevice->bss_attr[0].frame_type;
+	pmadapter->priv[0]->bss_priority =
+		(t_u8)pmdevice->bss_attr[0].bss_priority;
+	if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_STA)
+		pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
+	else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_UAP)
+		pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_UAP;
+#ifdef WIFI_DIRECT_SUPPORT
+	else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
+		if (pmdevice->bss_attr[0].bss_virtual)
+			pmadapter->priv[0]->bss_virtual = MTRUE;
+	}
+#endif
+	/* Save bss_index and bss_num */
+	pmadapter->priv[0]->bss_index = 0;
+	pmadapter->priv[0]->bss_num = (t_u8)pmdevice->bss_attr[0].bss_num;
+
+	/* init function table */
+	for (j = 0; mlan_ops[j]; j++) {
+		if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmadapter->priv[0])) {
+			memcpy_ext(pmadapter, &pmadapter->priv[0]->ops,
+				   mlan_ops[j], sizeof(mlan_operations),
+				   sizeof(mlan_operations));
+			break;
+		}
+	}
+	/** back up bss_attr table */
+	memcpy_ext(pmadapter, pmadapter->bss_attr, pmdevice->bss_attr,
+		   sizeof(pmadapter->bss_attr), sizeof(pmadapter->bss_attr));
+
+	/* Initialize lock variables */
+	if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+
+	/** init lock varible for first priv */
+	if (wlan_init_priv_lock_list(pmadapter, 0) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+
+	/* Allocate memory for member of adapter structure */
+	if (wlan_allocate_adapter(pmadapter)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+
+	/* Initialize timers */
+	if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+	/* Return pointer of mlan_adapter to MOAL */
+	*ppmlan_adapter = pmadapter;
+
+	goto exit_register;
+
+error:
+	PRINTM(MINFO, "Leave mlan_register with error\n");
+	/* Free adapter structure */
+	wlan_free_adapter(pmadapter);
+
+	for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
+		if (pmadapter->priv[i]) {
+			if (pcb->moal_vmalloc && pcb->moal_vfree)
+				pcb->moal_vfree(pmadapter->pmoal_handle,
+						(t_u8 *)pmadapter->priv[i]);
+			else if (pcb->moal_mfree)
+				pcb->moal_mfree(pmadapter->pmoal_handle,
+						(t_u8 *)pmadapter->priv[i]);
+		}
+	}
+	if (pcb->moal_vmalloc && pcb->moal_vfree)
+		pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+	else if (pcb->moal_mfree)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
+
+exit_register:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function unregisters MOAL from MLAN module.
+ *
+ *  @param 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 */
+		if (pmadapter->cmd_resp_received) {
+			pmadapter->cmd_resp_received = MFALSE;
+			wlan_process_cmdresp(pmadapter);
+
+			/* call moal back when init_fw is done */
+			if (pmadapter->hw_status == WlanHardwareStatusInitdone) {
+				pmadapter->hw_status = WlanHardwareStatusReady;
+				wlan_init_fw_complete(pmadapter);
+			} else if (pmadapter->hw_status ==
+				   WlanHardwareStatusGetHwSpecdone) {
+				pmadapter->hw_status =
+					WlanHardwareStatusInitializing;
+				wlan_get_hw_spec_complete(pmadapter);
+			}
+		}
+
+		/* Check for event */
+		if (pmadapter->event_received) {
+			pmadapter->event_received = MFALSE;
+			wlan_process_event(pmadapter);
+		}
+
+		/* Check if we need to confirm Sleep Request received previously
+		 */
+		if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
+			if (!pmadapter->cmd_sent && !pmadapter->curr_cmd
+			    && !pmadapter->vdll_ctrl.pending_block)
+				wlan_check_ps_cond(pmadapter);
+
+		/*
+		 * The ps_state may have been changed during processing of
+		 * Sleep Request event.
+		 */
+		if ((pmadapter->ps_state == PS_STATE_SLEEP) ||
+		    (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
+		    || (pmadapter->ps_state == PS_STATE_SLEEP_CFM) ||
+		    (pmadapter->tx_lock_flag == MTRUE)
+			) {
+			continue;
+		}
+
+		/* in a case of race condition, download the VDLL block here */
+		if (!pmadapter->cmd_sent && pmadapter->vdll_ctrl.pending_block) {
+			wlan_download_vdll_block(pmadapter,
+						 pmadapter->vdll_ctrl.
+						 pending_block,
+						 pmadapter->vdll_ctrl.
+						 pending_block_len);
+			pmadapter->vdll_ctrl.pending_block = MNULL;
+		}
+		if (!pmadapter->cmd_sent && !pmadapter->curr_cmd
+		    && 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)
+		mlan_shutdown_fw(pmadapter);
+	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;
+	}
+	if (pioctl_req->action == MLAN_ACT_CANCEL) {
+		wlan_cancel_pending_ioctl(pmadapter, pioctl_req);
+		ret = MLAN_STATUS_SUCCESS;
+		goto exit;
+	}
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	ret = pmpriv->ops.ioctl(adapter, pioctl_req);
+exit:
+	LEAVE();
+	return ret;
+}
+
+#ifdef USB
+/**
+ *  @brief Packet send completion callback
+ *
+ *  @param 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;
+		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;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec, usec;
+#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 {
+				pmadapter->upld_len = len;
+				pmbuf->data_offset += MLAN_TYPE_LEN;
+				pmbuf->data_len -= MLAN_TYPE_LEN;
+				pmadapter->curr_cmd->respbuf = pmbuf;
+				pmadapter->cmd_resp_received = MTRUE;
+			}
+			break;
+		case MLAN_USB_TYPE_EVENT:
+			MASSERT(len >= sizeof(t_u32));
+			memmove(pmadapter, &event_cause, pbuf, sizeof(t_u32));
+			pmadapter->event_cause = wlan_le32_to_cpu(event_cause);
+			PRINTM_GET_SYS_TIME(MEVENT, &sec, &usec);
+			PRINTM(MEVENT, "mlan_recv: EVENT 0x%x (%lu.%06lu)\n",
+			       pmadapter->event_cause, sec, usec);
+			pbuf += sizeof(t_u32);
+			len -= sizeof(t_u32);
+			if ((len > 0) && (len < MAX_EVENT_SIZE))
+				memmove(pmadapter, pmadapter->event_body, pbuf,
+					len);
+			pmadapter->event_received = MTRUE;
+			pmadapter->pmlan_buffer_event = pmbuf;
+			/* remove 4 byte recv_type */
+			pmbuf->data_offset += MLAN_TYPE_LEN;
+			pmbuf->data_len -= MLAN_TYPE_LEN;
+			/* MOAL to call mlan_main_process for processing */
+			break;
+		default:
+			pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			PRINTM(MERROR, "mlan_recv: unknown recv_type 0x%x\n",
+			       recv_type);
+			break;
+		}
+	} else if (port == pmadapter->rx_data_ep) {
+		PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+		PRINTM(MDATA, "mlan_recv: DATA (%lu.%06lu)\n", sec, usec);
+#if defined(USB)
+		if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable) {
+			max_rx_data_size =
+				pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+				aggr_max;
+			if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+			    aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
+				max_rx_data_size *=
+					MAX(MLAN_USB_MAX_PKT_SIZE,
+					    pmadapter->pcard_usb->usb_rx_deaggr.
+					    aggr_ctrl.aggr_align);
+				max_rx_data_size =
+					MAX(max_rx_data_size,
+					    MLAN_RX_DATA_BUF_SIZE);
+			}
+		}
+#endif
+		if (len > max_rx_data_size) {
+			pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			PRINTM(MERROR, "mlan_recv: DATA too large\n");
+		} else {
+			pmadapter->upld_len = len;
+			pmadapter->callbacks.moal_get_system_time(pmadapter->
+								  pmoal_handle,
+								  &pmbuf->
+								  in_ts_sec,
+								  &pmbuf->
+								  in_ts_usec);
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    pmadapter->
+							    rx_data_queue.
+							    plock);
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->rx_data_queue,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+			pmadapter->rx_pkts_queued++;
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      pmadapter->
+							      rx_data_queue.
+							      plock);
+			pmadapter->data_received = MTRUE;
+			mlan_queue_rx_work(pmadapter);
+		}
+	} else {
+		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		PRINTM(MERROR, "mlan_recv: unknown port number 0x%x\n", port);
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif /* USB */
+
+/**
+ *  @brief Packet receive completion callback handler
+ *
+ *  @param 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;
+			wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_EAPOL_PKT,
+					 0, 0, MNULL, pmbuf);
+			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
diff --git a/wlan_sd8987/mlan/mlan_sta_cmd.c b/wlan_sd8987/mlan/mlan_sta_cmd.c
new file mode 100755
index 0000000..f51619c
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_cmd.c
@@ -0,0 +1,3711 @@
+/** @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-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+ * Change log:
+ *    10/21/2008: initial version
+ ******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#include "mlan_meas.h"
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+
+/********************************************************
+ *                 Local Variables
+ ********************************************************/
+
+/********************************************************
+ *                 Global Variables
+ ********************************************************/
+
+/********************************************************
+ *                 Local Functions
+ ********************************************************/
+
+/**
+ *  @brief This function prepares command of RSSI info.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Command action
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_rssi_info(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action)
+{
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_RSSI_INFO);
+	pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RSSI_INFO) +
+				      S_DS_GEN);
+	pcmd->params.rssi_info.action = wlan_cpu_to_le16(cmd_action);
+	pcmd->params.rssi_info.ndata =
+		wlan_cpu_to_le16(pmpriv->data_avg_factor);
+	pcmd->params.rssi_info.nbcn = wlan_cpu_to_le16(pmpriv->bcn_avg_factor);
+
+	/* Reset SNR/NF/RSSI values in private structure */
+	pmpriv->data_rssi_last = 0;
+	pmpriv->data_nf_last = 0;
+	pmpriv->data_rssi_avg = 0;
+	pmpriv->data_nf_avg = 0;
+	pmpriv->bcn_rssi_last = 0;
+	pmpriv->bcn_nf_last = 0;
+	pmpriv->bcn_rssi_avg = 0;
+	pmpriv->bcn_nf_avg = 0;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of RSSI info.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Command action
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_rssi_info_ext(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *pcmd,
+			      t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_RSSI_INFO_EXT *rssi_info_ext_cmd =
+		&pcmd->params.rssi_info_ext;
+	mlan_ds_get_info *info = (mlan_ds_get_info *)pdata_buf;
+	MrvlIEtypes_RSSI_EXT_t *signal_info_tlv = MNULL;
+	t_u8 *pos = MNULL;
+
+	ENTER();
+
+	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_RSSI_INFO_EXT);
+	pcmd->size = sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT) + S_DS_GEN;
+	rssi_info_ext_cmd->action = wlan_cpu_to_le16(cmd_action);
+	rssi_info_ext_cmd->ndata = 0;
+	rssi_info_ext_cmd->nbcn = 0;
+
+	if (info->param.path_id) {
+		pos = (t_u8 *)rssi_info_ext_cmd->tlv_buf;
+		signal_info_tlv = (MrvlIEtypes_RSSI_EXT_t *) pos;
+		signal_info_tlv->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_RSSI_EXT_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		signal_info_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_RSSI_INFO);
+		signal_info_tlv->path_id =
+			wlan_cpu_to_le16(info->param.path_id);
+		pcmd->size += sizeof(MrvlIEtypes_RSSI_EXT_t);
+	}
+	pcmd->size = wlan_cpu_to_le16(pcmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of snmp_mib.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param cmd_oid      OID: ENABLE or DISABLE
+ *  @param pdata_buf    A pointer to command information buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_snmp_mib(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd,
+			 t_u16 cmd_action, t_u32 cmd_oid, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.smib;
+	t_u32 ul_temp;
+
+	ENTER();
+	PRINTM(MINFO, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+	cmd->size = sizeof(HostCmd_DS_802_11_SNMP_MIB) - 1 + S_DS_GEN;
+
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+		psnmp_mib->buf_size = wlan_cpu_to_le16(MAX_SNMP_BUF_SIZE);
+		cmd->size += MAX_SNMP_BUF_SIZE;
+	}
+
+	switch (cmd_oid) {
+	case DtimPeriod_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)DtimPeriod_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+			ul_temp = *((t_u32 *)pdata_buf);
+			psnmp_mib->value[0] = (t_u8)ul_temp;
+			cmd->size += sizeof(t_u8);
+		}
+		break;
+	case FragThresh_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)FragThresh_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = *((t_u32 *)pdata_buf);
+			*((t_u16 *)(psnmp_mib->value)) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+		}
+		break;
+	case RtsThresh_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)RtsThresh_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = *((t_u32 *)pdata_buf);
+			*(t_u16 *)(psnmp_mib->value) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+		}
+		break;
+
+	case ShortRetryLim_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)ShortRetryLim_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = (*(t_u32 *)pdata_buf);
+			*((t_u16 *)(psnmp_mib->value)) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+		}
+		break;
+	case Dot11D_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11D_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = *(t_u32 *)pdata_buf;
+			*((t_u16 *)(psnmp_mib->value)) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+		}
+		break;
+	case Dot11H_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11H_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = *(t_u32 *)pdata_buf;
+			*((t_u16 *)(psnmp_mib->value)) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+		}
+		break;
+	case WwsMode_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)WwsMode_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = *((t_u32 *)pdata_buf);
+			*((t_u16 *)(psnmp_mib->value)) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+		}
+		break;
+	case Thermal_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Thermal_i);
+		break;
+	case NullPktPeriod_i:
+		/** keep alive null data pkt interval in full power mode */
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)NullPktPeriod_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u32));
+			ul_temp = *((t_u32 *)pdata_buf);
+			ul_temp = wlan_cpu_to_le32(ul_temp);
+			memcpy_ext(pmpriv->adapter, psnmp_mib->value, &ul_temp,
+				   sizeof(t_u32), sizeof(t_u32));
+			cmd->size += sizeof(t_u32);
+		}
+		break;
+	case ECSAEnable_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)ECSAEnable_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+			psnmp_mib->value[0] = *((t_u8 *)pdata_buf);
+			cmd->size += sizeof(t_u8);
+		}
+		break;
+	case SignalextEnable_i:
+		psnmp_mib->oid = wlan_cpu_to_le16((t_u16)SignalextEnable_i);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			psnmp_mib->query_type =
+				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+			psnmp_mib->value[0] = *(t_u8 *)pdata_buf;
+			cmd->size += sizeof(t_u8);
+		}
+		break;
+	default:
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	PRINTM(MINFO,
+	       "SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x, Value=0x%x\n",
+	       cmd_action, cmd_oid, wlan_le16_to_cpu(psnmp_mib->buf_size),
+	       wlan_le16_to_cpu(*(t_u16 *)psnmp_mib->value));
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of get_log.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_get_log(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd)
+{
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of MFG Continuous Tx cmd.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param action       The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_mfg_tx_cont(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *cmd, t_u16 action, t_void *pdata_buf)
+{
+	struct mfg_cmd_tx_cont *mcmd = (struct mfg_cmd_tx_cont
+					*)&cmd->params.mfg_tx_cont;
+	struct mfg_cmd_tx_cont *cfg = (struct mfg_cmd_tx_cont *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
+	cmd->size = wlan_cpu_to_le16(sizeof(struct mfg_cmd_tx_cont) + S_DS_GEN);
+
+	mcmd->mfg_cmd = wlan_cpu_to_le32(cfg->mfg_cmd);
+	mcmd->action = wlan_cpu_to_le16(action);
+	if (action == HostCmd_ACT_GEN_SET) {
+		mcmd->enable_tx = wlan_cpu_to_le32(cfg->enable_tx);
+		mcmd->cw_mode = wlan_cpu_to_le32(cfg->cw_mode);
+		mcmd->payload_pattern = wlan_cpu_to_le32(cfg->payload_pattern);
+		mcmd->cs_mode = wlan_cpu_to_le32(cfg->cs_mode);
+		mcmd->act_sub_ch = wlan_cpu_to_le32(cfg->act_sub_ch);
+		mcmd->tx_rate = wlan_cpu_to_le32(cfg->tx_rate);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of MFG Tx frame.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param action       The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_mfg_tx_frame(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *cmd, t_u16 action, t_void *pdata_buf)
+{
+	struct mfg_cmd_tx_frame2 *mcmd = (struct mfg_cmd_tx_frame2
+					  *)&cmd->params.mfg_tx_frame2;
+	struct mfg_cmd_tx_frame2 *cfg = (struct mfg_cmd_tx_frame2 *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
+	cmd->size = wlan_cpu_to_le16(sizeof(struct mfg_cmd_tx_frame2) +
+				     S_DS_GEN);
+
+	mcmd->mfg_cmd = wlan_cpu_to_le32(cfg->mfg_cmd);
+	mcmd->action = wlan_cpu_to_le16(action);
+	if (action == HostCmd_ACT_GEN_SET) {
+		mcmd->enable = wlan_cpu_to_le32(cfg->enable);
+		mcmd->data_rate = wlan_cpu_to_le32(cfg->data_rate);
+		mcmd->frame_pattern = wlan_cpu_to_le32(cfg->frame_pattern);
+		mcmd->frame_length = wlan_cpu_to_le32(cfg->frame_length);
+		mcmd->adjust_burst_sifs =
+			wlan_cpu_to_le16(cfg->adjust_burst_sifs);
+		mcmd->burst_sifs_in_us =
+			wlan_cpu_to_le32(cfg->burst_sifs_in_us);
+		mcmd->short_preamble = wlan_cpu_to_le32(cfg->short_preamble);
+		mcmd->act_sub_ch = wlan_cpu_to_le32(cfg->act_sub_ch);
+		mcmd->short_gi = wlan_cpu_to_le32(cfg->short_gi);
+		mcmd->tx_bf = wlan_cpu_to_le32(cfg->tx_bf);
+		mcmd->gf_mode = wlan_cpu_to_le32(cfg->gf_mode);
+		mcmd->stbc = wlan_cpu_to_le32(cfg->stbc);
+		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 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_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();
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_MULTICAST_ADR) +
+				     S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
+
+	pmc_addr->action = wlan_cpu_to_le16(cmd_action);
+	pmc_addr->num_of_adrs =
+		wlan_cpu_to_le16((t_u16)pmcast_list->num_multicast_addr);
+	memcpy_ext(pmpriv->adapter, pmc_addr->mac_list, pmcast_list->mac_list,
+		   pmcast_list->num_multicast_addr * MLAN_MAC_ADDR_LENGTH,
+		   sizeof(pmc_addr->mac_list));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of deauthenticate/disassociate.
+ *
+ * @param pmpriv       A pointer to mlan_private structure
+ * @param cmd_no       Command number
+ * @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ * @param pdata_buf    A pointer to data buffer
+ *
+ * @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_deauthenticate(pmlan_private pmpriv,
+			       t_u16 cmd_no,
+			       HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_DEAUTHENTICATE *pdeauth = &cmd->params.deauth;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(cmd_no);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_DEAUTHENTICATE) +
+				     S_DS_GEN);
+
+	/* Set AP MAC address */
+	memcpy_ext(pmpriv->adapter, pdeauth, (t_u8 *)pdata_buf,
+		   sizeof(*pdeauth), sizeof(*pdeauth));
+	if (cmd_no == HostCmd_CMD_802_11_DEAUTHENTICATE)
+		PRINTM(MCMND, "Deauth: " MACSTR "\n",
+		       MAC2STR(pdeauth->mac_addr));
+	else
+		PRINTM(MCMND, "Disassociate: " MACSTR "\n",
+		       MAC2STR(pdeauth->mac_addr));
+
+	if (pmpriv->adapter->state_11h.recvd_chanswann_event) {
+/** Reason code 36 = Requested from peer station as it is leaving the BSS */
+#define REASON_CODE_PEER_STA_LEAVING 36
+		pdeauth->reason_code =
+			wlan_cpu_to_le16(REASON_CODE_PEER_STA_LEAVING);
+	} else {
+		pdeauth->reason_code = wlan_cpu_to_le16(pdeauth->reason_code);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of ad_hoc_stop.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_802_11_ad_hoc_stop(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd)
+{
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN);
+
+	if (wlan_11h_is_active(pmpriv))
+		wlan_11h_activate(pmpriv, MNULL, MFALSE);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of key_material.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param cmd_oid      OID: ENABLE or DISABLE
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_802_11_key_material(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *cmd,
+			     t_u16 cmd_action, t_u32 cmd_oid, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_KEY_MATERIAL *pkey_material =
+		&cmd->params.key_material;
+	mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *)pdata_buf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (!pkey) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+	pkey_material->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		PRINTM(MCMND, "GET Key\n");
+		pkey_material->key_param_set.key_idx =
+			pkey->key_index & KEY_INDEX_MASK;
+		pkey_material->key_param_set.type =
+			wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.mac_addr,
+			   pkey->mac_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_MCAST_KEY;
+		else
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_UCAST_KEY;
+		if (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)
+			pkey_material->key_param_set.key_info =
+				KEY_INFO_CMAC_AES_KEY;
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+		cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					     S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					     sizeof(pkey_material->action));
+		goto done;
+	}
+	memset(pmpriv->adapter, &pkey_material->key_param_set, 0,
+	       sizeof(MrvlIEtype_KeyParamSetV2_t));
+	if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) {
+		pkey_material->action =
+			wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+		pkey_material->key_param_set.type =
+			wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+		pkey_material->key_param_set.key_idx =
+			pkey->key_index & KEY_INDEX_MASK;
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(KEY_INFO_MCAST_KEY |
+					 KEY_INFO_UCAST_KEY);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.mac_addr,
+			   pkey->mac_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Remove Key\n");
+		goto done;
+	}
+	pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+	pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK;
+	pkey_material->key_param_set.type =
+		wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+	pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY;
+	memcpy_ext(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		   pkey->mac_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	if (pkey->key_len <= MAX_WEP_KEY_SIZE) {
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(wep_param_t));
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_WEP;
+		if (pkey->is_current_wep_key) {
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY;
+			if (pkey_material->key_param_set.key_idx ==
+			    (pmpriv->wep_key_curr_index & KEY_INDEX_MASK))
+				pkey_material->key_param_set.key_info |=
+					KEY_INFO_DEFAULT_KEY;
+		} else {
+			if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+				pkey_material->key_param_set.key_info |=
+					KEY_INFO_MCAST_KEY;
+			else
+				pkey_material->key_param_set.key_info |=
+					KEY_INFO_UCAST_KEY;
+		}
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+		pkey_material->key_param_set.key_params.wep.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.wep.key,
+			   pkey->key_material, pkey->key_len, MAX_WEP_KEY_SIZE);
+		cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					     S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					     sizeof(wep_param_t) +
+					     sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set WEP Key\n");
+		goto done;
+	}
+	if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+		pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY;
+	else
+		pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY;
+	if (pkey->key_flags & KEY_FLAG_SET_TX_KEY)
+		pkey_material->key_param_set.key_info |=
+			KEY_INFO_TX_KEY | KEY_INFO_RX_KEY;
+	else
+		pkey_material->key_param_set.key_info |= KEY_INFO_RX_KEY;
+	if (pkey->is_wapi_key) {
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_WAPI;
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.wapi.pn,
+			   pkey->pn, PN_SIZE, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.wapi.key,
+			   pkey->key_material, pkey->key_len, WAPI_KEY_SIZE);
+		if (!pmpriv->sec_info.wapi_key_on)
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_DEFAULT_KEY;
+		if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+			pmpriv->sec_info.wapi_key_on = MTRUE;
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(wapi_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(wapi_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set WAPI Key\n");
+		goto done;
+	}
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+		/* Enable default key for WPA/WPA2 */
+		if (!pmpriv->wpa_is_gtk_set)
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_DEFAULT_KEY;
+	} else {
+		pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY;
+		/* Enable unicast bit for WPA-NONE/ADHOC_AES */
+		if ((!pmpriv->sec_info.wpa2_enabled) &&
+		    (pkey->key_flags & KEY_FLAG_SET_TX_KEY))
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_UCAST_KEY;
+	}
+	pkey_material->key_param_set.key_info =
+		wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+	if (pkey->key_flags & KEY_FLAG_GCMP ||
+	    pkey->key_flags & KEY_FLAG_GCMP_256) {
+		if (pkey->key_flags &
+		    (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) {
+			memcpy_ext(pmpriv->adapter,
+				   pkey_material->key_param_set.key_params.gcmp.
+				   pn, pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+		}
+		if (pkey->key_flags & KEY_FLAG_GCMP)
+			pkey_material->key_param_set.key_type =
+				KEY_TYPE_ID_GCMP;
+		else
+			pkey_material->key_param_set.key_type =
+				KEY_TYPE_ID_GCMP_256;
+		pkey_material->key_param_set.key_params.gcmp.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.gcmp.key,
+			   pkey->key_material, pkey->key_len, WPA_GCMP_KEY_LEN);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(gcmp_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(gcmp_param) +
+					 sizeof(pkey_material->action));
+
+		goto done;
+	}
+	if (pkey->key_flags & KEY_FLAG_CCMP_256) {
+		if (pkey->key_flags &
+		    (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) {
+			memcpy_ext(pmpriv->adapter,
+				   pkey_material->key_param_set.key_params.
+				   ccmp256.pn, pkey->pn, SEQ_MAX_SIZE,
+				   WPA_PN_SIZE);
+		}
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_CCMP_256;
+		pkey_material->key_param_set.key_params.ccmp256.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.ccmp256.key,
+			   pkey->key_material, pkey->key_len,
+			   WPA_CCMP_256_KEY_LEN);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(ccmp_256_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(ccmp_256_param) +
+					 sizeof(pkey_material->action));
+
+		goto done;
+	}
+	if (pkey->key_len == WPA_AES_KEY_LEN &&
+	    !(pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+		if (pkey->key_flags &
+		    (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy_ext(pmpriv->adapter,
+				   pkey_material->key_param_set.key_params.aes.
+				   pn, pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES;
+		pkey_material->key_param_set.key_params.aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.aes.key,
+			   pkey->key_material, pkey->key_len, WPA_AES_KEY_LEN);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_IGTK_KEY_LEN &&
+	    (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+		if (pkey->key_flags &
+		    (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy_ext(pmpriv->adapter,
+				   pkey_material->key_param_set.key_params.
+				   cmac_aes.ipn, pkey->pn, SEQ_MAX_SIZE,
+				   IGTK_PN_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		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.
+				   cmac_aes.ipn, pkey->pn, SEQ_MAX_SIZE,
+				   IGTK_PN_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type =
+			KEY_TYPE_ID_BIP_GMAC_256;
+		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,
+			   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;
+	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_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);
+				}
+				/* 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, "FW Vhtcap",
+						    (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(VHTOper_tlv->chan_width));
+				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, "VHT operation",
+					    (t_u8 *)VHTOper_tlv,
+					    sizeof(MrvlIETypes_VHTOprat_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;
+}
+
+#ifdef USB
+/**
+ *  @brief This function prepares command of packet aggragation
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_packet_aggr_over_host_interface(pmlan_private pmpriv,
+					 HostCmd_DS_COMMAND *cmd,
+					 t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE *packet_aggr =
+		&cmd->params.packet_aggr;
+	MrvlIETypes_USBAggrParam_t *usb_aggr_param_tlv = MNULL;
+	mlan_ds_misc_usb_aggr_ctrl *usb_aggr_ctrl =
+		(mlan_ds_misc_usb_aggr_ctrl *)pdata_buf;
+	t_u8 *ptlv_buffer = (t_u8 *)packet_aggr->tlv_buf;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	usb_aggr_param_tlv = (MrvlIETypes_USBAggrParam_t *)ptlv_buffer;
+
+	cmd->command =
+		wlan_cpu_to_le16(HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE);
+	packet_aggr->action = wlan_cpu_to_le16(cmd_action);
+	memset(pmadapter, usb_aggr_param_tlv, 0,
+	       MRVL_USB_AGGR_PARAM_TLV_LEN + sizeof(MrvlIEtypesHeader_t));
+	usb_aggr_param_tlv->header.type =
+		wlan_cpu_to_le16(MRVL_USB_AGGR_PARAM_TLV_ID);
+	usb_aggr_param_tlv->header.len =
+		wlan_cpu_to_le16(MRVL_USB_AGGR_PARAM_TLV_LEN);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof
+				 (HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE) +
+				 S_DS_GEN + MRVL_USB_AGGR_PARAM_TLV_LEN +
+				 sizeof(MrvlIEtypesHeader_t) - 1);
+
+	if (pmadapter->data_sent || (!wlan_bypass_tx_list_empty(pmadapter)) ||
+	    (!wlan_wmm_lists_empty(pmadapter))) {
+		/* Make sure this is not issued during traffic */
+		PRINTM(MERROR,
+		       "USB aggregation parameters cannot be accessed during traffic.\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		usb_aggr_param_tlv->enable = 0;
+		if (usb_aggr_ctrl->tx_aggr_ctrl.enable)
+			usb_aggr_param_tlv->enable |= MBIT(1);
+		usb_aggr_param_tlv->tx_aggr_align =
+			wlan_cpu_to_le16(usb_aggr_ctrl->tx_aggr_ctrl.
+					 aggr_align);
+		if (usb_aggr_ctrl->rx_deaggr_ctrl.enable)
+			usb_aggr_param_tlv->enable |= MBIT(0);
+		usb_aggr_param_tlv->rx_aggr_mode =
+			wlan_cpu_to_le16(usb_aggr_ctrl->rx_deaggr_ctrl.
+					 aggr_mode);
+		usb_aggr_param_tlv->rx_aggr_align =
+			wlan_cpu_to_le16(usb_aggr_ctrl->rx_deaggr_ctrl.
+					 aggr_align);
+		usb_aggr_param_tlv->rx_aggr_max =
+			wlan_cpu_to_le16(usb_aggr_ctrl->rx_deaggr_ctrl.
+					 aggr_max);
+		usb_aggr_param_tlv->rx_aggr_tmo =
+			wlan_cpu_to_le16(usb_aggr_ctrl->rx_deaggr_ctrl.
+					 aggr_tmo);
+		usb_aggr_param_tlv->enable =
+			wlan_cpu_to_le16(usb_aggr_param_tlv->enable);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function prepares inactivity timeout command
+ *
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_inactivity_timeout(HostCmd_DS_COMMAND *cmd,
+			    t_u16 cmd_action, t_void *pdata_buf)
+{
+	pmlan_ds_inactivity_to inac_to;
+	HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
+		&cmd->params.inactivity_to;
+
+	ENTER();
+
+	inac_to = (mlan_ds_inactivity_to *)pdata_buf;
+
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_INACTIVITY_TIMEOUT_EXT) +
+				     S_DS_GEN);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_inac_to->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cmd_inac_to->timeout_unit =
+			wlan_cpu_to_le16((t_u16)inac_to->timeout_unit);
+		cmd_inac_to->unicast_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->unicast_timeout);
+		cmd_inac_to->mcast_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->mcast_timeout);
+		cmd_inac_to->ps_entry_timeout =
+			wlan_cpu_to_le16((t_u16)inac_to->ps_entry_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares Low Power Mode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_low_pwr_mode(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	HostCmd_CONFIG_LOW_PWR_MODE *cmd_lpm_cfg =
+		&cmd->params.low_pwr_mode_cfg;
+	t_u8 *enable;
+
+	ENTER();
+
+	cmd->size = S_DS_GEN + sizeof(HostCmd_CONFIG_LOW_PWR_MODE);
+
+	enable = (t_u8 *)pdata_buf;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_lpm_cfg->enable = *enable;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares DFS repeater mode configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_cmd_dfs_repeater_cfg(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd,
+			  t_u16 cmd_action, t_void *pdata_buf)
+{
+	mlan_ds_misc_dfs_repeater *dfs_repeater = MNULL;
+	HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+		&cmd->params.dfs_repeater;
+
+	ENTER();
+
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DFS_REPEATER_MODE);
+
+	dfs_repeater = (mlan_ds_misc_dfs_repeater *)pdata_buf;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	cmd->command = wlan_cpu_to_le16(cmd->command);
+	cmd_dfs_repeater->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET)
+		cmd_dfs_repeater->mode = wlan_cpu_to_le16(dfs_repeater->mode);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of coalesce_config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+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
+ ********************************************************/
+
+static mlan_status
+wlan_cmd_get_sensor_temp(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action)
+{
+	ENTER();
+
+	if (cmd_action != HostCmd_ACT_GEN_GET) {
+		PRINTM(MERROR, "wlan_cmd_get_sensor_temp: support GET only.\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_DS_GET_SENSOR_TEMP);
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN + 4);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of arb cfg
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_arb_cfg(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_ARB_CONFIG *cfg_cmd =
+		(HostCmd_DS_CMD_ARB_CONFIG *) & cmd->params.arb_cfg;
+	mlan_ds_misc_arb_cfg *misc_cfg = (mlan_ds_misc_arb_cfg *) pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ARB_CONFIG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_ARB_CONFIG) +
+				     S_DS_GEN);
+	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		cfg_cmd->arb_mode = wlan_cpu_to_le32(misc_cfg->arb_mode);
+		if (misc_cfg->arb_mode == 3) {
+#define DEF_ARB_TX_WIN   4
+#define DEF_ARB_TIMEOUT  0
+			pmpriv->add_ba_param.timeout = DEF_ARB_TIMEOUT;
+			pmpriv->add_ba_param.tx_win_size = DEF_ARB_TX_WIN;
+		} else {
+			pmpriv->add_ba_param.timeout =
+				MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+			pmpriv->add_ba_param.tx_win_size =
+				MLAN_STA_AMPDU_DEF_TXWINSIZE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function 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 sends set and get auto tx command to firmware.
+ *
+ *  @param pmpriv         A pointer to mlan_private structure
+ *  @param pcmd          Hostcmd ID
+ *  @param cmd_action   Command action
+ *  @param cmd_oid      Cmd oid: treated as sub command
+ *  @param pdata_buf    A void pointer to information buffer
+ *  @return             N/A
+ */
+static mlan_status
+wlan_cmd_auto_tx(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *cmd,
+		 t_u16 cmd_action, t_u32 cmd_oid, t_void *pdata_buf)
+{
+	HostCmd_DS_AUTO_TX *auto_tx_cmd = &cmd->params.auto_tx;
+	t_u8 *pos = (t_u8 *)auto_tx_cmd->tlv_buffer;
+	t_u16 len = 0;
+	MrvlIEtypes_Cloud_Keep_Alive_t *keep_alive_tlv = MNULL;
+	MrvlIEtypes_Keep_Alive_Ctrl_t *ctrl_tlv = MNULL;
+	MrvlIEtypes_Keep_Alive_Pkt_t *pkt_tlv = MNULL;
+	mlan_ds_misc_keep_alive *misc_keep_alive = MNULL;
+	t_u8 eth_ip[] = { 0x08, 0x00 };
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_AUTO_TX);
+	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_AUTO_TX);
+	auto_tx_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	switch (cmd_oid) {
+	case OID_CLOUD_KEEP_ALIVE:
+		misc_keep_alive = (mlan_ds_misc_keep_alive *) pdata_buf;
+		keep_alive_tlv = (MrvlIEtypes_Cloud_Keep_Alive_t *) pos;
+
+		keep_alive_tlv->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_CLOUD_KEEP_ALIVE);
+		keep_alive_tlv->keep_alive_id = misc_keep_alive->mkeep_alive_id;
+		keep_alive_tlv->enable = misc_keep_alive->enable;
+		len = len + sizeof(keep_alive_tlv->keep_alive_id) +
+			sizeof(keep_alive_tlv->enable);
+		pos = pos + len + sizeof(MrvlIEtypesHeader_t);
+		if (cmd_action == HostCmd_ACT_GEN_SET) {
+			if (misc_keep_alive->enable) {
+				ctrl_tlv =
+					(MrvlIEtypes_Keep_Alive_Ctrl_t *) pos;
+				ctrl_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_KEEP_ALIVE_CTRL);
+				ctrl_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_Keep_Alive_Ctrl_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				ctrl_tlv->snd_interval =
+					wlan_cpu_to_le32(misc_keep_alive->
+							 send_interval);
+				ctrl_tlv->retry_interval =
+					wlan_cpu_to_le16(misc_keep_alive->
+							 retry_interval);
+				ctrl_tlv->retry_count =
+					wlan_cpu_to_le16(misc_keep_alive->
+							 retry_count);
+				len = len +
+					sizeof(MrvlIEtypes_Keep_Alive_Ctrl_t);
+
+				pos = pos +
+					sizeof(MrvlIEtypes_Keep_Alive_Ctrl_t);
+				pkt_tlv = (MrvlIEtypes_Keep_Alive_Pkt_t *) pos;
+				pkt_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_KEEP_ALIVE_PKT);
+				memcpy_ext(pmpriv->adapter,
+					   pkt_tlv->eth_header.dest_addr,
+					   misc_keep_alive->dst_mac,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				memcpy_ext(pmpriv->adapter,
+					   pkt_tlv->eth_header.src_addr,
+					   misc_keep_alive->src_mac,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				memcpy_ext(pmpriv->adapter,
+					   (t_u8 *)&pkt_tlv->eth_header.
+					   h803_len, eth_ip, sizeof(t_u16),
+					   sizeof(t_u16));
+				if (misc_keep_alive->ether_type)
+					pkt_tlv->eth_header.h803_len =
+						mlan_htons(misc_keep_alive->
+							   ether_type);
+				else
+					memcpy_ext(pmpriv->adapter,
+						   (t_u8 *)&pkt_tlv->eth_header.
+						   h803_len, eth_ip,
+						   sizeof(t_u16),
+						   sizeof(t_u16));
+				pkt_tlv->header.len =
+					wlan_cpu_to_le16(sizeof(Eth803Hdr_t) +
+							 misc_keep_alive->
+							 pkt_len);
+				len = len + sizeof(MrvlIEtypesHeader_t) +
+					sizeof(Eth803Hdr_t) +
+					misc_keep_alive->pkt_len;
+			} else {
+				pkt_tlv = (MrvlIEtypes_Keep_Alive_Pkt_t *) pos;
+				pkt_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_KEEP_ALIVE_PKT);
+				pkt_tlv->header.len = 0;
+				len = len + sizeof(MrvlIEtypesHeader_t);
+			}
+		}
+		if (cmd_action == HostCmd_ACT_GEN_RESET) {
+			pkt_tlv = (MrvlIEtypes_Keep_Alive_Pkt_t *) pos;
+			pkt_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_KEEP_ALIVE_PKT);
+			pkt_tlv->header.len = 0;
+			len = len + sizeof(MrvlIEtypesHeader_t);
+		}
+		keep_alive_tlv->header.len = wlan_cpu_to_le16(len);
+
+		cmd->size = cmd->size + len + sizeof(MrvlIEtypesHeader_t);
+		cmd->size = wlan_cpu_to_le16(cmd->size);
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function check if the command is supported by firmware
+ *
+ *  @param priv       A pointer to mlan_private structure
+ *  @param cmd_no       Command number
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+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 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_HAL_PHY_CFG:
+		ret = wlan_cmd_hal_phy_cfg(pmpriv, cmd_ptr, cmd_action,
+					   pdata_buf);
+		break;
+	case HOST_CMD_PMIC_CONFIGURE:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_802_11_SLEEP_PERIOD:
+		ret = wlan_cmd_802_11_sleep_period(pmpriv, cmd_ptr, cmd_action,
+						   (t_u16 *)pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_SLEEP_PARAMS:
+		ret = wlan_cmd_802_11_sleep_params(pmpriv, cmd_ptr, cmd_action,
+						   (t_u16 *)pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_SCAN:
+		ret = wlan_cmd_802_11_scan(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
+		ret = wlan_cmd_bgscan_config(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
+		ret = wlan_cmd_802_11_bg_scan_query(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_ASSOCIATE:
+		ret = wlan_cmd_802_11_associate(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_DEAUTHENTICATE:
+	case HostCmd_CMD_802_11_DISASSOCIATE:
+		ret = wlan_cmd_802_11_deauthenticate(pmpriv, cmd_no, cmd_ptr,
+						     pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_AD_HOC_START:
+		ret = wlan_cmd_802_11_ad_hoc_start(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_AD_HOC_JOIN:
+		ret = wlan_cmd_802_11_ad_hoc_join(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_AD_HOC_STOP:
+		ret = wlan_cmd_802_11_ad_hoc_stop(pmpriv, cmd_ptr);
+		break;
+	case HostCmd_CMD_802_11_GET_LOG:
+		ret = wlan_cmd_802_11_get_log(pmpriv, cmd_ptr);
+		break;
+	case HostCmd_CMD_802_11_LINK_STATS:
+		ret = wlan_cmd_802_11_link_statistic(pmpriv, cmd_ptr,
+						     cmd_action, pioctl_buf);
+		break;
+	case HostCmd_CMD_RSSI_INFO:
+		ret = wlan_cmd_802_11_rssi_info(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_RSSI_INFO_EXT:
+		ret = wlan_cmd_802_11_rssi_info_ext(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_SNMP_MIB:
+		ret = wlan_cmd_802_11_snmp_mib(pmpriv, cmd_ptr, cmd_action,
+					       cmd_oid, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_cmd_802_11_radio_control(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		cmd_ptr->command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+						 S_DS_GEN);
+		pmpriv->tx_rate = 0;
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->params.verext.version_str_sel =
+			(t_u8)(*((t_u32 *)pdata_buf));
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_VERSION_EXT) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->params.rx_mgmt_ind.action =
+			wlan_cpu_to_le16(cmd_action);
+		cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask =
+			wlan_cpu_to_le32((t_u32)(*((t_u32 *)pdata_buf)));
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_MGMT_IND) +
+					 S_DS_GEN);
+		break;
+	case HostCmd_CMD_802_11_RF_CHANNEL:
+		ret = wlan_cmd_802_11_rf_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_FUNC_INIT:
+		if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
+			pmpriv->adapter->hw_status =
+				WlanHardwareStatusInitializing;
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+		pmpriv->adapter->hw_status = WlanHardwareStatusReset;
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_SOFT_RESET:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_11N_ADDBA_REQ:
+		ret = wlan_cmd_11n_addba_req(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_DELBA:
+		ret = wlan_cmd_11n_delba(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_ADDBA_RSP:
+		ret = wlan_cmd_11n_addba_rspgen(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_KEY_MATERIAL:
+		ret = wlan_cmd_802_11_key_material(pmpriv, cmd_ptr, cmd_action,
+						   cmd_oid, pdata_buf);
+		break;
+	case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
+		ret = wlan_cmd_gtk_rekey_offload(pmpriv, cmd_ptr, cmd_action,
+						 cmd_oid, pdata_buf);
+		break;
+
+	case HostCmd_CMD_SUPPLICANT_PMK:
+		ret = wlan_cmd_802_11_supplicant_pmk(pmpriv, cmd_ptr,
+						     cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_EAPOL_PKT:
+		ret = wlan_cmd_eapol_pkt(pmpriv, cmd_ptr, cmd_action,
+					 pdata_buf);
+		break;
+	case HostCmd_CMD_SUPPLICANT_PROFILE:
+		ret = wlan_cmd_802_11_supplicant_profile(pmpriv, cmd_ptr,
+							 cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+	case HostCmd_CMD_802_11_TPC_INFO:
+	case HostCmd_CMD_802_11_CHAN_SW_ANN:
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		ret = wlan_11h_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+		ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
+					    pdata_buf);
+		break;
+	case HostCmd_CMD_AMSDU_AGGR_CTRL:
+		ret = wlan_cmd_amsdu_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_11N_CFG:
+		ret = wlan_cmd_11n_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#if 0
+	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+		ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
+					    pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_TX_BF_CFG:
+		ret = wlan_cmd_tx_bf_cfg(pmpriv, cmd_ptr, cmd_action,
+					 pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_GET_STATUS:
+		PRINTM(MINFO, "WMM: WMM_GET_STATUS cmd sent\n");
+		cmd_ptr->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_GET_STATUS) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_WMM_ADDTS_REQ:
+		ret = wlan_cmd_wmm_addts_req(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_DELTS_REQ:
+		ret = wlan_cmd_wmm_delts_req(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_QUEUE_CONFIG:
+		ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_QUEUE_STATS:
+		ret = wlan_cmd_wmm_queue_stats(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_TS_STATUS:
+		ret = wlan_cmd_wmm_ts_status(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_PARAM_CONFIG:
+		ret = wlan_cmd_wmm_param_config(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+		ret = wlan_cmd_ibss_coalescing_status(pmpriv, cmd_ptr,
+						      cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_MGMT_IE_LIST:
+		ret = wlan_cmd_mgmt_ie_list(pmpriv, cmd_ptr, cmd_action,
+					    pdata_buf);
+		break;
+	case HostCmd_CMD_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:
+		ret = wlan_cmd_reg_access(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
+	case HostCmd_CMD_MEM_ACCESS:
+		ret = wlan_cmd_mem_access(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_INACTIVITY_TIMEOUT_EXT:
+		ret = wlan_cmd_inactivity_timeout(cmd_ptr, cmd_action,
+						  pdata_buf);
+		break;
+	case HostCmd_CMD_GET_TSF:
+		ret = wlan_cmd_get_tsf(pmpriv, cmd_ptr, cmd_action);
+		break;
+#if defined(SDIO)
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_SET_BSS_MODE:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+#ifdef WIFI_DIRECT_SUPPORT
+		if (pdata_buf) {
+			cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
+		} else
+#endif
+		if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+			cmd_ptr->params.bss_mode.con_type =
+				CONNECTION_TYPE_ADHOC;
+		else if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
+			cmd_ptr->params.bss_mode.con_type =
+				CONNECTION_TYPE_INFRA;
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_SET_BSS_MODE) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_MEASUREMENT_REQUEST:
+	case HostCmd_CMD_MEASUREMENT_REPORT:
+		ret = wlan_meas_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+		break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+	case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+		ret = wlan_cmd_pcie_host_buf_cfg(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#endif
+#endif
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+		ret = wlan_cmd_subscribe_event(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_OTP_READ_USER_DATA:
+		ret = wlan_cmd_otp_user_data(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_HS_WAKEUP_REASON:
+		ret = wlan_cmd_hs_wakeup_reason(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_REJECT_ADDBA_REQ:
+		ret = wlan_cmd_reject_addba_req(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+		ret = wlan_cmd_packet_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+#ifdef USB
+	case HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE:
+		ret = wlan_cmd_packet_aggr_over_host_interface(pmpriv, cmd_ptr,
+							       cmd_action,
+							       pdata_buf);
+		break;
+#endif
+#ifdef RX_PACKET_COALESCE
+	case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+		ret = wlan_cmd_rx_pkt_coalesce_cfg(pmpriv, cmd_ptr, cmd_action,
+						   pdata_buf);
+		break;
+#endif
+	case HostCMD_CONFIG_LOW_POWER_MODE:
+		ret = wlan_cmd_low_pwr_mode(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_DFS_REPEATER_MODE:
+		ret = wlan_cmd_dfs_repeater_cfg(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HostCmd_CMD_COALESCE_CFG:
+		ret = wlan_cmd_coalesce_config(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_DS_GET_SENSOR_TEMP:
+		ret = wlan_cmd_get_sensor_temp(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_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_802_11_PS_INACTIVITY_TIMEOUT:
+		ret = wlan_cmd_ps_inactivity_timeout(pmpriv, cmd_ptr,
+						     cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_CHAN_REGION_CFG) +
+					 S_DS_GEN);
+		cmd_ptr->params.reg_cfg.action = wlan_cpu_to_le16(cmd_action);
+		break;
+	case HostCmd_CMD_AUTO_TX:
+		ret = wlan_cmd_auto_tx(pmpriv, cmd_ptr, cmd_action, cmd_oid,
+				       pdata_buf);
+		break;
+	case HOST_CMD_TX_RX_PKT_STATS:
+		ret = wlan_cmd_tx_rx_pkt_stats(pmpriv, cmd_ptr,
+					       (pmlan_ioctl_req)pioctl_buf,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_DYN_BW:
+		ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_cmd_boot_sleep(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
+	case HostCmd_CMD_FW_DUMP_EVENT:
+		ret = wlan_cmd_fw_dump_event(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+#if defined(DRV_EMBEDDED_SUPPLICANT)
+	case HostCmd_CMD_CRYPTO:
+		ret = wlan_cmd_crypto(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_11AX_CFG:
+		ret = wlan_cmd_11ax_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_11AX_CMD:
+		ret = wlan_cmd_11ax_cmd(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_RANGE_EXT:
+		ret = wlan_cmd_range_ext(pmpriv, cmd_ptr, cmd_action,
+					 pdata_buf);
+		break;
+	case HostCmd_CMD_TWT_CFG:
+		ret = wlan_cmd_twt_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HOST_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_RX_ABORT_CFG_EXT:
+		ret = wlan_cmd_rxabortcfg_ext(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_ARB_CONFIG:
+		ret = wlan_cmd_arb_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+		ret = wlan_cmd_tx_ampdu_prot_mode(pmpriv, cmd_ptr, cmd_action,
+						  pdata_buf);
+		break;
+	case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+		ret = wlan_cmd_dot11mc_unassoc_ftm_cfg(pmpriv, cmd_ptr,
+						       cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_RATE_ADAPT_CFG:
+		ret = wlan_cmd_rate_adapt_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_CCK_DESENSE_CFG:
+		ret = wlan_cmd_cck_desense_cfg(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_cmd_get_chan_trpc_config(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_LOW_POWER_MODE_CFG:
+		ret = wlan_cmd_set_get_low_power_mode_cfg(pmpriv, cmd_ptr,
+							  cmd_action,
+							  pdata_buf);
+		break;
+	case HostCmd_CMD_MFG_COMMAND:
+		ret = wlan_cmd_mfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	default:
+		PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues commands to initialize firmware
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param first_bss    flag for first BSS
+ *
+ *  @return		MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_sta_init_cmd(t_void *priv, t_u8 first_bss)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+
+	ENTER();
+
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (first_bss == MTRUE) {
+		ret = wlan_adapter_init_cmd(pmpriv->adapter);
+		if (ret == MLAN_STATUS_FAILURE)
+			goto done;
+	}
+
+	/* get tx rate */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pmpriv->data_rate = 0;
+
+	/* get tx power */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_TX_POWER,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(pmpriv->adapter, &amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
+	amsdu_aggr_ctrl.enable = MLAN_ACT_ENABLE;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AMSDU_AGGR_CTRL,
+			       HostCmd_ACT_GEN_SET, 0, MNULL,
+			       (t_void *)&amsdu_aggr_ctrl);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* MAC Control must be the last command in init_fw */
+	/* set MAC Control */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+			       HostCmd_ACT_GEN_SET, 0, MNULL,
+			       &pmpriv->curr_pkt_filter);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/** set last_init_cmd */
+	pmpriv->adapter->last_init_cmd = HostCmd_CMD_MAC_CONTROL;
+
+	if (first_bss == MFALSE) {
+		/* Get MAC address */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MAC_ADDRESS,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmpriv->adapter->last_init_cmd = HostCmd_CMD_802_11_MAC_ADDRESS;
+	}
+
+	ret = MLAN_STATUS_PENDING;
+done:
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_sta_cmdresp.c b/wlan_sd8987/mlan/mlan_sta_cmdresp.c
new file mode 100755
index 0000000..baa1bb6
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_cmdresp.c
@@ -0,0 +1,3395 @@
+/** @file mlan_sta_cmdresp.c
+ *
+ *  @brief This file contains the handling of command
+ *  responses generated by firmware.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+ * Change log:
+ *   10/21/2008: initial version
+ ******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#include "mlan_meas.h"
+
+/********************************************************
+ *			Local Variables
+ ********************************************************/
+
+/********************************************************
+ *			Global Variables
+ ********************************************************/
+
+/********************************************************
+ *			Local Functions
+ ********************************************************/
+/**
+ *  @brief This function handles the command response error for TDLS operation
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return             N/A
+ */
+static void
+wlan_process_cmdreps_error_tdls_operation(mlan_private *pmpriv,
+					  HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	HostCmd_DS_TDLS_OPER *ptdls_oper_data = &(resp->params.tdls_oper_data);
+	sta_node *sta_ptr = MNULL;
+	t_u16 reason;
+
+	ENTER();
+	ptdls_oper_data->tdls_action =
+		wlan_le16_to_cpu(ptdls_oper_data->tdls_action);
+	reason = wlan_le16_to_cpu(ptdls_oper_data->reason);
+	sta_ptr = wlan_get_station_entry(pmpriv, ptdls_oper_data->peer_mac);
+	switch (ptdls_oper_data->tdls_action) {
+	case TDLS_CREATE:
+		/* TDLS create command error */
+		if (reason != TDLS_LINK_EXISTS && sta_ptr) {
+			PRINTM(MERROR,
+			       "TDLS CREATE operation: cmd error reason %d\n",
+			       reason);
+			sta_ptr->status = TDLS_SETUP_FAILURE;
+		}
+		if (reason == TDLS_LINK_EXISTS && pioctl_buf)
+			pioctl_buf->status_code = MLAN_STATUS_SUCCESS;
+		break;
+	case TDLS_CONFIG:
+		/* TDLS config command error */
+		PRINTM(MERROR,
+		       "TDLS CONFIG operation: command error, reason %d\n",
+		       reason);
+		if (sta_ptr)
+			sta_ptr->status = TDLS_SETUP_FAILURE;
+		break;
+	case TDLS_DELETE:
+		/* TDLS delete command error */
+		wlan_restore_tdls_packets(pmpriv, ptdls_oper_data->peer_mac,
+					  TDLS_TEAR_DOWN);
+		if (sta_ptr) {
+			/**tdls cs stop*/
+			if (ISSUPP_EXTCAP_TDLS_CHAN_SWITCH
+			    (sta_ptr->ExtCap.ext_cap))
+				wlan_tdls_config(pmpriv, MFALSE);
+			if (sta_ptr->is_11n_enabled) {
+				wlan_cleanup_reorder_tbl(pmpriv,
+							 ptdls_oper_data->
+							 peer_mac);
+				wlan_11n_cleanup_txbastream_tbl(pmpriv,
+								ptdls_oper_data->
+								peer_mac);
+			}
+			if (sta_ptr->status >= TDLS_SETUP_INPROGRESS)
+				wlan_delete_station_entry(pmpriv,
+							  ptdls_oper_data->
+							  peer_mac);
+		}
+		if (wlan_is_station_list_empty(pmpriv) == MTRUE)
+			pmadapter->tdls_status = TDLS_NOT_SETUP;
+		else
+			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+
+		if (reason == TDLS_LINK_NONEXISTENT) {
+			if (pioctl_buf)
+				pioctl_buf->status_code = MLAN_STATUS_SUCCESS;
+		} else {
+			PRINTM(MERROR,
+			       "TDLS DELETE operation: cmd error, reason %d\n",
+			       reason);
+		}
+		break;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the command response error
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             N/A
+ */
+static mlan_status
+wlan_process_cmdresp_error(mlan_private *pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	pmlan_ioctl_req pscan_ioctl_req = MNULL;
+	mlan_callbacks *pcb = MNULL;
+	tdls_all_config *tdls_all_cfg = MNULL;
+	HostCmd_DS_TDLS_CONFIG *ptdls_config_data =
+		&(resp->params.tdls_config_data);
+
+#if defined(USB)
+	t_s32 i = 0;
+#endif
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+	if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG
+	    && resp->command != HostCmd_CMD_CHAN_REGION_CFG)
+		PRINTM(MERROR, "CMD_RESP: cmd %#x error, result=%#x\n",
+		       resp->command, resp->result);
+	if (pioctl_buf)
+		pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
+
+	switch (resp->command) {
+	case HostCmd_CMD_802_11_PS_MODE_ENH:{
+			HostCmd_DS_802_11_PS_MODE_ENH *pm =
+				&resp->params.psmode_enh;
+			PRINTM(MERROR,
+			       "PS_MODE_ENH command failed: result=0x%x action=0x%X\n",
+			       resp->result, wlan_le16_to_cpu(pm->action));
+			/*
+			 * We do not re-try enter-ps command in ad-hoc mode.
+			 */
+			if (wlan_le16_to_cpu(pm->action) == EN_AUTO_PS &&
+			    (wlan_le16_to_cpu(pm->params.auto_ps.ps_bitmap) &
+			     BITMAP_STA_PS) &&
+			    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
+				pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+		}
+		break;
+	case HostCmd_CMD_802_11_SCAN_EXT:
+	case HostCmd_CMD_802_11_SCAN:
+		/* Cancel all pending scan command */
+		wlan_flush_scan_queue(pmadapter);
+
+		pcb = (pmlan_callbacks)&pmadapter->callbacks;
+
+		wlan_request_cmd_lock(pmadapter);
+		pmadapter->scan_processing = MFALSE;
+		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
+		pmadapter->pscan_ioctl_req = MNULL;
+		/* Need to indicate IOCTL complete */
+		if (pscan_ioctl_req) {
+			pscan_ioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
+			/* Indicate ioctl complete */
+			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+						 (pmlan_ioctl_req)
+						 pscan_ioctl_req,
+						 MLAN_STATUS_FAILURE);
+		}
+		wlan_release_cmd_lock(pmadapter);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
+		break;
+
+	case HostCmd_CMD_MAC_CONTROL:
+		break;
+
+	case HostCmd_CMD_TDLS_CONFIG:
+		ptdls_config_data->tdls_info.tdls_action =
+			wlan_le16_to_cpu(ptdls_config_data->tdls_info.
+					 tdls_action);
+		switch (ptdls_config_data->tdls_info.tdls_action) {
+		case WLAN_TDLS_SETUP_REQ:
+			/* TDLS link setup error ;display error in logs */
+			tdls_all_cfg = (tdls_all_config *)
+				ptdls_config_data->tdls_info.tdls_data;
+			PRINTM(MERROR, "TDLS Setup Failed, error %d\n",
+			       wlan_le16_to_cpu(tdls_all_cfg->u.tdls_cmd_resp.
+						reason_code));
+			break;
+		case WLAN_TDLS_INIT_CHAN_SWITCH:
+			tdls_all_cfg = (tdls_all_config *)
+				ptdls_config_data->tdls_info.tdls_data;
+			PRINTM(MERROR,
+			       "TDLS init channel switch failed," MACSTR
+			       ": reason=%d\n",
+			       MAC2STR(tdls_all_cfg->u.tdls_cmd_resp.
+				       peer_mac_addr),
+			       wlan_le16_to_cpu(tdls_all_cfg->u.tdls_cmd_resp.
+						reason_code));
+			break;
+		}
+		break;
+	case HostCmd_CMD_TDLS_OPERATION:
+		wlan_process_cmdreps_error_tdls_operation(pmpriv, resp,
+							  pioctl_buf);
+		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+#ifdef USB
+		if (IS_USB(pmadapter->card_type)) {
+			for (i = 0; i < MAX_USB_TX_PORT_NUM; i++)
+				pmadapter->pcard_usb->usb_tx_aggr[i]
+					.aggr_ctrl.enable = MFALSE;
+			pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable =
+				MFALSE;
+		}
+#endif
+		break;
+#ifdef USB
+	case HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE:
+		pmadapter->pcard_usb->fw_usb_aggr = MFALSE;
+		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++)
+			pmadapter->pcard_usb->usb_tx_aggr[i].aggr_ctrl.enable =
+				MFALSE;
+		pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable = MFALSE;
+		break;
+#endif
+	case HostCmd_CMD_802_11_ASSOCIATE:
+		wlan_reset_connect_state(pmpriv, MTRUE);
+		break;
+#ifdef SDIO
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+		break;
+#endif
+
+	case HostCmd_CMD_MGMT_IE_LIST:{
+			HostCmd_DS_MGMT_IE_LIST_CFG *pmgmt_ie_list =
+				&(resp->params.mgmt_ie_list);
+			t_u16 resp_len = 0, travel_len = 0, index;
+			mlan_ds_misc_custom_ie *cust_ie = MNULL;
+			custom_ie *cptr;
+
+			if (wlan_le16_to_cpu(pmgmt_ie_list->action) ==
+			    HostCmd_ACT_GEN_GET)
+				break;
+
+			cust_ie =
+				(mlan_ds_misc_custom_ie *)&pmgmt_ie_list->
+				ds_mgmt_ie;
+			if (cust_ie) {
+				cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+				resp_len = cust_ie->len =
+					wlan_le16_to_cpu(cust_ie->len);
+				travel_len = 0;
+				/* conversion for index, mask, len */
+				if (resp_len == sizeof(t_u16))
+					cust_ie->ie_data_list[0]
+						.ie_index =
+						wlan_cpu_to_le16(cust_ie->
+								 ie_data_list
+								 [0].ie_index);
+
+				while (resp_len > sizeof(t_u16)) {
+					cptr = (custom_ie
+						*)(((t_u8 *)cust_ie->
+						    ie_data_list) + travel_len);
+					index = cptr->ie_index =
+						wlan_le16_to_cpu(cptr->
+								 ie_index);
+					cptr->mgmt_subtype_mask =
+						wlan_le16_to_cpu(cptr->
+								 mgmt_subtype_mask);
+					cptr->ie_length =
+						wlan_le16_to_cpu(cptr->
+								 ie_length);
+					travel_len +=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					resp_len -=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					if ((pmpriv->mgmt_ie[index].
+					     mgmt_subtype_mask ==
+					     cptr->mgmt_subtype_mask) &&
+					    (pmpriv->mgmt_ie[index].ie_length ==
+					     cptr->ie_length) &&
+					    !memcmp(pmpriv->adapter,
+						    pmpriv->mgmt_ie[index].
+						    ie_buffer, cptr->ie_buffer,
+						    cptr->ie_length)) {
+						PRINTM(MERROR,
+						       "set custom ie fail, remove ie index :%d\n",
+						       index);
+						memset(pmadapter,
+						       &pmpriv->mgmt_ie[index],
+						       0, sizeof(custom_ie));
+					}
+				}
+			}
+		} break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = MLAN_STATUS_SUCCESS;
+		PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+		break;
+#if defined(DRV_EMBEDDED_SUPPLICANT)
+	case HostCmd_CMD_CRYPTO:
+		PRINTM(MCMND, "crypto cmd result=0x%x!\n", resp->result);
+		ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	default:
+		break;
+	}
+	/*
+	 * Handling errors here
+	 */
+	wlan_request_cmd_lock(pmadapter);
+	wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+	pmadapter->curr_cmd = MNULL;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of RSSI info
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_rssi_info_ext(pmlan_private pmpriv,
+			      HostCmd_DS_COMMAND *resp,
+			      mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_RSSI_INFO_EXT *prssi_info_rsp =
+		&resp->params.rssi_info_ext;
+	mlan_ds_get_signal *signal = MNULL;
+	mlan_ds_get_info *info = MNULL;
+	MrvlIEtypes_RSSI_EXT_t *signal_info_tlv = MNULL;
+	t_u16 tlv_left_len = 0, tlv_num = 0;
+	t_u16 tlv_id, tlv_len;
+
+	ENTER();
+
+	/* Need to indicate IOCTL complete */
+	if (pioctl_buf != MNULL) {
+		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		signal_info_tlv =
+			(MrvlIEtypes_RSSI_EXT_t *) (prssi_info_rsp->tlv_buf);
+		tlv_left_len =
+			resp->size -
+			(sizeof(HostCmd_DS_802_11_RSSI_INFO_EXT) + S_DS_GEN);
+
+		while (tlv_left_len >= sizeof(MrvlIEtypes_RSSI_EXT_t)) {
+			tlv_id = wlan_le16_to_cpu(signal_info_tlv->header.type);
+			tlv_len = wlan_le16_to_cpu(signal_info_tlv->header.len);
+			if ((tlv_id != TLV_TYPE_RSSI_INFO) ||
+			    (tlv_len != sizeof(MrvlIEtypes_RSSI_EXT_t) -
+			     sizeof(MrvlIEtypesHeader_t))) {
+				PRINTM(MERROR,
+				       "Invalid RSSI INFO TLV, type=%d, len=%d\n",
+				       tlv_id, tlv_len);
+				break;
+			}
+
+			signal = (mlan_ds_get_signal *)&info->param.
+				signal_ext[tlv_num];
+			/* PATH ID */
+			signal->selector =
+				wlan_le16_to_cpu(signal_info_tlv->path_id);
+
+			/* RSSI */
+			signal->bcn_rssi_last =
+				wlan_le16_to_cpu(signal_info_tlv->
+						 bcn_rssi_last);
+			signal->bcn_rssi_avg =
+				wlan_le16_to_cpu(signal_info_tlv->bcn_rssi_avg);
+			signal->data_rssi_last =
+				wlan_le16_to_cpu(signal_info_tlv->
+						 data_rssi_last);
+			signal->data_rssi_avg =
+				wlan_le16_to_cpu(signal_info_tlv->
+						 data_rssi_avg);
+
+			/* SNR */
+			signal->bcn_snr_last =
+				CAL_SNR(wlan_le16_to_cpu
+					(signal_info_tlv->bcn_rssi_last),
+					wlan_le16_to_cpu(signal_info_tlv->
+							 bcn_nf_last));
+			signal->bcn_snr_avg =
+				CAL_SNR(wlan_le16_to_cpu
+					(signal_info_tlv->bcn_rssi_avg),
+					wlan_le16_to_cpu(signal_info_tlv->
+							 bcn_nf_avg));
+			signal->data_snr_last =
+				CAL_SNR(wlan_le16_to_cpu
+					(signal_info_tlv->data_rssi_last),
+					wlan_le16_to_cpu(signal_info_tlv->
+							 data_nf_last));
+			signal->data_snr_avg =
+				CAL_SNR(wlan_le16_to_cpu
+					(signal_info_tlv->data_rssi_avg),
+					wlan_le16_to_cpu(signal_info_tlv->
+							 data_nf_avg));
+
+			/* NF */
+			signal->bcn_nf_last =
+				wlan_le16_to_cpu(signal_info_tlv->bcn_nf_last);
+			signal->bcn_nf_avg =
+				wlan_le16_to_cpu(signal_info_tlv->bcn_nf_avg);
+			signal->data_nf_last =
+				wlan_le16_to_cpu(signal_info_tlv->data_nf_last);
+			signal->data_nf_avg =
+				wlan_le16_to_cpu(signal_info_tlv->data_nf_avg);
+
+			tlv_left_len -= sizeof(MrvlIEtypes_RSSI_EXT_t);
+			signal_info_tlv++;
+			tlv_num++;
+			if (tlv_num > MAX_PATH_NUM)
+				break;
+		}
+
+		pioctl_buf->data_read_written =
+			tlv_num * sizeof(mlan_ds_get_signal) + sizeof(t_u32);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of RSSI info
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_rssi_info(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_RSSI_INFO_RSP *prssi_info_rsp =
+		&resp->params.rssi_info_rsp;
+	mlan_ds_get_info *pget_info = MNULL;
+	BSSDescriptor_t *pbss_desc;
+	t_s32 tbl_idx = 0;
+
+	ENTER();
+
+	pmpriv->data_rssi_last =
+		wlan_le16_to_cpu(prssi_info_rsp->data_rssi_last);
+	pmpriv->data_nf_last = wlan_le16_to_cpu(prssi_info_rsp->data_nf_last);
+
+	pmpriv->data_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->data_rssi_avg);
+	pmpriv->data_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->data_nf_avg);
+
+	pmpriv->bcn_rssi_last = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_last);
+	pmpriv->bcn_nf_last = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_last);
+
+	pmpriv->bcn_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_avg);
+	pmpriv->bcn_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_avg);
+
+	/* Get current BSS info */
+	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+	pbss_desc->rssi = -pmpriv->bcn_rssi_avg;
+	tbl_idx = wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid,
+					 pbss_desc->mac_address,
+					 pmpriv->bss_mode);
+	if (tbl_idx >= 0) {
+		pbss_desc = &pmpriv->adapter->pscan_table[tbl_idx];
+		pbss_desc->rssi = -pmpriv->bcn_rssi_avg;
+	}
+
+	/* Need to indicate IOCTL complete */
+	if (pioctl_buf != MNULL) {
+		pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+
+		memset(pmpriv->adapter, &pget_info->param.signal, 0,
+		       sizeof(mlan_ds_get_signal));
+
+		pget_info->param.signal.selector = ALL_RSSI_INFO_MASK;
+
+		/* RSSI */
+		pget_info->param.signal.bcn_rssi_last = pmpriv->bcn_rssi_last;
+		pget_info->param.signal.bcn_rssi_avg = pmpriv->bcn_rssi_avg;
+		pget_info->param.signal.data_rssi_last = pmpriv->data_rssi_last;
+		pget_info->param.signal.data_rssi_avg = pmpriv->data_rssi_avg;
+
+		/* SNR */
+		pget_info->param.signal.bcn_snr_last =
+			CAL_SNR(pmpriv->bcn_rssi_last, pmpriv->bcn_nf_last);
+		pget_info->param.signal.bcn_snr_avg =
+			CAL_SNR(pmpriv->bcn_rssi_avg, pmpriv->bcn_nf_avg);
+		pget_info->param.signal.data_snr_last =
+			CAL_SNR(pmpriv->data_rssi_last, pmpriv->data_nf_last);
+		pget_info->param.signal.data_snr_avg =
+			CAL_SNR(pmpriv->data_rssi_avg, pmpriv->data_nf_avg);
+
+		/* NF */
+		pget_info->param.signal.bcn_nf_last = pmpriv->bcn_nf_last;
+		pget_info->param.signal.bcn_nf_avg = pmpriv->bcn_nf_avg;
+		pget_info->param.signal.data_nf_last = pmpriv->data_nf_last;
+		pget_info->param.signal.data_nf_avg = pmpriv->data_nf_avg;
+
+		pioctl_buf->data_read_written = sizeof(mlan_ds_get_info);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of snmp_mib
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_snmp_mib(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SNMP_MIB *psmib = &resp->params.smib;
+	t_u16 oid = wlan_le16_to_cpu(psmib->oid);
+	t_u16 query_type = wlan_le16_to_cpu(psmib->query_type);
+	t_u32 ul_temp;
+	mlan_ds_snmp_mib *mib = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf)
+		mib = (mlan_ds_snmp_mib *)pioctl_buf->pbuf;
+
+	PRINTM(MINFO, "SNMP_RESP: value of the oid = 0x%x, query_type=0x%x\n",
+	       oid, query_type);
+	PRINTM(MINFO, "SNMP_RESP: Buf size  = 0x%x\n",
+	       wlan_le16_to_cpu(psmib->buf_size));
+	if (query_type == HostCmd_ACT_GEN_GET) {
+		switch (oid) {
+		case DtimPeriod_i:
+			ul_temp = psmib->value[0];
+			PRINTM(MINFO, "SNMP_RESP: DTIM Period =%u\n", ul_temp);
+			if (mib)
+				mib->param.dtim_period = ul_temp;
+			break;
+		case FragThresh_i:
+			ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+			PRINTM(MINFO, "SNMP_RESP: FragThsd =%u\n", ul_temp);
+			if (mib)
+				mib->param.frag_threshold = ul_temp;
+			break;
+
+		case RtsThresh_i:
+			ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+			PRINTM(MINFO, "SNMP_RESP: RTSThsd =%u\n", ul_temp);
+			if (mib)
+				mib->param.rts_threshold = ul_temp;
+			break;
+
+		case ShortRetryLim_i:
+			ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+			PRINTM(MINFO, "SNMP_RESP: TxRetryCount=%u\n", ul_temp);
+			if (mib)
+				mib->param.retry_count = ul_temp;
+			break;
+		case WwsMode_i:
+			ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+			PRINTM(MINFO, "SNMP_RESP: WWSCfg =%u\n", ul_temp);
+			if (pioctl_buf)
+				((mlan_ds_misc_cfg *)pioctl_buf->pbuf)
+					->param.wws_cfg = ul_temp;
+			break;
+		case Thermal_i:
+			ul_temp = wlan_le32_to_cpu(*((t_u32 *)(psmib->value)));
+			PRINTM(MINFO, "SNMP_RESP: Thermal =%u\n", ul_temp);
+			if (pioctl_buf)
+				((mlan_ds_misc_cfg *)pioctl_buf->pbuf)
+					->param.thermal = ul_temp;
+			break;
+		case NullPktPeriod_i:
+			ul_temp = psmib->value[0];
+			PRINTM(MINFO, "SNMP_RESP: Auto NULL Pkt Period =%u\n",
+			       ul_temp);
+			break;
+		default:
+			break;
+		}
+	} else {		/* (query_type == HostCmd_ACT_GEN_SET) */
+		/* Update state for 11d */
+		if (oid == Dot11D_i) {
+			ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+			/* Set 11d state to private */
+			pmpriv->state_11d.enable_11d = ul_temp;
+			/* Set user enable flag if called from ioctl */
+			if (pioctl_buf)
+				pmpriv->state_11d.user_enable_11d = ul_temp;
+		}
+		/* Update state for 11h */
+		if (oid == Dot11H_i) {
+			ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value)));
+			/* Set 11h state to priv */
+			pmpriv->intf_state_11h.is_11h_active =
+				(ul_temp & ENABLE_11H_MASK);
+			/* Set radar_det state to adapter */
+			pmpriv->adapter->state_11h.is_master_radar_det_active =
+				(ul_temp & MASTER_RADAR_DET_MASK) ? MTRUE :
+				MFALSE;
+			pmpriv->adapter->state_11h.is_slave_radar_det_active =
+				(ul_temp & SLAVE_RADAR_DET_MASK) ? MTRUE :
+				MFALSE;
+		}
+	}
+
+	if (pioctl_buf) {
+		/* Indicate ioctl complete */
+		pioctl_buf->data_read_written = sizeof(mlan_ds_snmp_mib);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of get_log
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_get_log(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_GET_LOG *pget_log =
+		(HostCmd_DS_802_11_GET_LOG *)&resp->params.get_log;
+	mlan_ds_get_info *pget_info = MNULL;
+	int i = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		pget_info->param.stats.mcast_tx_frame =
+			wlan_le32_to_cpu(pget_log->mcast_tx_frame);
+		pget_info->param.stats.failed =
+			wlan_le32_to_cpu(pget_log->failed);
+		pget_info->param.stats.retry =
+			wlan_le32_to_cpu(pget_log->retry);
+		pget_info->param.stats.multi_retry =
+			wlan_le32_to_cpu(pget_log->multiretry);
+		pget_info->param.stats.frame_dup =
+			wlan_le32_to_cpu(pget_log->frame_dup);
+		pget_info->param.stats.rts_success =
+			wlan_le32_to_cpu(pget_log->rts_success);
+		pget_info->param.stats.rts_failure =
+			wlan_le32_to_cpu(pget_log->rts_failure);
+		pget_info->param.stats.ack_failure =
+			wlan_le32_to_cpu(pget_log->ack_failure);
+		pget_info->param.stats.rx_frag =
+			wlan_le32_to_cpu(pget_log->rx_frag);
+		pget_info->param.stats.mcast_rx_frame =
+			wlan_le32_to_cpu(pget_log->mcast_rx_frame);
+		pget_info->param.stats.fcs_error =
+			wlan_le32_to_cpu(pget_log->fcs_error);
+		pget_info->param.stats.tx_frame =
+			wlan_le32_to_cpu(pget_log->tx_frame);
+		pget_info->param.stats.wep_icv_error[0] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[0]);
+		pget_info->param.stats.wep_icv_error[1] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[1]);
+		pget_info->param.stats.wep_icv_error[2] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]);
+		pget_info->param.stats.wep_icv_error[3] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]);
+		pget_info->param.stats.bcn_rcv_cnt =
+			wlan_le32_to_cpu(pget_log->bcn_rcv_cnt);
+		pget_info->param.stats.bcn_miss_cnt =
+			wlan_le32_to_cpu(pget_log->bcn_miss_cnt);
+		pget_info->param.stats.amsdu_rx_cnt = pmpriv->amsdu_rx_cnt;
+		pget_info->param.stats.msdu_in_rx_amsdu_cnt =
+			pmpriv->msdu_in_rx_amsdu_cnt;
+		pget_info->param.stats.amsdu_tx_cnt = pmpriv->amsdu_tx_cnt;
+		pget_info->param.stats.msdu_in_tx_amsdu_cnt =
+			pmpriv->msdu_in_tx_amsdu_cnt;
+		pget_info->param.stats.rx_stuck_issue_cnt[0] =
+			wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[0]);
+		pget_info->param.stats.rx_stuck_issue_cnt[1] =
+			wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[1]);
+		pget_info->param.stats.rx_stuck_recovery_cnt =
+			wlan_le32_to_cpu(pget_log->rx_stuck_recovery_cnt);
+		pget_info->param.stats.rx_stuck_tsf[0] =
+			wlan_le64_to_cpu(pget_log->rx_stuck_tsf[0]);
+		pget_info->param.stats.rx_stuck_tsf[1] =
+			wlan_le64_to_cpu(pget_log->rx_stuck_tsf[1]);
+		pget_info->param.stats.tx_watchdog_recovery_cnt =
+			wlan_le32_to_cpu(pget_log->tx_watchdog_recovery_cnt);
+		pget_info->param.stats.tx_watchdog_tsf[0] =
+			wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[0]);
+		pget_info->param.stats.tx_watchdog_tsf[1] =
+			wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[1]);
+		pget_info->param.stats.channel_switch_ann_sent =
+			wlan_le32_to_cpu(pget_log->channel_switch_ann_sent);
+		pget_info->param.stats.channel_switch_state =
+			wlan_le32_to_cpu(pget_log->channel_switch_state);
+		pget_info->param.stats.reg_class =
+			wlan_le32_to_cpu(pget_log->reg_class);
+		pget_info->param.stats.channel_number =
+			wlan_le32_to_cpu(pget_log->channel_number);
+		pget_info->param.stats.channel_switch_mode =
+			wlan_le32_to_cpu(pget_log->channel_switch_mode);
+		pget_info->param.stats.rx_reset_mac_recovery_cnt =
+			wlan_le32_to_cpu(pget_log->rx_reset_mac_recovery_cnt);
+		pget_info->param.stats.rx_Isr2_NotDone_Cnt =
+			wlan_le32_to_cpu(pget_log->rx_Isr2_NotDone_Cnt);
+		pget_info->param.stats.gdma_abort_cnt =
+			wlan_le32_to_cpu(pget_log->gdma_abort_cnt);
+		pget_info->param.stats.g_reset_rx_mac_cnt =
+			wlan_le32_to_cpu(pget_log->g_reset_rx_mac_cnt);
+		//Ownership error counters
+		pget_info->param.stats.dwCtlErrCnt =
+			wlan_le32_to_cpu(pget_log->dwCtlErrCnt);
+		pget_info->param.stats.dwBcnErrCnt =
+			wlan_le32_to_cpu(pget_log->dwBcnErrCnt);
+		pget_info->param.stats.dwMgtErrCnt =
+			wlan_le32_to_cpu(pget_log->dwMgtErrCnt);
+		pget_info->param.stats.dwDatErrCnt =
+			wlan_le32_to_cpu(pget_log->dwDatErrCnt);
+		pget_info->param.stats.bigtk_mmeGoodCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_mmeGoodCnt);
+		pget_info->param.stats.bigtk_replayErrCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_replayErrCnt);
+		pget_info->param.stats.bigtk_micErrCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_micErrCnt);
+		pget_info->param.stats.bigtk_mmeNotFoundCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_mmeNotFoundCnt);
+
+		if (pmpriv->adapter->getlog_enable) {
+			pget_info->param.stats.tx_frag_cnt =
+				wlan_le32_to_cpu(pget_log->tx_frag_cnt);
+			for (i = 0; i < 8; i++) {
+				pget_info->param.stats.qos_tx_frag_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_tx_frag_cnt[i]);
+				pget_info->param.stats.qos_failed_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_failed_cnt[i]);
+				pget_info->param.stats.qos_retry_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_retry_cnt[i]);
+				pget_info->param.stats.qos_multi_retry_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_multi_retry_cnt
+							 [i]);
+				pget_info->param.stats.qos_frm_dup_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_frm_dup_cnt[i]);
+				pget_info->param.stats.qos_rts_suc_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_rts_suc_cnt[i]);
+				pget_info->param.stats.qos_rts_failure_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_rts_failure_cnt
+							 [i]);
+				pget_info->param.stats.qos_ack_failure_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_ack_failure_cnt
+							 [i]);
+				pget_info->param.stats.qos_rx_frag_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_rx_frag_cnt[i]);
+				pget_info->param.stats.qos_tx_frm_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_tx_frm_cnt[i]);
+				pget_info->param.stats.
+					qos_discarded_frm_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_discarded_frm_cnt
+							 [i]);
+				pget_info->param.stats.qos_mpdus_rx_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_mpdus_rx_cnt[i]);
+				pget_info->param.stats.qos_retries_rx_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_retries_rx_cnt[i]);
+			}
+			pget_info->param.stats.cmacicv_errors =
+				wlan_le32_to_cpu(pget_log->cmacicv_errors);
+			pget_info->param.stats.cmac_replays =
+				wlan_le32_to_cpu(pget_log->cmac_replays);
+			pget_info->param.stats.mgmt_ccmp_replays =
+				wlan_le32_to_cpu(pget_log->mgmt_ccmp_replays);
+			pget_info->param.stats.tkipicv_errors =
+				wlan_le32_to_cpu(pget_log->tkipicv_errors);
+			pget_info->param.stats.tkip_replays =
+				wlan_le32_to_cpu(pget_log->tkip_replays);
+			pget_info->param.stats.ccmp_decrypt_errors =
+				wlan_le32_to_cpu(pget_log->ccmp_decrypt_errors);
+			pget_info->param.stats.ccmp_replays =
+				wlan_le32_to_cpu(pget_log->ccmp_replays);
+			pget_info->param.stats.tx_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->tx_amsdu_cnt);
+			pget_info->param.stats.failed_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->failed_amsdu_cnt);
+			pget_info->param.stats.retry_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->retry_amsdu_cnt);
+			pget_info->param.stats.multi_retry_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 multi_retry_amsdu_cnt);
+			pget_info->param.stats.tx_octets_in_amsdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 tx_octets_in_amsdu_cnt);
+			pget_info->param.stats.amsdu_ack_failure_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 amsdu_ack_failure_cnt);
+			pget_info->param.stats.rx_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->rx_amsdu_cnt);
+			pget_info->param.stats.rx_octets_in_amsdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 rx_octets_in_amsdu_cnt);
+			pget_info->param.stats.tx_ampdu_cnt =
+				wlan_le32_to_cpu(pget_log->tx_ampdu_cnt);
+			pget_info->param.stats.tx_mpdus_in_ampdu_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 tx_mpdus_in_ampdu_cnt);
+			pget_info->param.stats.tx_octets_in_ampdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 tx_octets_in_ampdu_cnt);
+			pget_info->param.stats.ampdu_rx_cnt =
+				wlan_le32_to_cpu(pget_log->ampdu_rx_cnt);
+			pget_info->param.stats.mpdu_in_rx_ampdu_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 mpdu_in_rx_ampdu_cnt);
+			pget_info->param.stats.rx_octets_in_ampdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 rx_octets_in_ampdu_cnt);
+			pget_info->param.stats.ampdu_delimiter_crc_error_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 ampdu_delimiter_crc_error_cnt);
+
+			/* Indicate ioctl complete */
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_get_info);
+		} else
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_get_stats_org) +
+				sizeof(pget_info->sub_command);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get power level and rate index
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pdata_buf    Pointer to the data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_get_power_level(pmlan_private pmpriv, void *pdata_buf)
+{
+	t_u16 length = 0;
+	t_s8 max_power = -1, min_power = -1;
+	MrvlTypes_Power_Group_t *ppg_tlv = MNULL;
+	Power_Group_t *pg = MNULL;
+
+	ENTER();
+
+	if (pdata_buf) {
+		ppg_tlv = (MrvlTypes_Power_Group_t
+			   *)((t_u8 *)pdata_buf + sizeof(HostCmd_DS_TXPWR_CFG));
+		pg = (Power_Group_t *)((t_u8 *)ppg_tlv +
+				       sizeof(MrvlTypes_Power_Group_t));
+		length = ppg_tlv->length;
+		if (length > 0) {
+			max_power = pg->power_max;
+			min_power = pg->power_min;
+			length -= sizeof(Power_Group_t);
+		}
+		while (length) {
+			pg++;
+			if (max_power < pg->power_max)
+				max_power = pg->power_max;
+			if (min_power > pg->power_min)
+				min_power = pg->power_min;
+			length -= sizeof(Power_Group_t);
+		}
+		if (ppg_tlv->length > 0) {
+			pmpriv->min_tx_power_level = min_power;
+			pmpriv->max_tx_power_level = max_power;
+		}
+	} else {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of tx_power_cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_tx_power_cfg(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_TXPWR_CFG *ptxp_cfg = &resp->params.txp_cfg;
+	MrvlTypes_Power_Group_t *ppg_tlv = MNULL;
+	Power_Group_t *pg = MNULL;
+	t_u16 action = wlan_le16_to_cpu(ptxp_cfg->action);
+	mlan_ds_power_cfg *power = MNULL;
+	mlan_power_group *pwr_grp = MNULL;
+	t_u8 i = 0;
+
+	ENTER();
+
+	ppg_tlv = (MrvlTypes_Power_Group_t *)(ptxp_cfg->tlv_buf);
+	pg = (Power_Group_t *)((t_u8 *)ppg_tlv +
+			       sizeof(MrvlTypes_Power_Group_t));
+
+	switch (action) {
+	case HostCmd_ACT_GEN_GET:
+		ppg_tlv->length = wlan_le16_to_cpu(ppg_tlv->length);
+		if (pmpriv->adapter->hw_status ==
+		    WlanHardwareStatusInitializing)
+			wlan_get_power_level(pmpriv, ptxp_cfg);
+		pmpriv->tx_power_level = (t_s16)pg->power_min;
+		break;
+
+	case HostCmd_ACT_GEN_SET:
+		if (wlan_le32_to_cpu(ptxp_cfg->mode)) {
+			if (pg->power_max == pg->power_min)
+				pmpriv->tx_power_level = (t_s16)pg->power_min;
+		}
+		break;
+
+	default:
+		PRINTM(MERROR, "CMD_RESP: unknown command action %d\n", action);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	PRINTM(MINFO, "Current TxPower Level = %d,Max Power=%d, Min Power=%d\n",
+	       pmpriv->tx_power_level, pmpriv->max_tx_power_level,
+	       pmpriv->min_tx_power_level);
+
+	if (pioctl_buf) {
+		power = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
+		if (action == HostCmd_ACT_GEN_GET) {
+			if (power->sub_command == MLAN_OID_POWER_CFG) {
+				pioctl_buf->data_read_written =
+					sizeof(mlan_power_cfg_t) +
+					MLAN_SUB_COMMAND_SIZE;
+				power->param.power_cfg.power_level =
+					pmpriv->tx_power_level;
+				if (wlan_le32_to_cpu(ptxp_cfg->mode))
+					power->param.power_cfg.is_power_auto =
+						0;
+				else
+					power->param.power_cfg.is_power_auto =
+						1;
+			} else {
+				power->param.power_ext.num_pwr_grp = 0;
+				i = 0;
+				while ((ppg_tlv->length) &&
+				       (i < MAX_POWER_GROUP)) {
+					pwr_grp =
+						(mlan_power_group *)&power->
+						param.power_ext.power_group[i];
+					pwr_grp->first_rate_ind = 0;
+					pwr_grp->last_rate_ind = 0;
+					if (pg->modulation_class ==
+					    MOD_CLASS_HR_DSSS) {
+						pwr_grp->rate_format =
+							MLAN_RATE_FORMAT_LG;
+						pwr_grp->first_rate_ind =
+							pg->first_rate_code;
+						pwr_grp->last_rate_ind =
+							pg->last_rate_code;
+					} else if (pg->modulation_class ==
+						   MOD_CLASS_OFDM) {
+						pwr_grp->rate_format =
+							MLAN_RATE_FORMAT_LG;
+						pwr_grp->first_rate_ind =
+							MLAN_RATE_INDEX_OFDM0 +
+							pg->first_rate_code;
+						pwr_grp->last_rate_ind =
+							MLAN_RATE_INDEX_OFDM0 +
+							pg->last_rate_code;
+					} else if (pg->modulation_class ==
+						   MOD_CLASS_HT) {
+						pwr_grp->rate_format =
+							MLAN_RATE_FORMAT_HT;
+						pwr_grp->first_rate_ind =
+							pg->first_rate_code;
+						pwr_grp->last_rate_ind =
+							pg->last_rate_code;
+					} else if (pg->modulation_class ==
+						   MOD_CLASS_VHT) {
+						pwr_grp->rate_format =
+							MLAN_RATE_FORMAT_VHT;
+						pwr_grp->first_rate_ind =
+							(pg->first_rate_code) &
+							0xF;
+						pwr_grp->last_rate_ind =
+							(pg->last_rate_code) &
+							0xF;
+						// pwr_grp->nss = 1 +
+						// (pg->first_rate_code >> 4);
+						pwr_grp->nss =
+							1 +
+							(pg->last_rate_code >>
+							 4);
+					}
+					pwr_grp->bandwidth = pg->ht_bandwidth;
+					pwr_grp->power_min = pg->power_min;
+					pwr_grp->power_max = pg->power_max;
+					pwr_grp->power_step = pg->power_step;
+					ppg_tlv->length -=
+						sizeof(Power_Group_t);
+					pg++;
+					i++;
+				}
+				power->param.power_ext.num_pwr_grp = i;
+				pioctl_buf->data_read_written =
+					sizeof(mlan_power_cfg_ext) +
+					MLAN_SUB_COMMAND_SIZE;
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of rf_tx_power
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_rf_tx_power(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_RF_TX_POWER *rtp = &resp->params.txp;
+	t_u16 action = wlan_le16_to_cpu(rtp->action);
+	mlan_ds_power_cfg *power = MNULL;
+
+	ENTER();
+
+	pmpriv->tx_power_level = wlan_le16_to_cpu(rtp->current_level);
+
+	if (action == HostCmd_ACT_GEN_GET) {
+		pmpriv->max_tx_power_level = rtp->max_power;
+		pmpriv->min_tx_power_level = rtp->min_power;
+		if (pioctl_buf) {
+			power = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
+			if (power->sub_command == MLAN_OID_POWER_CFG) {
+				pioctl_buf->data_read_written =
+					sizeof(mlan_power_cfg_t) +
+					MLAN_SUB_COMMAND_SIZE;
+				power->param.power_cfg.power_level =
+					pmpriv->tx_power_level;
+			}
+		}
+	}
+
+	PRINTM(MINFO, "Current TxPower Level = %d,Max Power=%d, Min Power=%d\n",
+	       pmpriv->tx_power_level, pmpriv->max_tx_power_level,
+	       pmpriv->min_tx_power_level);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sleep_period
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_sleep_period(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SLEEP_PERIOD *pcmd_sleep_pd = &resp->params.sleep_pd;
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+	t_u16 sleep_pd = 0;
+
+	ENTER();
+
+	sleep_pd = wlan_le16_to_cpu(pcmd_sleep_pd->sleep_pd);
+	if (pioctl_buf) {
+		pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+		pm_cfg->param.sleep_period = (t_u32)sleep_pd;
+		pioctl_buf->data_read_written =
+			sizeof(pm_cfg->param.sleep_period) +
+			MLAN_SUB_COMMAND_SIZE;
+	}
+	pmpriv->adapter->sleep_period.period = sleep_pd;
+	pmpriv->adapter->saved_sleep_period.period = sleep_pd;
+
+	pmpriv->adapter->pps_uapsd_mode = MFALSE;
+	if ((pmpriv->adapter->sleep_period.period != 0) &&
+	    (pmpriv->adapter->sleep_period.period !=
+	     SLEEP_PERIOD_RESERVED_FF)) {
+		pmpriv->adapter->gen_null_pkt = MTRUE;
+	} else {
+		pmpriv->adapter->delay_null_pkt = MFALSE;
+		pmpriv->adapter->gen_null_pkt = MFALSE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sleep_params
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_sleep_params(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SLEEP_PARAMS *presp_sp = &resp->params.sleep_param;
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+	mlan_ds_sleep_params *psp = MNULL;
+	sleep_params_t *psleep_params = &pmpriv->adapter->sleep_params;
+
+	ENTER();
+
+	psleep_params->sp_reserved = wlan_le16_to_cpu(presp_sp->reserved);
+	psleep_params->sp_error = wlan_le16_to_cpu(presp_sp->error);
+	psleep_params->sp_offset = wlan_le16_to_cpu(presp_sp->offset);
+	psleep_params->sp_stable_time = wlan_le16_to_cpu(presp_sp->stable_time);
+	psleep_params->sp_cal_control = presp_sp->cal_control;
+	psleep_params->sp_ext_sleep_clk = presp_sp->external_sleep_clk;
+
+	if (pioctl_buf) {
+		pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+		psp = (mlan_ds_sleep_params *)&pm_cfg->param.sleep_params;
+
+		psp->error = (t_u32)psleep_params->sp_error;
+		psp->offset = (t_u32)psleep_params->sp_offset;
+		psp->stable_time = (t_u32)psleep_params->sp_stable_time;
+		psp->cal_control = (t_u32)psleep_params->sp_cal_control;
+		psp->ext_sleep_clk = (t_u32)psleep_params->sp_ext_sleep_clk;
+		psp->reserved = (t_u32)psleep_params->sp_reserved;
+
+		pioctl_buf->data_read_written =
+			sizeof(pm_cfg->param.sleep_params) +
+			MLAN_SUB_COMMAND_SIZE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of multicast_address
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_mac_multicast_adr(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+	if (pioctl_buf) {
+		pioctl_buf->data_read_written =
+			sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of deauthenticate
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_deauthenticate(pmlan_private pmpriv,
+			       HostCmd_DS_COMMAND *resp,
+			       mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u8 event_buf[32];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	ENTER();
+
+	pmadapter->dbg.num_cmd_deauth++;
+
+	if (!memcmp(pmadapter, resp->params.deauth.mac_addr,
+		    &pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		    sizeof(resp->params.deauth.mac_addr))) {
+		wlan_reset_connect_state(pmpriv, MTRUE);
+
+	}
+	if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS)
+		wlan_11h_radar_detected_callback((t_void *)pmpriv);
+	memset(pmadapter, event_buf, 0, sizeof(event_buf));
+	pevent->bss_index = pmpriv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER;
+	pevent->event_len = sizeof(resp->params.deauth.reason_code);
+	memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+		   &resp->params.deauth.reason_code, pevent->event_len,
+		   pevent->event_len);
+	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER, pevent);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of ad_hoc_stop
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_ad_hoc_stop(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+
+	wlan_reset_connect_state(pmpriv, MTRUE);
+	if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS)
+		wlan_11h_radar_detected_callback((t_void *)pmpriv);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of key_material
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_key_material(pmlan_private pmpriv,
+			     HostCmd_DS_COMMAND *resp,
+			     mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_KEY_MATERIAL *pkey = &resp->params.key_material;
+	mlan_ds_sec_cfg *sec = MNULL;
+	t_u8 zero_kek[MLAN_KEK_LEN] = { 0 };
+
+	ENTER();
+
+	if (wlan_le16_to_cpu(pkey->action) == HostCmd_ACT_GEN_SET) {
+		if ((wlan_le16_to_cpu(pkey->key_param_set.key_info) &
+		     KEY_INFO_TKIP_MCAST)) {
+			PRINTM(MINFO, "key: GTK is set\n");
+			pmpriv->wpa_is_gtk_set = MTRUE;
+			if (pmpriv->port_ctrl_mode == MTRUE) {
+				/* GTK is set, open the port */
+				PRINTM(MINFO,
+				       "GTK_SET: Open port: WPA/WPA2 h-supp mode\n");
+				pmpriv->port_open = MTRUE;
+			}
+			if (memcmp(pmpriv->adapter, pmpriv->gtk_rekey.kek,
+				   zero_kek, sizeof(zero_kek)) != 0) {
+				wlan_prepare_cmd(pmpriv,
+						 HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
+						 HostCmd_ACT_GEN_SET, 0, MNULL,
+						 &pmpriv->gtk_rekey);
+				memset(pmpriv->adapter, &pmpriv->gtk_rekey, 0,
+				       sizeof(mlan_ds_misc_gtk_rekey_data));
+			}
+			pmpriv->adapter->scan_block = MFALSE;
+		}
+	} else if (wlan_le16_to_cpu(pkey->action) == HostCmd_ACT_GEN_GET) {
+		if (pioctl_buf && (wlan_le16_to_cpu(pkey->key_param_set.type) ==
+				   TLV_TYPE_KEY_PARAM_V2)) {
+			sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
+			memcpy_ext(pmpriv->adapter,
+				   sec->param.encrypt_key.mac_addr,
+				   pkey->key_param_set.mac_addr,
+				   MLAN_MAC_ADDR_LENGTH,
+				   sizeof(sec->param.encrypt_key.mac_addr));
+			sec->param.encrypt_key.key_index =
+				pkey->key_param_set.key_idx;
+			PRINTM(MIOCTL,
+			       "key_type=%d, key_index=%d, key_info=0x%x "
+			       MACSTR "\n", pkey->key_param_set.key_type,
+			       pkey->key_param_set.key_idx,
+			       wlan_le16_to_cpu(pkey->key_param_set.key_info),
+			       MAC2STR(sec->param.encrypt_key.mac_addr));
+			switch (pkey->key_param_set.key_type) {
+			case KEY_TYPE_ID_WAPI:
+				sec->param.encrypt_key.is_wapi_key = MTRUE;
+				sec->param.encrypt_key.key_len =
+					wlan_le16_to_cpu(pkey->key_param_set.
+							 key_params.wapi.
+							 key_len);
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.key_material,
+					   pkey->key_param_set.key_params.wapi.
+					   key, sec->param.encrypt_key.key_len,
+					   sizeof(sec->param.encrypt_key.
+						  key_material));
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.pn,
+					   pkey->key_param_set.key_params.wapi.
+					   pn, PN_SIZE,
+					   sizeof(sec->param.encrypt_key.pn));
+				break;
+			case KEY_TYPE_ID_TKIP:
+				sec->param.encrypt_key.key_len =
+					wlan_le16_to_cpu(pkey->key_param_set.
+							 key_params.tkip.
+							 key_len);
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.key_material,
+					   pkey->key_param_set.key_params.tkip.
+					   key, sec->param.encrypt_key.key_len,
+					   sizeof(sec->param.encrypt_key.
+						  key_material));
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.pn,
+					   pkey->key_param_set.key_params.tkip.
+					   pn, WPA_PN_SIZE,
+					   sizeof(sec->param.encrypt_key.pn));
+				break;
+			case KEY_TYPE_ID_AES:
+				sec->param.encrypt_key.key_len =
+					wlan_le16_to_cpu(pkey->key_param_set.
+							 key_params.aes.
+							 key_len);
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.key_material,
+					   pkey->key_param_set.key_params.aes.
+					   key, sec->param.encrypt_key.key_len,
+					   sizeof(sec->param.encrypt_key.
+						  key_material));
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.pn,
+					   pkey->key_param_set.key_params.aes.
+					   pn, WPA_PN_SIZE,
+					   sizeof(sec->param.encrypt_key.pn));
+				break;
+			case KEY_TYPE_ID_AES_CMAC:
+				sec->param.encrypt_key.key_len =
+					wlan_le16_to_cpu(pkey->key_param_set.
+							 key_params.cmac_aes.
+							 key_len);
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.key_material,
+					   pkey->key_param_set.key_params.
+					   cmac_aes.key,
+					   sec->param.encrypt_key.key_len,
+					   sizeof(sec->param.encrypt_key.
+						  key_material));
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.pn,
+					   pkey->key_param_set.key_params.
+					   cmac_aes.ipn, IGTK_PN_SIZE,
+					   sizeof(sec->param.encrypt_key.pn));
+				break;
+			case KEY_TYPE_ID_WEP:
+				sec->param.encrypt_key.key_len =
+					wlan_le16_to_cpu(pkey->key_param_set.
+							 key_params.wep.
+							 key_len);
+				memcpy_ext(pmpriv->adapter,
+					   sec->param.encrypt_key.key_material,
+					   pkey->key_param_set.key_params.wep.
+					   key, sec->param.encrypt_key.key_len,
+					   sizeof(sec->param.encrypt_key.
+						  key_material));
+				break;
+			}
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Handle the supplicant profile response
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_supplicant_profile(pmlan_private pmpriv,
+				   HostCmd_DS_COMMAND *resp,
+				   mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_SUPPLICANT_PROFILE *psup_profile =
+		&resp->params.esupplicant_profile;
+	MrvlIEtypesHeader_t *head;
+	MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL;
+	MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL;
+	mlan_ds_sec_cfg *sec = MNULL;
+	t_u8 *tlv;
+	int len;
+
+	ENTER();
+
+	len = resp->size - S_DS_GEN - sizeof(t_u16);
+	tlv = psup_profile->tlv_buf;
+	if (pioctl_buf) {
+		sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
+		while (len > 0) {
+			head = (MrvlIEtypesHeader_t *)tlv;
+			head->type = wlan_le16_to_cpu(head->type);
+			head->len = wlan_le16_to_cpu(head->len);
+			switch (head->type) {
+			case TLV_TYPE_ENCRYPTION_PROTO:
+				encr_proto_tlv =
+					(MrvlIEtypes_EncrProto_t *)head;
+				sec->param.esupp_mode.rsn_mode =
+					wlan_le16_to_cpu(encr_proto_tlv->
+							 rsn_mode);
+				PRINTM(MINFO, "rsn_mode=0x%x\n",
+				       sec->param.esupp_mode.rsn_mode);
+				break;
+			case TLV_TYPE_CIPHER:
+				pcipher_tlv = (MrvlIEtypes_Cipher_t *)head;
+				sec->param.esupp_mode.act_paircipher =
+					pcipher_tlv->pair_cipher;
+				sec->param.esupp_mode.act_groupcipher =
+					pcipher_tlv->group_cipher;
+				PRINTM(MINFO,
+				       "paircipher=0x%x, groupcipher=0x%x\n",
+				       sec->param.esupp_mode.act_paircipher,
+				       sec->param.esupp_mode.act_groupcipher);
+				break;
+			}
+			len -= (head->len - sizeof(MrvlIEtypesHeader_t));
+			tlv = tlv + (head->len + sizeof(MrvlIEtypesHeader_t));
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of rf_channel
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_802_11_rf_channel(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_RF_CHANNEL *prf_channel = &resp->params.rf_channel;
+	t_u16 new_channel = wlan_le16_to_cpu(prf_channel->current_channel);
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+	if (pmpriv->curr_bss_params.bss_descriptor.channel != new_channel) {
+		PRINTM(MINFO, "Channel Switch: %d to %d\n",
+		       pmpriv->curr_bss_params.bss_descriptor.channel,
+		       new_channel);
+		/* Update the channel again */
+		pmpriv->curr_bss_params.bss_descriptor.channel = new_channel;
+	}
+	if (pioctl_buf) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		bss->param.bss_chan.channel = new_channel;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Handle the ibss_coalescing_status resp
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_ibss_coalescing_status(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp)
+{
+	HostCmd_DS_802_11_IBSS_STATUS *pibss_coal_resp =
+		&(resp->params.ibss_coalescing);
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+
+	if (wlan_le16_to_cpu(pibss_coal_resp->action) == HostCmd_ACT_GEN_SET) {
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	PRINTM(MINFO, "New BSSID " MACSTR "\n",
+	       MAC2STR(pibss_coal_resp->bssid));
+
+	/* If rsp has MNULL BSSID, Just return..... No Action */
+	if (!memcmp(pmpriv->adapter, pibss_coal_resp->bssid, zero_mac,
+		    MLAN_MAC_ADDR_LENGTH)) {
+		PRINTM(MMSG, "New BSSID is MNULL\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	/* If BSSID is diff, modify current BSS parameters */
+	if (memcmp(pmpriv->adapter,
+		   pmpriv->curr_bss_params.bss_descriptor.mac_address,
+		   pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH)) {
+		/* BSSID */
+		memcpy_ext(pmpriv->adapter,
+			   pmpriv->curr_bss_params.bss_descriptor.mac_address,
+			   pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH,
+			   sizeof(pmpriv->curr_bss_params.bss_descriptor.
+				  mac_address));
+
+		/* Beacon Interval and ATIM window */
+		pmpriv->curr_bss_params.bss_descriptor.beacon_period =
+			wlan_le16_to_cpu(pibss_coal_resp->beacon_interval);
+		pmpriv->curr_bss_params.bss_descriptor.atim_window =
+			wlan_le16_to_cpu(pibss_coal_resp->atim_window);
+
+		/* ERP Information */
+		pmpriv->curr_bss_params.bss_descriptor.erp_flags =
+			(t_u8)wlan_le16_to_cpu(pibss_coal_resp->
+					       use_g_rate_protect);
+
+		pmpriv->adhoc_state = ADHOC_COALESCED;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of MGMT_IE_LIST
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_mgmt_ie_list(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	t_u16 resp_len = 0, travel_len = 0;
+	int i = 0;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	custom_ie *cptr;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+	HostCmd_DS_MGMT_IE_LIST_CFG *pmgmt_ie_list =
+		&(resp->params.mgmt_ie_list);
+
+	ENTER();
+
+	if (wlan_le16_to_cpu(pmgmt_ie_list->action) == HostCmd_ACT_GEN_SET) {
+		if ((pmpriv->adapter->state_rdh.stage == RDH_SET_CUSTOM_IE) ||
+		    (pmpriv->adapter->state_rdh.stage == RDH_REM_CUSTOM_IE))
+			if (!pmpriv->adapter->ecsa_enable)
+				wlan_11h_radar_detected_callback((t_void *)
+								 pmpriv);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+	cust_ie = (mlan_ds_misc_custom_ie *)&pmgmt_ie_list->ds_mgmt_ie;
+	if (cust_ie) {
+		cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+		resp_len = cust_ie->len = wlan_le16_to_cpu(cust_ie->len);
+		travel_len = 0;
+		/* conversion for index, mask, len */
+		if (resp_len == sizeof(t_u16))
+			cust_ie->ie_data_list[0].ie_index =
+				wlan_cpu_to_le16(cust_ie->ie_data_list[0].
+						 ie_index);
+
+		while (resp_len > sizeof(t_u16)) {
+			cptr = (custom_ie *)(((t_u8 *)cust_ie->ie_data_list) +
+					     travel_len);
+			cptr->ie_index = wlan_le16_to_cpu(cptr->ie_index);
+			cptr->mgmt_subtype_mask =
+				wlan_le16_to_cpu(cptr->mgmt_subtype_mask);
+			cptr->ie_length = wlan_le16_to_cpu(cptr->ie_length);
+			travel_len += cptr->ie_length + sizeof(custom_ie) -
+				MAX_IE_SIZE;
+			resp_len -= cptr->ie_length + sizeof(custom_ie) -
+				MAX_IE_SIZE;
+		}
+		memcpy_ext(pmpriv->adapter, &misc->param.cust_ie, cust_ie,
+			   (cust_ie->len + sizeof(MrvlIEtypesHeader_t)),
+			   sizeof(misc->param.cust_ie));
+		max_mgmt_ie =
+			(tlvbuf_max_mgmt_ie *)((t_u8 *)cust_ie + cust_ie->len +
+					       sizeof(MrvlIEtypesHeader_t));
+		if (max_mgmt_ie) {
+			max_mgmt_ie->type = wlan_le16_to_cpu(max_mgmt_ie->type);
+			if (max_mgmt_ie->type == TLV_TYPE_MAX_MGMT_IE) {
+				max_mgmt_ie->len =
+					wlan_le16_to_cpu(max_mgmt_ie->len);
+				max_mgmt_ie->count =
+					wlan_le16_to_cpu(max_mgmt_ie->count);
+				for (i = 0; i < max_mgmt_ie->count; i++) {
+					max_mgmt_ie->info[i]
+						.buf_size =
+						wlan_le16_to_cpu(max_mgmt_ie->
+								 info[i].
+								 buf_size);
+					max_mgmt_ie->info[i]
+						.buf_count =
+						wlan_le16_to_cpu(max_mgmt_ie->
+								 info[i].
+								 buf_count);
+				}
+				/* Append max_mgmt_ie TLV after custom_ie */
+				memcpy_ext(pmpriv->adapter,
+					   (t_u8 *)&misc->param.cust_ie +
+					   (cust_ie->len +
+					    sizeof(MrvlIEtypesHeader_t)),
+					   max_mgmt_ie,
+					   max_mgmt_ie->len +
+					   sizeof(MrvlIEtypesHeader_t),
+					   sizeof(misc->param.cust_ie) -
+					   (cust_ie->len +
+					    sizeof(MrvlIEtypesHeader_t)));
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function enable/disable tdls powermode
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param powermode    1--enable, 0--disable
+ *
+ *  @return             N/A
+ */
+static void
+wlan_set_tdls_powermode(pmlan_private pmpriv, t_u8 powermode)
+{
+	ENTER();
+
+	if (powermode) {
+		pmpriv->wmm_qosinfo = DEFAULT_TDLS_WMM_QOS_INFO;
+		if (!pmpriv->adapter->sleep_period.period)
+			pmpriv->adapter->sleep_period.period =
+				DEFAULT_TDLS_SLEEP_PERIOD;
+	} else {
+		pmpriv->wmm_qosinfo = pmpriv->saved_wmm_qosinfo;
+		pmpriv->adapter->sleep_period.period =
+			pmpriv->adapter->saved_sleep_period.period;
+	}
+	pmpriv->adapter->pps_uapsd_mode = MFALSE;
+	if ((pmpriv->adapter->sleep_period.period != 0) &&
+	    (pmpriv->adapter->sleep_period.period !=
+	     SLEEP_PERIOD_RESERVED_FF)) {
+		pmpriv->adapter->gen_null_pkt = MTRUE;
+	} else {
+		pmpriv->adapter->delay_null_pkt = MFALSE;
+		pmpriv->adapter->gen_null_pkt = MFALSE;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the command response of TDLS_CONFIG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_ret_tdls_config(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	t_u8 i = 0;
+	t_u16 link_length = 0, final_data_rate = 0;
+	mlan_ds_misc_cfg *misc = MNULL;
+	tdls_all_config *tdls_all_cfg = MNULL;
+	sta_node *sta_ptr = MNULL;
+	HostCmd_DS_TDLS_CONFIG *ptdls_config_data =
+		&(resp->params.tdls_config_data);
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	tdls_each_link_status *link_ptr = MNULL;
+
+	ENTER();
+
+	ptdls_config_data->tdls_info.tdls_action =
+		wlan_le16_to_cpu(ptdls_config_data->tdls_info.tdls_action);
+	switch (ptdls_config_data->tdls_info.tdls_action) {
+	case WLAN_TDLS_CONFIG:
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		if (pmpriv->host_tdls_cs_support ||
+		    pmpriv->host_tdls_uapsd_support)
+			break;
+		if (wlan_le16_to_cpu(tdls_all_cfg->u.tdls_config.enable) == 0) {
+			PRINTM(MINFO, "TDLS disable successful.\n");
+			wlan_delete_station_list(pmpriv);
+			pmadapter->tdls_status = TDLS_NOT_SETUP;
+			if (pmpriv->saved_wmm_qosinfo)
+				pmpriv->wmm_qosinfo = pmpriv->saved_wmm_qosinfo;
+			if (pmadapter->saved_sleep_period.period)
+				pmadapter->sleep_period.period =
+					pmadapter->saved_sleep_period.period;
+		}
+		break;
+
+	case WLAN_TDLS_SET_INFO:
+		break;
+
+	case WLAN_TDLS_DISCOVERY_REQ:
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		tdls_all_cfg->u.tdls_discovery_resp.payload_len =
+			wlan_le16_to_cpu(tdls_all_cfg->u.tdls_discovery_resp.
+					 payload_len);
+		tdls_all_cfg->u.tdls_discovery_resp.cap_info =
+			wlan_le16_to_cpu(tdls_all_cfg->u.tdls_discovery_resp.
+					 cap_info);
+		memcpy_ext(pmpriv->adapter, &misc->param.tdls_config,
+			   &ptdls_config_data->tdls_info,
+			   (resp->size - S_DS_GEN),
+			   sizeof(mlan_ds_misc_tdls_config));
+		PRINTM(MCMND, "TDLS_DISCOVERY_REQ: " MACSTR "\n",
+		       MAC2STR(tdls_all_cfg->u.tdls_discovery_resp
+			       .peer_mac_addr));
+		break;
+
+	case WLAN_TDLS_SETUP_REQ:
+		/*
+		 * TDLS link being setup, block all data for this Peer
+		 */
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		PRINTM(MCMND, "TDLS_SETUP_REQ: " MACSTR "\n",
+		       MAC2STR(tdls_all_cfg->u.tdls_setup.peer_mac_addr));
+		sta_ptr =
+			wlan_get_station_entry(pmpriv,
+					       tdls_all_cfg->u.tdls_setup.
+					       peer_mac_addr);
+		if (!sta_ptr) {
+			sta_ptr = wlan_add_station_entry(pmpriv,
+							 tdls_all_cfg->u.
+							 tdls_setup.
+							 peer_mac_addr);
+			if (sta_ptr) {
+				sta_ptr->status = TDLS_SETUP_INPROGRESS;
+				wlan_hold_tdls_packets(pmpriv,
+						       tdls_all_cfg->u.
+						       tdls_setup.
+						       peer_mac_addr);
+			}
+		}
+		break;
+
+	case WLAN_TDLS_TEAR_DOWN_REQ:
+		/*
+		 * TDLS link torn down, open data ports if blocked
+		 */
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		wlan_restore_tdls_packets(pmpriv,
+					  tdls_all_cfg->u.tdls_tear_down.
+					  peer_mac_addr, TDLS_TEAR_DOWN);
+		PRINTM(MCMND, "TDLS_TEARDOWN_REQ: " MACSTR "\n",
+		       MAC2STR(tdls_all_cfg->u.tdls_tear_down.peer_mac_addr));
+		sta_ptr =
+			wlan_get_station_entry(pmpriv,
+					       tdls_all_cfg->u.tdls_tear_down.
+					       peer_mac_addr);
+		if (sta_ptr) {
+			if (sta_ptr->is_11n_enabled) {
+				wlan_cleanup_reorder_tbl(pmpriv,
+							 tdls_all_cfg->u.
+							 tdls_tear_down.
+							 peer_mac_addr);
+				wlan_11n_cleanup_txbastream_tbl(pmpriv,
+								tdls_all_cfg->u.
+								tdls_tear_down.
+								peer_mac_addr);
+			}
+			wlan_delete_station_entry(pmpriv,
+						  tdls_all_cfg->u.
+						  tdls_tear_down.peer_mac_addr);
+			if (MTRUE == wlan_is_station_list_empty(pmpriv))
+				pmadapter->tdls_status = TDLS_NOT_SETUP;
+			else
+				pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+		}
+		break;
+	case WLAN_TDLS_INIT_CHAN_SWITCH:
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		PRINTM(MCMND,
+		       "TDLS_INIT_CHANNEL_SWITCH: " MACSTR
+		       " chan=%d periodicity=%d\n",
+		       MAC2STR(tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr),
+		       (int)tdls_all_cfg->u.tdls_chan_switch.primary_channel,
+		       (int)tdls_all_cfg->u.tdls_chan_switch.periodicity);
+		break;
+
+	case WLAN_TDLS_LINK_STATUS:
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		tdls_all_cfg->u.tdls_link_status_resp.payload_len =
+			wlan_le16_to_cpu(tdls_all_cfg->u.tdls_link_status_resp
+					 .payload_len);
+		link_ptr = tdls_all_cfg->u.tdls_link_status_resp.link_stats;
+		for (i = 0;
+		     i < tdls_all_cfg->u.tdls_link_status_resp.active_links;
+		     i++) {
+			link_ptr->active_channel =
+				wlan_le32_to_cpu(link_ptr->active_channel);
+			link_ptr->data_rssi_last =
+				wlan_le16_to_cpu(link_ptr->data_rssi_last);
+			link_ptr->data_nf_last =
+				wlan_le16_to_cpu(link_ptr->data_nf_last);
+			link_ptr->data_rssi_avg =
+				wlan_le16_to_cpu(link_ptr->data_rssi_avg);
+			link_ptr->data_nf_avg =
+				wlan_le16_to_cpu(link_ptr->data_nf_avg);
+			link_length = sizeof(tdls_each_link_status) - 1;
+			/* adjust as per open or secure network */
+			if (link_ptr->link_flags & 0x02) {
+				link_ptr->key_lifetime =
+					wlan_le32_to_cpu(link_ptr->
+							 key_lifetime);
+				link_length += link_ptr->key_length;
+			} else {
+				link_length -=
+					sizeof(link_ptr->security_method) +
+					sizeof(link_ptr->key_lifetime) +
+					sizeof(link_ptr->key_length);
+			}
+			final_data_rate =
+				(t_u16)wlan_index_to_data_rate(pmadapter,
+							       link_ptr->u.
+							       rate_info.
+							       tx_data_rate,
+							       link_ptr->u.
+							       rate_info.
+							       tx_rate_htinfo,
+							       0);
+			link_ptr->u.final_data_rate = final_data_rate / 2;
+
+			link_ptr =
+				(tdls_each_link_status *)(((t_u8 *)link_ptr) +
+							  link_length);
+		}
+		memcpy_ext(pmpriv->adapter, &misc->param.tdls_config,
+			   &ptdls_config_data->tdls_info,
+			   (resp->size - S_DS_GEN),
+			   sizeof(mlan_ds_misc_tdls_config));
+		break;
+	case WLAN_TDLS_POWER_MODE:
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		tdls_all_cfg->u.tdls_power_mode.power_mode =
+			wlan_le16_to_cpu(tdls_all_cfg->u.tdls_power_mode.
+					 power_mode);
+		wlan_set_tdls_powermode(pmpriv,
+					(t_u8)tdls_all_cfg->u.tdls_power_mode.
+					power_mode);
+		break;
+	case WLAN_TDLS_STOP_CHAN_SWITCH:
+		tdls_all_cfg = (tdls_all_config *)
+			ptdls_config_data->tdls_info.tdls_data;
+		PRINTM(MCMND, "TDLS_STOP_CHANNEL_SWITCH: " MACSTR "\n",
+		       MAC2STR(tdls_all_cfg->u.tdls_stop_chan_switch.
+			       peer_mac_addr));
+		break;
+	case WLAN_TDLS_CS_PARAMS:
+	case WLAN_TDLS_CS_DISABLE:
+	case WLAN_TDLS_DEBUG_STOP_RX:
+	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_CS_RET_IM:
+		break;
+	default:
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of TDLS_OPERATION
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_ret_tdls_oper(pmlan_private pmpriv,
+		   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_TDLS_OPER *ptdls_oper = &(resp->params.tdls_oper_data);
+	sta_node *sta_ptr = MNULL;
+	t_u16 reason = 0;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	ptdls_oper->tdls_action = wlan_le16_to_cpu(ptdls_oper->tdls_action);
+
+	sta_ptr = wlan_get_station_entry(pmpriv, ptdls_oper->peer_mac);
+	reason = wlan_le16_to_cpu(ptdls_oper->reason);
+	switch (ptdls_oper->tdls_action) {
+	case TDLS_CREATE:
+		if (reason) {
+			PRINTM(MMSG,
+			       "TDLS: create link " MACSTR " fail, reason=%d\n",
+			       MAC2STR(ptdls_oper->peer_mac), reason);
+			if (reason != TDLS_LINK_EXISTS && sta_ptr)
+				sta_ptr->status = TDLS_SETUP_FAILURE;
+		} else {
+			PRINTM(MMSG, "TDLS: create link " MACSTR " success\n",
+			       MAC2STR(ptdls_oper->peer_mac), reason);
+		}
+		break;
+	case TDLS_CONFIG:
+		if (reason) {
+			PRINTM(MMSG,
+			       "TDLS: Config link " MACSTR " fail, reason=%d\n",
+			       MAC2STR(ptdls_oper->peer_mac), reason);
+			if (sta_ptr)
+				sta_ptr->status = TDLS_SETUP_FAILURE;
+		} else {
+			PRINTM(MMSG, "TDLS: Config link " MACSTR " success\n",
+			       MAC2STR(ptdls_oper->peer_mac));
+		}
+		break;
+	case TDLS_DELETE:
+		wlan_restore_tdls_packets(pmpriv, ptdls_oper->peer_mac,
+					  TDLS_TEAR_DOWN);
+		if (sta_ptr) {
+			/**tdls cs stop*/
+			if (ISSUPP_EXTCAP_TDLS_CHAN_SWITCH
+			    (sta_ptr->ExtCap.ext_cap))
+				wlan_tdls_config(pmpriv, MFALSE);
+			if (sta_ptr->is_11n_enabled) {
+				wlan_cleanup_reorder_tbl(pmpriv,
+							 ptdls_oper->peer_mac);
+				wlan_11n_cleanup_txbastream_tbl(pmpriv,
+								ptdls_oper->
+								peer_mac);
+			}
+			if (sta_ptr->status >= TDLS_SETUP_INPROGRESS)
+				wlan_delete_station_entry(pmpriv,
+							  ptdls_oper->peer_mac);
+		}
+		if (MTRUE == wlan_is_station_list_empty(pmpriv))
+			pmadapter->tdls_status = TDLS_NOT_SETUP;
+		else
+			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+
+		if (reason)
+			PRINTM(MMSG,
+			       "TDLS: Delete link " MACSTR " fail, reason=%d\n",
+			       MAC2STR(ptdls_oper->peer_mac), reason);
+		else
+			PRINTM(MMSG, "TDLS: Delete link " MACSTR " success\n",
+			       MAC2STR(ptdls_oper->peer_mac));
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sysclock
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_sysclock_cfg(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *mis_ccfg = MNULL;
+	HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG *clk_cfg =
+		&resp->params.sys_clock_cfg;
+	int i = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		mis_ccfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		mis_ccfg->param.sys_clock.cur_sys_clk =
+			wlan_le16_to_cpu(clk_cfg->cur_sys_clk);
+		mis_ccfg->param.sys_clock.sys_clk_type =
+			wlan_le16_to_cpu(clk_cfg->sys_clk_type);
+		mis_ccfg->param.sys_clock.sys_clk_num =
+			wlan_le16_to_cpu(clk_cfg->sys_clk_len) / sizeof(t_u16);
+		for (i = 0; i < mis_ccfg->param.sys_clock.sys_clk_num; i++)
+			mis_ccfg->param.sys_clock.sys_clk[i] =
+				wlan_le16_to_cpu(clk_cfg->sys_clk[i]);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of inactivity timeout
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_inactivity_timeout(pmlan_private pmpriv,
+			    HostCmd_DS_COMMAND *resp,
+			    mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_pm_cfg *pmcfg = MNULL;
+	mlan_ds_inactivity_to *inac_to = MNULL;
+	HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
+		(HostCmd_DS_INACTIVITY_TIMEOUT_EXT *)
+		&resp->params.inactivity_to;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pmcfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+		inac_to = &pmcfg->param.inactivity_to;
+		inac_to->timeout_unit =
+			wlan_le16_to_cpu(cmd_inac_to->timeout_unit);
+		inac_to->unicast_timeout =
+			wlan_le16_to_cpu(cmd_inac_to->unicast_timeout);
+		inac_to->mcast_timeout =
+			wlan_le16_to_cpu(cmd_inac_to->mcast_timeout);
+		inac_to->ps_entry_timeout =
+			wlan_le16_to_cpu(cmd_inac_to->ps_entry_timeout);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *  subscribe event
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_subscribe_event(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_SUBSCRIBE_EVENT *evt =
+		(HostCmd_DS_SUBSCRIBE_EVENT *)&resp->params.subscribe_event;
+	mlan_ds_subscribe_evt *sub_evt = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		sub_evt = &misc->param.subscribe_event;
+		sub_evt->evt_bitmap = wlan_le16_to_cpu(evt->event_bitmap);
+		pioctl_buf->data_read_written = sizeof(mlan_ds_misc_cfg);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of
+ *  OTP user data
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_otp_user_data(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_OTP_USER_DATA *cmd_user_data =
+		(HostCmd_DS_OTP_USER_DATA *)&resp->params.otp_user_data;
+	mlan_ds_misc_otp_user_data *user_data = MNULL;
+
+	ENTER();
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+		user_data = (mlan_ds_misc_otp_user_data *)pioctl_buf->pbuf;
+		user_data->user_data_length =
+			MIN(MAX_OTP_USER_DATA_LEN,
+			    wlan_le16_to_cpu(cmd_user_data->user_data_length));
+		memcpy_ext(pmpriv->adapter, user_data->user_data,
+			   cmd_user_data->user_data,
+			   user_data->user_data_length,
+			   sizeof(user_data->user_data));
+		pioctl_buf->data_read_written =
+			sizeof(mlan_ds_misc_otp_user_data) +
+			user_data->user_data_length;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef USB
+/**
+ *  @brief This function handles the command response of
+ *  packet aggregation
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_packet_aggr_over_host_interface(pmlan_private pmpriv,
+					 HostCmd_DS_COMMAND *resp,
+					 mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE *packet_aggr =
+		(HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE *)&resp->params.
+		packet_aggr;
+	MrvlIETypes_USBAggrParam_t *usb_aggr_param_tlv = MNULL;
+	mlan_ds_misc_usb_aggr_ctrl *usb_aggr_ctrl = MNULL;
+	t_u8 *ptlv_buffer = (t_u8 *)packet_aggr->tlv_buf;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u16 tlv = 0;
+	int tlv_buf_len = 0;
+	t_u8 changed = 0;
+#if defined(USB)
+	t_s32 i = 0;
+#endif
+
+	ENTER();
+
+	tlv_buf_len =
+		resp->size -
+		(sizeof(HostCmd_DS_PACKET_AGGR_OVER_HOST_INTERFACE) + S_DS_GEN);
+
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	while (tlv_buf_len > 0) {
+		changed = 0;
+		tlv = (*ptlv_buffer) | (*(ptlv_buffer + 1) << 8);
+		switch (tlv) {
+		case MRVL_USB_AGGR_PARAM_TLV_ID:
+			usb_aggr_param_tlv = (MrvlIETypes_USBAggrParam_t *)
+				ptlv_buffer;
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			usb_aggr_ctrl =
+				(mlan_ds_misc_usb_aggr_ctrl *)&(misc->param.
+								usb_aggr_params);
+			usb_aggr_param_tlv->header.len =
+				wlan_le16_to_cpu(usb_aggr_param_tlv->header.
+						 len);
+			usb_aggr_param_tlv->enable =
+				wlan_le16_to_cpu(usb_aggr_param_tlv->enable);
+#if defined(USB)
+			if (pioctl_buf->action == MLAN_ACT_SET) {
+				/* Update the Tx aggregation values in
+				 * MLAN */
+				for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
+					pmadapter->pcard_usb->usb_tx_aggr[i]
+					.aggr_ctrl.enable =
+						usb_aggr_ctrl->tx_aggr_ctrl.
+						enable;
+					if (pmadapter->pcard_usb->usb_tx_aggr[i]
+					    .aggr_ctrl.aggr_mode !=
+					    usb_aggr_ctrl->tx_aggr_ctrl.
+					    aggr_mode) {
+						pmadapter->pcard_usb->
+							usb_tx_aggr[i]
+							.aggr_ctrl.aggr_mode = usb_aggr_ctrl
+						->tx_aggr_ctrl.aggr_mode;
+						changed = 1;
+					}
+					if (pmadapter->pcard_usb->usb_tx_aggr[i]
+					    .aggr_ctrl.aggr_align !=
+					    usb_aggr_ctrl->tx_aggr_ctrl.
+					    aggr_align) {
+						pmadapter->pcard_usb->
+							usb_tx_aggr[i]
+							.aggr_ctrl.aggr_align = usb_aggr_ctrl
+						->tx_aggr_ctrl.aggr_align;
+						changed = 1;
+					}
+					if (pmadapter->pcard_usb->usb_tx_aggr[i]
+					    .aggr_ctrl.aggr_max !=
+					    usb_aggr_ctrl->tx_aggr_ctrl.
+					    aggr_max) {
+						pmadapter->pcard_usb->
+							usb_tx_aggr[i]
+							.aggr_ctrl.aggr_max = usb_aggr_ctrl
+						->tx_aggr_ctrl.aggr_max;
+						changed = 1;
+					}
+					pmadapter->pcard_usb->usb_tx_aggr[i]
+						.aggr_ctrl.aggr_tmo = usb_aggr_ctrl
+					->tx_aggr_ctrl.aggr_tmo;
+				}
+			} else {
+				if (usb_aggr_param_tlv->enable & MBIT(1))
+					usb_aggr_ctrl->tx_aggr_ctrl.enable =
+						MTRUE;
+				else
+					usb_aggr_ctrl->tx_aggr_ctrl.enable =
+						MFALSE;
+				usb_aggr_ctrl->tx_aggr_ctrl.aggr_align =
+					wlan_le16_to_cpu(usb_aggr_param_tlv->
+							 tx_aggr_align);
+				usb_aggr_ctrl->tx_aggr_ctrl.aggr_mode =
+					pmadapter->pcard_usb->usb_tx_aggr[0]
+					.aggr_ctrl.aggr_mode;
+				usb_aggr_ctrl->tx_aggr_ctrl.aggr_max =
+					pmadapter->pcard_usb->usb_tx_aggr[0]
+					.aggr_ctrl.aggr_max;
+				usb_aggr_ctrl->tx_aggr_ctrl.aggr_tmo =
+					pmadapter->pcard_usb->usb_tx_aggr[0]
+					.aggr_ctrl.aggr_tmo;
+			}
+			if (changed)
+				wlan_reset_usb_tx_aggr(pmadapter);
+#endif
+
+#if defined(USB)
+			if (pioctl_buf->action == MLAN_ACT_SET) {
+				/* Update the Rx deaggregation values in
+				 * MLAN */
+				pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+					enable =
+					usb_aggr_ctrl->rx_deaggr_ctrl.enable;
+				if (pmadapter->pcard_usb->usb_rx_deaggr.
+				    aggr_ctrl.aggr_mode !=
+				    usb_aggr_ctrl->rx_deaggr_ctrl.aggr_mode)
+					pmadapter->pcard_usb->usb_rx_deaggr.
+						aggr_ctrl.aggr_mode =
+						usb_aggr_ctrl
+					->rx_deaggr_ctrl.aggr_mode;
+				if (pmadapter->pcard_usb->usb_rx_deaggr.
+				    aggr_ctrl.aggr_align !=
+				    usb_aggr_ctrl->rx_deaggr_ctrl.aggr_align)
+					pmadapter->pcard_usb->usb_rx_deaggr.
+						aggr_ctrl.aggr_align =
+						usb_aggr_ctrl
+					->rx_deaggr_ctrl.aggr_align;
+				if (pmadapter->pcard_usb->usb_rx_deaggr.
+				    aggr_ctrl.aggr_max !=
+				    usb_aggr_ctrl->rx_deaggr_ctrl.aggr_max)
+					pmadapter->pcard_usb->usb_rx_deaggr.
+						aggr_ctrl.aggr_max =
+						usb_aggr_ctrl
+					->rx_deaggr_ctrl.aggr_max;
+				pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+					aggr_tmo =
+					usb_aggr_ctrl->rx_deaggr_ctrl.aggr_tmo;
+			} else {
+				if (usb_aggr_param_tlv->enable & MBIT(0))
+					usb_aggr_ctrl->rx_deaggr_ctrl.enable =
+						MTRUE;
+				else
+					usb_aggr_ctrl->rx_deaggr_ctrl.enable =
+						MFALSE;
+				usb_aggr_ctrl->rx_deaggr_ctrl.aggr_mode =
+					wlan_le16_to_cpu(usb_aggr_param_tlv->
+							 rx_aggr_mode);
+				usb_aggr_ctrl->rx_deaggr_ctrl.aggr_align =
+					wlan_le16_to_cpu(usb_aggr_param_tlv->
+							 rx_aggr_align);
+				usb_aggr_ctrl->rx_deaggr_ctrl.aggr_max =
+					wlan_le16_to_cpu(usb_aggr_param_tlv->
+							 rx_aggr_max);
+				usb_aggr_ctrl->rx_deaggr_ctrl.aggr_tmo =
+					wlan_le16_to_cpu(usb_aggr_param_tlv->
+							 rx_aggr_tmo);
+			}
+#endif
+			ptlv_buffer += usb_aggr_param_tlv->header.len +
+				sizeof(MrvlIEtypesHeader_t);
+			tlv_buf_len -= (usb_aggr_param_tlv->header.len +
+					sizeof(MrvlIEtypesHeader_t));
+			break;
+		default:
+			break;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ *  @brief This function handles the command response of
+ *  DFS Repeater mode configuration
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_dfs_repeater_cfg(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_DFS_REPEATER_MODE *cmd_dfs_repeater =
+		&resp->params.dfs_repeater;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_dfs_repeater *dfs_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		dfs_cfg =
+			(mlan_ds_misc_dfs_repeater *)&misc->param.dfs_repeater;
+		dfs_cfg->mode = wlan_le16_to_cpu(cmd_dfs_repeater->mode);
+	}
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_SET)) {
+		if (wlan_le16_to_cpu(cmd_dfs_repeater->mode) == 1) {
+			/* Set dfs_repeater mode to true/enabled
+			 * for futher references.
+			 */
+			pmpriv->adapter->dfs_repeater = MTRUE;
+		} else {
+			pmpriv->adapter->dfs_repeater = MFALSE;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of coalesce config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_coalesce_config(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+static mlan_status
+wlan_ret_get_sensor_temp(pmlan_private pmpriv,
+			 const HostCmd_DS_COMMAND *resp,
+			 mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *pcfg = MNULL;
+	const HostCmd_DS_SENSOR_TEMP *pSensorT = &resp->params.temp_sensor;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		pcfg->param.sensor_temp.temperature =
+			wlan_le32_to_cpu(pSensorT->temperature);
+		PRINTM(MCMND, "get SOC temperature %u C \n",
+		       pSensorT->temperature);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of arb Cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_arb_cfg(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_ARB_CONFIG *cfg_cmd =
+		(HostCmd_DS_CMD_ARB_CONFIG *) & resp->params.arb_cfg;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.arb_cfg.arb_mode =
+			wlan_le32_to_cpu(cfg_cmd->arb_mode);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of ipv6 ra offload feature
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_ipv6_ra_offload(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_IPV6_RA_OFFLOAD *ipv6_ra_resp =
+		&resp->params.ipv6_ra_offload;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_misc_ipv6_ra_offload *ipv6_ra = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		ipv6_ra =
+			(mlan_ds_misc_ipv6_ra_offload *) & misc->param.
+			ipv6_ra_offload;
+		ipv6_ra->enable = ipv6_ra_resp->enable;
+		memcpy_ext(pmpriv->adapter, ipv6_ra->ipv6_addr,
+			   ipv6_ra_resp->ipv6_addr_param.ipv6_addr, 16,
+			   sizeof(ipv6_ra->ipv6_addr));
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sta get band and
+ * channel
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_sta_config(pmlan_private pmpriv,
+		    HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_STA_CONFIGURE *cmdrsp_sta_cfg =
+		(HostCmd_DS_STA_CONFIGURE *) & resp->params.sta_cfg;
+	mlan_ds_bss *bss = MNULL;
+	MrvlIEtypes_channel_band_t *tlv_band_channel = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+			bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+			if (bss->sub_command == MLAN_OID_BSS_CHAN_INFO) {
+				tlv_band_channel =
+					(MrvlIEtypes_channel_band_t *)
+					cmdrsp_sta_cfg->tlv_buffer;
+				bss->param.sta_channel.bandcfg =
+					tlv_band_channel->bandcfg;
+				bss->param.sta_channel.channel =
+					tlv_band_channel->channel;
+				bss->param.sta_channel.is_11n_enabled =
+					IS_11N_ENABLED(pmpriv);
+				if (bss->param.sta_channel.bandcfg.chanWidth ==
+				    CHAN_BW_80MHZ)
+					bss->param.sta_channel.center_chan =
+						wlan_get_center_freq_idx(pmpriv,
+									 BAND_AAC,
+									 bss->
+									 param.
+									 sta_channel.
+									 channel,
+									 CHANNEL_BW_80MHZ);
+				PRINTM(MCMND,
+				       "Get STA channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+				       bss->param.sta_channel.bandcfg,
+				       bss->param.sta_channel.channel,
+				       bss->param.sta_channel.is_11n_enabled,
+				       bss->param.sta_channel.center_chan);
+
+				pioctl_buf->data_read_written =
+					sizeof(mlan_ds_bss);
+			}
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of set/get auto tx
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_auto_tx(pmlan_private pmpriv,
+		 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_AUTO_TX *cmdrsp_auto_tx =
+		(HostCmd_DS_AUTO_TX *) & resp->params.auto_tx;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	MrvlIEtypesHeader_t *header = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 action;
+	t_u16 len = 0;
+	MrvlIEtypes_Cloud_Keep_Alive_t *keep_alive_tlv = MNULL;
+	MrvlIEtypes_Keep_Alive_Pkt_t *pkt_tlv = MNULL;
+	mlan_ds_misc_keep_alive *misc_keep_alive = MNULL;
+
+	ENTER();
+
+	action = wlan_le16_to_cpu(cmdrsp_auto_tx->action);
+	if (!pioctl_buf) {
+		PRINTM(MERROR, "ioctl is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	if (!misc) {
+		PRINTM(MERROR, "misc is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (resp->result == HostCmd_RESULT_OK) {
+		header = (MrvlIEtypesHeader_t *)cmdrsp_auto_tx->tlv_buffer;
+		header->type = wlan_le16_to_cpu(header->type);
+		len = wlan_le16_to_cpu(header->len);
+		if (header->type == TLV_TYPE_CLOUD_KEEP_ALIVE) {
+			keep_alive_tlv = (MrvlIEtypes_Cloud_Keep_Alive_t *)
+				cmdrsp_auto_tx->tlv_buffer;
+			misc_keep_alive =
+				(mlan_ds_misc_keep_alive *) & misc->param.
+				keep_alive;
+			misc_keep_alive->mkeep_alive_id =
+				keep_alive_tlv->keep_alive_id;
+			misc_keep_alive->enable = keep_alive_tlv->enable;
+			if (((action == HostCmd_ACT_GEN_SET) ||
+			     (action == HostCmd_ACT_GEN_RESET)) &&
+			    !keep_alive_tlv->enable) {
+				len = len -
+					sizeof(keep_alive_tlv->keep_alive_id) -
+					sizeof(keep_alive_tlv->enable);
+				if (len > sizeof(MrvlIEtypesHeader_t)) {
+					header = (MrvlIEtypesHeader_t *)
+						keep_alive_tlv->tlv;
+					header->type =
+						wlan_le16_to_cpu(header->type);
+					len = wlan_le16_to_cpu(header->len) -
+						sizeof(Eth803Hdr_t);
+					if (header->type ==
+					    TLV_TYPE_KEEP_ALIVE_PKT) {
+						pkt_tlv =
+							(MrvlIEtypes_Keep_Alive_Pkt_t
+							 *) keep_alive_tlv->tlv;
+						memcpy_ext(pmpriv->adapter,
+							   misc_keep_alive->
+							   dst_mac,
+							   pkt_tlv->eth_header.
+							   dest_addr,
+							   MLAN_MAC_ADDR_LENGTH,
+							   sizeof
+							   (misc_keep_alive->
+							    dst_mac));
+						memcpy_ext(pmpriv->adapter,
+							   misc_keep_alive->
+							   src_mac,
+							   pkt_tlv->eth_header.
+							   src_addr,
+							   MLAN_MAC_ADDR_LENGTH,
+							   sizeof
+							   (misc_keep_alive->
+							    src_mac));
+						memcpy_ext(pmpriv->adapter,
+							   misc_keep_alive->
+							   packet,
+							   pkt_tlv->ip_packet,
+							   len,
+							   sizeof
+							   (misc_keep_alive->
+							    packet));
+						misc_keep_alive->pkt_len = len;
+					}
+				}
+			}
+		}
+	}
+
+	LEAVE();
+	return status;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function prepares command resp of MFG Continuous Tx
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_mfg_tx_cont(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	struct mfg_cmd_tx_cont *mcmd = (struct mfg_cmd_tx_cont
+					*)&resp->params.mfg_tx_cont;
+	struct mfg_cmd_tx_cont *cfg = MNULL;
+
+	ENTER();
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+	cfg = (struct mfg_cmd_tx_cont *)&misc->param.mfg_tx_cont;
+
+	cfg->error = wlan_le32_to_cpu(mcmd->error);
+	cfg->enable_tx = wlan_le32_to_cpu(mcmd->enable_tx);
+	cfg->cw_mode = wlan_le32_to_cpu(mcmd->cw_mode);
+	cfg->payload_pattern = wlan_le32_to_cpu(mcmd->payload_pattern);
+	cfg->cs_mode = wlan_le32_to_cpu(mcmd->cs_mode);
+	cfg->act_sub_ch = wlan_le32_to_cpu(mcmd->act_sub_ch);
+	cfg->tx_rate = wlan_le32_to_cpu(mcmd->tx_rate);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command resp of MFG Tx frame
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_mfg_tx_frame(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	struct mfg_cmd_tx_frame2 *mcmd = (struct mfg_cmd_tx_frame2
+					  *)&resp->params.mfg_tx_frame2;
+	struct mfg_cmd_tx_frame2 *cfg = MNULL;
+
+	ENTER();
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+	cfg = (struct mfg_cmd_tx_frame2 *)&misc->param.mfg_tx_frame2;
+
+	cfg->error = wlan_le32_to_cpu(mcmd->error);
+	cfg->enable = wlan_le32_to_cpu(mcmd->enable);
+	cfg->data_rate = wlan_le32_to_cpu(mcmd->data_rate);
+	cfg->frame_pattern = wlan_le32_to_cpu(mcmd->frame_pattern);
+	cfg->frame_length = wlan_le32_to_cpu(mcmd->frame_length);
+	cfg->adjust_burst_sifs = wlan_le16_to_cpu(mcmd->adjust_burst_sifs);
+	cfg->burst_sifs_in_us = wlan_le32_to_cpu(mcmd->burst_sifs_in_us);
+	cfg->short_preamble = wlan_le32_to_cpu(mcmd->short_preamble);
+	cfg->act_sub_ch = wlan_le32_to_cpu(mcmd->act_sub_ch);
+	cfg->short_gi = wlan_le32_to_cpu(mcmd->short_gi);
+	cfg->tx_bf = wlan_le32_to_cpu(mcmd->tx_bf);
+	cfg->gf_mode = wlan_le32_to_cpu(mcmd->gf_mode);
+	cfg->stbc = wlan_le32_to_cpu(mcmd->stbc);
+	cfg->NumPkt = wlan_le32_to_cpu(mcmd->NumPkt);
+	cfg->MaxPE = wlan_le32_to_cpu(mcmd->MaxPE);
+	cfg->BeamChange = wlan_le32_to_cpu(mcmd->BeamChange);
+	cfg->Dcm = wlan_le32_to_cpu(mcmd->Dcm);
+	cfg->Doppler = wlan_le32_to_cpu(mcmd->Doppler);
+	cfg->MidP = wlan_le32_to_cpu(mcmd->MidP);
+	cfg->QNum = wlan_le32_to_cpu(mcmd->QNum);
+	memcpy_ext(pmpriv->adapter, cfg->bssid, mcmd->bssid,
+		   MLAN_MAC_ADDR_LENGTH, sizeof(cfg->bssid));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command resp of MFG HE TB Tx
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+
+static mlan_status
+wlan_ret_mfg_he_tb_tx(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	struct mfg_Cmd_HE_TBTx_t *mcmd = (struct mfg_Cmd_HE_TBTx_t
+					  *)&resp->params.mfg_he_power;
+	struct mfg_Cmd_HE_TBTx_t *cfg = MNULL;
+
+	ENTER();
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+	cfg = (struct mfg_Cmd_HE_TBTx_t *)&misc->param.mfg_he_power;
+
+	cfg->enable = wlan_le16_to_cpu(mcmd->enable);
+	cfg->qnum = wlan_le16_to_cpu(mcmd->qnum);
+	cfg->aid = wlan_le16_to_cpu(mcmd->aid);
+	cfg->axq_mu_timer = wlan_le16_to_cpu(mcmd->axq_mu_timer);
+	cfg->tx_power = wlan_le16_to_cpu(mcmd->tx_power);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+
+}
+
+/**
+ *  @brief This function prepares command resp of MFG Cmd
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_mfg(pmlan_private pmpriv,
+	     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	struct mfg_cmd_generic_cfg *mcmd = (struct mfg_cmd_generic_cfg
+					    *)&resp->params.mfg_generic_cfg;
+	struct mfg_cmd_generic_cfg *cfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	switch (wlan_le32_to_cpu(mcmd->mfg_cmd)) {
+	case MFG_CMD_TX_CONT:
+		ret = wlan_ret_mfg_tx_cont(pmpriv, resp, pioctl_buf);
+		goto cmd_mfg_done;
+	case MFG_CMD_TX_FRAME:
+		ret = wlan_ret_mfg_tx_frame(pmpriv, resp, pioctl_buf);
+		goto cmd_mfg_done;
+	case MFG_CMD_CONFIG_MAC_HE_TB_TX:
+		ret = wlan_ret_mfg_he_tb_tx(pmpriv, resp, pioctl_buf);
+		goto cmd_mfg_done;
+	case MFG_CMD_SET_TEST_MODE:
+	case MFG_CMD_UNSET_TEST_MODE:
+	case MFG_CMD_TX_ANT:
+	case MFG_CMD_RX_ANT:
+	case MFG_CMD_RF_CHAN:
+	case MFG_CMD_CLR_RX_ERR:
+	case MFG_CMD_RF_BAND_AG:
+	case MFG_CMD_RF_CHANNELBW:
+	case MFG_CMD_RADIO_MODE_CFG:
+	case MFG_CMD_RFPWR:
+		break;
+	default:
+		ret = MLAN_STATUS_FAILURE;
+		goto cmd_mfg_done;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+	cfg = (struct mfg_cmd_generic_cfg *)&misc->param.mfg_generic_cfg;
+
+	cfg->error = wlan_le32_to_cpu(mcmd->error);
+	cfg->data1 = wlan_le32_to_cpu(mcmd->data1);
+	cfg->data2 = wlan_le32_to_cpu(mcmd->data2);
+	cfg->data3 = wlan_le32_to_cpu(mcmd->data3);
+cmd_mfg_done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the station command response
+ *
+ *  @param priv             A pointer to mlan_private structure
+ *  @param cmdresp_no       cmd no
+ *  @param pcmd_buf         cmdresp buf
+ *  @param pioctl           A pointer to ioctl buf
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+			     t_void *pcmd_buf, t_void *pioctl)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *)pcmd_buf;
+	mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *)pioctl;
+
+	mlan_adapter *pmadapter = pmpriv->adapter;
+#ifdef SDIO
+	int ctr;
+#endif
+
+	ENTER();
+
+	/* If the command is not successful, cleanup and return failure */
+	if ((resp->result != HostCmd_RESULT_OK)
+		) {
+		ret = wlan_process_cmdresp_error(pmpriv, resp, pioctl_buf);
+		LEAVE();
+		return ret;
+	}
+	/* Command successful, handle response */
+	switch (cmdresp_no) {
+	case HostCmd_CMD_GET_HW_SPEC:
+		ret = wlan_ret_get_hw_spec(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef SDIO
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+		break;
+#endif
+	case HostCmd_CMD_CFG_DATA:
+		ret = wlan_ret_cfg_data(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MAC_CONTROL:
+		ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_MAC_ADDRESS:
+		ret = wlan_ret_802_11_mac_address(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MAC_MULTICAST_ADR:
+		ret = wlan_ret_mac_multicast_adr(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_RATE_CFG:
+		ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_SCAN:
+		ret = wlan_ret_802_11_scan(pmpriv, resp, pioctl_buf);
+		pioctl_buf = MNULL;
+		pmadapter->curr_cmd->pioctl_buf = MNULL;
+		break;
+	case HostCmd_CMD_802_11_SCAN_EXT:
+		ret = wlan_ret_802_11_scan_ext(pmpriv, resp, pioctl_buf);
+		pioctl_buf = MNULL;
+		pmadapter->curr_cmd->pioctl_buf = MNULL;
+		break;
+	case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
+		ret = wlan_ret_bgscan_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
+		ret = wlan_ret_802_11_bgscan_query(pmpriv, resp, pioctl_buf);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_BGSCAN_RESULT, MNULL);
+		PRINTM(MINFO, "CMD_RESP: BG_SCAN result is ready!\n");
+		break;
+	case HostCmd_CMD_TXPWR_CFG:
+		ret = wlan_ret_tx_power_cfg(pmpriv, resp, pioctl_buf);
+		break;
+
+	case HostCmd_CMD_802_11_RF_TX_POWER:
+		ret = wlan_ret_802_11_rf_tx_power(pmpriv, resp, pioctl_buf);
+		break;
+
+	case HostCmd_CMD_802_11_PS_MODE_ENH:
+		ret = wlan_ret_enh_power_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_HS_CFG_ENH:
+		ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_SLEEP_PERIOD:
+		ret = wlan_ret_802_11_sleep_period(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_SLEEP_PARAMS:
+		ret = wlan_ret_802_11_sleep_params(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		break;
+	case HostCmd_CMD_DMCS_CONFIG:
+		ret = wlan_ret_dmcs_config(pmpriv, resp, pioctl_buf);
+		break;
+#if defined(PCIE)
+	case HostCmd_CMD_SSU:
+		PRINTM(MCMND,
+		       "SSU cmdresp:number_of_buffers %d, buffer_size %d rec_len %d\n",
+		       resp->params.ssu_params.number_of_buffers,
+		       resp->params.ssu_params.buffer_size,
+		       resp->params.ssu_params.rec_len);
+		break;
+#endif
+	case HostCmd_CMD_802_11_ASSOCIATE:
+		ret = wlan_ret_802_11_associate(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_DEAUTHENTICATE:
+	case HostCmd_CMD_802_11_DISASSOCIATE:
+		ret = wlan_ret_802_11_deauthenticate(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_AD_HOC_START:
+	case HostCmd_CMD_802_11_AD_HOC_JOIN:
+		ret = wlan_ret_802_11_ad_hoc(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_AD_HOC_STOP:
+		ret = wlan_ret_802_11_ad_hoc_stop(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_GET_LOG:
+		ret = wlan_ret_get_log(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_LINK_STATS:
+		ret = wlan_ret_get_link_statistic(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RSSI_INFO_EXT:
+		ret = wlan_ret_802_11_rssi_info_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RSSI_INFO:
+		ret = wlan_ret_802_11_rssi_info(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_SNMP_MIB:
+		ret = wlan_ret_802_11_snmp_mib(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RF_CHANNEL:
+		ret = wlan_ret_802_11_rf_channel(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CW_MODE_CTRL:
+		ret = wlan_ret_cw_mode_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_FUNC_INIT:
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+		break;
+	case HostCmd_CMD_802_11_KEY_MATERIAL:
+		ret = wlan_ret_802_11_key_material(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
+		break;
+	case HostCmd_CMD_SUPPLICANT_PMK:
+		ret = wlan_ret_802_11_supplicant_pmk(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_SUPPLICANT_PROFILE:
+		ret = wlan_ret_802_11_supplicant_profile(pmpriv, resp,
+							 pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_EAPOL_PKT:
+		break;
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		ret = wlan_ret_802_11d_domain_info(pmpriv, resp);
+		break;
+	case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
+	case HostCmd_CMD_802_11_TPC_INFO:
+	case HostCmd_CMD_802_11_CHAN_SW_ANN:
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		ret = wlan_11h_cmdresp_process(pmpriv, resp);
+		break;
+	case HostCmd_CMD_11N_ADDBA_REQ:
+		ret = wlan_ret_11n_addba_req(pmpriv, resp);
+		break;
+	case HostCmd_CMD_11N_DELBA:
+		ret = wlan_ret_11n_delba(pmpriv, resp);
+		break;
+	case HostCmd_CMD_11N_ADDBA_RSP:
+		ret = wlan_ret_11n_addba_resp(pmpriv, resp);
+		break;
+	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+		wlan_set_tx_pause_flag(pmpriv, MFALSE);
+
+		pmadapter->tx_buf_size =
+			(t_u16)wlan_le16_to_cpu(resp->params.tx_buf.buff_size);
+#ifdef SDIO
+		if (IS_SD(pmadapter->card_type)) {
+			pmadapter->tx_buf_size = (pmadapter->tx_buf_size /
+						  MLAN_SDIO_BLOCK_SIZE) *
+				MLAN_SDIO_BLOCK_SIZE;
+			pmadapter->pcard_sd->mp_end_port =
+				wlan_le16_to_cpu(resp->params.tx_buf.
+						 mp_end_port);
+			pmadapter->pcard_sd->mp_data_port_mask =
+				pmadapter->pcard_sd->reg->data_port_mask;
+
+			for (ctr = 1;
+			     ctr <=
+			     pmadapter->pcard_sd->max_ports -
+			     pmadapter->pcard_sd->mp_end_port; ctr++) {
+				pmadapter->pcard_sd->mp_data_port_mask &=
+					~(1 <<
+					  (pmadapter->pcard_sd->max_ports -
+					   ctr));
+			}
+
+			pmadapter->pcard_sd->curr_wr_port =
+				pmadapter->pcard_sd->reg->start_wr_port;
+			pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+				MIN(pmadapter->pcard_sd->mp_aggr_pkt_limit,
+				    (pmadapter->pcard_sd->mp_end_port >> 1));
+			PRINTM(MCMND, "end port %d, data port mask %x\n",
+			       wlan_le16_to_cpu(resp->params.tx_buf.
+						mp_end_port),
+			       pmadapter->pcard_sd->mp_data_port_mask);
+		}
+#endif
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n",
+		       pmadapter->max_tx_buf_size, pmadapter->tx_buf_size);
+		break;
+	case HostCmd_CMD_AMSDU_AGGR_CTRL:
+		ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_GET_STATUS:
+		ret = wlan_ret_wmm_get_status(pmpriv,
+					      resp->params.get_wmm_status.
+					      queue_status_tlv,
+					      resp->size - S_DS_GEN);
+		break;
+	case HostCmd_CMD_WMM_ADDTS_REQ:
+		ret = wlan_ret_wmm_addts_req(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_DELTS_REQ:
+		ret = wlan_ret_wmm_delts_req(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_QUEUE_CONFIG:
+		ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_QUEUE_STATS:
+		ret = wlan_ret_wmm_queue_stats(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_TS_STATUS:
+		ret = wlan_ret_wmm_ts_status(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_PARAM_CONFIG:
+		ret = wlan_ret_wmm_param_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
+		ret = wlan_ret_ibss_coalescing_status(pmpriv, resp);
+		break;
+	case HostCmd_CMD_MGMT_IE_LIST:
+		ret = wlan_ret_mgmt_ie_list(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TDLS_CONFIG:
+		ret = wlan_ret_tdls_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TDLS_OPERATION:
+		ret = wlan_ret_tdls_oper(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11N_CFG:
+		ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_ret_11ac_cfg(pmpriv, resp, pioctl_buf);
+		break;
+#if 0
+	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+		pmadapter->tx_buf_size =
+			(t_u16)wlan_le16_to_cpu(resp->params.tx_buf.buff_size);
+		break;
+#endif
+	case HostCmd_CMD_TX_BF_CFG:
+		ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG:
+		ret = wlan_ret_sysclock_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MAC_REG_ACCESS:
+	case HostCmd_CMD_BBP_REG_ACCESS:
+	case HostCmd_CMD_RF_REG_ACCESS:
+	case HostCmd_CMD_CAU_REG_ACCESS:
+	case HostCmd_CMD_TARGET_ACCESS:
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:
+	case HostCmd_CMD_BCA_REG_ACCESS:
+		ret = wlan_ret_reg_access(pmpriv->adapter, cmdresp_no, resp,
+					  pioctl_buf);
+		break;
+	case HostCmd_CMD_MEM_ACCESS:
+		ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_INACTIVITY_TIMEOUT_EXT:
+		ret = wlan_ret_inactivity_timeout(pmpriv, resp, pioctl_buf);
+		break;
+#if defined(SDIO)
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+#endif
+	case HostCmd_CMD_SET_BSS_MODE:
+		break;
+	case HostCmd_CMD_MEASUREMENT_REQUEST:
+	case HostCmd_CMD_MEASUREMENT_REPORT:
+		ret = wlan_meas_cmdresp_process(pmpriv, resp);
+		break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+	case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+		PRINTM(MINFO, "PCIE host buffer configuration successful.\n");
+		break;
+#endif
+#endif
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
+		ret = wlan_ret_subscribe_event(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_OTP_READ_USER_DATA:
+		ret = wlan_ret_otp_user_data(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_HS_WAKEUP_REASON:
+		ret = wlan_ret_hs_wakeup_reason(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_REJECT_ADDBA_REQ:
+		ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+		ret = wlan_ret_packet_aggr_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef USB
+	case HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE:
+		ret = wlan_ret_packet_aggr_over_host_interface(pmpriv, resp,
+							       pioctl_buf);
+		break;
+#endif
+#ifdef RX_PACKET_COALESCE
+	case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+		ret = wlan_ret_rx_pkt_coalesce_cfg(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCMD_CONFIG_LOW_POWER_MODE:
+		break;
+	case HostCmd_DFS_REPEATER_MODE:
+		ret = wlan_ret_dfs_repeater_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_COALESCE_CFG:
+		ret = wlan_ret_coalesce_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MEF_CFG:
+		break;
+	case HostCmd_DS_GET_SENSOR_TEMP:
+		ret = wlan_ret_get_sensor_temp(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		break;
+	case HostCmd_CMD_IPV6_RA_OFFLOAD_CFG:
+		ret = wlan_ret_ipv6_ra_offload(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_STA_CONFIGURE:
+		ret = wlan_ret_sta_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_PMIC_CONFIGURE:
+		break;
+	case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+		ret = wlan_ret_ind_rst_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+		break;
+	case HostCmd_CMD_GET_TSF:
+		ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = wlan_ret_chan_region_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_AUTO_TX:
+		ret = wlan_ret_auto_tx(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_TX_RX_PKT_STATS:
+		ret = wlan_ret_tx_rx_pkt_stats(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DYN_BW:
+		ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_ret_boot_sleep(pmpriv, resp, pioctl_buf);
+		break;
+#if defined(DRV_EMBEDDED_SUPPLICANT)
+	case HostCmd_CMD_CRYPTO:
+		ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_11AX_CFG:
+		ret = wlan_ret_11ax_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11AX_CMD:
+		ret = wlan_ret_11ax_cmd(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RANGE_EXT:
+		ret = wlan_ret_range_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TWT_CFG:
+		break;
+	case HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG:
+		ret = wlan_ret_gpio_tsf_latch(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_ABORT_CFG:
+		ret = wlan_ret_rxabortcfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_ABORT_CFG_EXT:
+		ret = wlan_ret_rxabortcfg_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_ARB_CONFIG:
+		ret = wlan_ret_arb_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+		ret = wlan_ret_tx_ampdu_prot_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+		ret = wlan_ret_dot11mc_unassoc_ftm_cfg(pmpriv, resp,
+						       pioctl_buf);
+		break;
+	case HostCmd_CMD_HAL_PHY_CFG:
+		ret = wlan_ret_hal_phy_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RATE_ADAPT_CFG:
+		ret = wlan_ret_rate_adapt_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CCK_DESENSE_CFG:
+		ret = wlan_ret_cck_desense_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_ret_get_chan_trpc_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_LOW_POWER_MODE_CFG:
+		ret = wlan_ret_set_get_low_power_mode_cfg(pmpriv, resp,
+							  pioctl_buf);
+		break;
+	case HostCmd_CMD_MFG_COMMAND:
+		ret = wlan_ret_mfg(pmpriv, resp, pioctl_buf);
+		break;
+	default:
+		PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n",
+		       resp->command);
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_sta_event.c b/wlan_sd8987/mlan/mlan_sta_event.c
new file mode 100755
index 0000000..66c2fe5
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_event.c
@@ -0,0 +1,1359 @@
+/** @file mlan_sta_event.c
+ *
+ *  @brief This file contains MLAN event handling.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/13/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function handles link lost, deauth and
+ *          disassoc events.
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *  @return         N/A
+ */
+static t_void
+wlan_handle_disconnect_event(pmlan_private pmpriv)
+{
+	ENTER();
+
+	if (pmpriv->media_connected == MTRUE)
+		wlan_reset_connect_state(pmpriv, MTRUE);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will parse the TDLS event for further wlan action
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param pevent   A pointer to event buf
+ *
+ *  @return         N/A
+ */
+static void
+wlan_parse_tdls_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	Event_tdls_generic *tdls_event =
+		(Event_tdls_generic *)(pevent->pbuf + pevent->data_offset +
+				       sizeof(mlan_event_id));
+	sta_node *sta_ptr = MNULL;
+	pmlan_adapter pmadapter = priv->adapter;
+	t_u8 i = 0;
+	IEEEtypes_HTCap_t *pht_cap = MNULL;
+	t_u16 ie_len = 0;
+	mlan_ds_misc_tdls_oper tdls_oper;
+	t_u8 event_buf[100];
+	mlan_event *ptdls_event = (mlan_event *)event_buf;
+	tdls_tear_down_event *tdls_evt =
+		(tdls_tear_down_event *)ptdls_event->event_buf;
+	ENTER();
+
+	/* reason code is not mandatory, hence less by sizeof(t_u16) */
+	if (pevent->data_len < (sizeof(Event_tdls_generic) - sizeof(t_u16) -
+				sizeof(mlan_event_id))) {
+		PRINTM(MERROR, "Invalid length %d for TDLS event\n",
+		       pevent->data_len);
+		LEAVE();
+		return;
+	}
+	sta_ptr = wlan_get_station_entry(priv, tdls_event->peer_mac_addr);
+	PRINTM(MEVENT, "TDLS_EVENT: %d " MACSTR "\n",
+	       wlan_le16_to_cpu(tdls_event->event_type),
+	       MAC2STR(tdls_event->peer_mac_addr));
+	switch (wlan_le16_to_cpu(tdls_event->event_type)) {
+	case TDLS_EVENT_TYPE_SETUP_REQ:
+		if (sta_ptr == MNULL) {
+			sta_ptr =
+				wlan_add_station_entry(priv,
+						       tdls_event->
+						       peer_mac_addr);
+			if (sta_ptr) {
+				sta_ptr->status = TDLS_SETUP_INPROGRESS;
+				wlan_hold_tdls_packets(priv,
+						       tdls_event->
+						       peer_mac_addr);
+			}
+		}
+		break;
+
+	case TDLS_EVENT_TYPE_LINK_ESTABLISHED:
+		if (sta_ptr) {
+			sta_ptr->status = TDLS_SETUP_COMPLETE;
+			/* parse the TLV for station's capability */
+			ie_len = wlan_le16_to_cpu(tdls_event->u.ie_data.
+						  ie_length);
+			if (ie_len) {
+				pht_cap = (IEEEtypes_HTCap_t *)
+					wlan_get_specific_ie(priv,
+							     tdls_event->u.
+							     ie_data.ie_ptr,
+							     ie_len,
+							     HT_CAPABILITY, 0);
+				if (pht_cap) {
+					sta_ptr->is_11n_enabled = MTRUE;
+					if (GETHT_MAXAMSDU
+					    (pht_cap->ht_cap.ht_cap_info))
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_8K;
+					else
+						sta_ptr->max_amsdu =
+							MLAN_TX_DATA_BUF_SIZE_4K;
+				}
+			}
+			for (i = 0; i < MAX_NUM_TID; i++) {
+				if (sta_ptr->is_11n_enabled)
+					sta_ptr->ampdu_sta[i] =
+						priv->aggr_prio_tbl[i]
+					.ampdu_user;
+				else
+					sta_ptr->ampdu_sta[i] =
+						BA_STREAM_NOT_ALLOWED;
+			}
+			memset(priv->adapter, sta_ptr->rx_seq, 0xff,
+			       sizeof(sta_ptr->rx_seq));
+			wlan_restore_tdls_packets(priv,
+						  tdls_event->peer_mac_addr,
+						  TDLS_SETUP_COMPLETE);
+			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+		}
+		break;
+
+	case TDLS_EVENT_TYPE_SETUP_FAILURE:
+		wlan_restore_tdls_packets(priv, tdls_event->peer_mac_addr,
+					  TDLS_SETUP_FAILURE);
+		if (sta_ptr)
+			wlan_delete_station_entry(priv,
+						  tdls_event->peer_mac_addr);
+		if (MTRUE == wlan_is_station_list_empty(priv))
+			pmadapter->tdls_status = TDLS_NOT_SETUP;
+		else
+			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+		break;
+	case TDLS_EVENT_TYPE_LINK_TORN_DOWN:
+		if (sta_ptr) {
+			if (sta_ptr->external_tdls) {
+				PRINTM(MMSG,
+				       "Receive TDLS TEAR DOWN event, Disable TDLS LINK\n");
+				pmadapter->tdls_status = TDLS_TEAR_DOWN;
+				memset(pmadapter, &tdls_oper, 0,
+				       sizeof(tdls_oper));
+				tdls_oper.tdls_action = WLAN_TDLS_DISABLE_LINK;
+				memcpy_ext(priv->adapter, tdls_oper.peer_mac,
+					   tdls_event->peer_mac_addr,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				/* Send command to firmware to delete tdls
+				 * link*/
+				wlan_prepare_cmd(priv,
+						 HostCmd_CMD_TDLS_OPERATION,
+						 HostCmd_ACT_GEN_SET, 0,
+						 (t_void *)MNULL, &tdls_oper);
+				ptdls_event->bss_index = priv->bss_index;
+				ptdls_event->event_id =
+					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
+				ptdls_event->event_len =
+					sizeof(tdls_tear_down_event);
+				memcpy_ext(priv->adapter,
+					   (t_u8 *)tdls_evt->peer_mac_addr,
+					   tdls_event->peer_mac_addr,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				tdls_evt->reason_code =
+					wlan_le16_to_cpu(tdls_event->u.
+							 reason_code);
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
+						ptdls_event);
+				/* Signal MOAL to trigger mlan_main_process */
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+				LEAVE();
+				return;
+			}
+			wlan_restore_tdls_packets(priv,
+						  tdls_event->peer_mac_addr,
+						  TDLS_TEAR_DOWN);
+			if (sta_ptr->is_11n_enabled) {
+				wlan_cleanup_reorder_tbl(priv,
+							 tdls_event->
+							 peer_mac_addr);
+				wlan_11n_cleanup_txbastream_tbl(priv,
+								tdls_event->
+								peer_mac_addr);
+			}
+			wlan_delete_station_entry(priv,
+						  tdls_event->peer_mac_addr);
+			if (MTRUE == wlan_is_station_list_empty(priv))
+				pmadapter->tdls_status = TDLS_NOT_SETUP;
+			else
+				pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+		}
+		break;
+	case TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT:
+		PRINTM(MEVENT,
+		       "TDLS_CHAN_SWITCH_RESULT: status=0x%x, reason=0x%x current_channel=%d\n",
+		       tdls_event->u.switch_result.status,
+		       tdls_event->u.switch_result.reason,
+		       (int)tdls_event->u.switch_result.current_channel);
+		if (tdls_event->u.switch_result.status == MLAN_STATUS_SUCCESS) {
+			if (tdls_event->u.switch_result.current_channel ==
+			    TDLS_BASE_CHANNEL) {
+				/* enable traffic to AP */
+				if (pmadapter->tdls_status !=
+				    TDLS_IN_BASE_CHANNEL) {
+					wlan_update_non_tdls_ralist(priv,
+								    tdls_event->
+								    peer_mac_addr,
+								    MFALSE);
+					pmadapter->tdls_status =
+						TDLS_IN_BASE_CHANNEL;
+				}
+			} else if (tdls_event->u.switch_result.
+				   current_channel == TDLS_OFF_CHANNEL) {
+				/* pause traffic to AP */
+				if (pmadapter->tdls_status !=
+				    TDLS_IN_OFF_CHANNEL) {
+					wlan_update_non_tdls_ralist(priv,
+								    tdls_event->
+								    peer_mac_addr,
+								    MTRUE);
+					pmadapter->tdls_status =
+						TDLS_IN_OFF_CHANNEL;
+				}
+			}
+		} else {
+			if (tdls_event->u.switch_result.current_channel ==
+			    TDLS_BASE_CHANNEL)
+				pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
+			else if (tdls_event->u.switch_result.current_channel ==
+				 TDLS_OFF_CHANNEL)
+				pmadapter->tdls_status = TDLS_IN_OFF_CHANNEL;
+		}
+		break;
+	case TDLS_EVENT_TYPE_START_CHAN_SWITCH:
+		PRINTM(MEVENT, "TDLS start channel switch....\n");
+		pmadapter->tdls_status = TDLS_SWITCHING_CHANNEL;
+		break;
+	case TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED:
+		PRINTM(MEVENT, "TDLS channel switch stopped, reason=%d\n",
+		       tdls_event->u.cs_stop_reason);
+		break;
+	case TDLS_EVENT_TYPE_DEBUG:
+	case TDLS_EVENT_TYPE_PACKET:
+		break;
+	default:
+		PRINTM(MERROR, "unknown event type %d\n",
+		       wlan_le16_to_cpu(tdls_event->event_type));
+		break;
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief This function send the tdls teardown request event.
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return        N/A
+ */
+static void
+wlan_send_tdls_tear_down_request(pmlan_private priv)
+{
+	t_u8 event_buf[100];
+	mlan_event *ptdls_event = (mlan_event *)event_buf;
+	tdls_tear_down_event *tdls_evt =
+		(tdls_tear_down_event *)ptdls_event->event_buf;
+	sta_node *sta_ptr = MNULL;
+
+	ENTER();
+
+	sta_ptr =
+		(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					   &priv->sta_list,
+					   priv->adapter->callbacks.
+					   moal_spin_lock,
+					   priv->adapter->callbacks.
+					   moal_spin_unlock);
+	if (!sta_ptr) {
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		if (sta_ptr->external_tdls) {
+			ptdls_event->bss_index = priv->bss_index;
+			ptdls_event->event_id =
+				MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
+			ptdls_event->event_len = sizeof(tdls_tear_down_event);
+			memcpy_ext(priv->adapter,
+				   (t_u8 *)tdls_evt->peer_mac_addr,
+				   sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH,
+				   MLAN_MAC_ADDR_LENGTH);
+			tdls_evt->reason_code =
+				MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
+			wlan_recv_event(priv,
+					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
+					ptdls_event);
+		}
+		sta_ptr = sta_ptr->pnext;
+	}
+	LEAVE();
+	return;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *  @brief This function handles disconnect event, reports disconnect
+ *          to upper layer, cleans tx/rx packets,
+ *          resets link state etc.
+ *
+ *  @param priv             A pointer to mlan_private structure
+ *  @param drv_disconnect   Flag indicating the driver should disconnect
+ *                          and flush pending packets.
+ *
+ *  @return                 N/A
+ */
+t_void
+wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	state_11d_t enable;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+
+	ENTER();
+
+	PRINTM(MINFO, "Handles disconnect event.\n");
+
+#ifdef UAP_SUPPORT
+	/* If DFS repeater mode is enabled and station interface disconnects
+	 * then make sure that all uAPs are stopped.
+	 */
+	if (pmadapter->dfs_repeater)
+		wlan_dfs_rep_disconnect(pmadapter);
+#endif
+
+	if (drv_disconnect) {
+		priv->media_connected = MFALSE;
+		pmadapter->state_rdh.tx_block = MFALSE;
+		wlan_11h_check_update_radar_det_state(priv);
+	}
+
+	if (priv->port_ctrl_mode == MTRUE) {
+		/* Close the port on Disconnect */
+		PRINTM(MINFO, "DISC: port_status = CLOSED\n");
+		priv->port_open = MFALSE;
+	}
+	memset(pmadapter, &priv->gtk_rekey, 0,
+	       sizeof(mlan_ds_misc_gtk_rekey_data));
+	priv->tx_pause = MFALSE;
+	pmadapter->scan_block = MFALSE;
+
+	/* Reset SNR/NF/RSSI values */
+	priv->data_rssi_last = 0;
+	priv->data_nf_last = 0;
+	priv->data_rssi_avg = 0;
+	priv->data_nf_avg = 0;
+	priv->bcn_rssi_last = 0;
+	priv->bcn_nf_last = 0;
+	priv->bcn_rssi_avg = 0;
+	priv->bcn_nf_avg = 0;
+	priv->rxpd_rate = 0;
+	priv->rxpd_rate_info = 0;
+	priv->max_amsdu = 0;
+	priv->amsdu_disable = MFALSE;
+	wlan_coex_ampdu_rxwinsize(pmadapter);
+
+	priv->sec_info.ewpa_enabled = MFALSE;
+	priv->sec_info.wpa_enabled = MFALSE;
+	priv->sec_info.wpa2_enabled = MFALSE;
+	priv->wpa_ie_len = 0;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	supplicantStopSessionTimer(priv->psapriv);
+	supplicantClrEncryptKey(priv->psapriv);
+	supplicantDisable(priv->psapriv);
+#endif
+
+	priv->sec_info.wapi_enabled = MFALSE;
+	priv->wapi_ie_len = 0;
+	priv->sec_info.wapi_key_on = MFALSE;
+
+	priv->wps.session_enable = MFALSE;
+	memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie, 0x00,
+	       sizeof(priv->wps.wps_ie));
+	priv->sec_info.osen_enabled = MFALSE;
+	priv->osen_ie_len = 0;
+
+	priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;
+
+	/*Enable auto data rate */
+	priv->is_data_rate_auto = MTRUE;
+	priv->data_rate = 0;
+
+	if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
+		priv->adhoc_state = ADHOC_IDLE;
+		priv->adhoc_is_link_sensed = MFALSE;
+		priv->intf_state_11h.adhoc_auto_sel_chan = MTRUE;
+	}
+
+	if (drv_disconnect) {
+		/* Free Tx and Rx packets, report disconnect to upper layer */
+		wlan_clean_txrx(priv);
+
+		/* Need to erase the current SSID and BSSID info */
+		memset(pmadapter, &priv->curr_bss_params, 0x00,
+		       sizeof(priv->curr_bss_params));
+	}
+	wlan_send_tdls_tear_down_request(priv);
+	wlan_delete_station_list(priv);
+	pmadapter->tdls_status = TDLS_NOT_SETUP;
+	priv->wmm_qosinfo = priv->saved_wmm_qosinfo;
+	pmadapter->sleep_period.period = pmadapter->saved_sleep_period.period;
+	pmadapter->tx_lock_flag = MFALSE;
+	pmadapter->pps_uapsd_mode = MFALSE;
+	pmadapter->delay_null_pkt = MFALSE;
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		pmadapter->hs_wake_interval = 0;
+
+	if ((wlan_fw_11d_is_enabled(priv)) &&
+	    (priv->state_11d.user_enable_11d == DISABLE_11D)) {
+		priv->state_11d.enable_11d = DISABLE_11D;
+		enable = DISABLE_11D;
+
+		/* Send cmd to FW to enable/disable 11D function */
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+				       HostCmd_ACT_GEN_SET, Dot11D_i, MNULL,
+				       &enable);
+		if (ret)
+			PRINTM(MERROR, "11D: Failed to enable 11D\n");
+	}
+	if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
+	    (pmadapter->cmd_timer_is_set == MFALSE)) {
+		LEAVE();
+		return;
+	}
+
+	if (pmadapter->pending_disconnect_priv) {
+		LEAVE();
+		return;
+	}
+
+	pevent->bss_index = priv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_FW_DISCONNECTED;
+	pevent->event_len = sizeof(priv->disconnect_reason_code);
+	memcpy_ext(priv->adapter, pevent->event_buf,
+		   &priv->disconnect_reason_code, pevent->event_len,
+		   pevent->event_len);
+	wlan_recv_event(priv, MLAN_EVENT_ID_FW_DISCONNECTED, pevent);
+	priv->disconnect_reason_code = 0;
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function sends the OBSS scan parameters to the application
+ *
+ *  @param pmpriv     A pointer to mlan_private structure
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_2040_coex_event(pmlan_private pmpriv)
+{
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	t_u8 ele_len;
+
+	ENTER();
+
+	if (pmpriv->curr_bss_params.bss_descriptor.poverlap_bss_scan_param &&
+	    pmpriv->curr_bss_params.bss_descriptor.poverlap_bss_scan_param->
+	    ieee_hdr.element_id == OVERLAPBSSSCANPARAM) {
+		ele_len =
+			pmpriv->curr_bss_params.bss_descriptor.
+			poverlap_bss_scan_param->ieee_hdr.len;
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM;
+		pevent->event_len = ele_len;
+		/* Copy OBSS scan parameters */
+		memcpy_ext(pmpriv->adapter, (t_u8 *)pevent->event_buf,
+			   (t_u8 *)&pmpriv->curr_bss_params.bss_descriptor.
+			   poverlap_bss_scan_param->obss_scan_param, ele_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM,
+				pevent);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will process tx pause event
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to event buf
+ *
+ *  @return        N/A
+ */
+static void
+wlan_process_sta_tx_pause_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	t_u16 tlv_type, tlv_len;
+	int tlv_buf_left = pevent->data_len - sizeof(t_u32);
+	MrvlIEtypesHeader_t *tlv =
+		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+					sizeof(t_u32));
+	MrvlIEtypes_tx_pause_t *tx_pause_tlv;
+	sta_node *sta_ptr = MNULL;
+	tdlsStatus_e status;
+	t_u8 *bssid = MNULL;
+	ENTER();
+	if (priv->media_connected)
+		bssid = priv->curr_bss_params.bss_descriptor.mac_address;
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		if (tlv_type == TLV_TYPE_TX_PAUSE) {
+			tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv;
+			PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d\n",
+			       MAC2STR(tx_pause_tlv->peermac),
+			       tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt);
+
+			if (bssid &&
+			    !memcmp(priv->adapter, bssid, tx_pause_tlv->peermac,
+				    MLAN_MAC_ADDR_LENGTH)) {
+				if (tx_pause_tlv->tx_pause)
+					priv->tx_pause = MTRUE;
+				else
+					priv->tx_pause = MFALSE;
+			} else {
+				status = wlan_get_tdls_link_status(priv,
+								   tx_pause_tlv->
+								   peermac);
+				if (MTRUE == wlan_is_tdls_link_setup(status)) {
+					sta_ptr =
+						wlan_get_station_entry(priv,
+								       tx_pause_tlv->
+								       peermac);
+					if (sta_ptr) {
+						if (sta_ptr->tx_pause !=
+						    tx_pause_tlv->tx_pause) {
+							sta_ptr->tx_pause =
+								tx_pause_tlv->
+								tx_pause;
+							wlan_update_ralist_tx_pause
+								(priv,
+								 tx_pause_tlv->
+								 peermac,
+								 tx_pause_tlv->
+								 tx_pause);
+						}
+					}
+				}
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function will print diconnect reason code according
+ *  to IEEE 802.11 spec
+ *
+ *  @param reason_code    reason code for the deauth/disaccoc
+ *                        received from firmware
+ *  @return        N/A
+ */
+static void
+wlan_print_disconnect_reason(t_u16 reason_code)
+{
+	ENTER();
+
+	switch (reason_code) {
+	case MLAN_REASON_UNSPECIFIED:
+		PRINTM(MMSG, "wlan: REASON: Unspecified reason\n");
+		break;
+	case MLAN_REASON_PREV_AUTH_NOT_VALID:
+		PRINTM(MMSG,
+		       "wlan: REASON: Previous authentication no longer valid\n");
+		break;
+	case MLAN_REASON_DEAUTH_LEAVING:
+		PRINTM(MMSG,
+		       "wlan: REASON: (Deauth) Sending STA is leaving (or has left) IBSS or ESS\n");
+		break;
+	case MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
+		PRINTM(MMSG,
+		       "wlan: REASON: Disassociated due to inactivity \n");
+		break;
+	case MLAN_REASON_DISASSOC_AP_BUSY:
+		PRINTM(MMSG,
+		       "wlan: REASON: (Disassociated) AP unable to handle all connected STAs\n");
+		break;
+	case MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA:
+		PRINTM(MMSG,
+		       "wlan: REASON: Class 2 frame was received from nonauthenticated STA\n");
+		break;
+	case MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA:
+		PRINTM(MMSG,
+		       "wlan: REASON: Class 3 frame was received from nonassociated STA\n");
+		break;
+	case MLAN_REASON_DISASSOC_STA_HAS_LEFT:
+		PRINTM(MMSG,
+		       "wlan: REASON: (Disassocated) Sending STA is leaving (or has left) BSS\n");
+		break;
+	case MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
+		PRINTM(MMSG,
+		       "wlan: REASON: STA requesting (re)assoc is not authenticated with responding STA\n");
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles events generated by firmware
+ *
+ *  @param priv A pointer to mlan_private structure
+ *
+ *  @return     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_sta_process_event(t_void *priv)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 eventcause = pmadapter->event_cause;
+	t_u8 *event_buf = MNULL;
+	t_u8 *evt_buf = MNULL;
+	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+	t_u16 reason_code;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_event *pevent = MNULL;
+	chan_band_info *pchan_band_info = MNULL;
+	t_u8 radar_chan;
+	t_u16 enable = 0;
+
+	ENTER();
+
+	if (!pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Event length check */
+	if ((pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) {
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate memory for event buffer */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       MAX_EVENT_SIZE + sizeof(mlan_event),
+			       MLAN_MEM_DEF, &event_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
+		PRINTM(MERROR, "Could not allocate buffer for event buf\n");
+		if (pmbuf)
+			pmbuf->status_code = MLAN_ERROR_NO_MEM;
+		goto done;
+	}
+	pevent = (pmlan_event)event_buf;
+	memset(pmadapter, event_buf, 0, MAX_EVENT_SIZE);
+
+	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
+	    pmbuf->data_len > sizeof(eventcause))
+		DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset,
+			    pmbuf->data_len);
+
+	switch (eventcause) {
+	case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
+		PRINTM(MERROR,
+		       "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n");
+		break;
+	case EVENT_LINK_SENSED:
+		PRINTM(MEVENT, "EVENT: LINK_SENSED\n");
+		pmpriv->adhoc_is_link_sensed = MTRUE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED,
+				MNULL);
+		break;
+
+	case EVENT_DEAUTHENTICATED:
+		if (pmpriv->wps.session_enable) {
+			PRINTM(MMSG,
+			       "wlan: Receive deauth event in wps session\n");
+			break;
+		}
+		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+							  pmbuf->data_offset +
+							  sizeof(eventcause)));
+		PRINTM(MMSG, "wlan: EVENT: Deauthenticated (reason 0x%x)\n",
+		       reason_code);
+		wlan_print_disconnect_reason(reason_code);
+		pmpriv->disconnect_reason_code = reason_code;
+		pmadapter->dbg.num_event_deauth++;
+		wlan_handle_disconnect_event(pmpriv);
+
+		break;
+
+	case EVENT_DISASSOCIATED:
+		if (pmpriv->wps.session_enable) {
+			PRINTM(MMSG,
+			       "wlan: Receive disassociate event in wps session\n");
+			break;
+		}
+		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+							  pmbuf->data_offset +
+							  sizeof(eventcause)));
+		PRINTM(MMSG, "wlan: EVENT: Disassociated (reason 0x%x)\n",
+		       reason_code);
+		wlan_print_disconnect_reason(reason_code);
+		pmpriv->disconnect_reason_code = reason_code;
+		pmadapter->dbg.num_event_disassoc++;
+		wlan_handle_disconnect_event(pmpriv);
+		break;
+
+	case EVENT_LINK_LOST:
+		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+							  pmbuf->data_offset +
+							  sizeof(eventcause)));
+		PRINTM(MMSG, "wlan: EVENT: Link lost (reason 0x%x)\n",
+		       reason_code);
+		pmpriv->disconnect_reason_code = reason_code;
+		pmadapter->dbg.num_event_link_lost++;
+		wlan_handle_disconnect_event(pmpriv);
+		break;
+
+	case EVENT_PS_SLEEP:
+		PRINTM(MINFO, "EVENT: SLEEP\n");
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "_");
+
+		/* Handle unexpected PS SLEEP event */
+		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+			break;
+		pmadapter->ps_state = PS_STATE_PRE_SLEEP;
+
+		wlan_check_ps_cond(pmadapter);
+		break;
+
+	case EVENT_PS_AWAKE:
+		PRINTM(MINFO, "EVENT: AWAKE\n");
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "|");
+		if (!pmadapter->pps_uapsd_mode && pmpriv->media_connected &&
+		    (pmpriv->port_open || !pmpriv->port_ctrl_mode) &&
+		    pmadapter->sleep_period.period) {
+			pmadapter->pps_uapsd_mode = MTRUE;
+			PRINTM(MEVENT, "PPS/UAPSD mode activated\n");
+		}
+		/* Handle unexpected PS AWAKE event */
+		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+			break;
+		pmadapter->tx_lock_flag = MFALSE;
+		if (pmadapter->pps_uapsd_mode && pmadapter->gen_null_pkt) {
+			if (MTRUE == wlan_check_last_packet_indication(pmpriv)) {
+				if (!pmadapter->data_sent) {
+					if (wlan_send_null_packet(pmpriv,
+								  MRVDRV_TxPD_POWER_MGMT_NULL_PACKET
+								  |
+								  MRVDRV_TxPD_POWER_MGMT_LAST_PACKET)
+					    == MLAN_STATUS_SUCCESS) {
+						LEAVE();
+						return MLAN_STATUS_SUCCESS;
+					}
+				}
+			}
+		}
+		pmadapter->ps_state = PS_STATE_AWAKE;
+		pmadapter->pm_wakeup_card_req = MFALSE;
+		pmadapter->pm_wakeup_fw_try = MFALSE;
+		break;
+
+	case EVENT_HS_ACT_REQ:
+		PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, 0,
+				       0, MNULL, MNULL);
+		break;
+	case EVENT_MIC_ERR_UNICAST:
+		PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL);
+		break;
+
+	case EVENT_MIC_ERR_MULTICAST:
+		PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL);
+		break;
+	case EVENT_MIB_CHANGED:
+	case EVENT_INIT_DONE:
+		break;
+
+	case EVENT_ADHOC_BCN_LOST:
+		PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n");
+		pmpriv->adhoc_is_link_sensed = MFALSE;
+		wlan_clean_txrx(pmpriv);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST,
+				MNULL);
+		break;
+
+	case EVENT_FW_DEBUG_INFO:
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
+		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause),
+			   pevent->event_len, pevent->event_len);
+		PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
+		       (t_u8 *)pevent->event_buf);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+
+	case EVENT_BG_SCAN_REPORT:
+		PRINTM(MEVENT, "EVENT: BGS_REPORT\n");
+		pmadapter->bgscan_reported = MTRUE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL);
+		break;
+	case EVENT_BG_SCAN_STOPPED:
+		PRINTM(MEVENT, "EVENT: BGS_STOPPED\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN_STOPPED,
+				MNULL);
+		break;
+
+	case EVENT_PORT_RELEASE:
+		PRINTM(MEVENT, "EVENT: PORT RELEASE\n");
+		/* Open the port for e-supp mode */
+		if (pmpriv->port_ctrl_mode == MTRUE) {
+			PRINTM(MINFO, "PORT_REL: port_status = OPEN\n");
+			pmpriv->port_open = MTRUE;
+		}
+		pmadapter->scan_block = MFALSE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL);
+		break;
+
+	case EVENT_STOP_TX:
+		PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause);
+		wlan_11h_tx_disable(pmpriv);	/* this fn will send event up to
+						   MOAL */
+		break;
+	case EVENT_START_TX:
+		PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause);
+		wlan_11h_tx_enable(pmpriv);	/* this fn will send event up to
+						   MOAL */
+		break;
+	case EVENT_CHANNEL_SWITCH:
+		PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause);
+		if (pmadapter->ecsa_enable) {
+			MrvlIEtypes_channel_band_t *pchan_info =
+				(MrvlIEtypes_channel_band_t
+				 *)(pmadapter->event_body);
+			t_u8 channel = pchan_info->channel;
+			chan_freq_power_t *cfp = MNULL;
+			DBG_HEXDUMP(MCMD_D, "chan band config",
+				    (t_u8 *)pchan_info,
+				    sizeof(MrvlIEtypes_channel_band_t));
+			PRINTM(MEVENT, "Switch to channel %d success!\n",
+			       channel);
+#define MAX_CHANNEL_BAND_B 14
+			if (channel <= MAX_CHANNEL_BAND_B)
+				cfp = wlan_find_cfp_by_band_and_channel
+					(pmadapter, BAND_B, channel);
+			else
+				cfp = wlan_find_cfp_by_band_and_channel
+					(pmadapter, BAND_A, channel);
+			pmpriv->curr_bss_params.bss_descriptor.channel =
+				channel;
+			if (cfp)
+				pmpriv->curr_bss_params.bss_descriptor.freq =
+					cfp->freq;
+			else
+				pmpriv->curr_bss_params.bss_descriptor.freq = 0;
+			if (pmpriv->adapter->state_rdh.stage ==
+			    RDH_SET_CUSTOM_IE) {
+				pmadapter->state_rdh.stage =
+					RDH_RESTART_TRAFFIC;
+				wlan_11h_radar_detected_handling(pmadapter,
+								 pmpriv);
+			}
+			pmadapter->state_rdh.tx_block = MFALSE;
+			/* Setup event buffer */
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id =
+				MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE;
+			pevent->event_len = sizeof(chan_band_info);
+			pchan_band_info = (chan_band_info *) pevent->event_buf;
+			/* Copy event data */
+			memcpy_ext(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+				   (t_u8 *)&pchan_info->bandcfg,
+				   sizeof(pchan_info->bandcfg),
+				   sizeof(pchan_band_info->bandcfg));
+			pchan_band_info->channel = pchan_info->channel;
+			if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
+				pchan_band_info->center_chan =
+					wlan_get_center_freq_idx(priv, BAND_AAC,
+								 pchan_info->
+								 channel,
+								 CHANNEL_BW_80MHZ);
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE,
+					pevent);
+		}
+		break;
+	case EVENT_CHANNEL_SWITCH_ANN:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: Channel Switch Announcement\n");
+		/* Here, pass up event first, as handling will send deauth */
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN,
+				MNULL);
+		wlan_11h_handle_event_chanswann(pmpriv);
+		break;
+	case EVENT_RADAR_DETECTED:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: Radar Detected\n");
+
+		/* Send as passthru first, this event can cause other events */
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+
+		if (pmadapter->state_rdh.stage == RDH_OFF) {
+			pmadapter->state_rdh.stage = RDH_CHK_INTFS;
+			wlan_11h_radar_detected_handling(pmadapter, pmpriv);
+		} else {
+			PRINTM(MEVENT,
+			       "Ignore Event Radar Detected - handling"
+			       " already in progress.\n");
+		}
+
+		break;
+
+	case EVENT_CHANNEL_REPORT_RDY:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY;
+		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+		/* Copy event data */
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause),
+			   pevent->event_len, pevent->event_len);
+		/* Handle / pass event data */
+		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent,
+							  &radar_chan);
+		/* Also send this event as passthru */
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		/* Send up this Event to unblock MOAL waitqueue */
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
+		break;
+	case EVENT_EXT_SCAN_REPORT:
+		PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%d)\n",
+		       pmbuf->data_len);
+		if (pmadapter->pscan_ioctl_req && pmadapter->ext_scan)
+			ret = wlan_handle_event_ext_scan_report(priv, pmbuf);
+		break;
+	case EVENT_EXT_SCAN_STATUS_REPORT:
+		PRINTM(MEVENT, "EVENT: EXT_SCAN status report (%d)\n",
+		       pmbuf->data_len);
+		pmadapter->ext_scan_timeout = MFALSE;
+		ret = wlan_handle_event_ext_scan_status(priv, pmbuf);
+		break;
+	case EVENT_MEAS_REPORT_RDY:
+		PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n",
+		       eventcause);
+		ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
+				       HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+		break;
+	case EVENT_WMM_STATUS_CHANGE:
+		if (pmbuf &&
+		    pmbuf->data_len >
+		    sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
+			PRINTM(MEVENT, "EVENT: WMM status changed: %d\n",
+			       pmbuf->data_len);
+
+			evt_buf = (pmbuf->pbuf + pmbuf->data_offset +
+				   sizeof(eventcause));
+
+			wlan_ret_wmm_get_status(pmpriv, evt_buf,
+						pmbuf->data_len -
+						sizeof(eventcause));
+		} else {
+			PRINTM(MEVENT, "EVENT: WMM status changed\n");
+			ret = wlan_cmd_wmm_status_change(pmpriv);
+		}
+		break;
+
+	case EVENT_RSSI_LOW:
+		PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_LOW;
+		pevent->event_len = sizeof(t_u16);
+		/** Fw send bcnRssi low value in event reason field*/
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   (t_u8 *)&pmadapter->event_body, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+	case EVENT_SNR_LOW:
+		PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL);
+		break;
+	case EVENT_MAX_FAIL:
+		PRINTM(MEVENT, "EVENT: MAX_FAIL\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL);
+		break;
+	case EVENT_RSSI_HIGH:
+		PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_BCN_RSSI_HIGH;
+		pevent->event_len = sizeof(t_u16);
+		/** Fw send bcnRssi high value in event reason field*/
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   (t_u8 *)&pmadapter->event_body, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+	case EVENT_SNR_HIGH:
+		PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL);
+		break;
+	case EVENT_DATA_RSSI_LOW:
+		PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL);
+		break;
+	case EVENT_DATA_SNR_LOW:
+		PRINTM(MEVENT, "EVENT: Data SNR_LOW\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL);
+		break;
+	case EVENT_DATA_RSSI_HIGH:
+		PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL);
+		break;
+	case EVENT_DATA_SNR_HIGH:
+		PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL);
+		break;
+	case EVENT_LINK_QUALITY:
+		PRINTM(MEVENT, "EVENT: Link Quality\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL);
+		break;
+	case EVENT_PRE_BEACON_LOST:
+		PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n");
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL);
+		break;
+	case EVENT_IBSS_COALESCED:
+		PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n");
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		break;
+	case EVENT_ADDBA:
+		PRINTM(MEVENT, "EVENT: ADDBA Request\n");
+		if (pmpriv->media_connected == MTRUE)
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_11N_ADDBA_RSP,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       pmadapter->event_body);
+		else
+			PRINTM(MERROR,
+			       "Ignore ADDBA Request event in disconnected state\n");
+		break;
+	case EVENT_DELBA:
+		PRINTM(MEVENT, "EVENT: DELBA Request\n");
+		if (pmpriv->media_connected == MTRUE)
+			wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
+		else
+			PRINTM(MERROR,
+			       "Ignore DELBA Request event in disconnected state\n");
+		break;
+	case EVENT_BA_STREAM_TIMEOUT:
+		PRINTM(MEVENT, "EVENT:  BA Stream timeout\n");
+		if (pmpriv->media_connected == MTRUE)
+			wlan_11n_ba_stream_timeout(pmpriv,
+						   (HostCmd_DS_11N_BATIMEOUT *)
+						   pmadapter->event_body);
+		else
+			PRINTM(MERROR,
+			       "Ignore BA Stream timeout event in disconnected state\n");
+		break;
+	case EVENT_RXBA_SYNC:
+		PRINTM(MEVENT, "EVENT:  RXBA_SYNC\n");
+		wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body,
+					 pmbuf->data_len - sizeof(eventcause));
+		break;
+	case EVENT_AMSDU_AGGR_CTRL:
+		PRINTM(MEVENT, "EVENT:  AMSDU_AGGR_CTRL %d\n",
+		       *(t_u16 *)pmadapter->event_body);
+		pmadapter->tx_buf_size =
+			MIN(pmadapter->curr_tx_buf_size,
+			    wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body));
+		if (pmbuf->data_len == sizeof(eventcause) + sizeof(t_u32)) {
+			enable = wlan_le16_to_cpu(*(t_u16 *)
+						  (pmadapter->event_body +
+						   sizeof(t_u16)));
+			if (enable)
+				pmpriv->amsdu_disable = MFALSE;
+			else
+				pmpriv->amsdu_disable = MTRUE;
+			PRINTM(MEVENT, "amsdu_disable=%d\n",
+			       pmpriv->amsdu_disable);
+		}
+		PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size);
+		break;
+
+	case EVENT_WEP_ICV_ERR:
+		PRINTM(MEVENT, "EVENT: WEP ICV error\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR;
+		pevent->event_len = sizeof(Event_WEP_ICV_ERR);
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmadapter->event_body, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent);
+		break;
+
+	case EVENT_BW_CHANGE:
+		PRINTM(MEVENT, "EVENT: BW Change\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED;
+		pevent->event_len = sizeof(t_u8);
+		/* Copy event body from the event buffer */
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmadapter->event_body, pevent->event_len,
+			   pevent->event_len);
+#ifdef UAP_SUPPORT
+		if (pmadapter->dfs_repeater)
+			wlan_dfs_rep_bw_change(pmadapter);
+#endif
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent);
+		break;
+
+#ifdef WIFI_DIRECT_SUPPORT
+	case EVENT_WIFIDIRECT_GENERIC_EVENT:
+		PRINTM(MEVENT, "EVENT: WIFIDIRECT event %d\n", eventcause);
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+	case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
+		PRINTM(MEVENT, "EVENT: WIFIDIRECT service discovery event %d\n",
+		       eventcause);
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+#endif /* WIFI_DIRECT_SUPPORT */
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
+		       *(t_u16 *)pmadapter->event_body);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED,
+				MNULL);
+		break;
+	case EVENT_TDLS_GENERIC_EVENT:
+		PRINTM(MEVENT, "EVENT: TDLS event %d\n", eventcause);
+		wlan_parse_tdls_event(pmpriv, pmbuf);
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+
+	case EVENT_TX_DATA_PAUSE:
+		PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n");
+		wlan_process_sta_tx_pause_event(priv, pmbuf);
+		break;
+
+	case EVENT_IBSS_STATION_CONNECT:
+		break;
+	case EVENT_IBSS_STATION_DISCONNECT:
+		break;
+	case EVENT_SAD_REPORT:
+		{
+#ifdef DEBUG_LEVEL1
+			t_u8 *pevt_dat = pmbuf->pbuf + pmbuf->data_offset +
+				sizeof(t_u32);
+#endif
+			PRINTM(MEVENT,
+			       "EVENT: Antenna Diversity %d  (%d, %d, %d, %d)\n",
+			       eventcause, pevt_dat[0] + 1, pevt_dat[1] + 1,
+			       pevt_dat[2], pevt_dat[3]);
+		}
+		break;
+
+	case EVENT_FW_DUMP_INFO:
+		PRINTM(MINFO, "EVENT: Dump FW info\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_DUMP_INFO;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+	case EVENT_TX_STATUS_REPORT:
+		PRINTM(MINFO, "EVENT: TX_STATUS\n");
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		break;
+	case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+		PRINTM(MEVENT, "EVENT: BT coex wlan param update\n");
+		wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf);
+		break;
+
+#if defined(PCIE)
+	case EVENT_SSU_DUMP_DMA:
+		PRINTM(MEVENT, "EVENT: EVENT_SSU_DUMP_DMA\n");
+		if (!pmadapter->ssu_buf || !pmadapter->ssu_buf->pbuf)
+			break;
+
+		/* If ADMA is supported, SSU header could not be received with
+		 * SSU data. Instead, SSU header is received through this event.
+		 * So, copy the header into the buffer before passing the buffer
+		 * to upper layer for file writting
+		 */
+		memcpy_ext(pmadapter,
+			   (t_u8 *)pmadapter->ssu_buf->pbuf +
+			   pmadapter->ssu_buf->data_offset,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause),
+			   (pmbuf->data_len - sizeof(eventcause)),
+			   (pmbuf->data_len - sizeof(eventcause)));
+
+		DBG_HEXDUMP(MEVT_D, "SSU data",
+			    (t_u8 *)pmadapter->ssu_buf->pbuf +
+			    pmadapter->ssu_buf->data_offset, 512);
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_SSU_DUMP_FILE;
+		pevent->event_len = MLAN_SSU_BUF_SIZE;
+		*(t_ptr *)pevent->event_buf = (t_ptr)pmadapter->ssu_buf->pbuf +
+			pmadapter->ssu_buf->data_offset;
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		wlan_free_ssu_pcie_buf(pmadapter);
+		break;
+#endif
+	case EVENT_MEF_HOST_WAKEUP:
+		PRINTM(MEVENT, "EVENT: EVENT_MEF_HOST_WAKEUP len=%d\n",
+		       pmbuf->data_len);
+		break;
+	case EVENT_MANAGEMENT_FRAME_WAKEUP:
+		PRINTM(MEVENT, "EVENT: EVENT_MANAGEMENT_FRAME_WAKEUP HOST\n");
+		break;
+	case EVENT_CLOUD_KEEP_ALIVE_RETRY_FAIL:
+		break;
+	case EVENT_VDLL_IND:
+		wlan_process_vdll_event(pmpriv, pmbuf);
+		break;
+	case EVENT_FW_HANG_REPORT:
+		if (pmbuf->data_len < (sizeof(eventcause) + sizeof(t_u16))) {
+			PRINTM(MEVENT,
+			       "EVENT: EVENT_FW_HANG_REPORT skip for len too short: %d\n",
+			       pmbuf->data_len);
+			break;
+		}
+		PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT reasoncode=%d\n",
+		       wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+						   pmbuf->data_offset +
+						   sizeof(eventcause))));
+		pmadapter->fw_hang_report = MTRUE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+		break;
+	default:
+		PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
+		break;
+	}
+done:
+	if (event_buf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_sta_ioctl.c b/wlan_sd8987/mlan/mlan_sta_ioctl.c
new file mode 100755
index 0000000..1d62434
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_ioctl.c
@@ -0,0 +1,5733 @@
+/** @file mlan_sta_ioctl.c
+ *
+ *  @brief This file contains the functions for station ioctl.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/21/2008: initial version
+******************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#include "mlan_11h.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Get signal information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_get_info_signal(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Check information buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_signal)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_signal);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	/* Signal info can be obtained only if connected */
+	if (pmpriv->media_connected == MFALSE) {
+		PRINTM(MINFO, "Can not get signal in disconnected state\n");
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get signal information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_get_info_signal_ext(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *info = MNULL;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+	/* Check information buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_info)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_info);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO_EXT,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       (t_void *)info);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get statistics information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_get_info_stats(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Check information buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_GET_LOG,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get sta channel information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_get_chan_info(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Check information buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(chan_band_info)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(chan_band_info);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_STA_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get BSS information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_get_info_bss_info(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *info;
+	BSSDescriptor_t *pbss_desc;
+	t_s32 tbl_idx = 0;
+
+	ENTER();
+
+	/* Get current BSS info */
+	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
+	info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+	/* BSS mode */
+	info->param.bss_info.bss_mode = pmpriv->bss_mode;
+
+	/* SSID */
+	memcpy_ext(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
+		   sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
+
+	/* BSSID */
+	memcpy_ext(pmadapter, &info->param.bss_info.bssid,
+		   &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+
+	/* Channel */
+	info->param.bss_info.bss_chan = pbss_desc->channel;
+
+	/* Beacon interval */
+	info->param.bss_info.beacon_interval = pbss_desc->beacon_period;
+
+	/* Band */
+	info->param.bss_info.bss_band = (t_u8)pbss_desc->bss_band;
+
+	/* Region code */
+	info->param.bss_info.region_code = pmadapter->region_code;
+
+	/* Scan table index if connected */
+	info->param.bss_info.scan_table_idx = 0;
+	info->param.bss_info.scan_block = pmadapter->scan_block;
+	if (pmpriv->media_connected == MTRUE) {
+		tbl_idx = wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid,
+						 pbss_desc->mac_address,
+						 pmpriv->bss_mode);
+		if (tbl_idx >= 0)
+			info->param.bss_info.scan_table_idx = tbl_idx;
+	}
+
+	/* Connection status */
+	info->param.bss_info.media_connected = pmpriv->media_connected;
+
+	/* Radio status */
+	info->param.bss_info.radio_on = pmadapter->radio_on;
+
+	/* Tx power information */
+	info->param.bss_info.max_power_level = pmpriv->max_tx_power_level;
+	info->param.bss_info.min_power_level = pmpriv->min_tx_power_level;
+
+	/* AdHoc state */
+	info->param.bss_info.adhoc_state = pmpriv->adhoc_state;
+
+	/* Last beacon NF */
+	info->param.bss_info.bcn_nf_last = pmpriv->bcn_nf_last;
+
+	/* wep status */
+	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
+		info->param.bss_info.wep_status = MTRUE;
+	else
+		info->param.bss_info.wep_status = MFALSE;
+
+	info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured;
+	info->param.bss_info.is_deep_sleep = pmadapter->is_deep_sleep;
+
+	/* Capability Info */
+	info->param.bss_info.capability_info = 0;
+	memcpy_ext(pmadapter, &info->param.bss_info.capability_info,
+		   &pbss_desc->cap_info,
+		   sizeof(info->param.bss_info.capability_info),
+		   sizeof(info->param.bss_info.capability_info));
+
+	memset(pmadapter, &info->param.bss_info.ext_cap, 0, sizeof(ExtCap_t));
+	if (pbss_desc->pext_cap) {
+		memcpy_ext(pmadapter, &info->param.bss_info.ext_cap,
+			   (t_u8 *)pbss_desc->pext_cap +
+			   sizeof(IEEEtypes_Header_t),
+			   pbss_desc->pext_cap->ieee_hdr.len,
+			   sizeof(info->param.bss_info.ext_cap));
+	}
+
+	/* Listen Interval */
+	info->param.bss_info.listen_interval = pmpriv->listen_interval;
+
+	/* Association ID */
+	info->param.bss_info.assoc_id =
+		(t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)
+		->a_id;
+
+	/* AP/Peer supported rates */
+	memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
+	       sizeof(info->param.bss_info.peer_supp_rates));
+	memcpy_ext(pmadapter, info->param.bss_info.peer_supp_rates,
+		   pbss_desc->supported_rates,
+		   sizeof(pbss_desc->supported_rates),
+		   sizeof(info->param.bss_info.peer_supp_rates));
+	if (pbss_desc->pmd_ie) {
+		info->param.bss_info.mdid = pbss_desc->pmd_ie->mdid;
+		info->param.bss_info.ft_cap = pbss_desc->pmd_ie->ft_cap;
+	}
+	pioctl_req->data_read_written =
+		sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get information handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_get_info_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *pget_info = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+
+	switch (pget_info->sub_command) {
+	case MLAN_OID_GET_STATS:
+		status = wlan_get_info_stats(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL:
+		status = wlan_get_info_signal(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_SIGNAL_EXT:
+		status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_FW_INFO:
+		pioctl_req->data_read_written =
+			sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+		pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
+		pget_info->param.fw_info.hotfix_version =
+			pmadapter->fw_hotfix_ver;
+		memcpy_ext(pmadapter, &pget_info->param.fw_info.mac_addr,
+			   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+		pget_info->param.fw_info.region_code = pmadapter->region_code;
+		if (pmadapter->otp_region && pmadapter->otp_region->force_reg)
+			pget_info->param.fw_info.force_reg = MTRUE;
+		else
+			pget_info->param.fw_info.force_reg = MFALSE;
+		pget_info->param.fw_info.ecsa_enable = pmadapter->ecsa_enable;
+		pget_info->param.fw_info.getlog_enable =
+			pmadapter->getlog_enable;
+		pget_info->param.fw_info.hw_dev_mcs_support =
+			pmadapter->hw_dev_mcs_support;
+		pget_info->param.fw_info.hw_dot_11n_dev_cap =
+			pmadapter->hw_dot_11n_dev_cap;
+		pget_info->param.fw_info.usr_dev_mcs_support =
+			pmpriv->usr_dev_mcs_support;
+		if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+			pget_info->param.fw_info.prohibit_80mhz = MTRUE;
+		else
+			pget_info->param.fw_info.prohibit_80mhz = MFALSE;
+		pget_info->param.fw_info.hw_dot_11ac_mcs_support =
+			pmadapter->hw_dot_11ac_mcs_support;
+		pget_info->param.fw_info.hw_dot_11ac_dev_cap =
+			pmadapter->hw_dot_11ac_dev_cap;
+		pget_info->param.fw_info.usr_dot_11ac_dev_cap_bg =
+			pmpriv->usr_dot_11ac_dev_cap_bg;
+		pget_info->param.fw_info.usr_dot_11ac_mcs_support =
+			pmpriv->usr_dot_11ac_mcs_support;
+		pget_info->param.fw_info.usr_dot_11ac_dev_cap_a =
+			pmpriv->usr_dot_11ac_dev_cap_a;
+		pget_info->param.fw_info.hw_hecap_len = pmadapter->hw_hecap_len;
+		pget_info->param.fw_info.hw_2g_hecap_len =
+			pmadapter->hw_2g_hecap_len;
+		memcpy_ext(pmadapter, pget_info->param.fw_info.hw_he_cap,
+			   pmadapter->hw_he_cap, pmadapter->hw_hecap_len,
+			   sizeof(pget_info->param.fw_info.hw_he_cap));
+		memcpy_ext(pmadapter, pget_info->param.fw_info.hw_2g_he_cap,
+			   pmadapter->hw_2g_he_cap, pmadapter->hw_2g_hecap_len,
+			   sizeof(pget_info->param.fw_info.hw_2g_he_cap));
+		pget_info->param.fw_info.fw_supplicant_support =
+			IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 : 0x00;
+		pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+		pget_info->param.fw_info.max_ap_assoc_sta =
+			pmadapter->max_sta_conn;
+		pget_info->param.fw_info.fw_beacon_prot =
+			IS_FW_SUPPORT_BEACON_PROT(pmadapter) ? 0x01 : 0x00;
+		break;
+	case MLAN_OID_GET_BSS_INFO:
+		status = wlan_get_info_bss_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_DEBUG_INFO:
+		status = wlan_get_info_debug_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_VER_EXT:
+		status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_LINK_STATS:
+		status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get SNMP MIB handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_snmp_mib_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+	t_u16 cmd_oid = 0;
+	mlan_ds_snmp_mib *mib = MNULL;
+	t_u32 value = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	switch (mib->sub_command) {
+	case MLAN_OID_SNMP_MIB_RTS_THRESHOLD:
+		value = mib->param.rts_threshold;
+		cmd_oid = RtsThresh_i;
+		break;
+	case MLAN_OID_SNMP_MIB_FRAG_THRESHOLD:
+		value = mib->param.frag_threshold;
+		cmd_oid = FragThresh_i;
+		break;
+	case MLAN_OID_SNMP_MIB_RETRY_COUNT:
+		value = mib->param.retry_count;
+		cmd_oid = ShortRetryLim_i;
+		break;
+	case MLAN_OID_SNMP_MIB_DTIM_PERIOD:
+		value = mib->param.dtim_period;
+		cmd_oid = DtimPeriod_i;
+		break;
+	case MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE:
+		value = mib->param.signalext_enable;
+		cmd_oid = SignalextEnable_i;
+		break;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+			       cmd_oid, (t_void *)pioctl_req, &value);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Radio command handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_radio_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_radio_cfg *radio_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_radio_cfg)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_radio_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+	switch (radio_cfg->sub_command) {
+	case MLAN_OID_RADIO_CTRL:
+		status = wlan_radio_ioctl_radio_ctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BAND_CFG:
+		status = wlan_radio_ioctl_band_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_ANT_CFG:
+		status = wlan_radio_ioctl_ant_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_REMAIN_CHAN_CFG:
+		status = wlan_radio_ioctl_remain_chan_cfg(pmadapter,
+							  pioctl_req);
+		break;
+	case MLAN_OID_MIMO_SWITCH:
+		status = wlan_radio_ioctl_mimo_switch_cfg(pmadapter,
+							  pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get MAC address
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_mac_address(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	t_u16 cmd_action;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_SET;
+		memcpy_ext(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MAC_ADDRESS,
+			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set multicast list
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 old_pkt_filter;
+
+	ENTER();
+
+	old_pkt_filter = pmpriv->curr_pkt_filter;
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	pioctl_req->data_read_written =
+		sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
+	if (bss->param.multicast_list.mode == MLAN_PROMISC_MODE) {
+		PRINTM(MINFO, "Enable Promiscuous mode\n");
+		pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+		pmpriv->curr_pkt_filter &=
+			~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+	} else {
+		/* Multicast */
+		pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+		if (bss->param.multicast_list.mode == MLAN_ALL_MULTI_MODE) {
+			PRINTM(MINFO, "Enabling All Multicast!\n");
+			pmpriv->curr_pkt_filter |=
+				HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+		} else {
+			pmpriv->curr_pkt_filter &=
+				~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+			if (bss->param.multicast_list.num_multicast_addr) {
+				PRINTM(MINFO, "Set multicast list=%d\n",
+				       bss->param.multicast_list.
+				       num_multicast_addr);
+				/* Set multicast addresses to firmware */
+				if (old_pkt_filter == pmpriv->curr_pkt_filter) {
+					/* Send request to firmware */
+					ret = wlan_prepare_cmd(pmpriv,
+							       HostCmd_CMD_MAC_MULTICAST_ADR,
+							       HostCmd_ACT_GEN_SET,
+							       0,
+							       (t_void *)
+							       pioctl_req,
+							       &bss->param.
+							       multicast_list);
+					if (ret == MLAN_STATUS_SUCCESS)
+						ret = MLAN_STATUS_PENDING;
+				} else {
+					/* Send request to firmware */
+					ret = wlan_prepare_cmd(pmpriv,
+							       HostCmd_CMD_MAC_MULTICAST_ADR,
+							       HostCmd_ACT_GEN_SET,
+							       0, MNULL,
+							       &bss->param.
+							       multicast_list);
+				}
+				if (ret)
+					goto exit;
+			}
+		}
+	}
+	PRINTM(MINFO, "old_pkt_filter=0x%x, curr_pkt_filter=0x%x\n",
+	       old_pkt_filter, pmpriv->curr_pkt_filter);
+	if (old_pkt_filter != pmpriv->curr_pkt_filter) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req,
+				       &pmpriv->curr_pkt_filter);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get channel list
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_get_channel_list(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	chan_freq_power_t *cfp;
+	t_u32 i, j;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action != MLAN_ACT_GET) {
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if ((wlan_11d_is_enabled(pmpriv) && pmpriv->media_connected == MTRUE) &&
+	    ((pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ||
+	     (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS &&
+	      pmpriv->adhoc_state != ADHOC_STARTED))) {
+		t_u8 chan_no;
+		t_u8 band;
+
+		parsed_region_chan_11d_t *parsed_region_chan = MNULL;
+		parsed_region_chan_11d_t region_chan;
+
+		BSSDescriptor_t *pbss_desc =
+			&pmpriv->curr_bss_params.bss_descriptor;
+
+		memset(pmadapter, &region_chan, 0,
+		       sizeof(parsed_region_chan_11d_t));
+
+		/*If country IE is present in the associated AP then return the
+		   channel list from country IE
+		   else return it from the learning table */
+
+		if (wlan_11d_parse_domain_info
+		    (pmadapter, &pbss_desc->country_info,
+		     (t_u8)pbss_desc->bss_band,
+		     &region_chan) == MLAN_STATUS_SUCCESS) {
+			parsed_region_chan = &region_chan;
+		} else {
+			parsed_region_chan = &pmadapter->parsed_region_chan;
+		}
+
+		PRINTM(MINFO, "no_of_chan=%d\n",
+		       parsed_region_chan->no_of_chan);
+
+		for (i = 0;
+		     (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
+		     (i < parsed_region_chan->no_of_chan); i++) {
+			chan_no = parsed_region_chan->chan_pwr[i].chan;
+			band = parsed_region_chan->chan_pwr[i].band;
+			PRINTM(MINFO, "band=%d, chan_no=%d\n", band, chan_no);
+			bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
+				.channel = (t_u32)chan_no;
+			bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
+				.freq =
+				(t_u32)wlan_11d_chan_2_freq(pmadapter, chan_no,
+							    band);
+			bss->param.chanlist.num_of_chan++;
+		}
+	} else {
+		for (j = 0;
+		     (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
+		     (j < MAX_REGION_CHANNEL_NUM); j++) {
+			cfp = pmadapter->region_channel[j].pcfp;
+			for (i = 0; (bss->param.chanlist.num_of_chan <
+				     MLAN_MAX_CHANNEL_NUM) &&
+			     pmadapter->region_channel[j].valid && cfp &&
+			     (i < pmadapter->region_channel[j].num_cfp); i++) {
+				bss->param.chanlist.cf[bss->param.chanlist.
+						       num_of_chan]
+					.channel = (t_u32)cfp->channel;
+				bss->param.chanlist.cf[bss->param.chanlist.
+						       num_of_chan]
+					.freq = (t_u32)cfp->freq;
+				bss->param.chanlist.num_of_chan++;
+				cfp++;
+			}
+		}
+	}
+
+	PRINTM(MINFO, "num of channel=%d\n", bss->param.chanlist.num_of_chan);
+
+	LEAVE();
+	return ret;
+}
+
+/** Highest channel used in 2.4GHz band */
+#define MAX_CHANNEL_BAND_B (14)
+
+/** Highest frequency used in 2.4GHz band */
+#define MAX_FREQUENCY_BAND_B (2484)
+
+/**
+ *  @brief Set/Get BSS channel
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_channel(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = MNULL;
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	chan_freq_power_t *cfp = MNULL;
+	ENTER();
+
+	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+		PRINTM(MERROR, "Request buffer not found!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+							pmpriv->curr_bss_params.
+							band,
+							(t_u16)pmpriv->
+							curr_bss_params.
+							bss_descriptor.channel);
+		if (cfp) {
+			bss->param.bss_chan.channel = cfp->channel;
+			bss->param.bss_chan.freq = cfp->freq;
+		} else {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+		}
+		pioctl_req->data_read_written =
+			sizeof(chan_freq) + MLAN_SUB_COMMAND_SIZE;
+		LEAVE();
+		return ret;
+	}
+	if (!bss->param.bss_chan.channel && !bss->param.bss_chan.freq) {
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pmadapter->adhoc_start_band & BAND_A)
+		pmadapter->adhoc_start_band = BAND_G | BAND_B;
+	if (bss->param.bss_chan.channel) {
+		if (bss->param.bss_chan.channel <= MAX_CHANNEL_BAND_B)
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								BAND_B,
+								(t_u16)bss->
+								param.bss_chan.
+								channel);
+		if (!cfp) {
+			cfp = wlan_find_cfp_by_band_and_channel(pmadapter,
+								BAND_A,
+								(t_u16)bss->
+								param.bss_chan.
+								channel);
+			if (cfp) {
+				pmadapter->adhoc_start_band = BAND_A;
+			}
+		}
+	} else {
+		if (bss->param.bss_chan.freq <= MAX_FREQUENCY_BAND_B)
+			cfp = wlan_find_cfp_by_band_and_freq(pmadapter, BAND_B,
+							     bss->param.
+							     bss_chan.freq);
+		if (!cfp) {
+			cfp = wlan_find_cfp_by_band_and_freq(pmadapter, BAND_A,
+							     bss->param.
+							     bss_chan.freq);
+			if (cfp) {
+				pmadapter->adhoc_start_band = BAND_A;
+			}
+		}
+	}
+	if (!cfp || !cfp->channel) {
+		PRINTM(MERROR, "Invalid channel/freq\n");
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmpriv->adhoc_channel = (t_u8)cfp->channel;
+	pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
+	bss->param.bss_chan.channel = cfp->channel;
+	bss->param.bss_chan.freq = cfp->freq;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get BSS mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_mode(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		bss->param.bss_mode = pmpriv->bss_mode;
+		pioctl_req->data_read_written =
+			sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+		goto exit;
+	}
+
+	if ((pmpriv->bss_mode == bss->param.bss_mode) ||
+	    (bss->param.bss_mode == MLAN_BSS_MODE_AUTO)) {
+		PRINTM(MINFO, "Already set to required mode! No change!\n");
+		pmpriv->bss_mode = bss->param.bss_mode;
+		goto exit;
+	}
+
+	if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO)
+		ret = wlan_disconnect(pmpriv, MNULL, MNULL);
+	else
+		ret = wlan_disconnect(pmpriv, pioctl_req, MNULL);
+
+	if (pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)
+		pmpriv->sec_info.authentication_mode = MLAN_AUTH_MODE_OPEN;
+	pmpriv->bss_mode = bss->param.bss_mode;
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
+		pmpriv->port_ctrl_mode = MTRUE;
+	else
+		pmpriv->port_ctrl_mode = MFALSE;
+	if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req, MNULL);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Start BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_start(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	t_s32 i = -1;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+
+	/* Before ASSOC REQ, If "port ctrl" mode is enabled,
+	 * move the port to CLOSED state */
+	if (pmpriv->port_ctrl_mode == MTRUE) {
+		PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n");
+		pmpriv->prior_port_status = pmpriv->port_open;
+		pmpriv->port_open = MFALSE;
+	}
+	pmadapter->scan_block = MFALSE;
+
+	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
+		if (!bss->param.ssid_bssid.idx ||
+		    bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
+			/* Search for the requested SSID in the scan table */
+			if (bss->param.ssid_bssid.ssid.ssid_len) {
+				if (memcmp(pmadapter,
+					   &bss->param.ssid_bssid.bssid,
+					   zero_mac, sizeof(zero_mac)))
+					i = wlan_find_ssid_in_list(pmpriv,
+								   &bss->param.
+								   ssid_bssid.
+								   ssid,
+								   (t_u8 *)
+								   &bss->param.
+								   ssid_bssid.
+								   bssid,
+								   MLAN_BSS_MODE_INFRA);
+				else
+					i = wlan_find_ssid_in_list(pmpriv,
+								   &bss->param.
+								   ssid_bssid.
+								   ssid, MNULL,
+								   MLAN_BSS_MODE_INFRA);
+			} else {
+				i = wlan_find_bssid_in_list(pmpriv,
+							    (t_u8 *)&bss->param.
+							    ssid_bssid.bssid,
+							    MLAN_BSS_MODE_INFRA);
+			}
+		} else {
+			/* use bsslist index number to assoicate */
+			i = wlan_is_network_compatible(pmpriv,
+						       bss->param.ssid_bssid.
+						       idx - 1,
+						       pmpriv->bss_mode);
+		}
+		if (i >= 0) {
+			/* block if upper-layer tries to reconnect before new
+			 * scan */
+			if (wlan_11h_get_csa_closed_channel(pmpriv) ==
+			    (t_u8)pmadapter->pscan_table[i].channel) {
+				PRINTM(MINFO,
+				       "Attempt to reconnect on csa_closed_chan(%d)\n",
+				       pmadapter->pscan_table[i].channel);
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto start_ssid_done;
+			}
+			PRINTM(MINFO,
+			       "SSID found in scan list ... associating...\n");
+			pmpriv->curr_bss_params.host_mlme =
+				bss->param.ssid_bssid.host_mlme;
+			memcpy_ext(pmpriv->adapter,
+				   &pmpriv->curr_bss_params.prev_bssid,
+				   &bss->param.ssid_bssid.prev_bssid,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			/* Clear any past association response stored for
+			 * application retrieval */
+			pmpriv->assoc_rsp_size = 0;
+			pmpriv->curr_chan_flags =
+				bss->param.ssid_bssid.channel_flags;
+			if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+				pmpriv->curr_chan_flags |= CHAN_FLAGS_NO_80MHZ;
+			ret = wlan_associate(pmpriv, pioctl_req,
+					     &pmadapter->pscan_table[i]);
+			if (ret)
+				goto start_ssid_done;
+		} else {	/* i >= 0 */
+			PRINTM(MERROR,
+			       "SSID not found in scan list: ssid=%s, " MACSTR
+			       ", idx=%d\n",
+			       bss->param.ssid_bssid.ssid.ssid,
+			       MAC2STR(bss->param.ssid_bssid.bssid),
+			       (int)bss->param.ssid_bssid.idx);
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto start_ssid_done;
+		}
+	} else {
+		/* Adhoc mode */
+		/* If the requested SSID matches current SSID, return */
+		if (bss->param.ssid_bssid.ssid.ssid_len &&
+		    (!wlan_ssid_cmp(pmadapter,
+				    &pmpriv->curr_bss_params.bss_descriptor.
+				    ssid, &bss->param.ssid_bssid.ssid))) {
+			ret = MLAN_STATUS_SUCCESS;
+			goto start_ssid_done;
+		}
+
+		/* Exit Adhoc mode first */
+		PRINTM(MINFO, "Sending Adhoc Stop\n");
+		ret = wlan_disconnect(pmpriv, MNULL, MNULL);
+		if (ret)
+			goto start_ssid_done;
+
+		pmpriv->adhoc_is_link_sensed = MFALSE;
+
+		if (!bss->param.ssid_bssid.idx ||
+		    bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
+			/* Search for the requested network in the scan table */
+			if (bss->param.ssid_bssid.ssid.ssid_len) {
+				i = wlan_find_ssid_in_list(pmpriv,
+							   &bss->param.
+							   ssid_bssid.ssid,
+							   MNULL,
+							   MLAN_BSS_MODE_IBSS);
+			} else {
+				i = wlan_find_bssid_in_list(pmpriv,
+							    (t_u8 *)&bss->param.
+							    ssid_bssid.bssid,
+							    MLAN_BSS_MODE_IBSS);
+			}
+		} else {
+			/* use bsslist index number to assoicate */
+			i = wlan_is_network_compatible(pmpriv,
+						       bss->param.ssid_bssid.
+						       idx - 1,
+						       pmpriv->bss_mode);
+		}
+
+		if (i >= 0) {
+			PRINTM(MINFO,
+			       "Network found in scan list ... joining ...\n");
+			pmpriv->curr_chan_flags =
+				bss->param.ssid_bssid.channel_flags;
+			ret = wlan_adhoc_join(pmpriv, pioctl_req,
+					      &pmadapter->pscan_table[i]);
+			if (ret)
+				goto start_ssid_done;
+		} else {	/* i >= 0 */
+			PRINTM(MINFO,
+			       "Network not found in the list, "
+			       "creating adhoc with ssid = %s\n",
+			       bss->param.ssid_bssid.ssid.ssid);
+			pmpriv->curr_chan_flags =
+				bss->param.ssid_bssid.channel_flags;
+			ret = wlan_adhoc_start(pmpriv, pioctl_req,
+					       &bss->param.ssid_bssid.ssid);
+			if (ret)
+				goto start_ssid_done;
+		}
+	}
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+start_ssid_done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Stop BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_stop(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+	ENTER();
+
+	ret = wlan_disconnect(pmpriv, pioctl_req, &bss->param.deauth_param);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get IBSS channel
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_ibss_channel(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		if (pmpriv->media_connected == MFALSE) {
+			bss->param.bss_chan.channel = pmpriv->adhoc_channel;
+			goto exit;
+		}
+		cmd_action = HostCmd_ACT_GEN_GET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_SET;
+		pmpriv->adhoc_channel = (t_u8)bss->param.bss_chan.channel;
+		pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_CHANNEL,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &bss->param.bss_chan.channel);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Listen Interval
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_listen_interval(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		bss->param.listen_interval = pmpriv->listen_interval;
+	else
+		pmpriv->listen_interval = bss->param.listen_interval;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/*
+ *  @brief Set/Get beacon interval
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_bss_ioctl_beacon_interval(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		bss->param.bcn_interval = pmpriv->beacon_period;
+		if (pmpriv->media_connected == MTRUE)
+			bss->param.bcn_interval =
+				pmpriv->curr_bss_params.bss_descriptor.
+				beacon_period;
+	} else
+		pmpriv->beacon_period = (t_u16)bss->param.bcn_interval;
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get ATIM window
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_bss_ioctl_atim_window(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		bss->param.atim_window = pmpriv->atim_window;
+		if (pmpriv->media_connected == MTRUE)
+			bss->param.atim_window =
+				pmpriv->curr_bss_params.bss_descriptor.
+				atim_window;
+	} else
+		pmpriv->atim_window = (t_u16)bss->param.atim_window;
+
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Query embe
+ *
+ *  @param priv                 A pointer to mlan_private structure
+ *  @param pioctl_req           A pointer to ioctl request buffer
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+static mlan_status
+wlan_query_passphrase(mlan_private *priv, pmlan_ioctl_req pioctl_req)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ssid_bssid *ssid_bssid = MNULL;
+	mlan_ds_sec_cfg *sec = MNULL;
+	mlan_ds_passphrase *sec_pp;
+	int i = 0;
+	BSSDescriptor_t *pbss_desc;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	ssid_bssid = &bss->param.ssid_bssid;
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_ds_sec_cfg),
+			       MLAN_MEM_DEF, (t_u8 **)&sec);
+	if (ret || !sec) {
+		PRINTM(MERROR, "Could not allocate sec!\n");
+		LEAVE();
+		return ret;
+	}
+	memset(pmadapter, sec, 0, sizeof(mlan_ds_sec_cfg));
+	sec_pp = (mlan_ds_passphrase *)&sec->param.passphrase;
+	sec_pp->psk_type = MLAN_PSK_QUERY;
+	if (ssid_bssid->ssid.ssid_len == 0) {
+		i = wlan_find_bssid_in_list(priv, (t_u8 *)&ssid_bssid->bssid,
+					    MLAN_BSS_MODE_AUTO);
+		if (i >= 0) {
+			pbss_desc = &pmadapter->pscan_table[i];
+			memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid,
+				   &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
+				   sizeof(mlan_802_11_ssid));
+		} else
+			memcpy_ext(pmadapter, (t_u8 *)&sec_pp->bssid,
+				   &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH,
+				   MLAN_MAC_ADDR_LENGTH);
+	} else {
+		memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->ssid,
+			   sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_SUPPLICANT_PMK,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       (t_void *)sec);
+	if (sec)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)sec);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Search for a BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_find_bss(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	mlan_ds_bss *bss = MNULL;
+	mlan_ssid_bssid *ssid_bssid = MNULL;
+#endif
+
+	ENTER();
+
+	if (pmpriv->ewpa_query) {
+		if (wlan_query_passphrase(pmpriv, pioctl_req) ==
+		    MLAN_STATUS_SUCCESS) {
+			PRINTM(MINFO, "Find BSS ioctl: query passphrase\n");
+			LEAVE();
+			return MLAN_STATUS_PENDING;
+		}
+	}
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		ssid_bssid = &bss->param.ssid_bssid;
+		supplicantQueryPassphraseAndEnable(pmpriv->psapriv,
+						   (t_u8 *)ssid_bssid);
+	}
+#endif
+
+	ret = wlan_find_bss(pmpriv, pioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Search for a BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_find_bssid(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int i = 0;
+
+	ENTER();
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	i = wlan_find_bssid_in_list(pmpriv, (t_u8 *)&bss->param.bssid,
+				    MLAN_BSS_MODE_AUTO);
+	if (i < 0) {
+		PRINTM(MCMND, "Can not find bssid " MACSTR "\n",
+		       MAC2STR((t_u8 *)&bss->param.bssid));
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	PRINTM(MCMND, "Find bssid " MACSTR "\n",
+	       MAC2STR((t_u8 *)&bss->param.bssid));
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check if BSS channel is valid for Station's region
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl_bss_11d_check_channel(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ssid_bssid *ssid_bssid = MNULL;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	ssid_bssid = &bss->param.ssid_bssid;
+
+	PRINTM(MINFO, "ssid: %s idx:%d\n", ssid_bssid->ssid.ssid,
+	       ssid_bssid->idx);
+	PRINTM(MINFO, "band:%d channel:%d\n", (t_u8)ssid_bssid->bss_band,
+	       (t_u32)ssid_bssid->channel);
+
+	/* check if this channel is supported in the region */
+	if (!wlan_find_cfp_by_band_and_channel(pmadapter,
+					       (t_u8)ssid_bssid->bss_band,
+					       (t_u32)ssid_bssid->channel)) {
+		PRINTM(MERROR, "Unsupported Channel for region 0x%x\n",
+		       pmadapter->region_code);
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief BSS command handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_bss_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_bss)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_bss);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+	switch (bss->sub_command) {
+	case MLAN_OID_BSS_START:
+		status = wlan_bss_ioctl_start(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_STOP:
+		status = wlan_bss_ioctl_stop(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_MODE:
+		status = wlan_bss_ioctl_mode(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_CHANNEL:
+		status = wlan_bss_ioctl_channel(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_CHANNEL_LIST:
+		status = wlan_bss_ioctl_get_channel_list(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_MAC_ADDR:
+		status = wlan_bss_ioctl_mac_address(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_MULTICAST_LIST:
+		status = wlan_bss_ioctl_set_multicast_list(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_BSS_FIND_BSS:
+		status = wlan_bss_ioctl_find_bss(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_FIND_BSSID:
+		status = wlan_bss_ioctl_find_bssid(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_IBSS_BCN_INTERVAL:
+		status = wlan_bss_ioctl_beacon_interval(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_IBSS_ATIM_WINDOW:
+		status = wlan_bss_ioctl_atim_window(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_IBSS_CHANNEL:
+		status = wlan_bss_ioctl_ibss_channel(pmadapter, pioctl_req);
+		break;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	case MLAN_OID_BSS_ROLE:
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->ioctl_pending_q,
+				       (pmlan_linked_list)pioctl_req,
+				       pmadapter->callbacks.moal_spin_lock,
+				       pmadapter->callbacks.moal_spin_unlock);
+		pmadapter->pending_ioctl = MTRUE;
+		status = MLAN_STATUS_PENDING;
+		break;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	case MLAN_OID_WIFI_DIRECT_MODE:
+		status = wlan_bss_ioctl_wifi_direct_mode(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_BSS_LISTEN_INTERVAL:
+		status = wlan_bss_ioctl_listen_interval(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_BSS_REMOVE:
+		status = wlan_bss_ioctl_bss_remove(pmadapter, pioctl_req);
+		break;
+
+	case MLAN_OID_BSS_11D_CHECK_CHANNEL:
+		status = wlan_bss_ioctl_bss_11d_check_channel(pmadapter,
+							      pioctl_req);
+		break;
+	case MLAN_OID_BSS_CHAN_INFO:
+		status = wlan_bss_ioctl_get_chan_info(pmadapter, pioctl_req);
+		break;
+	default:
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get supported rates
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl_get_supported_rate(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_rate *rate = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (pioctl_req->action != MLAN_ACT_GET) {
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	rate = (mlan_ds_rate *)pioctl_req->pbuf;
+	if (rate->param.rate_band_cfg.config_bands &&
+	    rate->param.rate_band_cfg.bss_mode)
+		wlan_get_active_data_rates(pmpriv,
+					   rate->param.rate_band_cfg.bss_mode,
+					   rate->param.rate_band_cfg.
+					   config_bands, rate->param.rates);
+	else
+		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
+					   (pmpriv->bss_mode ==
+					    MLAN_BSS_MODE_INFRA) ?
+					   pmpriv->config_bands :
+					   pmadapter->adhoc_start_band,
+					   rate->param.rates);
+	pioctl_req->data_read_written =
+		MLAN_SUPPORTED_RATES + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Rate command handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_rate_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_rate *rate = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_rate)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_rate);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	rate = (mlan_ds_rate *)pioctl_req->pbuf;
+	switch (rate->sub_command) {
+	case MLAN_OID_RATE_CFG:
+		status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_GET_DATA_RATE:
+		status = wlan_rate_ioctl_get_data_rate(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SUPPORTED_RATES:
+		status = wlan_rate_ioctl_get_supported_rate(pmadapter,
+							    pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get Tx power configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param cmd_no	Firmware command number used to retrieve power values
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_power_ioctl_get_power(pmlan_adapter pmadapter,
+			   t_u16 cmd_no, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_GET, 0,
+			       (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Tx power configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_power_ioctl_set_power(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_power_cfg *power = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
+	MrvlTypes_Power_Group_t *pg_tlv = MNULL;
+	Power_Group_t *pg = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *buf = MNULL;
+	t_s8 dbm = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+	if (!power->param.power_cfg.is_power_auto) {
+		dbm = (t_s8)power->param.power_cfg.power_level;
+		if ((dbm < pmpriv->min_tx_power_level) ||
+		    (dbm > pmpriv->max_tx_power_level)) {
+			PRINTM(MERROR,
+			       "The set txpower value %d dBm is out of range (%d dBm-%d dBm)!\n",
+			       dbm, pmpriv->min_tx_power_level,
+			       pmpriv->max_tx_power_level);
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+	}
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
+	if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
+		PRINTM(MERROR,
+		       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
+	txp_cfg->action = HostCmd_ACT_GEN_SET;
+	if (!power->param.power_cfg.is_power_auto) {
+		txp_cfg->mode = 1;
+		pg_tlv = (MrvlTypes_Power_Group_t
+			  *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
+		pg_tlv->type = TLV_TYPE_POWER_GROUP;
+		pg_tlv->length = 4 * sizeof(Power_Group_t);
+		pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
+				       sizeof(MrvlTypes_Power_Group_t));
+		/* Power group for modulation class HR/DSSS */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x03;
+		pg->modulation_class = MOD_CLASS_HR_DSSS;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg++;
+		/* Power group for modulation class OFDM */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x07;
+		pg->modulation_class = MOD_CLASS_OFDM;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg++;
+		/* Power group for modulation class HTBW20 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x20;
+		pg->modulation_class = MOD_CLASS_HT;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = HT_BW_20;
+		pg++;
+		/* Power group for modulation class HTBW40 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x20;
+		pg->modulation_class = MOD_CLASS_HT;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = HT_BW_40;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       buf);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	if (buf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set extended power configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_power_ioctl_set_power_ext(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_power_cfg *power = MNULL;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *buf = MNULL;
+	HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
+	MrvlTypes_Power_Group_t *pg_tlv = MNULL;
+	Power_Group_t *pg = MNULL;
+	mlan_power_group *pwr_grp = MNULL;
+
+	ENTER();
+
+	power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
+	if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
+		PRINTM(MERROR,
+		       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
+		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
+	txp_cfg->action = HostCmd_ACT_GEN_SET;
+	pwr_grp = &power->param.power_ext.power_group[0];
+	if (pwr_grp->rate_format == TX_PWR_CFG_AUTO_CTRL_OFF)
+		txp_cfg->mode = 0;
+	else {
+		txp_cfg->mode = 1;
+
+		pg_tlv = (MrvlTypes_Power_Group_t
+			  *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
+		pg_tlv->type = TLV_TYPE_POWER_GROUP;
+		pg_tlv->length = sizeof(Power_Group_t);
+		pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
+				       sizeof(MrvlTypes_Power_Group_t));
+		pg->ht_bandwidth = pwr_grp->bandwidth;
+		pg->power_min = (t_s8)pwr_grp->power_min;
+		pg->power_max = (t_s8)pwr_grp->power_max;
+		pg->power_step = (t_s8)pwr_grp->power_step;
+
+		if (pwr_grp->rate_format == MLAN_RATE_FORMAT_LG) {
+			if (pwr_grp->first_rate_ind <= MLAN_RATE_INDEX_HRDSSS3) {
+				pg->modulation_class = MOD_CLASS_HR_DSSS;
+			} else {
+				pg->modulation_class = MOD_CLASS_OFDM;
+				pwr_grp->first_rate_ind -=
+					MLAN_RATE_INDEX_OFDM0;
+				pwr_grp->last_rate_ind -= MLAN_RATE_INDEX_OFDM0;
+			}
+			pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
+			pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
+		} else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT) {
+			pg->modulation_class = MOD_CLASS_HT;
+			pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
+			pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
+		} else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_VHT) {
+			pg->modulation_class = MOD_CLASS_VHT;
+			pg->first_rate_code =
+				(t_u8)((pwr_grp->first_rate_ind & 0xF) |
+				       ((pwr_grp->nss - 1) << 4));
+			pg->last_rate_code =
+				(t_u8)((pwr_grp->last_rate_ind & 0xF) |
+				       ((pwr_grp->nss - 1) << 4));
+		} else {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+	if (ret == MLAN_STATUS_FAILURE) {
+		if (buf)
+			pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       buf);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	if (buf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Power configuration command handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_power_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_power_cfg *power = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_power_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_power_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+	switch (power->sub_command) {
+	case MLAN_OID_POWER_CFG:
+		if (pioctl_req->action == MLAN_ACT_GET)
+			status = wlan_power_ioctl_get_power(pmadapter,
+							    HostCmd_CMD_TXPWR_CFG,
+							    pioctl_req);
+		else
+			status = wlan_power_ioctl_set_power(pmadapter,
+							    pioctl_req);
+		break;
+
+	case MLAN_OID_POWER_CFG_EXT:
+		if (pioctl_req->action == MLAN_ACT_GET)
+			status = wlan_power_ioctl_get_power(pmadapter,
+							    HostCmd_CMD_TXPWR_CFG,
+							    pioctl_req);
+		else
+			status = wlan_power_ioctl_set_power_ext(pmadapter,
+								pioctl_req);
+		break;
+	case MLAN_OID_POWER_LOW_POWER_MODE:
+		status = wlan_power_ioctl_set_get_lpm(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set power save configurations
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *  @param ps_mode	Power save mode
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_pm_ioctl_ps_mode(pmlan_adapter pmadapter,
+		      pmlan_ioctl_req pioctl_req, t_u16 ps_mode)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 sub_cmd;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		sub_cmd = (pmadapter->ps_mode == Wlan802_11PowerModePSP) ?
+			EN_AUTO_PS : DIS_AUTO_PS;
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+				       sub_cmd, BITMAP_STA_PS,
+				       (t_void *)pioctl_req, MNULL);
+		if ((ret == MLAN_STATUS_SUCCESS) && (sub_cmd == DIS_AUTO_PS)) {
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_PS_MODE_ENH,
+					       GET_PS, 0, MNULL, MNULL);
+		}
+	} else {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+				       GET_PS, 0, (t_void *)pioctl_req, MNULL);
+	}
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Inactivity timeout extend
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_pm_ioctl_inactivity_timeout(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pmcfg = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INACTIVITY_TIMEOUT_EXT,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       (t_void *)&pmcfg->param.inactivity_to);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable/Disable Auto Deep Sleep
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_set_auto_deep_sleep(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv =
+		(pmlan_private)pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_auto_ds auto_ds;
+	t_u32 mode;
+
+	ENTER();
+
+	if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+	    ->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
+		auto_ds.auto_ds = DEEP_SLEEP_ON;
+		PRINTM(MINFO, "Auto Deep Sleep: on\n");
+		mode = EN_AUTO_PS;
+	} else {
+		auto_ds.auto_ds = DEEP_SLEEP_OFF;
+		PRINTM(MINFO, "Auto Deep Sleep: off\n");
+		mode = DIS_AUTO_PS;
+	}
+	if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)->param.auto_deep_sleep.
+	    idletime)
+		auto_ds.idletime = ((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+			->param.auto_deep_sleep.idletime;
+	else
+		auto_ds.idletime = pmadapter->idle_time;
+	/* note: the command could be queued and executed
+	   later if there is command in progress. */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+			       (t_u16)mode, BITMAP_AUTO_DS,
+			       (t_void *)pioctl_req, &auto_ds);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+	ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get sleep period
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_set_get_sleep_pd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+	t_u16 cmd_action = 0, sleep_pd = 0;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		cmd_action = HostCmd_ACT_GEN_SET;
+		sleep_pd = (t_u16)pm_cfg->param.sleep_period;
+	}
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PERIOD,
+			       cmd_action, 0, (t_void *)pioctl_req, &sleep_pd);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get PS configuration parameter
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_set_get_ps_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		pm_cfg->param.ps_cfg.ps_null_interval =
+			(t_u32)pmadapter->null_pkt_interval;
+		pm_cfg->param.ps_cfg.multiple_dtim_interval =
+			(t_u32)pmadapter->multiple_dtim;
+		pm_cfg->param.ps_cfg.listen_interval =
+			(t_u32)pmadapter->local_listen_interval;
+		pm_cfg->param.ps_cfg.bcn_miss_timeout =
+			(t_u32)pmadapter->bcn_miss_time_out;
+		pm_cfg->param.ps_cfg.delay_to_ps =
+			(t_u32)pmadapter->delay_to_ps;
+		pm_cfg->param.ps_cfg.ps_mode =
+			(t_u32)pmadapter->enhanced_ps_mode;
+	} else {
+		if (pm_cfg->param.ps_cfg.ps_null_interval)
+			pmadapter->null_pkt_interval =
+				(t_u16)pm_cfg->param.ps_cfg.ps_null_interval;
+		else
+			pm_cfg->param.ps_cfg.ps_null_interval =
+				(t_u32)pmadapter->null_pkt_interval;
+		if (pm_cfg->param.ps_cfg.multiple_dtim_interval)
+			pmadapter->multiple_dtim =
+				(t_u16)pm_cfg->param.ps_cfg.
+				multiple_dtim_interval;
+		else
+			pm_cfg->param.ps_cfg.multiple_dtim_interval =
+				(t_u32)pmadapter->multiple_dtim;
+		if (((t_s32)pm_cfg->param.ps_cfg.listen_interval) ==
+		    MRVDRV_LISTEN_INTERVAL_DISABLE)
+			pmadapter->local_listen_interval = 0;
+		else if (pm_cfg->param.ps_cfg.listen_interval)
+			pmadapter->local_listen_interval =
+				(t_u16)pm_cfg->param.ps_cfg.listen_interval;
+		else
+			pm_cfg->param.ps_cfg.listen_interval =
+				(t_u32)pmadapter->local_listen_interval;
+		if (pm_cfg->param.ps_cfg.bcn_miss_timeout)
+			pmadapter->bcn_miss_time_out =
+				(t_u16)pm_cfg->param.ps_cfg.bcn_miss_timeout;
+		else
+			pm_cfg->param.ps_cfg.bcn_miss_timeout =
+				(t_u32)pmadapter->bcn_miss_time_out;
+		if (pm_cfg->param.ps_cfg.delay_to_ps != DELAY_TO_PS_UNCHANGED)
+			pmadapter->delay_to_ps =
+				(t_u16)pm_cfg->param.ps_cfg.delay_to_ps;
+		else
+			pm_cfg->param.ps_cfg.delay_to_ps =
+				(t_u32)pmadapter->delay_to_ps;
+		if (pm_cfg->param.ps_cfg.ps_mode)
+			pmadapter->enhanced_ps_mode =
+				(t_u16)pm_cfg->param.ps_cfg.ps_mode;
+		else
+			pm_cfg->param.ps_cfg.ps_mode =
+				(t_u32)pmadapter->enhanced_ps_mode;
+	}
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get PS configuration parameter
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_set_get_bcn_timeout(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+			       EN_AUTO_PS, BITMAP_BCN_TMO, (t_void *)pioctl_req,
+			       &pm_cfg->param.bcn_timeout);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set the sleep parameters
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_set_get_sleep_params(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	cmd_action = HostCmd_ACT_GEN_GET;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PARAMS,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &pm_cfg->param.sleep_params);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief config management frame wakeup filter
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_config_mgmt_filter(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pm_cfg = MNULL;
+	int i = 0;
+
+	ENTER();
+
+	memset(pmadapter, pmadapter->mgmt_filter, 0,
+	       sizeof(mlan_mgmt_frame_wakeup) * MAX_MGMT_FRAME_FILTER);
+	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		for (i = 0; i < MAX_MGMT_FRAME_FILTER; i++)
+			if (!pm_cfg->param.mgmt_filter[i].type)
+				break;
+		memcpy_ext(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
+			   (t_u8 *)pm_cfg->param.mgmt_filter,
+			   (i + 1) * sizeof(mlan_mgmt_frame_wakeup),
+			   sizeof(pmadapter->mgmt_filter));
+	} else if (pioctl_req->action == MLAN_ACT_GET)
+		PRINTM(MERROR, "Get not support\n");
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Power save command handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_pm_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pm = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg);
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	switch (pm->sub_command) {
+	case MLAN_OID_PM_CFG_IEEE_PS:
+		switch (pioctl_req->action) {
+		case MLAN_ACT_SET:
+			/**Block ieee power save disable command when bt coex
+			 * enable*/
+			if (pmadapter->coex_scan && !pm->param.ps_mode)
+				break;
+			if (pm->param.ps_mode)
+				pmadapter->ps_mode = Wlan802_11PowerModePSP;
+			else
+				pmadapter->ps_mode = Wlan802_11PowerModeCAM;
+			status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
+						       pmadapter->ps_mode);
+			break;
+		case MLAN_ACT_GET:
+			status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
+						       pmadapter->ps_mode);
+			break;
+		default:
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			status = MLAN_STATUS_FAILURE;
+			break;
+		}
+		break;
+	case MLAN_OID_PM_CFG_HS_CFG:
+		status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_CFG_INACTIVITY_TO:
+		status = wlan_pm_ioctl_inactivity_timeout(pmadapter,
+							  pioctl_req);
+		break;
+	case MLAN_OID_PM_CFG_DEEP_SLEEP:
+		switch (pioctl_req->action) {
+		case MLAN_ACT_SET:
+			if (pmadapter->is_deep_sleep &&
+			    pm->param.auto_deep_sleep.auto_ds ==
+			    DEEP_SLEEP_ON) {
+				PRINTM(MMSG,
+				       "Station already in enhanced deep sleep mode\n");
+				status = MLAN_STATUS_FAILURE;
+				break;
+			} else if (!pmadapter->is_deep_sleep &&
+				   pm->param.auto_deep_sleep.auto_ds ==
+				   DEEP_SLEEP_OFF) {
+				PRINTM(MMSG,
+				       "Station already not in enhanced deep sleep mode\n");
+				status = MLAN_STATUS_FAILURE;
+				break;
+			}
+			status = wlan_set_auto_deep_sleep(pmadapter,
+							  pioctl_req);
+			break;
+		case MLAN_ACT_GET:
+			if (pmadapter->is_deep_sleep) {
+				pm->param.auto_deep_sleep.auto_ds =
+					DEEP_SLEEP_ON;
+				pm->param.auto_deep_sleep.idletime =
+					pmadapter->idle_time;
+			} else
+				pm->param.auto_deep_sleep.auto_ds =
+					DEEP_SLEEP_OFF;
+			break;
+		default:
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			status = MLAN_STATUS_FAILURE;
+			break;
+		}
+		break;
+	case MLAN_OID_PM_CFG_PS_CFG:
+		status = wlan_set_get_ps_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_CFG_SLEEP_PD:
+		status = wlan_set_get_sleep_pd(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_CFG_SLEEP_PARAMS:
+		status = wlan_set_get_sleep_params(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_INFO:
+		status = wlan_get_pm_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_HS_WAKEUP_REASON:
+		status = wlan_get_hs_wakeup_reason(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_MGMT_FILTER:
+		status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_PM_CFG_BCN_TIMEOUT:
+		status = wlan_set_get_bcn_timeout(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get WPA IE
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param ie_data_ptr  A pointer to IE
+ *  @param ie_len       Length of the IE
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_set_wpa_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr, t_u16 ie_len)
+{
+	ENTER();
+
+	if (ie_len) {
+		if (ie_len > sizeof(priv->wpa_ie)) {
+			PRINTM(MERROR, "failed to copy, WPA IE is too big\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		memcpy_ext(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len,
+			   sizeof(priv->wpa_ie));
+		priv->wpa_ie_len = (t_u8)ie_len;
+		PRINTM(MIOCTL, "Set Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
+		       priv->wpa_ie[0]);
+		DBG_HEXDUMP(MCMD_D, "Wpa_ie", priv->wpa_ie, priv->wpa_ie_len);
+		if (priv->wpa_ie[0] == WPA_IE) {
+			priv->sec_info.wpa_enabled = MTRUE;
+		} else if (priv->wpa_ie[0] == RSN_IE) {
+			priv->sec_info.wpa2_enabled = MTRUE;
+		} else {
+			priv->sec_info.wpa_enabled = MFALSE;
+			priv->sec_info.wpa2_enabled = MFALSE;
+		}
+	} else {
+		memset(priv->adapter, priv->wpa_ie, 0, sizeof(priv->wpa_ie));
+		priv->wpa_ie_len = 0;
+		PRINTM(MINFO, "Reset Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
+		       priv->wpa_ie[0]);
+		priv->sec_info.wpa_enabled = MFALSE;
+		priv->sec_info.wpa2_enabled = MFALSE;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set OSEN IE
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param ie_data_ptr  A pointer to IE
+ *  @param ie_len       Length of the IE
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_set_osen_ie(mlan_private *priv, t_u8 *ie_data_ptr, t_u16 ie_len)
+{
+	ENTER();
+	if (ie_len) {
+		if (ie_len > sizeof(priv->osen_ie)) {
+			PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		memcpy_ext(priv->adapter, priv->osen_ie, ie_data_ptr, ie_len,
+			   sizeof(priv->osen_ie));
+		priv->osen_ie_len = (t_u8)ie_len;
+		PRINTM(MIOCTL, "Set osen_ie_len=%d IE=%#x\n", priv->osen_ie_len,
+		       priv->osen_ie[0]);
+		DBG_HEXDUMP(MCMD_D, "osen_ie", priv->osen_ie,
+			    priv->osen_ie_len);
+		priv->sec_info.osen_enabled = MTRUE;
+	} else {
+		memset(priv->adapter, priv->osen_ie, 0, sizeof(priv->osen_ie));
+		priv->osen_ie_len = (t_u8)ie_len;
+		PRINTM(MINFO, "Reset osen_ie_len=%d IE=%#x\n",
+		       priv->osen_ie_len, priv->osen_ie[0]);
+		priv->sec_info.osen_enabled = MFALSE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set WAPI IE
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param ie_data_ptr  A pointer to IE
+ *  @param ie_len       Length of the IE
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_set_wapi_ie(mlan_private *priv, t_u8 *ie_data_ptr, t_u16 ie_len)
+{
+	ENTER();
+	if (ie_len) {
+		if (ie_len > sizeof(priv->wapi_ie)) {
+			PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		memcpy_ext(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len,
+			   sizeof(priv->wapi_ie));
+		priv->wapi_ie_len = (t_u8)ie_len;
+		PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len,
+		       priv->wapi_ie[0]);
+		DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie,
+			    priv->wapi_ie_len);
+		if (priv->wapi_ie[0] == WAPI_IE)
+			priv->sec_info.wapi_enabled = MTRUE;
+	} else {
+		memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie));
+		priv->wapi_ie_len = (t_u8)ie_len;
+		PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
+		       priv->wapi_ie_len, priv->wapi_ie[0]);
+		priv->sec_info.wapi_enabled = MFALSE;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get WAPI status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_wapi_enable(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		if (pmpriv->wapi_ie_len)
+			sec->param.wapi_enabled = MTRUE;
+		else
+			sec->param.wapi_enabled = MFALSE;
+	} else {
+		if (sec->param.wapi_enabled == MFALSE)
+			wlan_set_wapi_ie(pmpriv, MNULL, 0);
+	}
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set WAPI key
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_set_wapi_key(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+			       HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+			       (t_void *)pioctl_req, &sec->param.encrypt_key);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Port Control status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_port_ctrl_enable(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_sec_cfg *sec = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		if (pmpriv->port_ctrl_mode)
+			sec->param.port_ctrl_enabled = MTRUE;
+		else
+			sec->param.port_ctrl_enabled = MFALSE;
+	} else {
+		if (sec->param.port_ctrl_enabled) {
+			pmpriv->port_ctrl_mode = MTRUE;
+			pmpriv->port_open = MFALSE;
+		} else {
+			if (pmpriv->port_ctrl_mode == MTRUE) {
+				pmpriv->port_ctrl_mode = MFALSE;
+				/* Cleanup the bypass TX queue */
+				wlan_cleanup_bypass_txq(pmpriv);
+			}
+		}
+	}
+	PRINTM(MINFO, "port_ctrl: port_ctrl_mode=%d port_open=%d\n",
+	       pmpriv->port_ctrl_mode, pmpriv->port_open);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get authentication mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_auth_mode(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		sec->param.auth_mode = pmpriv->sec_info.authentication_mode;
+	else
+		pmpriv->sec_info.authentication_mode = sec->param.auth_mode;
+
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get encryption mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_encrypt_mode(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
+	else
+		pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
+
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Random charactor
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *
+ *  @return		random charactor
+ */
+static t_u8
+wlan_get_random_charactor(pmlan_adapter pmadapter)
+{
+	t_u32 sec, usec;
+	t_u8 ch = 0;
+
+	ENTER();
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+						  &usec);
+	sec = (sec & 0xFFFF) + (sec >> 16);
+	usec = (usec & 0xFFFF) + (usec >> 16);
+	ch = (((sec << 16) + usec) % 26) + 'a';
+	LEAVE();
+	return ch;
+}
+
+/**
+ *  @brief Set/Get WPA status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_wpa_enable(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		if (pmpriv->wpa_ie_len)
+			sec->param.wpa_enabled = MTRUE;
+		else
+			sec->param.wpa_enabled = MFALSE;
+	} else {
+		if (sec->param.wpa_enabled == MFALSE)
+			wlan_set_wpa_ie_helper(pmpriv, MNULL, 0);
+	}
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set WEP keys
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	mrvl_wep_key_t *pwep_key = MNULL;
+	int index;
+	int i = 0;
+
+	ENTER();
+
+	if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
+		pmpriv->wep_key_curr_index = 0;
+	pwep_key = &pmpriv->wep_key[pmpriv->wep_key_curr_index];
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
+		index = pmpriv->wep_key_curr_index;
+		sec->param.encrypt_key.key_index = index;
+	} else {
+		if (sec->param.encrypt_key.key_index >= MRVL_NUM_WEP_KEY) {
+			if ((sec->param.encrypt_key.key_remove == MTRUE)&&
+			    (sec->param.encrypt_key.key_index <= 5)) {
+				/* call firmware remove key */
+				ret = wlan_prepare_cmd(pmpriv,
+						       HostCmd_CMD_802_11_KEY_MATERIAL,
+						       HostCmd_ACT_GEN_SET, 0,
+						       (t_void *)pioctl_req,
+						       &sec->param.encrypt_key);
+				if (ret == MLAN_STATUS_SUCCESS)
+					ret = MLAN_STATUS_PENDING;
+				goto exit;
+			}
+			PRINTM(MERROR, "Key_index is invalid\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		index = sec->param.encrypt_key.key_index;
+	}
+
+	if ((sec->param.encrypt_key.key_disable == MTRUE)||
+	    (sec->param.encrypt_key.key_remove == MTRUE)) {
+		pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
+		/* remove key */
+		if (sec->param.encrypt_key.key_remove == MTRUE) {
+			memset(pmadapter, &pmpriv->wep_key[index], 0,
+			       sizeof(mrvl_wep_key_t));
+			/* call firmware remove key */
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_KEY_MATERIAL,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       &sec->param.encrypt_key);
+			if (ret)
+				goto exit;
+		}
+	} else {
+		if (sec->param.encrypt_key.key_len) {
+			if ((sec->param.encrypt_key.key_len !=
+			     WEP_104_BIT_LEN)&&
+			    (sec->param.encrypt_key.key_len !=
+			     WEP_40_BIT_LEN)) {
+				PRINTM(MERROR, "Invalid wep key len=%d\n",
+				       sec->param.encrypt_key.key_len);
+				/* We will use random key to clear the key
+				 * buffer in FW */
+				if (sec->param.encrypt_key.key_len <
+				    WEP_40_BIT_LEN)
+					sec->param.encrypt_key.key_len =
+						WEP_40_BIT_LEN;
+				else
+					sec->param.encrypt_key.key_len =
+						WEP_104_BIT_LEN;
+				for (i = 0;
+				     i < (int)sec->param.encrypt_key.key_len;
+				     i++)
+					sec->param.encrypt_key.key_material[i] =
+						wlan_get_random_charactor
+						(pmadapter);
+			}
+			pwep_key = &pmpriv->wep_key[index];
+			/* Cleanup */
+			memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
+			/* Copy the key in the driver */
+
+			memcpy_ext(pmadapter, pwep_key->key_material,
+				   sec->param.encrypt_key.key_material,
+				   sec->param.encrypt_key.key_len,
+				   MRVL_KEY_BUFFER_SIZE_IN_BYTE);
+			pwep_key->key_index = index;
+			pwep_key->key_length = sec->param.encrypt_key.key_len;
+			if (pmpriv->sec_info.wep_status != Wlan802_11WEPEnabled) {
+				/*
+				 * The status is set as Key Absent
+				 * so as to make sure we display the
+				 * keys when iwlist mlanX key is used
+				 */
+				pmpriv->sec_info.wep_status =
+					Wlan802_11WEPKeyAbsent;
+			}
+		}
+		if (sec->param.encrypt_key.is_current_wep_key == MTRUE) {
+			/* Copy the required key as the current key */
+			pwep_key = &pmpriv->wep_key[index];
+			if (!pwep_key->key_length) {
+				if (pmpriv->sec_info.wpa_enabled ||
+				    pmpriv->sec_info.wpa2_enabled
+				    || pmpriv->sec_info.wapi_enabled) {
+					ret = MLAN_STATUS_SUCCESS;
+					goto exit;
+				}
+				PRINTM(MERROR,
+				       "Key %d not set,so cannot enable it\n",
+				       index);
+				pioctl_req->status_code =
+					MLAN_ERROR_CMD_RESP_FAIL;
+				ret = MLAN_STATUS_FAILURE;
+				goto exit;
+			}
+			pmpriv->wep_key_curr_index = (t_u16)index;
+			pmpriv->sec_info.wep_status = Wlan802_11WEPEnabled;
+		}
+		if (sec->param.encrypt_key.key_flags && pwep_key->key_length) {
+			pmpriv->wep_key_curr_index = (t_u16)index;
+			// Only do this if the key is an xmit key.  If the key
+			// is a group key, we might be in wpa/wep mixed mode in
+			// which case we don't want to set wep_status =
+			// Wlan802_11WEPEnabled because that enables WEP at the
+			// MAC controller level and WPA stops working properly.
+			if (sec->param.encrypt_key.key_flags &
+			    KEY_FLAG_SET_TX_KEY) {
+				pmpriv->sec_info.wep_status =
+					Wlan802_11WEPEnabled;
+			}
+		}
+	}
+	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
+		pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
+	else
+		pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+	/* Send request to firmware */
+	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled &&
+	    pwep_key->key_length) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+				       HostCmd_ACT_GEN_SET, 0, MNULL,
+				       &pmpriv->curr_pkt_filter);
+		if (ret)
+			goto exit;
+		if (!sec->param.encrypt_key.key_len) {
+			sec->param.encrypt_key.key_index = pwep_key->key_index;
+			sec->param.encrypt_key.key_len = pwep_key->key_length;
+			memcpy_ext(pmadapter,
+				   sec->param.encrypt_key.key_material,
+				   pwep_key->key_material,
+				   sec->param.encrypt_key.key_len,
+				   MLAN_MAX_KEY_LENGTH);
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req,
+				       &sec->param.encrypt_key);
+	} else {
+		if (pwep_key->key_length) {
+			if (!sec->param.encrypt_key.key_len) {
+				sec->param.encrypt_key.key_index =
+					pwep_key->key_index;
+				sec->param.encrypt_key.key_len =
+					pwep_key->key_length;
+				memcpy_ext(pmadapter,
+					   sec->param.encrypt_key.key_material,
+					   pwep_key->key_material,
+					   sec->param.encrypt_key.key_len,
+					   MLAN_MAX_KEY_LENGTH);
+			}
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_802_11_KEY_MATERIAL,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       &sec->param.encrypt_key);
+			if (ret)
+				goto exit;
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req,
+				       &pmpriv->curr_pkt_filter);
+	}
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set WPA key
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	/* Current driver only supports key length of up to 32 bytes */
+	if (sec->param.encrypt_key.key_len > MLAN_MAX_KEY_LENGTH) {
+		PRINTM(MERROR, "Key length is incorrect\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       &sec->param.encrypt_key);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get security keys
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_get_key(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	int index;
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+
+	if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
+		pmpriv->wep_key_curr_index = 0;
+
+	if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
+	    (pmpriv->sec_info.wep_status == Wlan802_11WEPKeyAbsent)
+	    || pmpriv->sec_info.ewpa_enabled
+	    || pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled) {
+		sec->param.encrypt_key.key_disable = MFALSE;
+	} else {
+		sec->param.encrypt_key.key_disable = MTRUE;
+	}
+	if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
+		if ((pmpriv->wep_key[pmpriv->wep_key_curr_index].key_length)&&
+		    (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)) {
+			index = pmpriv->wep_key_curr_index;
+			sec->param.encrypt_key.key_index =
+				pmpriv->wep_key[index].key_index;
+			memcpy_ext(pmadapter,
+				   sec->param.encrypt_key.key_material,
+				   pmpriv->wep_key[index].key_material,
+				   pmpriv->wep_key[index].key_length,
+				   MLAN_MAX_KEY_LENGTH);
+			sec->param.encrypt_key.key_len =
+				MIN(MLAN_MAX_KEY_LENGTH,
+				    pmpriv->wep_key[index].key_length);
+		} else if ((pmpriv->sec_info.wpa_enabled)
+			   || (pmpriv->sec_info.ewpa_enabled)
+			   || (pmpriv->sec_info.wpa2_enabled)
+			   || (pmpriv->sec_info.wapi_enabled)
+			) {
+			/* Return WPA enabled */
+			sec->param.encrypt_key.key_disable = MFALSE;
+			memcpy_ext(pmadapter,
+				   sec->param.encrypt_key.key_material,
+				   pmpriv->aes_key.key_material,
+				   pmpriv->aes_key.key_len,
+				   MLAN_MAX_KEY_LENGTH);
+			sec->param.encrypt_key.key_len =
+				MIN(MLAN_MAX_KEY_LENGTH,
+				    pmpriv->aes_key.key_len);
+		} else {
+			sec->param.encrypt_key.key_disable = MTRUE;
+		}
+	} else {
+		index = sec->param.encrypt_key.key_index;
+		if (pmpriv->wep_key[index].key_length) {
+			sec->param.encrypt_key.key_index =
+				pmpriv->wep_key[index].key_index;
+			memcpy_ext(pmadapter,
+				   sec->param.encrypt_key.key_material,
+				   pmpriv->wep_key[index].key_material,
+				   pmpriv->wep_key[index].key_length,
+				   MLAN_MAX_KEY_LENGTH);
+			sec->param.encrypt_key.key_len =
+				MIN(MLAN_MAX_KEY_LENGTH,
+				    pmpriv->wep_key[index].key_length);
+		} else if ((pmpriv->sec_info.wpa_enabled)
+			   || (pmpriv->sec_info.ewpa_enabled)
+			   || (pmpriv->sec_info.wpa2_enabled)
+			   || (pmpriv->sec_info.wapi_enabled)
+			) {
+			/* Return WPA enabled */
+			sec->param.encrypt_key.key_disable = MFALSE;
+		} else {
+			sec->param.encrypt_key.key_disable = MTRUE;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set security key(s)
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_encrypt_key(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (sec->param.encrypt_key.is_wapi_key)
+			status = wlan_sec_ioctl_set_wapi_key(pmadapter,
+							     pioctl_req);
+		else if (sec->param.encrypt_key.key_len > MAX_WEP_KEY_SIZE)
+			status = wlan_sec_ioctl_set_wpa_key(pmadapter,
+							    pioctl_req);
+		else
+			status = wlan_sec_ioctl_set_wep_key(pmadapter,
+							    pioctl_req);
+	} else {
+		status = wlan_sec_ioctl_get_key(pmadapter, pioctl_req);
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Query Encrpyt key
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_query_key(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	/* Current driver only supports get PTK/GTK */
+	if (pmpriv->port_open &&
+	    (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled
+	     || pmpriv->sec_info.wapi_enabled)) {
+		/* Send request to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+				       HostCmd_ACT_GEN_GET, KEY_INFO_ENABLED,
+				       (t_void *)pioctl_req,
+				       &sec->param.encrypt_key);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get esupplicant status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_sec_ioctl_ewpa_enable(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		sec->param.ewpa_enabled = pmpriv->sec_info.ewpa_enabled;
+	} else {
+		pmpriv->sec_info.ewpa_enabled = (t_u8)sec->param.ewpa_enabled;
+		PRINTM(MINFO, "Set: ewpa_enabled = %d\n",
+		       (int)pmpriv->sec_info.ewpa_enabled);
+	}
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get esupplicant mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_sec_ioctl_esupp_mode(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u16 cmd_action = 0;
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		cmd_action = HostCmd_ACT_GEN_SET;
+		if (pmpriv->media_connected == MTRUE) {
+			PRINTM(MERROR,
+			       "Cannot set esupplicant mode configuration while connected.\n");
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		if (!sec->param.esupp_mode.rsn_mode ||
+		    (sec->param.esupp_mode.rsn_mode & RSN_TYPE_VALID_BITS) !=
+		    sec->param.esupp_mode.rsn_mode) {
+			PRINTM(MERROR, "Invalid RSN mode\n");
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		if (!sec->param.esupp_mode.act_paircipher ||
+		    (sec->param.esupp_mode.act_paircipher &
+		     EMBED_CIPHER_VALID_BITS) !=
+		    sec->param.esupp_mode.act_paircipher) {
+			PRINTM(MERROR, "Invalid pairwise cipher\n");
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+		if (!sec->param.esupp_mode.act_groupcipher ||
+		    (sec->param.esupp_mode.act_groupcipher &
+		     EMBED_CIPHER_VALID_BITS) !=
+		    sec->param.esupp_mode.act_groupcipher) {
+			PRINTM(MERROR, "Invalid group cipher\n");
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET_CURRENT;
+	}
+
+	/* Send request to firmware */
+	if (sec) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &sec->param.esupp_mode);
+	} else {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       MNULL);
+	}
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Security configuration handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_sec_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_sec_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_sec_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	switch (sec->sub_command) {
+	case MLAN_OID_SEC_CFG_AUTH_MODE:
+		status = wlan_sec_ioctl_auth_mode(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_ENCRYPT_MODE:
+		status = wlan_sec_ioctl_encrypt_mode(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_WPA_ENABLED:
+		status = wlan_sec_ioctl_wpa_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_WAPI_ENABLED:
+		status = wlan_sec_ioctl_wapi_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED:
+		status = wlan_sec_ioctl_port_ctrl_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_ENCRYPT_KEY:
+		status = wlan_sec_ioctl_encrypt_key(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_QUERY_KEY:
+		status = wlan_sec_ioctl_query_key(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_PASSPHRASE:
+		status = wlan_sec_ioctl_passphrase(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_EWPA_ENABLED:
+		status = wlan_sec_ioctl_ewpa_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_SEC_CFG_ESUPP_MODE:
+		status = wlan_sec_ioctl_esupp_mode(pmadapter, pioctl_req);
+		break;
+
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief  Append/Reset IE buffer.
+ *
+ *  Pass an opaque block of data, expected to be IEEE IEs, to the driver
+ *    for eventual passthrough to the firmware in an associate/join
+ *    (and potentially start) command.  This function is the main body
+ *    for both wlan_set_gen_ie_ioctl and wlan_set_gen_ie
+ *
+ *  Data is appended to an existing buffer and then wrapped in a passthrough
+ *    TLV in the command API to the firmware.  The firmware treats the data
+ *    as a transparent passthrough to the transmitted management frame.
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param ie_data_ptr  A pointer to iwreq structure
+ *  @param ie_len       Length of the IE or IE block passed in ie_data_ptr
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+wlan_set_gen_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr, t_u16 ie_len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	IEEEtypes_VendorHeader_t *pvendor_ie;
+	const t_u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 };
+	const t_u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
+	const t_u8 osen_oui[] = { 0x50, 0x6f, 0x9a, 0x12 };
+	t_u8 i = 0, temp[12] = { 0 };
+
+	ENTER();
+
+	/* If the passed length is zero, reset the buffer */
+	if (!ie_len) {
+		priv->gen_ie_buf_len = 0;
+		priv->wps.session_enable = MFALSE;
+		wlan_set_wpa_ie_helper(priv, MNULL, 0);
+		wlan_set_wapi_ie(priv, MNULL, 0);
+		wlan_set_osen_ie(priv, MNULL, 0);
+	} else if (!ie_data_ptr) {
+		/* MNULL check */
+		ret = MLAN_STATUS_FAILURE;
+	} else {
+		pvendor_ie = (IEEEtypes_VendorHeader_t *)ie_data_ptr;
+		if (pvendor_ie->element_id == EXT_CAPABILITY) {
+			memcpy_ext(priv->adapter, temp, &priv->ext_cap,
+				   sizeof(priv->ext_cap), sizeof(temp));
+			for (i = 0;
+			     i < MIN(sizeof(priv->ext_cap), pvendor_ie->len);
+			     i++)
+				temp[i] |= ie_data_ptr[2 + i];
+			memcpy_ext(priv->adapter, &priv->ext_cap, temp,
+				   sizeof(temp), sizeof(priv->ext_cap));
+		} else
+			/* Test to see if it is a WPA IE, if not, then it is a
+			   gen IE */
+		if (((pvendor_ie->element_id == WPA_IE) &&
+			     (!memcmp
+				      (priv->adapter, pvendor_ie->oui,
+					       wpa_oui,
+					       sizeof(wpa_oui)))) ||
+			    (pvendor_ie->element_id == RSN_IE)) {
+			/* IE is a WPA/WPA2 IE so call set_wpa function */
+			ret = wlan_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
+			priv->wps.session_enable = MFALSE;
+		} else if (pvendor_ie->element_id == WAPI_IE) {
+			/* IE is a WAPI IE so call set_wapi function */
+			ret = wlan_set_wapi_ie(priv, ie_data_ptr, ie_len);
+		} else if ((pvendor_ie->element_id == VENDOR_SPECIFIC_221) &&
+			   (!memcmp(priv->adapter, pvendor_ie->oui, osen_oui,
+				    sizeof(osen_oui)))) {
+			/* IE is a OSEN IE so call set_osen function */
+			ret = wlan_set_osen_ie(priv, ie_data_ptr, ie_len);
+
+		} else if ((pvendor_ie->element_id == WPS_IE) &&
+			   (priv->wps.session_enable == MFALSE) &&
+			   (!memcmp(priv->adapter, pvendor_ie->oui, wps_oui,
+				    sizeof(wps_oui)))) {
+			/*
+			 * Discard first two byte (Element ID and Length)
+			 * because they are not needed in the case of setting
+			 * WPS_IE
+			 */
+			if (pvendor_ie->len > 4) {
+				memcpy_ext(priv->adapter,
+					   (t_u8 *)&priv->wps.wps_ie,
+					   ie_data_ptr, ie_len,
+					   sizeof(IEEEtypes_VendorSpecific_t));
+				HEXDUMP("wps_ie", (t_u8 *)&priv->wps.wps_ie,
+					priv->wps.wps_ie.vend_hdr.len + 2);
+			} else {
+				/* Only wps oui exist, reset driver wps buffer
+				 */
+				memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
+				       0x00, sizeof(priv->wps.wps_ie));
+				PRINTM(MINFO, "wps_ie cleared\n");
+			}
+		} else {
+			/*
+			 * Verify that the passed length is not larger than
+			 * the available space remaining in the buffer
+			 */
+			if (ie_len <
+			    (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
+				/* Test to see if it is a WPS IE, if so, enable
+				 * wps session flag */
+				pvendor_ie =
+					(IEEEtypes_VendorHeader_t *)ie_data_ptr;
+				if ((pvendor_ie->element_id == WPS_IE) &&
+				    (!memcmp(priv->adapter, pvendor_ie->oui,
+					     wps_oui, sizeof(wps_oui)))) {
+					priv->wps.session_enable = MTRUE;
+					PRINTM(MINFO, "WPS Session Enabled.\n");
+				}
+
+				/* Append the passed data to the end of
+				 * the genIeBuffer */
+				memcpy_ext(priv->adapter,
+					   priv->gen_ie_buf +
+					   priv->gen_ie_buf_len,
+					   ie_data_ptr, ie_len,
+					   MRVDRV_GENIE_BUF_SIZE -
+					   priv->gen_ie_buf_len);
+				/* Increment the stored buffer length by
+				 * the size passed */
+				priv->gen_ie_buf_len += ie_len;
+			} else {
+				/* Passed data does not fit in the
+				 * remaining buffer space */
+				ret = MLAN_STATUS_FAILURE;
+			}
+		}
+	}
+
+	/* Return MLAN_STATUS_SUCCESS, or MLAN_STATUS_FAILURE for error case */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get WWS mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_wws_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	t_u32 enable = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	enable = misc_cfg->param.wws_cfg;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+			       WwsMode_i, (t_void *)pioctl_req, &enable);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11D status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_11d_cfg_ioctl_enable(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11d_cfg *pcfg_11d = MNULL;
+
+	ENTER();
+
+	pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmpriv->media_connected == MTRUE) {
+			PRINTM(MIOCTL,
+			       "11D setting cannot be changed while interface is active.\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		PRINTM(MINFO, "11D: 11dcfg SET=%d\n",
+		       pcfg_11d->param.enable_11d);
+
+		/* Compare with current settings */
+		if (pmpriv->state_11d.user_enable_11d !=
+		    pcfg_11d->param.enable_11d) {
+			ret = wlan_11d_enable(pmpriv, pioctl_req,
+					      (state_11d_t)pcfg_11d->param.
+					      enable_11d);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+		} else {
+			PRINTM(MINFO,
+			       "11D: same as current setting, do nothing\n");
+		}
+	} else {
+		pcfg_11d->param.enable_11d =
+			(t_u32)pmpriv->state_11d.user_enable_11d;
+		pioctl_req->data_read_written =
+			sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+		PRINTM(MINFO, "11D: 11dcfg GET=%d\n",
+		       pcfg_11d->param.enable_11d);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Clear 11D chan table
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_11d_clr_chan_table(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MINFO, "11D: 11dclrtbl SET\n");
+
+		if (wlan_11d_clear_parsedtable(pmpriv) == MLAN_STATUS_SUCCESS)
+			PRINTM(MINFO,
+			       "11D: cleared parsed_region_chan (now no_of_chan=%d)\n",
+			       pmadapter->parsed_region_chan.no_of_chan);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 11D configuration handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_11d_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11d_cfg *pcfg_11d = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		status = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+	switch (pcfg_11d->sub_command) {
+	case MLAN_OID_11D_CFG_ENABLE:
+		status = wlan_11d_cfg_ioctl_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11D_CLR_CHAN_TABLE:
+		status = wlan_11d_clr_chan_table(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11D_DOMAIN_INFO_EXT:
+		status = wlan_11d_cfg_domain_info(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+exit:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief WPS configuration handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_wps_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wps_cfg *pwps = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_wps_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_wps_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	pwps = (mlan_ds_wps_cfg *)pioctl_req->pbuf;
+	switch (pwps->sub_command) {
+	case MLAN_OID_WPS_CFG_SESSION:
+		if (pioctl_req->action == MLAN_ACT_SET) {
+			if (pwps->param.wps_session ==
+			    MLAN_WPS_CFG_SESSION_START)
+				pmpriv->wps.session_enable = MTRUE;
+			else
+				pmpriv->wps.session_enable = MFALSE;
+		} else {
+			pwps->param.wps_session =
+				(t_u32)pmpriv->wps.session_enable;
+			pioctl_req->data_read_written = sizeof(t_u32);
+			PRINTM(MINFO, "wpscfg GET=%d\n",
+			       pwps->param.wps_session);
+		}
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief register memory access handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_reg_mem_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_reg_mem *reg_mem = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_reg_mem)) {
+		PRINTM(MWARN, "MLAN REG_MEM IOCTL length is too short\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_reg_mem);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+	switch (reg_mem->sub_command) {
+	case MLAN_OID_REG_RW:
+		status = wlan_reg_mem_ioctl_reg_rw(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_EEPROM_RD:
+		status = wlan_reg_mem_ioctl_read_eeprom(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MEM_RW:
+		status = wlan_reg_mem_ioctl_mem_rw(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief 802.11h ad-hoc start channel check
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_11h_channel_check_req(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 chan_width = CHAN_BW_20MHZ;
+	Band_Config_t bandcfg;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(pmadapter, &bandcfg, 0, sizeof(Band_Config_t));
+	pmpriv->adhoc_state = ADHOC_STARTING;
+
+	if ((pmadapter->adhoc_start_band & BAND_A)
+		) {
+		if (pmpriv->intf_state_11h.adhoc_auto_sel_chan)
+			pmpriv->adhoc_channel =
+				wlan_11h_get_adhoc_start_channel(pmpriv);
+
+		/*
+		 * Check if the region and channel requires a channel
+		 * availability check.
+		 */
+		if (wlan_11h_radar_detect_required(pmpriv,
+						   pmpriv->adhoc_channel)
+		    && !wlan_11h_is_channel_under_nop(pmadapter,
+						      pmpriv->adhoc_channel)
+			) {
+			/*
+			 * Radar detection is required for this channel, make
+			 * sure 11h is activated in the firmware
+			 */
+			ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+			ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+			ret = wlan_11h_check_update_radar_det_state(pmpriv);
+
+			/* Check for radar on the channel */
+			if ((pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_ABOVE) ||
+			    (pmadapter->chan_bandwidth ==
+			     CHANNEL_BW_40MHZ_BELOW)) {
+				chan_width = CHAN_BW_40MHZ;
+				if (pmadapter->chanrpt_param_bandcfg) {
+					bandcfg.chan2Offset =
+						pmadapter->chan_bandwidth;
+				}
+			} else if (pmadapter->chan_bandwidth ==
+				   CHANNEL_BW_80MHZ)
+				chan_width = CHAN_BW_80MHZ;
+			if (pmadapter->chanrpt_param_bandcfg) {
+				bandcfg.chanWidth = chan_width;
+				bandcfg.chanBand = BAND_5GHZ;
+			} else {
+				*((t_u8 *)&bandcfg) = chan_width;
+			}
+
+			ret = wlan_11h_issue_radar_detect(pmpriv, pioctl_req,
+							  pmpriv->adhoc_channel,
+							  bandcfg);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 802.11h set/get local power constraint
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_11h_ioctl_local_power_constraint(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+	t_s8 *plocalpower = &pmadapter->state_11h.usr_def_power_constraint;
+
+	ENTER();
+
+	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		ds_11hcfg->param.usr_local_power_constraint = *plocalpower;
+	else
+		*plocalpower = ds_11hcfg->param.usr_local_power_constraint;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief 11h configuration handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_11h_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) {
+		PRINTM(MWARN, "MLAN 11H IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+
+	switch (ds_11hcfg->sub_command) {
+	case MLAN_OID_11H_CHANNEL_CHECK:
+		status = wlan_11h_channel_check_req(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11H_LOCAL_POWER_CONSTRAINT:
+		status = wlan_11h_ioctl_local_power_constraint(pmadapter,
+							       pioctl_req);
+		break;
+	case MLAN_OID_11H_DFS_TESTING:
+		status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_11H_DFS_W53_CFG:
+		status = wlan_11h_ioctl_dfs_w53_cfg(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get generic IE
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	switch (misc->param.gen_ie.type) {
+	case MLAN_IE_TYPE_GEN_IE:
+		if (pioctl_req->action == MLAN_ACT_GET) {
+			misc->param.gen_ie.len = pmpriv->wpa_ie_len;
+			memcpy_ext(pmadapter, misc->param.gen_ie.ie_data,
+				   pmpriv->wpa_ie, misc->param.gen_ie.len,
+				   MAX_IE_SIZE);
+		} else {
+			wlan_set_gen_ie_helper(pmpriv,
+					       misc->param.gen_ie.ie_data,
+					       (t_u16)misc->param.gen_ie.len);
+		}
+		break;
+	case MLAN_IE_TYPE_ARP_FILTER:
+		memset(pmadapter, pmadapter->arp_filter, 0,
+		       sizeof(pmadapter->arp_filter));
+		if (misc->param.gen_ie.len > ARP_FILTER_MAX_BUF_SIZE) {
+			pmadapter->arp_filter_size = 0;
+			PRINTM(MERROR, "Invalid ARP Filter Size\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+		} else if (misc->param.gen_ie.len <=
+			   sizeof(MrvlIEtypesHeader_t)) {
+			pmadapter->arp_filter_size = 0;
+			PRINTM(MINFO, "Clear ARP filter\n");
+		} else {
+			memcpy_ext(pmadapter, pmadapter->arp_filter,
+				   misc->param.gen_ie.ie_data,
+				   misc->param.gen_ie.len,
+				   ARP_FILTER_MAX_BUF_SIZE);
+			pmadapter->arp_filter_size = misc->param.gen_ie.len;
+			HEXDUMP("ArpFilter", pmadapter->arp_filter,
+				pmadapter->arp_filter_size);
+		}
+		break;
+	default:
+		PRINTM(MERROR, "Invalid IE type\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+	}
+	pioctl_req->data_read_written =
+		sizeof(mlan_ds_misc_gen_ie) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Perform warm reset
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pmlan_buffer pmbuf;
+	t_s32 i = 0;
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+	mlan_block_rx_process(pmadapter, MTRUE);
+
+	/* Cancel all pending commands and complete ioctls */
+	if (misc->param.fw_reload)
+		wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
+
+	/** Init all the head nodes and free all the locks here */
+	for (i = 0; i < pmadapter->priv_num; i++)
+		wlan_free_priv(pmadapter->priv[i]);
+
+	while ((pmbuf =
+		(pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+						&pmadapter->rx_data_queue,
+						pcb->moal_spin_lock,
+						pcb->moal_spin_unlock))) {
+		pmadapter->ops.data_complete(pmadapter, pmbuf,
+					     MLAN_STATUS_FAILURE);
+	}
+	pmadapter->rx_pkts_queued = 0;
+
+	/* Initialize adapter structure */
+	wlan_init_adapter(pmadapter);
+	pmadapter->hw_status = WlanHardwareStatusInitializing;
+
+	/* Initialize private structures */
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		if (pmadapter->priv[i])
+			wlan_init_priv(pmadapter->priv[i]);
+	}
+	mlan_block_rx_process(pmadapter, MFALSE);
+
+	if (misc->param.fw_reload != MTRUE) {
+		/* Restart the firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FUNC_SHUTDOWN,
+				       HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
+		if (ret)
+			goto done;
+	}
+
+	/* Issue firmware initialize commands for first BSS,
+	 * for other interfaces it will be called after getting
+	 * the last init command response of previous interface
+	 */
+	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!pmpriv) {
+		ret = MLAN_STATUS_FAILURE;
+		LEAVE();
+		return ret;
+	}
+	ret = wlan_adapter_get_hw_spec(pmpriv->adapter);
+	if (ret == MLAN_STATUS_FAILURE) {
+		LEAVE();
+		return ret;
+	}
+	ret = pmpriv->ops.init_cmd(pmpriv, MTRUE);
+	if (ret == MLAN_STATUS_FAILURE) {
+		LEAVE();
+		return ret;
+	}
+	if (ret == MLAN_STATUS_PENDING)
+		pmadapter->pwarm_reset_ioctl_req = pioctl_req;
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO
+/**
+ *  @brief Reconfigure SDIO multiport aggregation parameters
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_sdio_mpa_ctrl(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_ds_misc_sdio_mpa_ctrl *mpa_ctrl = MNULL;
+
+	ENTER();
+
+	mpa_ctrl = &misc->param.mpa_ctrl;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmpriv->media_connected == MTRUE) {
+			PRINTM(MMSG,
+			       "SDIO MPA CTRL: not allowed in connected state\n");
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+
+		if (mpa_ctrl->tx_enable > 1) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+
+		if (mpa_ctrl->rx_enable > 1) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+
+		if (mpa_ctrl->tx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+
+		if (mpa_ctrl->rx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto exit;
+		}
+
+		if (mpa_ctrl->tx_buf_size || mpa_ctrl->rx_buf_size) {
+			wlan_free_sdio_mpa_buffers(pmadapter);
+
+			if (mpa_ctrl->tx_buf_size > 0)
+				pmadapter->pcard_sd->mpa_tx.buf_size =
+					mpa_ctrl->tx_buf_size;
+
+			if (mpa_ctrl->rx_buf_size > 0)
+				pmadapter->pcard_sd->mpa_rx.buf_size =
+					mpa_ctrl->rx_buf_size;
+
+			if (wlan_alloc_sdio_mpa_buffers(pmadapter,
+							pmadapter->pcard_sd->
+							mpa_tx.buf_size,
+							pmadapter->pcard_sd->
+							mpa_rx.buf_size) !=
+			    MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "Failed to allocate sdio mp-a buffers\n");
+				pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+				ret = MLAN_STATUS_FAILURE;
+				goto exit;
+			}
+		}
+
+		if (mpa_ctrl->tx_max_ports > 0)
+			pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+				mpa_ctrl->tx_max_ports;
+		if (mpa_ctrl->rx_max_ports > 0)
+			pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit =
+				mpa_ctrl->rx_max_ports;
+
+		pmadapter->pcard_sd->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
+		pmadapter->pcard_sd->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
+
+	} else {
+		mpa_ctrl->tx_enable =
+			(t_u16)pmadapter->pcard_sd->mpa_tx.enabled;
+		mpa_ctrl->rx_enable =
+			(t_u16)pmadapter->pcard_sd->mpa_rx.enabled;
+		mpa_ctrl->tx_buf_size =
+			(t_u16)pmadapter->pcard_sd->mpa_tx.buf_size;
+		mpa_ctrl->rx_buf_size =
+			(t_u16)pmadapter->pcard_sd->mpa_rx.buf_size;
+		mpa_ctrl->tx_max_ports =
+			(t_u16)pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit;
+		mpa_ctrl->rx_max_ports =
+			(t_u16)pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit;
+	}
+
+exit:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/Get system clock configuration
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_sysclock(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else
+		cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       (t_void *)&misc->param.sys_clock);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the associate response
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_misc_ioctl_get_assoc_rsp(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_rsp_size) {
+		memcpy_ext(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
+			   pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
+			   ASSOC_RSP_BUF_SIZE);
+		misc->param.assoc_resp.assoc_resp_len =
+			MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_rsp_size);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Send function softreset command to firmware
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_soft_reset(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the thermal reading
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_thermal(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+			       Thermal_i, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set subscribe event
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc->param.subscribe_event);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set ARP filter based on IP address
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *  @param ipv4_addr    ipv4 Address
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_ipaddr_arp_filter(pmlan_adapter pmadapter,
+		       pmlan_ioctl_req pioctl_req, t_u32 ipv4_addr)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *buf;
+	arpfilter_header *arpfilter = MNULL;
+	filter_entry *entry = MNULL;
+	t_u32 len;
+
+	ENTER();
+
+	pcb->moal_malloc(pmadapter->pmoal_handle, MRVDRV_SIZE_OF_CMD_BUFFER,
+			 MLAN_MEM_DEF, &buf);
+	if (!buf) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Construct the ARP filter TLV */
+	arpfilter = (arpfilter_header *)buf;
+	arpfilter->type = wlan_cpu_to_le16(TLV_TYPE_ARP_FILTER);
+
+	if (ipv4_addr) {
+		arpfilter->len = wlan_cpu_to_le16(sizeof(filter_entry) * 3);
+		entry = (filter_entry *)(buf + sizeof(arpfilter_header));
+		entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_BROADCAST);
+		entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ARP);
+		entry->ipv4_addr = wlan_cpu_to_le32(ipv4_addr);
+		entry++;
+		entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_UNICAST);
+		entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY);
+		entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY);
+		entry++;
+		entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_MULTICAST);
+		entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY);
+		entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY);
+	} else
+		arpfilter->len = 0;
+
+	/* Update the total length */
+	len = sizeof(arpfilter_header) + wlan_le16_to_cpu(arpfilter->len);
+
+	memset(pmadapter, pmadapter->arp_filter, 0,
+	       sizeof(pmadapter->arp_filter));
+	if (len > ARP_FILTER_MAX_BUF_SIZE) {
+		pmadapter->arp_filter_size = 0;
+		PRINTM(MERROR, "Invalid ARP Filter Size\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+	} else if (len <= sizeof(MrvlIEtypesHeader_t)) {
+		pmadapter->arp_filter_size = 0;
+		PRINTM(MINFO, "Clear ARP filter\n");
+	} else {
+		memcpy_ext(pmadapter, pmadapter->arp_filter, buf, len,
+			   ARP_FILTER_MAX_BUF_SIZE);
+		pmadapter->arp_filter_size = len;
+		HEXDUMP("ArpFilter", pmadapter->arp_filter,
+			pmadapter->arp_filter_size);
+	}
+
+done:
+	if (buf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief MEF configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_mef_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_mef_cfg *mef_cfg =
+		&((mlan_ds_misc_cfg *)pioctl_req->pbuf)->param.mef_cfg;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	HostCmd_DS_GEN *hostcmd_hdr;
+	HostCmd_DS_MEF_CFG *mefcmd;
+	mlan_ds_misc_cmd *hostcmd = MNULL;
+	t_u32 buf_len = 0;
+	t_u8 *buf, *filter;
+	t_u8 fltr_buf[] = { 0x02, 0x00, 0x2f, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x01, 0x00, 0x5e, 0x03, 0x02, 0x00, 0x00,
+		0x00, 0x00, 0x01, 0x41, 0x06, 0x00, 0x00, 0x00,
+		0x01, 0xff, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x41, 0x45, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0x33, 0x33, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x41, 0x45
+	};
+
+	ENTER();
+
+	/* GET operation */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		/* TODO: need to store for get operation */
+		goto done;
+	}
+
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
+			       (t_u8 **)&hostcmd);
+
+	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
+		PRINTM(MERROR, "Failed to allocate hostcmd  buffer\n");
+		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
+	buf = hostcmd->cmd;
+
+	/* Prepare hostcmd buffer */
+	hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
+	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
+	mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
+	buf_len = S_DS_GEN;
+
+	switch (mef_cfg->sub_id) {
+	case MEF_CFG_DISABLE:
+		PRINTM(MINFO, "Disable MEF\n");
+		mefcmd->criteria = wlan_cpu_to_le32(0);
+		mefcmd->nentries = wlan_cpu_to_le16(0);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+		break;
+	case MEF_CFG_RX_FILTER_ENABLE:
+		PRINTM(MINFO, "Enable Rx filter\n");
+		mefcmd->criteria = wlan_cpu_to_le32((MBIT(3) | MBIT(0)));
+		mefcmd->nentries = wlan_cpu_to_le16(1);
+		buf_len += sizeof(HostCmd_DS_MEF_CFG);
+		filter = buf + buf_len;
+		memcpy_ext(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf),
+			   MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
+		buf_len += sizeof(fltr_buf);
+		break;
+	case MEF_CFG_AUTO_ARP_RESP:
+		PRINTM(MINFO, "Enable auto ARP response\n");
+		/* TODO */
+		break;
+	case MEF_CFG_HOSTCMD:
+		PRINTM(MINFO, "MEF hostcmd from MOAL\n");
+		filter = buf + buf_len;
+		memcpy_ext(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
+			   mef_cfg->param.cmd_buf.len,
+			   MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
+		buf_len += mef_cfg->param.cmd_buf.len;
+		break;
+	default:
+		PRINTM(MERROR, "Invalid sub ID parameter\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+		break;
+	}
+	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
+	hostcmd->len = buf_len;
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
+			       (t_void *)hostcmd);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	if (hostcmd)
+		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief ipaddr configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 ipv4_addr[MAX_IPADDR] = { 0 };
+	int i = 0;
+
+	ENTER();
+
+	/* GET operation */
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		memcpy_ext(pmadapter, misc->param.ipaddr_cfg.ip_addr,
+			   pmpriv->ip_addr, IPADDR_LEN, IPADDR_LEN);
+		misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
+		goto done;
+	}
+	/* only one IP is supported in current firmware */
+	for (i = 0; i < (int)misc->param.ipaddr_cfg.ip_addr_num; i++) {
+		memcpy_ext(pmadapter, &ipv4_addr[i],
+			   misc->param.ipaddr_cfg.ip_addr[i], sizeof(t_u32),
+			   sizeof(t_u32));
+	}
+
+	if (misc->param.ipaddr_cfg.op_code != MLAN_IPADDR_OP_IP_REMOVE &&
+	    !misc->param.ipaddr_cfg.ip_addr_num) {
+		PRINTM(MERROR, "Invalid IPv4 address\n");
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_ARP_FILTER)
+		ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req,
+					     ipv4_addr[0]);
+	else if (pmpriv->op_code & MLAN_IPADDR_OP_ARP_FILTER)
+		ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req, 0);
+	if (ret == MLAN_STATUS_FAILURE)
+		goto done;
+
+	/* Save the values in MLAN */
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		pmpriv->op_code = misc->param.ipaddr_cfg.op_code;
+		memcpy_ext(pmadapter, pmpriv->ip_addr,
+			   misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN,
+			   IPADDR_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief CFP code configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_cfp_code_cfg(pmlan_adapter pmadapter,
+			     pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_ds_misc_cfp_code *cfp_code = MNULL;
+	t_u32 region_bg = 0;
+	t_u32 region_a = 0;
+	int i;
+
+	ENTER();
+
+	cfp_code = &misc->param.cfp_code;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+			PRINTM(MERROR,
+			       "ForceRegionRule is set in the on-chip OTP"
+			       "memory\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Save the values in MLAN */
+		if (!cfp_code->cfp_code_bg)
+			cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_bg == region_code_index[i]) {
+				region_bg = cfp_code->cfp_code_bg;
+				break;
+			}
+		}
+		if (!cfp_code->cfp_code_a)
+			cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+			/* Use the region code to search for the index */
+			if (cfp_code->cfp_code_a == region_code_index[i]) {
+				region_a = cfp_code->cfp_code_a;
+				break;
+			}
+		}
+		if (!region_a) {
+			for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
+				/* Use the CFP code to search for the index */
+				if (cfp_code->cfp_code_a == cfp_code_index_a[i])
+					break;
+			}
+			if (i >= MRVDRV_MAX_CFP_CODE_A) {
+				PRINTM(MERROR,
+				       "CFP Code not identified for A\n");
+				pioctl_req->status_code =
+					MLAN_ERROR_INVALID_PARAMETER;
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
+		pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
+		if (region_bg && region_a && (region_bg == region_a))
+			pmadapter->region_code = pmadapter->cfp_code_a;
+		else
+			pmadapter->region_code = 0;
+		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
+					 pmadapter->config_bands |
+					 pmadapter->adhoc_start_band)) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	} else {
+		/* GET operation */
+		cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
+		cfp_code->cfp_code_a = pmadapter->cfp_code_a;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets up country code and downloads CMD to FW
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,
+			     mlan_ioctl_req *pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_country_code *country_code = MNULL;
+	mlan_ds_misc_cfg *cfg_misc = MNULL;
+	t_u8 cfp_bg = 0, cfp_a = 0;
+
+	ENTER();
+
+	cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	country_code = &cfg_misc->param.country_code;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
+			PRINTM(MERROR,
+			       "ForceRegionRule is set in the on-chip OTP"
+			       "memory\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		/* Update region code and table based on country code */
+		if (wlan_misc_country_2_cfp_table_code
+		    (pmadapter, country_code->country_code, &cfp_bg, &cfp_a)) {
+			PRINTM(MERROR, "Country code not found!\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		pmadapter->cfp_code_bg = cfp_bg;
+		pmadapter->cfp_code_a = cfp_a;
+		if (cfp_a)
+			pmadapter->region_code = cfp_a;
+		else if (cfp_bg)
+			pmadapter->region_code = cfp_bg;
+		else
+			pmadapter->region_code = 0;
+		if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
+					 pmadapter->config_bands |
+					 pmadapter->adhoc_start_band)) {
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		memcpy_ext(pmadapter, pmadapter->country_code,
+			   country_code->country_code, COUNTRY_CODE_LEN,
+			   COUNTRY_CODE_LEN);
+	} else {
+		/* GET operation */
+		memcpy_ext(pmadapter, country_code->country_code,
+			   pmadapter->country_code, COUNTRY_CODE_LEN,
+			   COUNTRY_CODE_LEN);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure MFPC and MFPR for management frame protection
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_misc_pmfcfg(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *cfg_misc = MNULL;
+	mlan_ds_misc_pmfcfg *pmfcfg;
+
+	cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	pmfcfg = &cfg_misc->param.pmfcfg;
+
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		pmpriv->pmfcfg.mfpc = pmfcfg->mfpc;
+		pmpriv->pmfcfg.mfpr = pmfcfg->mfpr;
+	} else {
+		/* GET operation */
+		pmfcfg->mfpc = pmpriv->pmfcfg.mfpc;
+		pmfcfg->mfpr = pmpriv->pmfcfg.mfpr;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief HW ARB Cfg
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ARB_CONFIG, cmd_action, 0,
+			       (t_void *)pioctl_req, &(pmisc->param.arb_cfg));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Save tp accounting command configurations.
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+mlan_status
+wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	pmadapter->tp_state_on = pmisc->param.tp_state.on;
+	pmadapter->tp_state_drop_point = pmisc->param.tp_state.drop_point;
+
+	LEAVE();
+	return ret;
+}
+
+static mlan_status
+wlan_misc_ioctl_get_sensor_temp(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, " sensor temp only support get operation \n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_DS_GET_SENSOR_TEMP, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief IPv6 Router Advertisement offload configuration
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_misc_ioctl_ipv6_ra_offload(pmlan_adapter pmadapter,
+				mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_IPV6_RA_OFFLOAD_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc->param.ipv6_ra_offload);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Gtk Rekey Offload
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_CLEAR)
+		cmd_action = HostCmd_ACT_GEN_REMOVE;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	if (!pmpriv->wpa_is_gtk_set) {
+		/* Store the gtk rekey data if it has already set gtk */
+		memcpy_ext(pmadapter, &pmpriv->gtk_rekey,
+			   &misc_cfg->param.gtk_rekey,
+			   sizeof(mlan_ds_misc_gtk_rekey_data),
+			   sizeof(mlan_ds_misc_gtk_rekey_data));
+		LEAVE();
+		return ret;
+	}
+	/* Send request to firmware if it hasn't set gtk yet */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &misc_cfg->param.gtk_rekey);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief cloud keep alive
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   Pointer to the IOCTL request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_misc_cloud_keep_alive(pmlan_adapter pmadapter, mlan_ioctl_req *pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET) {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	} else if (pioctl_req->action == MLAN_ACT_RESET) {
+		cmd_action = HostCmd_ACT_GEN_RESET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_REMOVE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AUTO_TX, cmd_action,
+			       OID_CLOUD_KEEP_ALIVE, (t_void *)pioctl_req,
+			       &misc->param.keep_alive);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Miscellaneous configuration handler
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_misc_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = MNULL;
+
+	ENTER();
+
+	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
+		PRINTM(MERROR, "Request buffer not found!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	switch (misc->sub_command) {
+	case MLAN_OID_MISC_GEN_IE:
+		status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_REGION:
+		status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_WARM_RESET:
+		PRINTM(MCMND, "Request WARM RESET\n");
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &pmadapter->ioctl_pending_q,
+				       (pmlan_linked_list)pioctl_req,
+				       pmadapter->callbacks.moal_spin_lock,
+				       pmadapter->callbacks.moal_spin_unlock);
+		pmadapter->pending_ioctl = MTRUE;
+		status = MLAN_STATUS_PENDING;
+		break;
+#ifdef SDIO
+	case MLAN_OID_MISC_SDIO_MPA_CTRL:
+		status = wlan_misc_ioctl_sdio_mpa_ctrl(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_MISC_HOST_CMD:
+		status = wlan_misc_ioctl_host_cmd(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_SYS_CLOCK:
+		status = wlan_misc_ioctl_sysclock(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_WWS:
+		status = wlan_misc_ioctl_wws_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_ASSOC_RSP:
+		status = wlan_misc_ioctl_get_assoc_rsp(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_INIT_SHUTDOWN:
+		status = wlan_misc_ioctl_init_shutdown(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_SOFT_RESET:
+		status = wlan_misc_ioctl_soft_reset(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CUSTOM_IE:
+		status = wlan_misc_ioctl_custom_ie_list(pmadapter, pioctl_req,
+							MTRUE);
+		break;
+	case MLAN_OID_MISC_TDLS_CONFIG:
+		status = wlan_misc_ioctl_tdls_config(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_TDLS_OPER:
+		status = wlan_misc_ioctl_tdls_oper(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_TDLS_IES:
+		status = wlan_misc_ioctl_tdls_get_ies(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_TDLS_CS_CHANNEL:
+		status = wlan_misc_ioctl_tdls_cs_channel(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_TDLS_IDLE_TIME:
+		status = wlan_misc_ioctl_tdls_idle_time(pmadapter, pioctl_req);
+		break;
+
+	case MLAN_OID_MISC_MAC_CONTROL:
+		status = wlan_misc_ioctl_mac_control(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_MEF_CFG:
+		status = wlan_misc_ioctl_mef_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_RX_MGMT_IND:
+		status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req);
+		break;
+#ifdef DEBUG_LEVEL1
+	case MLAN_OID_MISC_DRVDBG:
+		status = wlan_set_drvdbg(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_MISC_IP_ADDR:
+		status = wlan_misc_ioctl_ipaddr_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CFP_CODE:
+		status = wlan_misc_ioctl_cfp_code_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_COUNTRY_CODE:
+		status = wlan_misc_ioctl_country_code(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_THERMAL:
+		status = wlan_misc_ioctl_thermal(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_SUBSCRIBE_EVENT:
+		status = wlan_misc_ioctl_subscribe_evt(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_HOTSPOT_CFG:
+		status = wlan_misc_hotspot_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_OTP_USER_DATA:
+		status = wlan_misc_otp_user_data(pmadapter, pioctl_req);
+		break;
+#ifdef USB
+	case MLAN_OID_MISC_USB_AGGR_CTRL:
+		status = wlan_misc_ioctl_usb_aggr_ctrl(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_MISC_AGGR_CTRL:
+		status = wlan_misc_ioctl_aggr_ctrl(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_TXCONTROL:
+		status = wlan_misc_ioctl_txcontrol(pmadapter, pioctl_req);
+		break;
+#ifdef STA_SUPPORT
+	case MLAN_OID_MISC_EXT_CAP_CFG:
+		status = wlan_misc_ext_capa_cfg(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_MISC_PMFCFG:
+		status = wlan_misc_pmfcfg(pmadapter, pioctl_req);
+		break;
+#ifdef RX_PACKET_COALESCE
+	case MLAN_OID_MISC_RX_PACKET_COALESCE:
+		status = wlan_misc_ioctl_rx_pkt_coalesce_config(pmadapter,
+								pioctl_req);
+		break;
+#endif
+	case MLAN_OID_MISC_LOW_PWR_MODE:
+		status = wlan_misc_ioctl_low_pwr_mode(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_PMIC_CFG:
+		status = wlan_misc_ioctl_pmic_configure(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CWMODE_CTRL:
+		status = wlan_misc_ioctl_cwmode_ctrl(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_MEF_FLT_CFG:
+		status = wlan_misc_ioctl_mef_flt_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_DFS_REAPTER_MODE:
+		status = wlan_misc_ioctl_dfs_repeater_cfg(pmadapter,
+							  pioctl_req);
+		break;
+	case MLAN_OID_MISC_COALESCE_CFG:
+		status = wlan_misc_ioctl_coalesce_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_SENSOR_TEMP:
+		status = wlan_misc_ioctl_get_sensor_temp(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_OPER_CLASS:
+		status = wlan_misc_ioctl_oper_class(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_OPER_CLASS_CHECK:
+		status = wlan_misc_ioctl_operclass_validation(pmadapter,
+							      pioctl_req);
+		break;
+	case MLAN_OID_MISC_IPV6_RA_OFFLOAD:
+		status = wlan_misc_ioctl_ipv6_ra_offload(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GTK_REKEY_OFFLOAD:
+		status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_OID_MISC_IND_RST_CFG:
+		status = wlan_misc_ioctl_ind_rst_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_TSF:
+		status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_CHAN_REGION_CFG:
+		status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CLOUD_KEEP_ALIVE:
+		status = wlan_misc_cloud_keep_alive(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_DYN_BW:
+		status = wlan_misc_ioctl_dyn_bw(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_FW_DUMP_EVENT:
+		status = wlan_misc_ioctl_fw_dump_event(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_PER_PKT_CFG:
+		status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_ROBUSTCOEX:
+		status = wlan_misc_robustcoex(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_DMCS_CONFIG:
+		status = wlan_misc_dmcs_config(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_TX_RX_HISTOGRAM:
+		status = wlan_get_tx_rx_histogram(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_BOOT_SLEEP:
+		status = wlan_misc_bootsleep(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CFP_INFO:
+		status = wlan_get_cfpinfo(pmadapter, pioctl_req);
+		break;
+#if defined(PCIE)
+	case MLAN_OID_MISC_SSU:
+		if (pmadapter->ssu_buf)
+			status = MLAN_STATUS_FAILURE;
+		else
+			status = wlan_misc_ssu(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_MISC_HAL_PHY_CFG:
+		status = wlan_misc_hal_phy_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GPIO_TSF_LATCH:
+		status = wlan_misc_gpio_tsf_latch_config(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_TSF_INFO:
+		status = wlan_misc_get_tsf_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_RX_ABORT_CFG:
+		status = wlan_misc_ioctl_rxabortcfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_RX_ABORT_CFG_EXT:
+		status = wlan_misc_ioctl_rxabortcfg_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_TX_AMPDU_PROT_MODE:
+		status = wlan_misc_ioctl_tx_ampdu_prot_mode(pmadapter,
+							    pioctl_req);
+		break;
+	case MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG:
+		status = wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmadapter,
+								 pioctl_req);
+		break;
+	case MLAN_OID_MISC_RATE_ADAPT_CFG:
+		status = wlan_misc_ioctl_rate_adapt_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_CCK_DESENSE_CFG:
+		status = wlan_misc_ioctl_cck_desense_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_REGIONPWR_CFG:
+		status = wlan_get_rgchnpwr_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_GET_CHAN_TRPC_CFG:
+		status = wlan_get_chan_trpc_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_RF_TEST_GENERIC:
+	case MLAN_OID_MISC_RF_TEST_TX_CONT:
+	case MLAN_OID_MISC_RF_TEST_TX_FRAME:
+	case MLAN_OID_MISC_RF_TEST_HE_POWER:
+		status = wlan_misc_ioctl_rf_test_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_ARB_CONFIG:
+		status = wlan_misc_ioctl_arb_cfg(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_RANGE_EXT:
+		status = wlan_misc_ioctl_range_ext(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_MISC_TP_STATE:
+		status = wlan_misc_ioctl_tp_state(pmadapter, pioctl_req);
+		break;
+	default:
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get scan configuration parameter
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *  @param action	    Set/Get
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_set_get_scan_cfg(pmlan_adapter pmadapter,
+		      pmlan_ioctl_req pioctl_req, t_u32 action)
+{
+	mlan_ds_scan *scan = MNULL;
+
+	ENTER();
+
+	scan = (mlan_ds_scan *)pioctl_req->pbuf;
+	if (action == MLAN_ACT_SET) {
+		if (scan->param.scan_cfg.scan_type)
+			pmadapter->scan_type =
+				(t_u8)scan->param.scan_cfg.scan_type;
+		if (scan->param.scan_cfg.scan_mode)
+			pmadapter->scan_mode = scan->param.scan_cfg.scan_mode;
+		if (scan->param.scan_cfg.scan_probe)
+			pmadapter->scan_probes =
+				(t_u16)scan->param.scan_cfg.scan_probe;
+		if (scan->param.scan_cfg.scan_time.specific_scan_time)
+			pmadapter->specific_scan_time =
+				(t_u16)scan->param.scan_cfg.scan_time.
+				specific_scan_time;
+		if (scan->param.scan_cfg.scan_time.active_scan_time)
+			pmadapter->active_scan_time =
+				(t_u16)scan->param.scan_cfg.scan_time.
+				active_scan_time;
+		if (scan->param.scan_cfg.scan_time.passive_scan_time)
+			pmadapter->passive_scan_time =
+				(t_u16)scan->param.scan_cfg.scan_time.
+				passive_scan_time;
+		if (scan->param.scan_cfg.passive_to_active_scan)
+			pmadapter->passive_to_active_scan =
+				scan->param.scan_cfg.passive_to_active_scan;
+		if (scan->param.scan_cfg.ext_scan)
+			pmadapter->ext_scan = scan->param.scan_cfg.ext_scan - 1;
+		pmadapter->scan_chan_gap = scan->param.scan_cfg.scan_chan_gap;
+	}
+	scan->param.scan_cfg.scan_type = (t_u32)pmadapter->scan_type;
+	scan->param.scan_cfg.scan_mode = pmadapter->scan_mode;
+	scan->param.scan_cfg.scan_probe = (t_u32)pmadapter->scan_probes;
+	scan->param.scan_cfg.scan_time.specific_scan_time =
+		(t_u32)pmadapter->specific_scan_time;
+	scan->param.scan_cfg.scan_time.active_scan_time =
+		(t_u32)pmadapter->active_scan_time;
+	scan->param.scan_cfg.scan_time.passive_scan_time =
+		(t_u32)pmadapter->passive_scan_time;
+	scan->param.scan_cfg.passive_to_active_scan =
+		pmadapter->passive_to_active_scan;
+	scan->param.scan_cfg.ext_scan = pmadapter->ext_scan + 1;
+	scan->param.scan_cfg.scan_chan_gap = pmadapter->scan_chan_gap;
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get scan
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_scan_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_scan *pscan;
+
+	ENTER();
+
+	pscan = (mlan_ds_scan *)pioctl_req->pbuf;
+	if (pscan->sub_command == MLAN_OID_SCAN_CONFIG
+	    || pscan->sub_command == MLAN_OID_SCAN_BGSCAN_CONFIG)
+		goto start_config;
+	if (pmadapter->scan_processing && pioctl_req->action == MLAN_ACT_SET &&
+	    pscan->sub_command != MLAN_OID_SCAN_CANCEL) {
+		PRINTM(MINFO, "Scan already in process...\n");
+		LEAVE();
+		return status;
+	}
+
+	if (pmadapter->scan_block && pioctl_req->action == MLAN_ACT_SET) {
+		PRINTM(MERROR, "Scan is blocked during association...\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+start_config:
+	/* Set scan */
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		switch (pscan->sub_command) {
+		case MLAN_OID_SCAN_NORMAL:
+			status = wlan_scan_networks(pmpriv, pioctl_req, MNULL);
+			break;
+		case MLAN_OID_SCAN_SPECIFIC_SSID:
+			status = wlan_scan_specific_ssid(pmpriv, pioctl_req,
+							 &pscan->param.scan_req.
+							 scan_ssid);
+			break;
+		case MLAN_OID_SCAN_USER_CONFIG:
+			status = wlan_scan_networks(pmpriv, pioctl_req,
+						    (wlan_user_scan_cfg *)
+						    pscan->param.user_scan.
+						    scan_cfg_buf);
+			break;
+		case MLAN_OID_SCAN_CONFIG:
+			status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
+						       MLAN_ACT_SET);
+			break;
+		case MLAN_OID_SCAN_CANCEL:
+			status = wlan_cancel_pending_scan_cmd(pmadapter,
+							      pioctl_req);
+			break;
+		case MLAN_OID_SCAN_TABLE_FLUSH:
+			status = wlan_flush_scan_table(pmadapter);
+			break;
+		case MLAN_OID_SCAN_BGSCAN_CONFIG:
+			/* Send request to firmware */
+			status = wlan_prepare_cmd(pmpriv,
+						  HostCmd_CMD_802_11_BG_SCAN_CONFIG,
+						  HostCmd_ACT_GEN_SET, 0,
+						  (t_void *)pioctl_req,
+						  pscan->param.user_scan.
+						  scan_cfg_buf);
+			break;
+		default:
+			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+			status = MLAN_STATUS_FAILURE;
+			break;
+		}
+
+		if ((status == MLAN_STATUS_SUCCESS)
+		    && (pscan->sub_command != MLAN_OID_SCAN_TABLE_FLUSH)
+		    && (pscan->sub_command != MLAN_OID_SCAN_CANCEL)
+		    && (pscan->sub_command != MLAN_OID_SCAN_CONFIG)) {
+			PRINTM(MINFO,
+			       "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
+			status = MLAN_STATUS_PENDING;
+		}
+	}
+	/* Get scan */
+	else {
+		if (pscan->sub_command == MLAN_OID_SCAN_CONFIG) {
+			status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
+						       MLAN_ACT_GET);
+		} else if (pscan->sub_command == MLAN_OID_SCAN_GET_CURRENT_BSS) {
+			pscan->param.scan_resp.num_in_scan_table =
+				pmadapter->num_in_scan_table;
+			pscan->param.scan_resp.pscan_table =
+				(t_u8 *)&pmpriv->curr_bss_params.bss_descriptor;
+			pioctl_req->data_read_written =
+				sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+		} else {
+			if (pmadapter->bgscan_reported) {
+				pmadapter->bgscan_reported = MFALSE;
+				/* Clear the previous scan result */
+				memset(pmadapter, pmadapter->pscan_table, 0x00,
+				       sizeof(BSSDescriptor_t) *
+				       MRVDRV_MAX_BSSID_LIST);
+				pmadapter->num_in_scan_table = 0;
+				pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
+				status = wlan_prepare_cmd(pmpriv,
+							  HostCmd_CMD_802_11_BG_SCAN_QUERY,
+							  HostCmd_ACT_GEN_GET,
+							  0,
+							  (t_void *)pioctl_req,
+							  MNULL);
+				if (status == MLAN_STATUS_SUCCESS) {
+					PRINTM(MINFO,
+					       "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
+					status = MLAN_STATUS_PENDING;
+				}
+			} else {
+				pscan->param.scan_resp.pscan_table =
+					(t_u8 *)pmadapter->pscan_table;
+				pscan->param.scan_resp.num_in_scan_table =
+					pmadapter->num_in_scan_table;
+				pscan->param.scan_resp.age_in_secs =
+					pmadapter->age_in_secs;
+				pioctl_req->data_read_written =
+					sizeof(mlan_scan_resp) +
+					MLAN_SUB_COMMAND_SIZE;
+				pscan->param.scan_resp.pchan_stats =
+					(t_u8 *)pmadapter->pchan_stats;
+				pscan->param.scan_resp.num_in_chan_stats =
+					pmadapter->num_in_chan_stats;
+			}
+		}
+	}
+
+	LEAVE();
+	return status;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Set ewpa mode
+ *
+ *  @param priv                 A pointer to mlan_private structure
+ *  @param psec_pp              A pointer to mlan_ds_passphrase structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_set_ewpa_mode(mlan_private *priv, mlan_ds_passphrase *psec_pp)
+{
+	ENTER();
+
+	if ((psec_pp->psk_type == MLAN_PSK_PASSPHRASE &&
+	     psec_pp->psk.passphrase.passphrase_len > 0) ||
+	    (psec_pp->psk_type == MLAN_PSK_PMK))
+		priv->sec_info.ewpa_enabled = MTRUE;
+	else
+		priv->sec_info.ewpa_enabled = MFALSE;
+
+	PRINTM(MINFO, "Set ewpa mode = %d\n", priv->sec_info.ewpa_enabled);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Search for a BSS
+ *
+ *  @param pmpriv           A pointer to mlan_private structure
+ *  @param pioctl_req       A pointer to ioctl request buffer
+ *
+ *  @return		            MLAN_STATUS_SUCCESS --success, otherwise
+ * fail
+ */
+mlan_status
+wlan_find_bss(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+	int i = 0;
+	BSSDescriptor_t *pbss_desc = MNULL;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+
+	if (memcmp(pmadapter, &bss->param.ssid_bssid.bssid, zero_mac,
+		   sizeof(zero_mac))) {
+		if (bss->param.ssid_bssid.ssid.ssid_len)	/* ssid & bssid */
+			i = wlan_find_ssid_in_list(pmpriv,
+						   &bss->param.ssid_bssid.ssid,
+						   (t_u8 *)&bss->param.
+						   ssid_bssid.bssid,
+						   pmpriv->bss_mode);
+		else
+			i = wlan_find_bssid_in_list(pmpriv,
+						    (t_u8 *)&bss->param.
+						    ssid_bssid.bssid,
+						    pmpriv->bss_mode);
+		if (i < 0) {
+			memcpy_ext(pmadapter, mac, &bss->param.ssid_bssid.bssid,
+				   sizeof(mac), MLAN_MAC_ADDR_LENGTH);
+			PRINTM(MIOCTL, "Can not find bssid " MACSTR "\n",
+			       MAC2STR(mac));
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pbss_desc = &pmadapter->pscan_table[i];
+		memcpy_ext(pmadapter, &bss->param.ssid_bssid.ssid,
+			   &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
+			   sizeof(mlan_802_11_ssid));
+		bss->param.ssid_bssid.rssi = pbss_desc->rssi;
+		bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
+
+		bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
+		/* index in bss list,start from 1 */
+		bss->param.ssid_bssid.idx = i + 1;
+	} else if (bss->param.ssid_bssid.ssid.ssid_len) {
+		i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid,
+					   MNULL, pmpriv->bss_mode);
+		if (i < 0) {
+			PRINTM(MIOCTL, "Can not find ssid %s\n",
+			       bss->param.ssid_bssid.ssid.ssid);
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		pbss_desc = &pmadapter->pscan_table[i];
+		memcpy_ext(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
+			   (t_u8 *)&pbss_desc->mac_address,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		bss->param.ssid_bssid.rssi = pbss_desc->rssi;
+		bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
+
+		bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
+		/* index in bss list, start from 1 */
+		bss->param.ssid_bssid.idx = i + 1;
+	} else {
+		ret = wlan_find_best_network(pmpriv, &bss->param.ssid_bssid);
+	}
+
+	if (pbss_desc) {
+		/**if rsn do not have ft akm, don't set ft cap and ft md*/
+		if (pbss_desc->pmd_ie
+		    && wlan_ft_akm_is_used(pmpriv, (t_u8 *)pbss_desc->prsn_ie)
+			) {
+			bss->param.ssid_bssid.ft_md = pbss_desc->pmd_ie->mdid;
+			bss->param.ssid_bssid.ft_cap =
+				pbss_desc->pmd_ie->ft_cap;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief MLAN station ioctl handler
+ *
+ *  @param adapter  A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status
+wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	switch (pioctl_req->req_id) {
+	case MLAN_IOCTL_SCAN:
+		status = wlan_scan_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_BSS:
+		status = wlan_bss_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_RADIO_CFG:
+		status = wlan_radio_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_SNMP_MIB:
+		status = wlan_snmp_mib_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_GET_INFO:
+		status = wlan_get_info_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_SEC_CFG:
+		status = wlan_sec_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_RATE:
+		status = wlan_rate_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_POWER_CFG:
+		status = wlan_power_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_PM_CFG:
+		status = wlan_pm_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_WMM_CFG:
+		status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_WPS_CFG:
+		status = wlan_wps_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11N_CFG:
+		status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11D_CFG:
+		status = wlan_11d_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_REG_MEM:
+		status = wlan_reg_mem_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_MISC_CFG:
+		status = wlan_misc_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11H_CFG:
+		status = wlan_11h_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11AC_CFG:
+		status = wlan_11ac_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11AX_CFG:
+		status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
diff --git a/wlan_sd8987/mlan/mlan_sta_rx.c b/wlan_sd8987/mlan/mlan_sta_rx.c
new file mode 100755
index 0000000..fd8aada
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_rx.c
@@ -0,0 +1,732 @@
+/** @file mlan_sta_rx.c
+ *
+ *  @brief This file contains the handling of RX in MLAN
+ *  module.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/27/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#ifdef DRV_EMBEDDED_SUPPLICANT
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/** Ethernet II header */
+typedef struct {
+	/** Ethernet II header destination address */
+	t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Ethernet II header source address */
+	t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Ethernet II header length */
+	t_u16 ethertype;
+
+} EthII_Hdr_t;
+
+/** IPv4 ARP request header */
+typedef MLAN_PACK_START struct {
+	/** Hardware type */
+	t_u16 Htype;
+	/** Protocol type */
+	t_u16 Ptype;
+	/** Hardware address length */
+	t_u8 addr_len;
+	/** Protocol address length */
+	t_u8 proto_len;
+	/** Operation code */
+	t_u16 op_code;
+	/** Source mac address */
+	t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Sender IP address */
+	t_u8 src_ip[4];
+	/** Destination mac address */
+	t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Destination IP address */
+	t_u8 dst_ip[4];
+} MLAN_PACK_END IPv4_ARP_t;
+
+/** IPv6 Nadv packet header */
+typedef MLAN_PACK_START struct {
+	/** IP protocol version */
+	t_u8 version;
+	/** flow label */
+	t_u8 flow_lab[3];
+	/** Payload length */
+	t_u16 payload_len;
+	/** Next header type */
+	t_u8 next_hdr;
+	/** Hot limit */
+	t_u8 hop_limit;
+	/** Source address */
+	t_u8 src_addr[16];
+	/** Destination address */
+	t_u8 dst_addr[16];
+	/** ICMP type */
+	t_u8 icmp_type;
+	/** IPv6 Code */
+	t_u8 ipv6_code;
+	/** IPv6 Checksum */
+	t_u16 ipv6_checksum;
+	/** Flags */
+	t_u32 flags;
+	/** Target address */
+	t_u8 taget_addr[16];
+	/** Reserved */
+	t_u8 rev[8];
+} MLAN_PACK_END IPv6_Nadv_t;
+
+/********************************************************
+		Global functions
+********************************************************/
+/**
+ *  @brief This function check and discard IPv4 and IPv6 gratuitous broadcast
+ * packets
+ *
+ *  @param prx_pkt     A pointer to RxPacketHdr_t structure of received packet
+ *  @param pmadapter   A pointer to pmlan_adapter structure
+ *  @return            TRUE if found such type of packets, FALSE not found
+ */
+static t_u8
+discard_gratuitous_ARP_msg(RxPacketHdr_t *prx_pkt, pmlan_adapter pmadapter)
+{
+	t_u8 proto_ARP_type[] = { 0x08, 0x06 };
+	t_u8 proto_ARP_type_v6[] = { 0x86, 0xDD };
+	IPv4_ARP_t *parp_hdr;
+	IPv6_Nadv_t *pNadv_hdr;
+	t_u8 ret = MFALSE;
+
+	/* IPV4 pkt check
+	 * A gratuitous ARP is an ARP packet
+	 * where the source and destination IP are both set to
+	 * the IP of the machine issuing the packet.
+	 */
+	if (memcmp(pmadapter, proto_ARP_type, &prx_pkt->eth803_hdr.h803_len,
+		   sizeof(proto_ARP_type)) == 0) {
+		parp_hdr = (IPv4_ARP_t *)(&prx_pkt->rfc1042_hdr);
+		/* Graguitous ARP can be ARP request or ARP reply */
+		if ((parp_hdr->op_code == mlan_htons(0x01)) ||
+		    (parp_hdr->op_code == mlan_htons(0x02)))
+			if (memcmp(pmadapter, parp_hdr->src_ip,
+				   parp_hdr->dst_ip, 4) == 0)
+				ret = MTRUE;
+	}
+
+	/* IPV6 pkt check
+	 * An unsolicited Neighbor Advertisement pkt is
+	 * marked by a cleared Solicited Flag
+	 */
+	if (memcmp(pmadapter, proto_ARP_type_v6, &prx_pkt->eth803_hdr.h803_len,
+		   sizeof(proto_ARP_type_v6)) == 0) {
+		pNadv_hdr = (IPv6_Nadv_t *)(&prx_pkt->rfc1042_hdr);
+		/* Check Nadv type: next header is ICMPv6 and
+		 * icmp type is Nadv */
+		if (pNadv_hdr->next_hdr == 0x3A && pNadv_hdr->icmp_type == 0x88)
+			if ((pNadv_hdr->flags & mlan_htonl(0x40000000)) == 0)
+				ret = MTRUE;
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief This function process tdls action frame
+ *
+ *  @param priv        A pointer to mlan_private structure
+ *  @param pbuf        A pointer to tdls action frame buffer
+ *  @param len         len of tdls action frame buffer
+ *  @return            N/A
+ */
+void
+wlan_process_tdls_action_frame(pmlan_private priv, t_u8 *pbuf, t_u32 len)
+{
+	sta_node *sta_ptr = MNULL;
+	IEEEtypes_VendorHeader_t *pvendor_ie = MNULL;
+	const t_u8 wmm_oui[] = { 0x00, 0x50, 0xf2, 0x02 };
+	t_u8 *peer;
+	t_u8 *pos, *end;
+	t_u8 action;
+	int ie_len = 0;
+	t_u8 i;
+	int rate_len;
+
+#define TDLS_PAYLOAD_TYPE 2
+#define TDLS_CATEGORY 0x0c
+#define TDLS_REQ_FIX_LEN 6
+#define TDLS_RESP_FIX_LEN 8
+#define TDLS_CONFIRM_FIX_LEN 6
+	if (len < (sizeof(EthII_Hdr_t) + 3))
+		return;
+	if (*(t_u8 *)(pbuf + sizeof(EthII_Hdr_t)) != TDLS_PAYLOAD_TYPE)
+		/*TDLS payload type = 2 */
+		return;
+	if (*(t_u8 *)(pbuf + sizeof(EthII_Hdr_t) + 1) != TDLS_CATEGORY)
+		/*TDLS category = 0xc */
+		return;
+	peer = pbuf + MLAN_MAC_ADDR_LENGTH;
+
+	action = *(t_u8 *)(pbuf + sizeof(EthII_Hdr_t) + 2);
+	/*2= payload type + category */
+
+	if (action > TDLS_SETUP_CONFIRM) {
+		/*just handle TDLS setup request/response/confirm */
+		PRINTM(MMSG, "Recv TDLS Action: peer=" MACSTR ", action=%d\n",
+		       MAC2STR(peer), action);
+		return;
+	}
+
+	sta_ptr = wlan_add_station_entry(priv, peer);
+	if (!sta_ptr)
+		return;
+	if (action == TDLS_SETUP_REQUEST) {	/*setup request */
+		sta_ptr->status = TDLS_NOT_SETUP;
+		PRINTM(MMSG, "Recv TDLS SETUP Request: peer=" MACSTR "\n",
+		       MAC2STR(peer));
+		wlan_hold_tdls_packets(priv, peer);
+		if (len < (sizeof(EthII_Hdr_t) + TDLS_REQ_FIX_LEN))
+			return;
+		pos = pbuf + sizeof(EthII_Hdr_t) + 4;
+		/*payload 1+ category 1 + action 1 +dialog 1 */
+		sta_ptr->capability = mlan_ntohs(*(t_u16 *)pos);
+		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_REQ_FIX_LEN;
+		pos += 2;
+	} else if (action == 1) {	/*setup respons */
+		PRINTM(MMSG, "Recv TDLS SETUP Response: peer=" MACSTR "\n",
+		       MAC2STR(peer));
+		if (len < (sizeof(EthII_Hdr_t) + TDLS_RESP_FIX_LEN))
+			return;
+		pos = pbuf + sizeof(EthII_Hdr_t) + 6;
+		/*payload 1+ category 1 + action 1 +dialog 1 +status 2 */
+		sta_ptr->capability = mlan_ntohs(*(t_u16 *)pos);
+		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_RESP_FIX_LEN;
+		pos += 2;
+	} else {		/*setup confirm */
+		PRINTM(MMSG, "Recv TDLS SETUP Confirm: peer=" MACSTR "\n",
+		       MAC2STR(peer));
+		if (len < (sizeof(EthII_Hdr_t) + TDLS_CONFIRM_FIX_LEN))
+			return;
+		pos = pbuf + sizeof(EthII_Hdr_t) + TDLS_CONFIRM_FIX_LEN;
+		/*payload 1+ category 1 + action 1 +dialog 1 + status 2 */
+		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_CONFIRM_FIX_LEN;
+	}
+	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
+		if (pos + 2 + pos[1] > end)
+			break;
+		switch (*pos) {
+		case SUPPORTED_RATES:
+			sta_ptr->rate_len =
+				MIN(pos[1], sizeof(sta_ptr->support_rate));
+			for (i = 0; i < sta_ptr->rate_len; i++)
+				sta_ptr->support_rate[i] = pos[2 + i];
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+			rate_len = MIN(pos[1], sizeof(sta_ptr->support_rate) -
+				       sta_ptr->rate_len);
+			for (i = 0; i < rate_len; i++)
+				sta_ptr->support_rate[sta_ptr->rate_len + i] =
+					pos[2 + i];
+			sta_ptr->rate_len += rate_len;
+			break;
+		case HT_CAPABILITY:
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->HTcap, pos,
+				   sizeof(IEEEtypes_HTCap_t),
+				   sizeof(IEEEtypes_HTCap_t));
+			sta_ptr->is_11n_enabled = 1;
+			DBG_HEXDUMP(MDAT_D, "TDLS HT capability",
+				    (t_u8 *)(&sta_ptr->HTcap),
+				    MIN(sizeof(IEEEtypes_HTCap_t),
+					MAX_DATA_DUMP_LEN));
+			break;
+		case HT_OPERATION:
+			memcpy_ext(priv->adapter, &sta_ptr->HTInfo, pos,
+				   sizeof(IEEEtypes_HTInfo_t),
+				   sizeof(IEEEtypes_HTInfo_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS HT info",
+				    (t_u8 *)(&sta_ptr->HTInfo),
+				    MIN(sizeof(IEEEtypes_HTInfo_t),
+					MAX_DATA_DUMP_LEN));
+			break;
+		case BSSCO_2040:
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->BSSCO_20_40,
+				   pos, sizeof(IEEEtypes_2040BSSCo_t),
+				   sizeof(IEEEtypes_2040BSSCo_t));
+			break;
+		case EXT_CAPABILITY:
+			sta_ptr->ExtCap.ieee_hdr.len =
+				MIN(pos[1], sizeof(ExtCap_t));
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->ExtCap, pos,
+				   sta_ptr->ExtCap.ieee_hdr.len +
+				   sizeof(IEEEtypes_Header_t),
+				   sizeof(IEEEtypes_ExtCap_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Extended capability",
+				    (t_u8 *)(&sta_ptr->ExtCap),
+				    sta_ptr->ExtCap.ieee_hdr.len + 2);
+			break;
+		case RSN_IE:
+			sta_ptr->rsn_ie.ieee_hdr.len =
+				MIN(pos[1], IEEE_MAX_IE_SIZE -
+				    sizeof(IEEEtypes_Header_t));
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->rsn_ie, pos,
+				   sta_ptr->rsn_ie.ieee_hdr.len +
+				   sizeof(IEEEtypes_Header_t),
+				   sizeof(IEEEtypes_Generic_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS Rsn ie ",
+				    (t_u8 *)(&sta_ptr->rsn_ie),
+				    sta_ptr->rsn_ie.ieee_hdr.len +
+				    sizeof(IEEEtypes_Header_t));
+			break;
+		case QOS_INFO:
+			sta_ptr->qos_info = pos[2];
+			PRINTM(MDAT_D, "TDLS qos info %x\n", sta_ptr->qos_info);
+			break;
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorHeader_t *)pos;
+			if (!memcmp(priv->adapter, pvendor_ie->oui, wmm_oui,
+				    sizeof(wmm_oui))) {
+				sta_ptr->qos_info = pos[8]; /** qos info in wmm
+							       parameters in
+							       response and
+							       confirm */
+				PRINTM(MDAT_D, "TDLS qos info %x\n",
+				       sta_ptr->qos_info);
+			}
+			break;
+		case LINK_ID:
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->link_ie,
+				   pos, sizeof(IEEEtypes_LinkIDElement_t),
+				   sizeof(IEEEtypes_LinkIDElement_t));
+			break;
+
+		case VHT_CAPABILITY:
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->vht_cap,
+				   pos, sizeof(IEEEtypes_VHTCap_t),
+				   sizeof(IEEEtypes_VHTCap_t));
+			sta_ptr->is_11ac_enabled = 1;
+			DBG_HEXDUMP(MDAT_D, "TDLS VHT capability",
+				    (t_u8 *)(&sta_ptr->vht_cap),
+				    MIN(sizeof(IEEEtypes_VHTCap_t),
+					MAX_DATA_DUMP_LEN));
+			break;
+		case VHT_OPERATION:
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->vht_oprat,
+				   pos, sizeof(IEEEtypes_VHTOprat_t),
+				   sizeof(IEEEtypes_VHTOprat_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS VHT Operation",
+				    (t_u8 *)(&sta_ptr->vht_oprat),
+				    MIN(sizeof(IEEEtypes_VHTOprat_t),
+					MAX_DATA_DUMP_LEN));
+			break;
+		case AID_INFO:
+			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->aid_info,
+				   pos, sizeof(IEEEtypes_AID_t),
+				   sizeof(IEEEtypes_AID_t));
+			DBG_HEXDUMP(MDAT_D, "TDLS AID Info",
+				    (t_u8 *)(&sta_ptr->aid_info),
+				    MIN(sizeof(IEEEtypes_AID_t),
+					MAX_DATA_DUMP_LEN));
+			break;
+		default:
+			break;
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief This function processes received packet and forwards it
+ *          to kernel/upper layer
+ *
+ *  @param pmadapter A pointer to mlan_adapter
+ *  @param pmbuf   A pointer to mlan_buffer which includes the received packet
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+	RxPacketHdr_t *prx_pkt;
+	RxPD *prx_pd;
+	int hdr_chop;
+	EthII_Hdr_t *peth_hdr;
+	t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03,
+		0x00, 0x00, 0x00
+	};
+	t_u8 snap_oui_802_h[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03,
+		0x00, 0x00, 0xf8
+	};
+	t_u8 appletalk_aarp_type[2] = { 0x80, 0xf3 };
+	t_u8 ipx_snap_type[2] = { 0x81, 0x37 };
+	t_u8 tdls_action_type[2] = { 0x89, 0x0d };
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	t_u8 eapol_type[2] = { 0x88, 0x8e };
+#endif
+	t_u8 ext_rate_info = 0;
+
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+/** Small debug type */
+#define DBG_TYPE_SMALL 2
+/** Size of debugging structure */
+#define SIZE_OF_DBG_STRUCT 4
+	if (prx_pd->rx_pkt_type == PKT_TYPE_DEBUG) {
+		t_u8 dbg_type;
+		dbg_type = *(t_u8 *)&prx_pkt->eth803_hdr;
+		if (dbg_type == DBG_TYPE_SMALL) {
+			PRINTM(MFW_D, "\n");
+			DBG_HEXDUMP(MFW_D, "FWDBG",
+				    (char *)((t_u8 *)&prx_pkt->eth803_hdr +
+					     SIZE_OF_DBG_STRUCT),
+				    prx_pd->rx_pkt_length);
+			PRINTM(MFW_D, "FWDBG::\n");
+		}
+		goto done;
+	}
+
+	PRINTM(MINFO,
+	       "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
+	       pmbuf->data_len, prx_pd->rx_pkt_offset,
+	       pmbuf->data_len - prx_pd->rx_pkt_offset);
+
+	HEXDUMP("RX Data: Dest", prx_pkt->eth803_hdr.dest_addr,
+		sizeof(prx_pkt->eth803_hdr.dest_addr));
+	HEXDUMP("RX Data: Src", prx_pkt->eth803_hdr.src_addr,
+		sizeof(prx_pkt->eth803_hdr.src_addr));
+
+	if ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, snap_oui_802_h,
+		    sizeof(snap_oui_802_h)) == 0) ||
+	    ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr,
+		     sizeof(rfc1042_eth_hdr)) == 0) &&
+	     memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type,
+		    appletalk_aarp_type, sizeof(appletalk_aarp_type)) &&
+	     memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, ipx_snap_type,
+		    sizeof(ipx_snap_type)))) {
+		/*
+		 * Replace the 803 header and rfc1042 header (llc/snap) with an
+		 * EthernetII header, keep the src/dst and snap_type
+		 * (ethertype). The firmware only passes up SNAP frames
+		 * converting all RX Data from 802.11 to 802.2/LLC/SNAP frames.
+		 * To create the Ethernet II, just move the src, dst address
+		 * right before the snap_type.
+		 */
+		peth_hdr =
+			(EthII_Hdr_t *)((t_u8 *)&prx_pkt->eth803_hdr +
+					sizeof(prx_pkt->eth803_hdr) +
+					sizeof(prx_pkt->rfc1042_hdr) -
+					sizeof(prx_pkt->eth803_hdr.dest_addr) -
+					sizeof(prx_pkt->eth803_hdr.src_addr) -
+					sizeof(prx_pkt->rfc1042_hdr.snap_type));
+
+		memcpy_ext(pmadapter, peth_hdr->src_addr,
+			   prx_pkt->eth803_hdr.src_addr,
+			   sizeof(peth_hdr->src_addr),
+			   sizeof(peth_hdr->src_addr));
+		memcpy_ext(pmadapter, peth_hdr->dest_addr,
+			   prx_pkt->eth803_hdr.dest_addr,
+			   sizeof(peth_hdr->dest_addr),
+			   sizeof(peth_hdr->dest_addr));
+
+		/* Chop off the RxPD + the excess memory from the 802.2/llc/snap
+		 *  header that was removed.
+		 */
+		hdr_chop = (t_u32)((t_ptr)peth_hdr - (t_ptr)prx_pd);
+	} else {
+		HEXDUMP("RX Data: LLC/SNAP", (t_u8 *)&prx_pkt->rfc1042_hdr,
+			sizeof(prx_pkt->rfc1042_hdr));
+		if ((priv->hotspot_cfg & HOTSPOT_ENABLED) &&
+		    discard_gratuitous_ARP_msg(prx_pkt, pmadapter)) {
+			ret = MLAN_STATUS_SUCCESS;
+			PRINTM(MDATA,
+			       "Bypass sending Gratuitous ARP frame to Kernel.\n");
+			goto done;
+		}
+		if (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len,
+			    tdls_action_type, sizeof(tdls_action_type))) {
+			wlan_process_tdls_action_frame(priv,
+						       ((t_u8 *)prx_pd +
+							prx_pd->rx_pkt_offset),
+						       prx_pd->rx_pkt_length);
+		}
+		/* Chop off the RxPD */
+		hdr_chop = (t_u32)((t_ptr)&prx_pkt->eth803_hdr - (t_ptr)prx_pd);
+	}
+
+	/* Chop off the leading header bytes so the it points to the start of
+	 *   either the reconstructed EthII frame or the 802.2/llc/snap frame
+	 */
+	pmbuf->data_len -= hdr_chop;
+	pmbuf->data_offset += hdr_chop;
+	pmbuf->pparent = MNULL;
+	DBG_HEXDUMP(MDAT_D, "RxPD", (t_u8 *)prx_pd,
+		    MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
+	DBG_HEXDUMP(MDAT_D, "Rx Payload",
+		    ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+		    MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
+
+	priv->rxpd_rate = prx_pd->rx_rate;
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->out_ts_sec,
+						  &pmbuf->out_ts_usec);
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
+	       pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
+	       prx_pd->priority);
+
+#ifdef DRV_EMBEDDED_SUPPLICANT
+	if (supplicantIsEnabled(priv->psapriv) &&
+	    (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type,
+		     sizeof(eapol_type)))) {
+		// BML_SET_OFFSET(bufDesc, offset);
+		if (ProcessEAPoLPkt(priv->psapriv, pmbuf)) {
+			pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+			ret = MLAN_STATUS_SUCCESS;
+			PRINTM(MMSG,
+			       "host supplicant eapol pkt process done.\n");
+
+			LEAVE();
+			return ret;
+		}
+	}
+#endif
+
+	if (MFALSE || priv->rx_pkt_info) {
+
+		ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
+		pmbuf->u.rx_info.data_rate =
+			wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+						prx_pd->rate_info,
+						ext_rate_info);
+
+		pmbuf->u.rx_info.channel =
+			(prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+		pmbuf->u.rx_info.antenna = prx_pd->antenna;
+		pmbuf->u.rx_info.rssi = prx_pd->snr - prx_pd->nf;
+	}
+	ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+						    pmbuf);
+	if (ret == MLAN_STATUS_FAILURE) {
+		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+		PRINTM(MERROR,
+		       "STA Rx Error: moal_recv_packet returned error\n");
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+#ifdef USB
+	else if (IS_USB(pmadapter->card_type))
+		pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
+							MNULL, MLAN_USB_EP_DATA,
+							MLAN_STATUS_SUCCESS);
+#endif
+	LEAVE();
+
+	return ret;
+}
+
+/**
+ *   @brief This function processes the received buffer
+ *
+ *   @param adapter A pointer to mlan_adapter
+ *   @param pmbuf     A pointer to the received buffer
+ *
+ *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_sta_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	RxPD *prx_pd;
+	RxPacketHdr_t *prx_pkt;
+	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+	t_u16 rx_pkt_type = 0;
+	wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL;
+
+	sta_node *sta_ptr = MNULL;
+	t_u16 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	endian_convert_RxPD(prx_pd);
+	if (priv->adapter->pcard_info->v14_fw_api) {
+		t_u8 rxpd_rate_info_orig = prx_pd->rate_info;
+		prx_pd->rate_info =
+			wlan_convert_v14_rx_rate_info(priv,
+						      rxpd_rate_info_orig);
+		PRINTM(MINFO,
+		       "STA RX: v14_fw_api=%d rx_rate =%d rxpd_rate_info=0x%x->0x%x\n",
+		       priv->adapter->pcard_info->v14_fw_api, prx_pd->rx_rate,
+		       rxpd_rate_info_orig, prx_pd->rate_info);
+	}
+	rx_pkt_type = prx_pd->rx_pkt_type;
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+	if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) !=
+	    (t_u16)pmbuf->data_len) {
+		PRINTM(MERROR,
+		       "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
+		       " rx_pkt_length=%d\n",
+		       pmbuf->data_len, prx_pd->rx_pkt_offset,
+		       prx_pd->rx_pkt_length);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+		goto done;
+	}
+	pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
+
+	if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask &&
+	    prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) {
+		/* Check if this is mgmt packet and needs to
+		 * forwarded to app as an event
+		 */
+		pmgmt_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd +
+						  prx_pd->rx_pkt_offset);
+		pmgmt_pkt_hdr->frm_len =
+			wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len);
+
+		if ((pmgmt_pkt_hdr->wlan_header.frm_ctl &
+		     IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
+			wlan_process_802dot11_mgmt_pkt(pmadapter->
+						       priv[pmbuf->bss_index],
+						       (t_u8 *)&pmgmt_pkt_hdr->
+						       wlan_header,
+						       pmgmt_pkt_hdr->frm_len +
+						       sizeof(wlan_mgmt_pkt) -
+						       sizeof(pmgmt_pkt_hdr->
+							      frm_len), prx_pd);
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+		goto done;
+	}
+	if (rx_pkt_type != PKT_TYPE_BAR) {
+		priv->rxpd_rate_info = prx_pd->rate_info;
+		priv->rxpd_rate = prx_pd->rx_rate;
+		priv->rxpd_rx_info = (t_u8)(prx_pd->rx_info >> 16);
+		if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+			antenna = wlan_adjust_antenna(priv, prx_pd);
+			adj_rx_rate =
+				wlan_adjust_data_rate(priv, priv->rxpd_rate,
+						      priv->rxpd_rate_info);
+			pmadapter->callbacks.moal_hist_data_add(pmadapter->
+								pmoal_handle,
+								pmbuf->
+								bss_index,
+								adj_rx_rate,
+								prx_pd->snr,
+								prx_pd->nf,
+								antenna);
+		}
+	}
+
+	/*
+	 * If the packet is not an unicast packet then send the packet
+	 * directly to os. Don't pass thru rx reordering
+	 */
+	if ((!IS_11N_ENABLED(priv)
+	     && !(prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)
+	    ) ||
+	    memcmp(priv->adapter, priv->curr_addr,
+		   prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) {
+		priv->snr = prx_pd->snr;
+		priv->nf = prx_pd->nf;
+		wlan_process_rx_packet(pmadapter, pmbuf);
+		goto done;
+	}
+
+	if (queuing_ra_based(priv) ||
+	    (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) {
+		memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		if (prx_pd->priority < MAX_NUM_TID) {
+			PRINTM(MDATA, "adhoc/tdls packet %p " MACSTR "\n",
+			       pmbuf, MAC2STR(ta));
+			sta_ptr = wlan_get_station_entry(priv, ta);
+			if (sta_ptr) {
+				sta_ptr->rx_seq[prx_pd->priority] =
+					prx_pd->seq_num;
+				sta_ptr->snr = prx_pd->snr;
+				sta_ptr->nf = prx_pd->nf;
+				if (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK) {
+					pmadapter->callbacks.
+						moal_updata_peer_signal
+						(pmadapter->pmoal_handle,
+						 pmbuf->bss_index, ta,
+						 prx_pd->snr, prx_pd->nf);
+				}
+			}
+			if (!sta_ptr || !sta_ptr->is_11n_enabled) {
+				wlan_process_rx_packet(pmadapter, pmbuf);
+				goto done;
+			}
+		}
+	} else {
+		priv->snr = prx_pd->snr;
+		priv->nf = prx_pd->nf;
+		if ((rx_pkt_type != PKT_TYPE_BAR) &&
+		    (prx_pd->priority < MAX_NUM_TID))
+			priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
+		memcpy_ext(pmadapter, ta,
+			   priv->curr_bss_params.bss_descriptor.mac_address,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	}
+	if ((priv->port_ctrl_mode == MTRUE && priv->port_open == MFALSE) &&
+	    (rx_pkt_type != PKT_TYPE_BAR)) {
+		mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
+				       ta, (t_u8)prx_pd->rx_pkt_type,
+				       (t_void *)RX_PKT_DROPPED_IN_FW);
+		if (rx_pkt_type == PKT_TYPE_AMSDU) {
+			pmbuf->data_len = prx_pd->rx_pkt_length;
+			pmbuf->data_offset += prx_pd->rx_pkt_offset;
+			wlan_11n_deaggregate_pkt(priv, pmbuf);
+		} else {
+			wlan_process_rx_packet(pmadapter, pmbuf);
+		}
+		goto done;
+	}
+	/* Reorder and send to OS */
+	ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
+				     ta, (t_u8)prx_pd->rx_pkt_type,
+				     (void *)pmbuf);
+	if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+
+done:
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_sta_tx.c b/wlan_sd8987/mlan/mlan_sta_tx.c
new file mode 100755
index 0000000..73ca1bf
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_sta_tx.c
@@ -0,0 +1,331 @@
+/** @file mlan_sta_tx.c
+ *
+ *  @brief This file contains the handling of data packet
+ *  transmission in MLAN module.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_join.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		Global functions
+********************************************************/
+/**
+ *  @brief This function fill the txpd for tx packet
+ *
+ *  @param priv    A pointer to mlan_private structure
+ *  @param pmbuf   A pointer to the mlan_buffer for process
+ *
+ *  @return        headptr or MNULL
+ */
+t_void *
+wlan_ops_sta_process_txpd(t_void *priv, pmlan_buffer pmbuf)
+{
+	mlan_private *pmpriv = (mlan_private *)priv;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	TxPD *plocal_tx_pd;
+	t_u8 *head_ptr = MNULL;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+
+	ENTER();
+
+	if (!pmbuf->data_len) {
+		PRINTM(MERROR, "STA Tx Error: Invalid packet length: %d\n",
+		       pmbuf->data_len);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		goto done;
+	}
+	if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+		memcpy_ext(pmpriv->adapter, &pkt_type,
+			   pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type),
+			   sizeof(pkt_type));
+		memcpy_ext(pmpriv->adapter, &tx_control,
+			   pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+			   sizeof(tx_control), sizeof(tx_control));
+		pmbuf->data_offset += sizeof(pkt_type) + sizeof(tx_control);
+		pmbuf->data_len -= sizeof(pkt_type) + sizeof(tx_control);
+	}
+
+	if (pmbuf->data_offset <
+	    (sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT)) {
+		PRINTM(MERROR,
+		       "not enough space for TxPD: headroom=%d pkt_len=%d, required=%d\n",
+		       pmbuf->data_offset, pmbuf->data_len,
+		       sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		goto done;
+	}
+
+	/* head_ptr should be aligned */
+	head_ptr = pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) -
+		pmpriv->intf_hr_len;
+	head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+	plocal_tx_pd = (TxPD *)(head_ptr + pmpriv->intf_hr_len);
+	memset(pmadapter, plocal_tx_pd, 0, sizeof(TxPD));
+	/* Set the BSS number to TxPD */
+	plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv);
+	plocal_tx_pd->bss_type = pmpriv->bss_type;
+	plocal_tx_pd->tx_pkt_length = (t_u16)pmbuf->data_len;
+
+	plocal_tx_pd->priority = (t_u8)pmbuf->priority;
+	plocal_tx_pd->pkt_delay_2ms =
+		wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf);
+
+	if (plocal_tx_pd->priority <
+	    NELEMENTS(pmpriv->wmm.user_pri_pkt_tx_ctrl))
+		/*
+		 * Set the priority specific tx_control field, setting of 0 will
+		 *   cause the default value to be used later in this function
+		 */
+		plocal_tx_pd->tx_control =
+			pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->
+							 priority];
+	if (pmadapter->pps_uapsd_mode) {
+		if (MTRUE == wlan_check_last_packet_indication(pmpriv)) {
+			pmadapter->tx_lock_flag = MTRUE;
+			plocal_tx_pd->flags =
+				MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
+		}
+	}
+	if (pmbuf->flags & MLAN_BUF_FLAG_TDLS)
+		plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TDLS_PACKET;
+	/* Offset of actual data */
+	plocal_tx_pd->tx_pkt_offset = (t_u16)((t_ptr)pmbuf->pbuf +
+					      pmbuf->data_offset -
+					      (t_ptr)plocal_tx_pd);
+
+	if (!plocal_tx_pd->tx_control) {
+		/* TxCtrl set by user or default */
+		plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl;
+	}
+
+	if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+		plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type;
+		plocal_tx_pd->tx_control = tx_control;
+	}
+
+	if (pmbuf->flags & MLAN_BUF_FLAG_TX_STATUS) {
+		plocal_tx_pd->tx_control_1 |= pmbuf->tx_seq_num << 8;
+		plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
+	}
+	if (pmbuf->flags & MLAN_BUF_FLAG_TX_CTRL) {
+		if (pmbuf->u.tx_info.data_rate) {
+			plocal_tx_pd->tx_control |=
+				(wlan_ieee_rateid_to_mrvl_rateid
+				 (pmpriv, pmbuf->u.tx_info.data_rate, MNULL)
+				 << 16);
+			plocal_tx_pd->tx_control |= TXPD_TXRATE_ENABLE;
+		}
+		plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.channel << 21;
+		if (pmbuf->u.tx_info.bw) {
+			plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.bw << 16;
+			plocal_tx_pd->tx_control_1 |= TXPD_BW_ENABLE;
+		}
+		if (pmbuf->u.tx_info.tx_power.tp.hostctl)
+			plocal_tx_pd->tx_control |=
+				(t_u32)pmbuf->u.tx_info.tx_power.val;
+		if (pmbuf->u.tx_info.retry_limit) {
+			plocal_tx_pd->tx_control |= pmbuf->u.tx_info.retry_limit
+				<< 8;
+			plocal_tx_pd->tx_control |= TXPD_RETRY_ENABLE;
+		}
+	}
+	endian_convert_TxPD(plocal_tx_pd);
+
+	/* Adjust the data offset and length to include TxPD in pmbuf */
+	pmbuf->data_len += pmbuf->data_offset;
+	pmbuf->data_offset = (t_u32)(head_ptr - pmbuf->pbuf);
+	pmbuf->data_len -= pmbuf->data_offset;
+
+done:
+	LEAVE();
+	return head_ptr;
+}
+
+/**
+ *  @brief This function tells firmware to send a NULL data packet.
+ *
+ *  @param priv     A pointer to mlan_private structure
+ *  @param flags    Transmit Pkt Flags
+ *
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
+ * failure
+ */
+mlan_status
+wlan_send_null_packet(pmlan_private priv, t_u8 flags)
+{
+	pmlan_adapter pmadapter = MNULL;
+	TxPD *ptx_pd;
+/* sizeof(TxPD) + Interface specific header */
+#define NULL_PACKET_HDR 256
+	t_u32 data_len = NULL_PACKET_HDR;
+	pmlan_buffer pmbuf = MNULL;
+	t_u8 *ptr;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pmadapter = priv->adapter;
+
+	if (pmadapter->surprise_removed == MTRUE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (pmadapter->data_sent == MTRUE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	pmbuf = wlan_alloc_mlan_buffer(pmadapter, data_len, 0,
+				       MOAL_MALLOC_BUFFER);
+	if (!pmbuf) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	memset(pmadapter, pmbuf->pbuf, 0, data_len);
+	pmbuf->bss_index = priv->bss_index;
+	pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+	pmbuf->flags |= MLAN_BUF_FLAG_NULL_PKT;
+	ptr = pmbuf->pbuf + pmbuf->data_offset;
+	pmbuf->data_len = sizeof(TxPD) + priv->intf_hr_len;
+	ptx_pd = (TxPD *)(ptr + priv->intf_hr_len);
+	ptx_pd->tx_control = priv->pkt_tx_ctrl;
+	ptx_pd->flags = flags;
+	ptx_pd->priority = WMM_HIGHEST_PRIORITY;
+	ptx_pd->tx_pkt_offset = sizeof(TxPD);
+	/* Set the BSS number to TxPD */
+	ptx_pd->bss_num = GET_BSS_NUM(priv);
+	ptx_pd->bss_type = priv->bss_type;
+
+	endian_convert_TxPD(ptx_pd);
+
+	ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf, MNULL);
+
+	switch (ret) {
+#ifdef USB
+	case MLAN_STATUS_PRESOURCE:
+		PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+		break;
+#endif
+	case MLAN_STATUS_RESOURCE:
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n");
+		pmadapter->dbg.num_tx_host_to_card_failure++;
+		goto done;
+	case MLAN_STATUS_FAILURE:
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n");
+		pmadapter->dbg.num_tx_host_to_card_failure++;
+		goto done;
+	case MLAN_STATUS_SUCCESS:
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+		PRINTM(MINFO, "STA Tx: Successfully send the NULL packet\n");
+		pmadapter->tx_lock_flag = MTRUE;
+		break;
+	case MLAN_STATUS_PENDING:
+		pmadapter->tx_lock_flag = MTRUE;
+		break;
+	default:
+		break;
+	}
+
+	PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA, "%lu.%06lu : Null data => FW\n", sec, usec);
+	DBG_HEXDUMP(MDAT_D, "Null data", ptr, sizeof(TxPD) + priv->intf_hr_len);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks if we need to send last packet indication.
+ *
+ *  @param priv    A pointer to mlan_private structure
+ *
+ *  @return        MTRUE or MFALSE
+ */
+t_u8
+wlan_check_last_packet_indication(pmlan_private priv)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	t_u8 ret = MFALSE;
+	t_u8 prop_ps = MTRUE;
+
+	ENTER();
+
+	if (!pmadapter->sleep_period.period) {
+		LEAVE();
+		return ret;
+	}
+	if (wlan_bypass_tx_list_empty(pmadapter) &&
+	    wlan_wmm_lists_empty(pmadapter)) {
+		if (((priv->curr_bss_params.wmm_uapsd_enabled == MTRUE) &&
+		     priv->wmm_qosinfo) || prop_ps)
+
+			ret = MTRUE;
+	}
+	if (ret && !pmadapter->cmd_sent && !pmadapter->curr_cmd &&
+	    !wlan_is_cmd_pending(pmadapter)) {
+		pmadapter->delay_null_pkt = MFALSE;
+		ret = MTRUE;
+	} else {
+		ret = MFALSE;
+		pmadapter->delay_null_pkt = MTRUE;
+	}
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_txrx.c b/wlan_sd8987/mlan/mlan_txrx.c
new file mode 100755
index 0000000..feeddd9
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_txrx.c
@@ -0,0 +1,449 @@
+/**
+ * @file mlan_txrx.c
+ *
+ *  @brief This file contains the handling of TX/RX in MLAN
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/*************************************************************
+Change Log:
+    05/11/2009: initial version
+************************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *   @brief This function processes the received buffer
+ *
+ *   @param pmadapter A pointer to mlan_adapter
+ *   @param pmbuf     A pointer to the received buffer
+ *
+ *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private priv = MNULL;
+	RxPD *prx_pd;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Get the BSS number from RxPD, get corresponding priv */
+	priv = wlan_get_priv_by_id(pmadapter, prx_pd->bss_num & BSS_NUM_MASK,
+				   prx_pd->bss_type);
+	if (!priv)
+		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pmbuf->bss_index = priv->bss_index;
+	PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA, "%lu.%06lu : Data <= FW\n", sec, usec);
+	ret = priv->ops.process_rx_packet(pmadapter, pmbuf);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function checks the conditions and sends packet to device
+ *
+ *  @param priv	   A pointer to mlan_private structure
+ *  @param pmbuf   A pointer to the mlan_buffer for process
+ *  @param tx_param A pointer to mlan_tx_param structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
+ * failure
+ */
+mlan_status
+wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf, mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_adapter pmadapter = priv->adapter;
+	t_u8 *head_ptr = MNULL;
+#ifdef DEBUG_LEVEL1
+	t_u32 sec = 0, usec = 0;
+#endif
+#ifdef STA_SUPPORT
+	PTxPD plocal_tx_pd = MNULL;
+#endif
+
+	ENTER();
+	head_ptr = (t_u8 *)priv->ops.process_txpd(priv, pmbuf);
+	if (!head_ptr) {
+		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+		plocal_tx_pd = (TxPD *)(head_ptr + priv->intf_hr_len);
+#endif
+	if (pmadapter->tp_state_on)
+		pmadapter->callbacks.moal_tp_accounting(pmadapter->pmoal_handle,
+							pmbuf, 4);
+	if (pmadapter->tp_state_drop_point == 4)
+		goto done;
+	else {
+
+		ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf,
+						  tx_param);
+	}
+done:
+	switch (ret) {
+#ifdef USB
+	case MLAN_STATUS_PRESOURCE:
+		PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+		DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + priv->intf_hr_len,
+			    MIN(pmbuf->data_len + sizeof(TxPD),
+				MAX_DATA_DUMP_LEN));
+		break;
+#endif
+	case MLAN_STATUS_RESOURCE:
+#ifdef STA_SUPPORT
+		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+		    pmadapter->pps_uapsd_mode &&
+		    (pmadapter->tx_lock_flag == MTRUE)) {
+			pmadapter->tx_lock_flag = MFALSE;
+			if (plocal_tx_pd != MNULL)
+				plocal_tx_pd->flags = 0;
+		}
+#endif
+		PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+		break;
+	case MLAN_STATUS_FAILURE:
+		pmadapter->dbg.num_tx_host_to_card_failure++;
+		pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
+		wlan_write_data_complete(pmadapter, pmbuf, ret);
+		break;
+	case MLAN_STATUS_PENDING:
+		DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + priv->intf_hr_len,
+			    MIN(pmbuf->data_len + sizeof(TxPD),
+				MAX_DATA_DUMP_LEN));
+		break;
+	case MLAN_STATUS_SUCCESS:
+		DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + priv->intf_hr_len,
+			    MIN(pmbuf->data_len + sizeof(TxPD),
+				MAX_DATA_DUMP_LEN));
+		wlan_write_data_complete(pmadapter, pmbuf, ret);
+		break;
+	default:
+		break;
+	}
+
+	if ((ret == MLAN_STATUS_SUCCESS) || (ret == MLAN_STATUS_PENDING)) {
+		PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
+		PRINTM_NETINTF(MDATA, priv);
+		PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Packet send completion handling
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *  @param status		Callback status
+ *
+ *  @return			MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_write_data_complete(pmlan_adapter pmadapter,
+			 pmlan_buffer pmbuf, mlan_status status)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb;
+
+	ENTER();
+
+	MASSERT(pmadapter && pmbuf);
+	if (!pmadapter || !pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	pcb = &pmadapter->callbacks;
+
+	if ((pmbuf->buf_type == MLAN_BUF_TYPE_DATA) ||
+	    (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)) {
+		PRINTM(MINFO, "wlan_write_data_complete: DATA %p\n", pmbuf);
+#if defined(USB)
+		if ((pmbuf->flags & MLAN_BUF_FLAG_USB_TX_AGGR) &&
+		    pmbuf->use_count) {
+			pmlan_buffer pmbuf_next;
+			t_u32 i, use_count = pmbuf->use_count;
+			for (i = 0; i <= use_count; i++) {
+				pmbuf_next = pmbuf->pnext;
+				if (pmbuf->flags & MLAN_BUF_FLAG_MOAL_TX_BUF)
+					pcb->moal_send_packet_complete
+						(pmadapter->pmoal_handle, pmbuf,
+						 status);
+				else
+					wlan_free_mlan_buffer(pmadapter, pmbuf);
+				pmbuf = pmbuf_next;
+			}
+		} else {
+#endif
+			if (pmbuf->flags & MLAN_BUF_FLAG_MOAL_TX_BUF) {
+				/* pmbuf was allocated by MOAL */
+				pcb->moal_send_packet_complete(pmadapter->
+							       pmoal_handle,
+							       pmbuf, status);
+			} else {
+				/* pmbuf was allocated by MLAN */
+				wlan_free_mlan_buffer(pmadapter, pmbuf);
+			}
+#if defined(USB)
+		}
+#endif
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Packet receive completion callback handler
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *  @param pmbuf		A pointer to mlan_buffer structure
+ *  @param status		Callback status
+ *
+ *  @return			MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_recv_packet_complete(pmlan_adapter pmadapter,
+			  pmlan_buffer pmbuf, mlan_status status)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	MASSERT(pmadapter && pmbuf);
+	if (!pmadapter || !pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	MASSERT(pmbuf->bss_index < pmadapter->priv_num);
+
+	if (pmbuf->pparent) {
+		/** we will free the pparaent at the end of deaggr */
+		wlan_free_mlan_buffer(pmadapter, pmbuf);
+	} else {
+		pmadapter->ops.data_complete(pmadapter, pmbuf, status);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Add packet to Bypass TX queue
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *  @param pmbuf      Pointer to the mlan_buffer data struct
+ *
+ *  @return         N/A
+ */
+t_void
+wlan_add_buf_bypass_txqueue(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
+{
+	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+	ENTER();
+
+	if (pmbuf->buf_type != MLAN_BUF_TYPE_RAW_DATA)
+		pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->bypass_txq.plock);
+	pmadapter->bypass_pkt_count++;
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &priv->bypass_txq,
+			       (pmlan_linked_list)pmbuf, MNULL, MNULL);
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->bypass_txq.plock);
+	LEAVE();
+}
+
+/**
+ *  @brief Check if packets are available in Bypass TX queue
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *
+ *  @return         MFALSE if not empty; MTRUE if empty
+ */
+INLINE t_u8
+wlan_bypass_tx_list_empty(mlan_adapter *pmadapter)
+{
+	return (pmadapter->bypass_pkt_count) ? MFALSE : MTRUE;
+}
+
+/**
+ *  @brief Clean up the By-pass TX queue
+ *
+ *  @param priv     Pointer to the mlan_private data struct
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_cleanup_bypass_txq(mlan_private *priv)
+{
+	pmlan_buffer pmbuf;
+	mlan_adapter *pmadapter = priv->adapter;
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->bypass_txq.plock);
+	while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &priv->bypass_txq, MNULL,
+						     MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle, &priv->bypass_txq,
+				 (pmlan_linked_list)pmbuf, MNULL, MNULL);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+		pmadapter->bypass_pkt_count--;
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->bypass_txq.plock);
+	LEAVE();
+}
+
+/**
+ *  @brief Transmit the By-passed packet awaiting in by-pass queue
+ *
+ *  @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ *  @return        N/A
+ */
+t_void
+wlan_process_bypass_tx(pmlan_adapter pmadapter)
+{
+	pmlan_buffer pmbuf;
+	mlan_tx_param tx_param;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_private priv;
+	int j = 0;
+	ENTER();
+	do {
+		for (j = 0; j < pmadapter->priv_num; ++j) {
+			priv = pmadapter->priv[j];
+			if (priv) {
+				pmbuf = (pmlan_buffer)
+					util_dequeue_list(pmadapter->
+							  pmoal_handle,
+							  &priv->bypass_txq,
+							  pmadapter->callbacks.
+							  moal_spin_lock,
+							  pmadapter->callbacks.
+							  moal_spin_unlock);
+				if (pmbuf) {
+					pmadapter->callbacks.
+						moal_spin_lock(pmadapter->
+							       pmoal_handle,
+							       priv->bypass_txq.
+							       plock);
+					pmadapter->bypass_pkt_count--;
+					pmadapter->callbacks.
+						moal_spin_unlock(pmadapter->
+								 pmoal_handle,
+								 priv->
+								 bypass_txq.
+								 plock);
+					PRINTM(MINFO,
+					       "Dequeuing bypassed packet %p\n",
+					       pmbuf);
+					if (wlan_bypass_tx_list_empty
+					    (pmadapter))
+						tx_param.next_pkt_len = 0;
+					else
+						tx_param.next_pkt_len =
+							pmbuf->data_len;
+					status = wlan_process_tx(pmadapter->
+								 priv[pmbuf->
+								      bss_index],
+								 pmbuf,
+								 &tx_param);
+
+					if (status == MLAN_STATUS_RESOURCE) {
+						/* Queue the packet again so
+						 * that it will be TX'ed later
+						 */
+						pmadapter->callbacks.
+							moal_spin_lock
+							(pmadapter->
+							 pmoal_handle,
+							 priv->bypass_txq.
+							 plock);
+						pmadapter->bypass_pkt_count++;
+						util_enqueue_list_head
+							(pmadapter->
+							 pmoal_handle,
+							 &priv->bypass_txq,
+							 (pmlan_linked_list)
+							 pmbuf,
+							 pmadapter->callbacks.
+							 moal_spin_lock,
+							 pmadapter->callbacks.
+							 moal_spin_unlock);
+						pmadapter->callbacks.
+							moal_spin_unlock
+							(pmadapter->
+							 pmoal_handle,
+							 priv->bypass_txq.
+							 plock);
+					}
+					break;
+				} else {
+					PRINTM(MINFO, "Nothing to send\n");
+				}
+			}
+		}
+	} while (!pmadapter->data_sent && !pmadapter->tx_lock_flag &&
+		 !wlan_bypass_tx_list_empty(pmadapter));
+	LEAVE();
+}
diff --git a/wlan_sd8987/mlan/mlan_uap.h b/wlan_sd8987/mlan/mlan_uap.h
new file mode 100755
index 0000000..63e6fd4
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap.h
@@ -0,0 +1,57 @@
+/** @file mlan_uap.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of uap functionalities
+ *
+ *
+ *  Copyright 2009-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#ifndef _MLAN_UAP_H_
+#define _MLAN_UAP_H_
+
+mlan_status wlan_uap_get_channel(pmlan_private pmpriv);
+
+mlan_status wlan_uap_set_channel(pmlan_private pmpriv,
+				 Band_Config_t uap_band_cfg, t_u8 channel);
+
+mlan_status wlan_uap_get_beacon_dtim(pmlan_private pmpriv);
+
+mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req);
+
+mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
+				     t_u16 cmd_action, t_u32 cmd_oid,
+				     t_void *pioctl_buf,
+				     t_void *pdata_buf, t_void *pcmd_buf);
+
+mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+					 t_void *pcmd_buf, t_void *pioctl);
+
+mlan_status wlan_ops_uap_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_process_event(t_void *priv);
+
+t_void *wlan_ops_uap_process_txpd(t_void *priv, pmlan_buffer pmbuf);
+
+mlan_status wlan_ops_uap_init_cmd(t_void *priv, t_u8 first_bss);
+
+#endif /* _MLAN_UAP_H_ */
diff --git a/wlan_sd8987/mlan/mlan_uap_cmdevent.c b/wlan_sd8987/mlan/mlan_uap_cmdevent.c
new file mode 100755
index 0000000..cfdd7f3
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap_cmdevent.c
@@ -0,0 +1,5927 @@
+/** @file mlan_uap_cmdevent.c
+ *
+ *  @brief This file contains the handling of AP mode command and event
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_main.h"
+#include "mlan_uap.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#include "mlan_11n.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function prepares command of BAND_STEERING_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_set_get_band_steering_cfg(pmlan_private pmpriv,
+				   HostCmd_DS_COMMAND *cmd,
+				   t_u16 cmd_action, t_void *pdata_buf)
+{
+	mlan_ds_band_steer_cfg *pband_steer_cfg =
+		(mlan_ds_band_steer_cfg *) pdata_buf;
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BAND_STEERING);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_BAND_STEERING) + S_DS_GEN);
+	cmd->params.band_steer_info.state = pband_steer_cfg->state;
+	cmd->params.band_steer_info.block_2g_prb_req =
+		pband_steer_cfg->block_2g_prb_req;
+	cmd->params.band_steer_info.max_btm_req_allowed =
+		pband_steer_cfg->max_btm_req_allowed;
+	cmd->params.band_steer_info.action = cmd_action;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle response of HostCmd_CMD_802_11_BAND_STEERING
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         Pointer to command response buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_ret_set_get_band_steering_cfg(mlan_private *pmpriv,
+				   HostCmd_DS_COMMAND *resp,
+				   mlan_ioctl_req *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_BAND_STEERING *pband_steer_info =
+		&resp->params.band_steer_info;
+	mlan_ds_misc_cfg *pband_steer;
+
+	ENTER();
+
+	pband_steer = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	pband_steer->param.band_steer_cfg.action = pband_steer_info->action;
+	pband_steer->param.band_steer_cfg.state = pband_steer_info->state;
+	pband_steer->param.band_steer_cfg.block_2g_prb_req =
+		pband_steer_info->block_2g_prb_req;
+	pband_steer->param.band_steer_cfg.max_btm_req_allowed =
+		pband_steer_info->max_btm_req_allowed;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of BEACON_STUCK_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_cmd_set_get_beacon_stuck_cfg(IN pmlan_private pmpriv,
+				  IN HostCmd_DS_COMMAND *cmd,
+				  IN t_u16 cmd_action, IN t_void *pdata_buf)
+{
+	HostCmd_DS_BEACON_STUCK_CFG *pbeacon_stuck_param_cfg =
+		(HostCmd_DS_BEACON_STUCK_CFG *) (pdata_buf + sizeof(t_u32));
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_UAP_BEACON_STUCK_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BEACON_STUCK_CFG) +
+				     S_DS_GEN);
+	cmd->params.beacon_stuck_cfg.beacon_stuck_detect_count =
+		pbeacon_stuck_param_cfg->beacon_stuck_detect_count;
+	cmd->params.beacon_stuck_cfg.recovery_confirm_count =
+		pbeacon_stuck_param_cfg->recovery_confirm_count;
+	cmd->params.beacon_stuck_cfg.action = cmd_action;
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle response of HostCmd_CMD_UAP_BEACON_STUCK_CFG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         Pointer to command response buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_ret_set_get_beacon_stuck_cfg(mlan_private *pmpriv,
+				  HostCmd_DS_COMMAND *resp,
+				  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	HostCmd_DS_BEACON_STUCK_CFG *pbeacon_stuck_param_cfg =
+		&resp->params.beacon_stuck_cfg;
+	mlan_ds_misc_cfg *pbeacon_stuck;
+
+	ENTER();
+
+	pbeacon_stuck = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+	pbeacon_stuck->param.beacon_stuck_cfg.action =
+		pbeacon_stuck_param_cfg->action;
+	pbeacon_stuck->param.beacon_stuck_cfg.beacon_stuck_detect_count =
+		pbeacon_stuck_param_cfg->beacon_stuck_detect_count;
+	pbeacon_stuck->param.beacon_stuck_cfg.recovery_confirm_count =
+		pbeacon_stuck_param_cfg->recovery_confirm_count;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response error
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to command buffer
+ *
+ *  @return             N/A
+ */
+static mlan_status
+uap_process_cmdresp_error(mlan_private *pmpriv,
+			  HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+#if defined(USB)
+	t_u8 i;
+#endif
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+	if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG
+	    || resp->command != HostCmd_CMD_CHAN_REGION_CFG)
+		PRINTM(MERROR, "CMD_RESP: cmd %#x error, result=%#x\n",
+		       resp->command, resp->result);
+	if (pioctl_buf)
+		pioctl_buf->status_code = resp->result;
+	/*
+	 * Handling errors here
+	 */
+	switch (resp->command) {
+#ifdef SDIO
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
+		PRINTM(MMSG, "FW don't support SDIO single port rx aggr\n");
+		break;
+#endif
+
+	case HOST_CMD_APCMD_SYS_CONFIGURE:{
+			HostCmd_DS_SYS_CONFIG *sys_config =
+				(HostCmd_DS_SYS_CONFIG *)&resp->params.
+				sys_config;
+			t_u16 resp_len = 0, travel_len = 0, index;
+			mlan_ds_misc_custom_ie *cust_ie = MNULL;
+			mlan_ds_misc_cfg *misc = MNULL;
+			custom_ie *cptr;
+
+			if (!pioctl_buf ||
+			    (pioctl_buf->req_id != MLAN_IOCTL_MISC_CFG))
+				break;
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			if ((pioctl_buf->action == MLAN_ACT_SET) &&
+			    (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+				cust_ie = (mlan_ds_misc_custom_ie *)
+					sys_config->tlv_buffer;
+				if (cust_ie) {
+					cust_ie->type =
+						wlan_le16_to_cpu(cust_ie->type);
+					resp_len = cust_ie->len =
+						wlan_le16_to_cpu(cust_ie->len);
+					travel_len = 0;
+					/* conversion for index, mask, len */
+					if (resp_len == sizeof(t_u16))
+						cust_ie->ie_data_list[0].
+							ie_index =
+							wlan_cpu_to_le16
+							(cust_ie->
+							 ie_data_list[0]
+							 .ie_index);
+
+					while (resp_len > sizeof(t_u16)) {
+						cptr = (custom_ie
+							*)(((t_u8 *)cust_ie->
+							    ie_data_list) +
+							   travel_len);
+						index = cptr->ie_index =
+							wlan_le16_to_cpu(cptr->
+									 ie_index);
+						cptr->mgmt_subtype_mask =
+							wlan_le16_to_cpu(cptr->
+									 mgmt_subtype_mask);
+						cptr->ie_length =
+							wlan_le16_to_cpu(cptr->
+									 ie_length);
+						travel_len +=
+							cptr->ie_length +
+							sizeof(custom_ie) -
+							MAX_IE_SIZE;
+						resp_len -=
+							cptr->ie_length +
+							sizeof(custom_ie) -
+							MAX_IE_SIZE;
+						if ((pmpriv->mgmt_ie[index]
+						     .mgmt_subtype_mask ==
+						     cptr->mgmt_subtype_mask) &&
+						    (pmpriv->mgmt_ie[index].
+						     ie_length ==
+						     cptr->ie_length) &&
+						    !memcmp(pmpriv->adapter,
+							    pmpriv->
+							    mgmt_ie[index]
+							    .ie_buffer,
+							    cptr->ie_buffer,
+							    cptr->ie_length)) {
+							PRINTM(MERROR,
+							       "set custom ie fail, remove ie index :%d\n",
+							       index);
+							memset(pmadapter,
+							       &pmpriv->
+							       mgmt_ie[index],
+							       0,
+							       sizeof
+							       (custom_ie));
+						}
+					}
+				}
+			}
+		} break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+#ifdef USB
+		if (IS_USB(pmadapter->card_type)) {
+			for (i = 0; i < MAX_USB_TX_PORT_NUM; i++)
+				pmadapter->pcard_usb->usb_tx_aggr[i]
+					.aggr_ctrl.enable = MFALSE;
+			pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable =
+				MFALSE;
+		}
+#endif
+		break;
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = MLAN_STATUS_SUCCESS;
+		PRINTM(MCMND, "FW don't support chan region cfg command!\n");
+		break;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+	case HostCmd_CMD_CRYPTO:
+		PRINTM(MCMND, "crypto cmd result=0x%x!\n", resp->result);
+		ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	default:
+		break;
+	}
+
+	wlan_request_cmd_lock(pmadapter);
+	wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
+	pmadapter->curr_cmd = MNULL;
+	wlan_release_cmd_lock(pmadapter);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will return the pointer to station entry in station
+ * list table which matches the give mac address
+ *
+ *  @param priv    A pointer to mlan_private
+ *
+ *  @return	   A pointer to structure sta_node
+ */
+static void
+wlan_notify_station_deauth(mlan_private *priv)
+{
+	sta_node *sta_ptr;
+	t_u8 event_buf[100];
+	mlan_event *pevent = (mlan_event *)event_buf;
+	t_u8 *pbuf;
+
+	ENTER();
+	sta_ptr =
+		(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
+					   &priv->sta_list,
+					   priv->adapter->callbacks.
+					   moal_spin_lock,
+					   priv->adapter->callbacks.
+					   moal_spin_unlock);
+	if (!sta_ptr) {
+		LEAVE();
+		return;
+	}
+	while (sta_ptr != (sta_node *)&priv->sta_list) {
+		memset(priv->adapter, event_buf, 0, sizeof(event_buf));
+		pevent->bss_index = priv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+		pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2;
+		pbuf = (t_u8 *)pevent->event_buf;
+		/* reason field set to 0, Unspecified */
+		memcpy_ext(priv->adapter, pbuf + 2, sta_ptr->mac_addr,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		wlan_recv_event(priv, pevent->event_id, pevent);
+		sta_ptr = sta_ptr->pnext;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief This function prepares command of hs_cfg.
+ *
+ * @param pmpriv       A pointer to mlan_private structure
+ * @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action   The action: GET or SET
+ * @param pdata_buf    A pointer to data buffer
+ *
+ * @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_802_11_hs_cfg(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *cmd,
+			   t_u16 cmd_action, hs_config_param *pdata_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg =
+		(HostCmd_DS_802_11_HS_CFG_ENH *)&(cmd->params.opt_hs_cfg);
+	t_u8 *tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH);
+	MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL;
+	MrvlIEtypes_HS_Antmode_t *antmode_tlv = MNULL;
+	MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv = MNULL;
+	MrvlIEtypes_MgmtFrameFilter_t *mgmt_filter_tlv = MNULL;
+	MrvlIEtypes_WakeupExtend_t *ext_tlv = MNULL;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+				     sizeof(HostCmd_DS_802_11_HS_CFG_ENH));
+
+	if (pdata_buf == MNULL) {
+		phs_cfg->action = wlan_cpu_to_le16(HS_ACTIVATE);
+		phs_cfg->params.hs_activate.resp_ctrl =
+			wlan_cpu_to_le16(RESP_NEEDED);
+	} else {
+		phs_cfg->action = wlan_cpu_to_le16(HS_CONFIGURE);
+		phs_cfg->params.hs_config.conditions =
+			wlan_cpu_to_le32(pdata_buf->conditions);
+		phs_cfg->params.hs_config.gpio = pdata_buf->gpio;
+		phs_cfg->params.hs_config.gap = pdata_buf->gap;
+		if (pmpriv->adapter->min_wake_holdoff) {
+			cmd->size = wlan_cpu_to_le16(S_DS_GEN +
+						     sizeof
+						     (HostCmd_DS_802_11_HS_CFG_ENH)
+						     +
+						     sizeof
+						     (MrvlIEtypes_HsWakeHoldoff_t));
+			holdoff_tlv = (MrvlIEtypes_HsWakeHoldoff_t *)tlv;
+			holdoff_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_HS_WAKE_HOLDOFF);
+			holdoff_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_HsWakeHoldoff_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			holdoff_tlv->min_wake_holdoff =
+				wlan_cpu_to_le16(pmpriv->adapter->
+						 min_wake_holdoff);
+			tlv += sizeof(MrvlIEtypes_HsWakeHoldoff_t);
+		}
+		PRINTM(MCMND,
+		       "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d\n",
+		       phs_cfg->params.hs_config.conditions,
+		       phs_cfg->params.hs_config.gpio,
+		       phs_cfg->params.hs_config.gap,
+		       pmpriv->adapter->min_wake_holdoff);
+
+		if (pmadapter->param_type_ind == 1) {
+			cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+			gpio_tlv = (MrvlIEtypes_WakeupSourceGPIO_t *) tlv;
+			gpio_tlv->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
+			gpio_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_WakeupSourceGPIO_t)
+						 - sizeof(MrvlIEtypesHeader_t));
+			gpio_tlv->ind_gpio = (t_u8)pmadapter->ind_gpio;
+			gpio_tlv->level = (t_u8)pmadapter->level;
+			tlv += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+		}
+		if (pmadapter->param_type_ext == 2) {
+			cmd->size += sizeof(MrvlIEtypes_WakeupExtend_t);
+			ext_tlv = (MrvlIEtypes_WakeupExtend_t *) tlv;
+			ext_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_WAKEUP_EXTEND);
+			ext_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_WakeupExtend_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			ext_tlv->event_force_ignore =
+				wlan_cpu_to_le32(pmadapter->event_force_ignore);
+			ext_tlv->event_use_ext_gap =
+				wlan_cpu_to_le32(pmadapter->event_use_ext_gap);
+			ext_tlv->ext_gap = pmadapter->ext_gap;
+			ext_tlv->gpio_wave = pmadapter->gpio_wave;
+			tlv += sizeof(MrvlIEtypes_WakeupExtend_t);
+		}
+		if (pmadapter->mgmt_filter[0].type) {
+			int i = 0;
+			mgmt_frame_filter mgmt_filter[MAX_MGMT_FRAME_FILTER];
+			memset(pmadapter, mgmt_filter, 0,
+			       MAX_MGMT_FRAME_FILTER *
+			       sizeof(mgmt_frame_filter));
+			mgmt_filter_tlv = (MrvlIEtypes_MgmtFrameFilter_t *) tlv;
+			mgmt_filter_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_MGMT_FRAME_WAKEUP);
+			tlv += sizeof(MrvlIEtypesHeader_t);
+			while (i < MAX_MGMT_FRAME_FILTER &&
+			       pmadapter->mgmt_filter[i].type) {
+				mgmt_filter[i].action =
+					(t_u8)pmadapter->mgmt_filter[i].action;
+				mgmt_filter[i].type =
+					(t_u8)pmadapter->mgmt_filter[i].type;
+				mgmt_filter[i].frame_mask =
+					wlan_cpu_to_le32(pmadapter->
+							 mgmt_filter[i].
+							 frame_mask);
+				i++;
+			}
+			memcpy_ext(pmadapter, (t_u8 *)mgmt_filter_tlv->filter,
+				   (t_u8 *)mgmt_filter,
+				   i * sizeof(mgmt_frame_filter),
+				   sizeof(mgmt_filter_tlv->filter));
+			tlv += i * sizeof(mgmt_frame_filter);
+			mgmt_filter_tlv->header.len =
+				wlan_cpu_to_le16(i * sizeof(mgmt_frame_filter));
+			cmd->size += i * sizeof(mgmt_frame_filter) +
+				sizeof(MrvlIEtypesHeader_t);
+		}
+		if (pmadapter->hs_mimo_switch) {
+			cmd->size += sizeof(MrvlIEtypes_HS_Antmode_t);
+			antmode_tlv = (MrvlIEtypes_HS_Antmode_t *) tlv;
+			antmode_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_HS_ANTMODE);
+			antmode_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_HS_Antmode_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			antmode_tlv->txpath_antmode = ANTMODE_FW_DECISION;
+			antmode_tlv->rxpath_antmode = ANTMODE_FW_DECISION;
+			tlv += sizeof(MrvlIEtypes_HS_Antmode_t);
+			PRINTM(MCMND,
+			       "hs_mimo_switch=%d, txpath_antmode=%d, rxpath_antmode=%d\n",
+			       pmadapter->hs_mimo_switch,
+			       antmode_tlv->txpath_antmode,
+			       antmode_tlv->rxpath_antmode);
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of Tx data pause
+ *
+ *  @param pmpriv		A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_txdatapause(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd,
+			 t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_CMD_TX_DATA_PAUSE *pause_cmd =
+		(HostCmd_DS_CMD_TX_DATA_PAUSE *)&cmd->params.tx_data_pause;
+	mlan_ds_misc_tx_datapause *data_pause =
+		(mlan_ds_misc_tx_datapause *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CFG_TX_DATA_PAUSE);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_DATA_PAUSE) +
+				     S_DS_GEN);
+	pause_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		pause_cmd->enable_tx_pause = (t_u8)data_pause->tx_pause;
+		pause_cmd->pause_tx_count = (t_u8)data_pause->tx_buf_cnt;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of Tx data pause
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_txdatapause(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_CMD_TX_DATA_PAUSE *pause_cmd =
+		(HostCmd_DS_CMD_TX_DATA_PAUSE *)&resp->params.tx_data_pause;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.tx_datapause.tx_pause =
+			pause_cmd->enable_tx_pause;
+		misc_cfg->param.tx_datapause.tx_buf_cnt =
+			pause_cmd->pause_tx_count;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function will process tx pause event
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to event buf
+ *
+ *  @return	       N/A
+ */
+static void
+wlan_process_tx_pause_event(pmlan_private priv, pmlan_buffer pevent)
+{
+	t_u16 tlv_type, tlv_len;
+	int tlv_buf_left = pevent->data_len - sizeof(t_u32);
+	MrvlIEtypesHeader_t *tlv =
+		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+					sizeof(t_u32));
+	MrvlIEtypes_tx_pause_t *tx_pause_tlv;
+	sta_node *sta_ptr = MNULL;
+	t_u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	t_u32 total_pkts_queued;
+	t_u16 tx_pkts_queued = 0;
+	;
+
+	ENTER();
+
+	total_pkts_queued =
+		util_scalar_read(priv->adapter->pmoal_handle,
+				 &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		if (tlv_type == TLV_TYPE_TX_PAUSE) {
+			tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv;
+
+			if (!memcmp(priv->adapter, bc_mac,
+				    tx_pause_tlv->peermac,
+				    MLAN_MAC_ADDR_LENGTH))
+				tx_pkts_queued =
+					wlan_update_ralist_tx_pause(priv,
+								    tx_pause_tlv->
+								    peermac,
+								    tx_pause_tlv->
+								    tx_pause);
+			else if (!memcmp
+				 (priv->adapter, priv->curr_addr,
+				  tx_pause_tlv->peermac,
+				  MLAN_MAC_ADDR_LENGTH)) {
+				if (tx_pause_tlv->tx_pause)
+					priv->tx_pause = MTRUE;
+				else
+					priv->tx_pause = MFALSE;
+			} else {
+				sta_ptr =
+					wlan_get_station_entry(priv,
+							       tx_pause_tlv->
+							       peermac);
+				if (sta_ptr) {
+					if (sta_ptr->tx_pause !=
+					    tx_pause_tlv->tx_pause) {
+						sta_ptr->tx_pause =
+							tx_pause_tlv->tx_pause;
+						tx_pkts_queued =
+							wlan_update_ralist_tx_pause
+							(priv,
+							 tx_pause_tlv->peermac,
+							 tx_pause_tlv->
+							 tx_pause);
+					}
+				}
+			}
+			if (!tx_pause_tlv->tx_pause)
+				total_pkts_queued += tx_pkts_queued;
+			PRINTM(MCMND,
+			       "TxPause: " MACSTR
+			       " pause=%d, pkts=%d  pending=%d total=%d\n",
+			       MAC2STR(tx_pause_tlv->peermac),
+			       tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt,
+			       tx_pkts_queued, total_pkts_queued);
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function prepares command for config uap settings
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_cmd_ap_config(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd,
+		       t_u16 cmd_action, pmlan_ioctl_req pioctl_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+	t_u8 *tlv = MNULL;
+	MrvlIEtypes_MacAddr_t *tlv_mac = MNULL;
+	MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
+	MrvlIEtypes_beacon_period_t *tlv_beacon_period = MNULL;
+	MrvlIEtypes_dtim_period_t *tlv_dtim_period = MNULL;
+	MrvlIEtypes_RatesParamSet_t *tlv_rates = MNULL;
+	MrvlIEtypes_tx_rate_t *tlv_txrate = MNULL;
+	MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = MNULL;
+	MrvlIEtypes_tx_power_t *tlv_tx_power = MNULL;
+	MrvlIEtypes_bcast_ssid_t *tlv_bcast_ssid = MNULL;
+	MrvlIEtypes_antenna_mode_t *tlv_antenna = MNULL;
+	MrvlIEtypes_pkt_forward_t *tlv_pkt_forward = MNULL;
+	MrvlIEtypes_max_sta_count_t *tlv_sta_count = MNULL;
+	MrvlIEtypes_sta_ageout_t *tlv_sta_ageout = MNULL;
+	MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout = MNULL;
+	MrvlIEtypes_rts_threshold_t *tlv_rts_threshold = MNULL;
+	MrvlIEtypes_frag_threshold_t *tlv_frag_threshold = MNULL;
+	MrvlIEtypes_retry_limit_t *tlv_retry_limit = MNULL;
+	MrvlIEtypes_eapol_pwk_hsk_timeout_t *tlv_pairwise_timeout = MNULL;
+	MrvlIEtypes_eapol_pwk_hsk_retries_t *tlv_pairwise_retries = MNULL;
+	MrvlIEtypes_eapol_gwk_hsk_timeout_t *tlv_groupwise_timeout = MNULL;
+	MrvlIEtypes_eapol_gwk_hsk_retries_t *tlv_groupwise_retries = MNULL;
+	MrvlIEtypes_mgmt_ie_passthru_t *tlv_mgmt_ie_passthru = MNULL;
+	MrvlIEtypes_2040_coex_enable_t *tlv_2040_coex_enable = MNULL;
+	MrvlIEtypes_mac_filter_t *tlv_mac_filter = MNULL;
+	MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	MrvlIEtypes_auth_type_t *tlv_auth_type = MNULL;
+	MrvlIEtypes_encrypt_protocol_t *tlv_encrypt_protocol = MNULL;
+	MrvlIEtypes_akmp_t *tlv_akmp = MNULL;
+	MrvlIEtypes_pwk_cipher_t *tlv_pwk_cipher = MNULL;
+	MrvlIEtypes_gwk_cipher_t *tlv_gwk_cipher = MNULL;
+	MrvlIEtypes_rsn_replay_prot_t *tlv_rsn_prot = MNULL;
+	MrvlIEtypes_passphrase_t *tlv_passphrase = MNULL;
+	MrvlIEtypes_group_rekey_time_t *tlv_rekey_time = MNULL;
+	MrvlIEtypes_wep_key_t *tlv_wep_key = MNULL;
+	MrvlIETypes_HTCap_t *tlv_htcap = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+	MrvlIEtypes_preamble_t *tlv_preamble = MNULL;
+
+	t_u32 cmd_size = 0;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u16 i;
+	t_u16 ac;
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+	int rx_mcs_supp = 0;
+#endif
+
+	ENTER();
+	if (pioctl_buf == MNULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+	sys_config->action = wlan_cpu_to_le16(cmd_action);
+	cmd_size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN;
+
+	tlv = (t_u8 *)sys_config->tlv_buffer;
+	if (memcmp(pmpriv->adapter, zero_mac, &bss->param.bss_config.mac_addr,
+		   MLAN_MAC_ADDR_LENGTH)) {
+		tlv_mac = (MrvlIEtypes_MacAddr_t *)tlv;
+		tlv_mac->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+		tlv_mac->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+		memcpy_ext(pmpriv->adapter, tlv_mac->mac,
+			   &bss->param.bss_config.mac_addr,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
+		tlv += sizeof(MrvlIEtypes_MacAddr_t);
+	}
+
+	if (bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_ACS) {
+		/* ACS is not allowed when DFS repeater mode is on */
+		if (pmpriv->adapter->dfs_repeater) {
+			PRINTM(MERROR, "ACS is not allowed when"
+			       "DFS repeater mode is on.\n");
+			return MLAN_STATUS_FAILURE;
+		}
+	}
+
+	if (bss->param.bss_config.ssid.ssid_len) {
+		tlv_ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv;
+		tlv_ssid->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+		tlv_ssid->header.len = wlan_cpu_to_le16((t_u16)bss->param.
+							bss_config.ssid.
+							ssid_len);
+		memcpy_ext(pmpriv->adapter, tlv_ssid->ssid,
+			   bss->param.bss_config.ssid.ssid,
+			   bss->param.bss_config.ssid.ssid_len,
+			   MLAN_MAX_SSID_LENGTH);
+		cmd_size +=
+			sizeof(MrvlIEtypesHeader_t) +
+			bss->param.bss_config.ssid.ssid_len;
+		tlv += sizeof(MrvlIEtypesHeader_t) +
+			bss->param.bss_config.ssid.ssid_len;
+	}
+
+	if ((bss->param.bss_config.beacon_period >= MIN_BEACON_PERIOD) &&
+	    (bss->param.bss_config.beacon_period <= MAX_BEACON_PERIOD)) {
+		tlv_beacon_period = (MrvlIEtypes_beacon_period_t *)tlv;
+		tlv_beacon_period->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
+		tlv_beacon_period->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_beacon_period->beacon_period =
+			wlan_cpu_to_le16(bss->param.bss_config.beacon_period);
+		cmd_size += sizeof(MrvlIEtypes_beacon_period_t);
+		tlv += sizeof(MrvlIEtypes_beacon_period_t);
+	}
+
+	if ((bss->param.bss_config.dtim_period >= MIN_DTIM_PERIOD) &&
+	    (bss->param.bss_config.dtim_period <= MAX_DTIM_PERIOD)) {
+		tlv_dtim_period = (MrvlIEtypes_dtim_period_t *)tlv;
+		tlv_dtim_period->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
+		tlv_dtim_period->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_dtim_period->dtim_period =
+			bss->param.bss_config.dtim_period;
+		cmd_size += sizeof(MrvlIEtypes_dtim_period_t);
+		tlv += sizeof(MrvlIEtypes_dtim_period_t);
+	}
+
+	if (bss->param.bss_config.rates[0]) {
+		tlv_rates = (MrvlIEtypes_RatesParamSet_t *)tlv;
+		tlv_rates->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+		for (i = 0;
+		     i < MAX_DATA_RATES && bss->param.bss_config.rates[i];
+		     i++) {
+			tlv_rates->rates[i] = bss->param.bss_config.rates[i];
+		}
+		tlv_rates->header.len = wlan_cpu_to_le16(i);
+		cmd_size += sizeof(MrvlIEtypesHeader_t) + i;
+		tlv += sizeof(MrvlIEtypesHeader_t) + i;
+	}
+
+	if (bss->param.bss_config.tx_data_rate <= DATA_RATE_54M) {
+		tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+		tlv_txrate->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_TX_DATA_RATE);
+		tlv_txrate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_txrate->tx_data_rate =
+			wlan_cpu_to_le16(bss->param.bss_config.tx_data_rate);
+		cmd_size += sizeof(MrvlIEtypes_tx_rate_t);
+		tlv += sizeof(MrvlIEtypes_tx_rate_t);
+	}
+
+	if (bss->param.bss_config.tx_beacon_rate <= DATA_RATE_54M) {
+		tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+		tlv_txrate->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_TX_BEACON_RATE);
+		tlv_txrate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_txrate->tx_data_rate =
+			wlan_cpu_to_le16(bss->param.bss_config.tx_beacon_rate);
+		cmd_size += sizeof(MrvlIEtypes_tx_rate_t);
+		tlv += sizeof(MrvlIEtypes_tx_rate_t);
+	}
+
+	if (bss->param.bss_config.mcbc_data_rate <= DATA_RATE_54M) {
+		tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)tlv;
+		tlv_mcbc_rate->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_MCBC_DATA_RATE);
+		tlv_mcbc_rate->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_mcbc_rate->mcbc_data_rate =
+			wlan_cpu_to_le16(bss->param.bss_config.mcbc_data_rate);
+		cmd_size += sizeof(MrvlIEtypes_mcbc_rate_t);
+		tlv += sizeof(MrvlIEtypes_mcbc_rate_t);
+	}
+
+	if (bss->param.bss_config.tx_power_level <= MAX_TX_POWER) {
+		tlv_tx_power = (MrvlIEtypes_tx_power_t *)tlv;
+		tlv_tx_power->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_TX_POWER);
+		tlv_tx_power->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_tx_power->tx_power = bss->param.bss_config.tx_power_level;
+		cmd_size += sizeof(MrvlIEtypes_tx_power_t);
+		tlv += sizeof(MrvlIEtypes_tx_power_t);
+	}
+
+	if (bss->param.bss_config.bcast_ssid_ctl <= MAX_BCAST_SSID_CTL) {
+		tlv_bcast_ssid = (MrvlIEtypes_bcast_ssid_t *)tlv;
+		tlv_bcast_ssid->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID_CTL);
+		tlv_bcast_ssid->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_bcast_ssid->bcast_ssid_ctl =
+			bss->param.bss_config.bcast_ssid_ctl;
+		cmd_size += sizeof(MrvlIEtypes_bcast_ssid_t);
+		tlv += sizeof(MrvlIEtypes_bcast_ssid_t);
+	}
+
+	if ((bss->param.bss_config.tx_antenna == ANTENNA_MODE_A) ||
+	    (bss->param.bss_config.tx_antenna == ANTENNA_MODE_B)) {
+		tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv;
+		tlv_antenna->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_ANTENNA_CTL);
+		tlv_antenna->header.len =
+			wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+		tlv_antenna->which_antenna = TX_ANTENNA;
+		tlv_antenna->antenna_mode = bss->param.bss_config.tx_antenna;
+		cmd_size += sizeof(MrvlIEtypes_antenna_mode_t);
+		tlv += sizeof(MrvlIEtypes_antenna_mode_t);
+	}
+
+	if ((bss->param.bss_config.rx_antenna == ANTENNA_MODE_A) ||
+	    (bss->param.bss_config.rx_antenna == ANTENNA_MODE_B)) {
+		tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv;
+		tlv_antenna->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_ANTENNA_CTL);
+		tlv_antenna->header.len =
+			wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+		tlv_antenna->which_antenna = RX_ANTENNA;
+		tlv_antenna->antenna_mode = bss->param.bss_config.rx_antenna;
+		cmd_size += sizeof(MrvlIEtypes_antenna_mode_t);
+		tlv += sizeof(MrvlIEtypes_antenna_mode_t);
+	}
+
+	if (bss->param.bss_config.pkt_forward_ctl <= MAX_PKT_FWD_CTRL) {
+		tlv_pkt_forward = (MrvlIEtypes_pkt_forward_t *)tlv;
+		tlv_pkt_forward->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_PKT_FWD_CTL);
+		tlv_pkt_forward->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_pkt_forward->pkt_forward_ctl =
+			bss->param.bss_config.pkt_forward_ctl;
+		cmd_size += sizeof(MrvlIEtypes_pkt_forward_t);
+		tlv += sizeof(MrvlIEtypes_pkt_forward_t);
+	}
+
+	if (bss->param.bss_config.max_sta_count <= MAX_STA_COUNT) {
+		tlv_sta_count = (MrvlIEtypes_max_sta_count_t *)tlv;
+		tlv_sta_count->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_MAX_STA_CNT);
+		tlv_sta_count->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_sta_count->max_sta_count =
+			wlan_cpu_to_le16(bss->param.bss_config.max_sta_count);
+		cmd_size += sizeof(MrvlIEtypes_max_sta_count_t);
+		tlv += sizeof(MrvlIEtypes_max_sta_count_t);
+	}
+
+	if (((bss->param.bss_config.sta_ageout_timer >= MIN_STAGE_OUT_TIME) &&
+	     (bss->param.bss_config.sta_ageout_timer <= MAX_STAGE_OUT_TIME)) ||
+	    (bss->param.bss_config.sta_ageout_timer == 0)) {
+		tlv_sta_ageout = (MrvlIEtypes_sta_ageout_t *)tlv;
+		tlv_sta_ageout->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_STA_AGEOUT_TIMER);
+		tlv_sta_ageout->header.len = wlan_cpu_to_le16(sizeof(t_u32));
+		tlv_sta_ageout->sta_ageout_timer =
+			wlan_cpu_to_le32(bss->param.bss_config.
+					 sta_ageout_timer);
+		cmd_size += sizeof(MrvlIEtypes_sta_ageout_t);
+		tlv += sizeof(MrvlIEtypes_sta_ageout_t);
+	}
+
+	if (((bss->param.bss_config.ps_sta_ageout_timer >= MIN_STAGE_OUT_TIME)
+	     && (bss->param.bss_config.ps_sta_ageout_timer <=
+		 MAX_STAGE_OUT_TIME)) ||
+	    (bss->param.bss_config.ps_sta_ageout_timer == 0)) {
+		tlv_ps_sta_ageout = (MrvlIEtypes_ps_sta_ageout_t *)tlv;
+		tlv_ps_sta_ageout->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER);
+		tlv_ps_sta_ageout->header.len = wlan_cpu_to_le16(sizeof(t_u32));
+		tlv_ps_sta_ageout->ps_sta_ageout_timer =
+			wlan_cpu_to_le32(bss->param.bss_config.
+					 ps_sta_ageout_timer);
+		cmd_size += sizeof(MrvlIEtypes_ps_sta_ageout_t);
+		tlv += sizeof(MrvlIEtypes_ps_sta_ageout_t);
+	}
+	if (bss->param.bss_config.rts_threshold <= MAX_RTS_THRESHOLD) {
+		tlv_rts_threshold = (MrvlIEtypes_rts_threshold_t *)tlv;
+		tlv_rts_threshold->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
+		tlv_rts_threshold->header.len = wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_rts_threshold->rts_threshold =
+			wlan_cpu_to_le16(bss->param.bss_config.rts_threshold);
+		cmd_size += sizeof(MrvlIEtypes_rts_threshold_t);
+		tlv += sizeof(MrvlIEtypes_rts_threshold_t);
+	}
+
+	if ((bss->param.bss_config.frag_threshold >= MIN_FRAG_THRESHOLD) &&
+	    (bss->param.bss_config.frag_threshold <= MAX_FRAG_THRESHOLD)) {
+		tlv_frag_threshold = (MrvlIEtypes_frag_threshold_t *)tlv;
+		tlv_frag_threshold->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
+		tlv_frag_threshold->header.len =
+			wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_frag_threshold->frag_threshold =
+			wlan_cpu_to_le16(bss->param.bss_config.frag_threshold);
+		cmd_size += sizeof(MrvlIEtypes_frag_threshold_t);
+		tlv += sizeof(MrvlIEtypes_frag_threshold_t);
+	}
+
+	if (bss->param.bss_config.retry_limit <= MAX_RETRY_LIMIT) {
+		tlv_retry_limit = (MrvlIEtypes_retry_limit_t *)tlv;
+		tlv_retry_limit->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
+		tlv_retry_limit->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_retry_limit->retry_limit =
+			(t_u8)bss->param.bss_config.retry_limit;
+		cmd_size += sizeof(MrvlIEtypes_retry_limit_t);
+		tlv += sizeof(MrvlIEtypes_retry_limit_t);
+	}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	if (IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) {
+#endif
+		if (bss->param.bss_config.pairwise_update_timeout <
+		    (MAX_VALID_DWORD)) {
+			tlv_pairwise_timeout =
+				(MrvlIEtypes_eapol_pwk_hsk_timeout_t *)tlv;
+			tlv_pairwise_timeout->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT);
+			tlv_pairwise_timeout->header.len =
+				wlan_cpu_to_le16(sizeof(t_u32));
+			tlv_pairwise_timeout->pairwise_update_timeout =
+				wlan_cpu_to_le32(bss->param.bss_config.
+						 pairwise_update_timeout);
+			cmd_size += sizeof(MrvlIEtypes_eapol_pwk_hsk_timeout_t);
+			tlv += sizeof(MrvlIEtypes_eapol_pwk_hsk_timeout_t);
+		}
+
+		if (bss->param.bss_config.pwk_retries < (MAX_VALID_DWORD)) {
+			tlv_pairwise_retries =
+				(MrvlIEtypes_eapol_pwk_hsk_retries_t *)tlv;
+			tlv_pairwise_retries->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES);
+			tlv_pairwise_retries->header.len =
+				wlan_cpu_to_le16(sizeof(t_u32));
+			tlv_pairwise_retries->pwk_retries =
+				wlan_cpu_to_le32(bss->param.bss_config.
+						 pwk_retries);
+			cmd_size += sizeof(MrvlIEtypes_eapol_pwk_hsk_retries_t);
+			tlv += sizeof(MrvlIEtypes_eapol_pwk_hsk_retries_t);
+		}
+
+		if (bss->param.bss_config.groupwise_update_timeout <
+		    (MAX_VALID_DWORD)) {
+			tlv_groupwise_timeout =
+				(MrvlIEtypes_eapol_gwk_hsk_timeout_t *)tlv;
+			tlv_groupwise_timeout->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT);
+			tlv_groupwise_timeout->header.len =
+				wlan_cpu_to_le16(sizeof(t_u32));
+			tlv_groupwise_timeout->groupwise_update_timeout =
+				wlan_cpu_to_le32(bss->param.bss_config.
+						 groupwise_update_timeout);
+			cmd_size += sizeof(MrvlIEtypes_eapol_gwk_hsk_timeout_t);
+			tlv += sizeof(MrvlIEtypes_eapol_gwk_hsk_timeout_t);
+		}
+
+		if (bss->param.bss_config.gwk_retries < (MAX_VALID_DWORD)) {
+			tlv_groupwise_retries =
+				(MrvlIEtypes_eapol_gwk_hsk_retries_t *)tlv;
+			tlv_groupwise_retries->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES);
+			tlv_groupwise_retries->header.len =
+				wlan_cpu_to_le16(sizeof(t_u32));
+			tlv_groupwise_retries->gwk_retries =
+				wlan_cpu_to_le32(bss->param.bss_config.
+						 gwk_retries);
+			cmd_size += sizeof(MrvlIEtypes_eapol_gwk_hsk_retries_t);
+			tlv += sizeof(MrvlIEtypes_eapol_gwk_hsk_retries_t);
+		}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	}
+#endif
+	if ((bss->param.bss_config.filter.filter_mode <=
+	     MAC_FILTER_MODE_BLOCK_MAC) &&
+	    (bss->param.bss_config.filter.mac_count <= MAX_MAC_FILTER_NUM)) {
+		tlv_mac_filter = (MrvlIEtypes_mac_filter_t *)tlv;
+		tlv_mac_filter->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_STA_MAC_ADDR_FILTER);
+		tlv_mac_filter->header.len =
+			wlan_cpu_to_le16(2 +
+					 MLAN_MAC_ADDR_LENGTH *
+					 bss->param.bss_config.filter.
+					 mac_count);
+		tlv_mac_filter->count =
+			(t_u8)bss->param.bss_config.filter.mac_count;
+		tlv_mac_filter->filter_mode =
+			(t_u8)bss->param.bss_config.filter.filter_mode;
+		memcpy_ext(pmpriv->adapter, tlv_mac_filter->mac_address,
+			   (t_u8 *)bss->param.bss_config.filter.mac_list,
+			   MLAN_MAC_ADDR_LENGTH *
+			   bss->param.bss_config.filter.mac_count,
+			   MLAN_MAC_ADDR_LENGTH * MAX_MAC_FILTER_NUM);
+		cmd_size +=
+			sizeof(MrvlIEtypesHeader_t) + 2 +
+			MLAN_MAC_ADDR_LENGTH *
+			bss->param.bss_config.filter.mac_count;
+		tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+			MLAN_MAC_ADDR_LENGTH *
+			bss->param.bss_config.filter.mac_count;
+	}
+
+	if (((bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_MANUAL) &&
+	     (bss->param.bss_config.channel > 0) &&
+	     (bss->param.bss_config.channel <= MLAN_MAX_CHANNEL)) ||
+	    (bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_ACS)) {
+		tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv;
+		tlv_chan_band->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+		tlv_chan_band->header.len =
+			wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+		tlv_chan_band->bandcfg = bss->param.bss_config.bandcfg;
+		tlv_chan_band->channel = bss->param.bss_config.channel;
+		cmd_size += sizeof(MrvlIEtypes_channel_band_t);
+		tlv += sizeof(MrvlIEtypes_channel_band_t);
+	}
+
+	if ((bss->param.bss_config.num_of_chan) &&
+	    (bss->param.bss_config.num_of_chan <= MLAN_MAX_CHANNEL)) {
+		tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+		tlv_chan_list->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+		tlv_chan_list->header.len = wlan_cpu_to_le16((t_u16)
+							     (sizeof
+							      (ChanScanParamSet_t)
+							      *
+							      bss->param.
+							      bss_config.
+							      num_of_chan));
+		pscan_chan = tlv_chan_list->chan_scan_param;
+		for (i = 0; i < bss->param.bss_config.num_of_chan; i++) {
+			pscan_chan->chan_number =
+				bss->param.bss_config.chan_list[i].chan_number;
+			pscan_chan->bandcfg =
+				bss->param.bss_config.chan_list[i].bandcfg;
+			pscan_chan++;
+		}
+		cmd_size += sizeof(tlv_chan_list->header) +
+			(sizeof(ChanScanParamSet_t) *
+			 bss->param.bss_config.num_of_chan);
+		tlv += sizeof(tlv_chan_list->header) +
+			(sizeof(ChanScanParamSet_t) *
+			 bss->param.bss_config.num_of_chan);
+	}
+
+	if ((bss->param.bss_config.auth_mode <= MLAN_AUTH_MODE_SHARED) ||
+	    (bss->param.bss_config.auth_mode == MLAN_AUTH_MODE_AUTO)) {
+		tlv_auth_type = (MrvlIEtypes_auth_type_t *)tlv;
+		tlv_auth_type->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+		tlv_auth_type->header.len = wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_auth_type->auth_type =
+			(t_u8)bss->param.bss_config.auth_mode;
+		cmd_size += sizeof(MrvlIEtypes_auth_type_t);
+		tlv += sizeof(MrvlIEtypes_auth_type_t);
+	}
+
+	if (bss->param.bss_config.protocol) {
+		tlv_encrypt_protocol = (MrvlIEtypes_encrypt_protocol_t *)tlv;
+		tlv_encrypt_protocol->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_ENCRYPT_PROTOCOL);
+		tlv_encrypt_protocol->header.len =
+			wlan_cpu_to_le16(sizeof(t_u16));
+		tlv_encrypt_protocol->protocol =
+			wlan_cpu_to_le16(bss->param.bss_config.protocol);
+		cmd_size += sizeof(MrvlIEtypes_encrypt_protocol_t);
+		tlv += sizeof(MrvlIEtypes_encrypt_protocol_t);
+	}
+
+	if ((bss->param.bss_config.protocol & PROTOCOL_WPA) ||
+	    (bss->param.bss_config.protocol & PROTOCOL_WPA2) ||
+	    (bss->param.bss_config.protocol & PROTOCOL_EAP)) {
+		tlv_akmp = (MrvlIEtypes_akmp_t *)tlv;
+		tlv_akmp->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_AKMP);
+		tlv_akmp->key_mgmt =
+			wlan_cpu_to_le16(bss->param.bss_config.key_mgmt);
+		tlv_akmp->header.len = sizeof(t_u16);
+		tlv_akmp->key_mgmt_operation =
+			wlan_cpu_to_le16(bss->param.bss_config.
+					 key_mgmt_operation);
+		tlv_akmp->header.len += sizeof(t_u16);
+		tlv_akmp->header.len = wlan_cpu_to_le16(tlv_akmp->header.len);
+		cmd_size += sizeof(MrvlIEtypes_akmp_t);
+		tlv += sizeof(MrvlIEtypes_akmp_t);
+
+		if (bss->param.bss_config.wpa_cfg.pairwise_cipher_wpa &
+		    VALID_CIPHER_BITMAP) {
+			tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv;
+			tlv_pwk_cipher->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+			tlv_pwk_cipher->header.len =
+				wlan_cpu_to_le16(sizeof(t_u16) + sizeof(t_u8) +
+						 sizeof(t_u8));
+			tlv_pwk_cipher->protocol =
+				wlan_cpu_to_le16(PROTOCOL_WPA);
+			tlv_pwk_cipher->pairwise_cipher =
+				bss->param.bss_config.wpa_cfg.
+				pairwise_cipher_wpa;
+			cmd_size += sizeof(MrvlIEtypes_pwk_cipher_t);
+			tlv += sizeof(MrvlIEtypes_pwk_cipher_t);
+		}
+
+		if (bss->param.bss_config.wpa_cfg.pairwise_cipher_wpa2 &
+		    VALID_CIPHER_BITMAP) {
+			tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv;
+			tlv_pwk_cipher->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+			tlv_pwk_cipher->header.len =
+				wlan_cpu_to_le16(sizeof(t_u16) + sizeof(t_u8) +
+						 sizeof(t_u8));
+			tlv_pwk_cipher->protocol =
+				wlan_cpu_to_le16(PROTOCOL_WPA2);
+			tlv_pwk_cipher->pairwise_cipher =
+				bss->param.bss_config.wpa_cfg.
+				pairwise_cipher_wpa2;
+			cmd_size += sizeof(MrvlIEtypes_pwk_cipher_t);
+			tlv += sizeof(MrvlIEtypes_pwk_cipher_t);
+		}
+
+		if (bss->param.bss_config.wpa_cfg.group_cipher &
+		    VALID_CIPHER_BITMAP) {
+			tlv_gwk_cipher = (MrvlIEtypes_gwk_cipher_t *)tlv;
+			tlv_gwk_cipher->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_GWK_CIPHER);
+			tlv_gwk_cipher->header.len =
+				wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8));
+			tlv_gwk_cipher->group_cipher =
+				bss->param.bss_config.wpa_cfg.group_cipher;
+			cmd_size += sizeof(MrvlIEtypes_gwk_cipher_t);
+			tlv += sizeof(MrvlIEtypes_gwk_cipher_t);
+		}
+
+		if (bss->param.bss_config.wpa_cfg.rsn_protection <= MTRUE) {
+			tlv_rsn_prot = (MrvlIEtypes_rsn_replay_prot_t *)tlv;
+			tlv_rsn_prot->header.type =
+				wlan_cpu_to_le16
+				(TLV_TYPE_UAP_RSN_REPLAY_PROTECT);
+			tlv_rsn_prot->header.len =
+				wlan_cpu_to_le16(sizeof(t_u8));
+			tlv_rsn_prot->rsn_replay_prot =
+				bss->param.bss_config.wpa_cfg.rsn_protection;
+			cmd_size += sizeof(MrvlIEtypes_rsn_replay_prot_t);
+			tlv += sizeof(MrvlIEtypes_rsn_replay_prot_t);
+		}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if (IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) {
+#endif
+			if (bss->param.bss_config.wpa_cfg.length) {
+				tlv_passphrase =
+					(MrvlIEtypes_passphrase_t *)tlv;
+				tlv_passphrase->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_WPA_PASSPHRASE);
+				tlv_passphrase->header.len =
+					(t_u16)wlan_cpu_to_le16(bss->param.
+								bss_config.
+								wpa_cfg.length);
+				memcpy_ext(pmpriv->adapter,
+					   tlv_passphrase->passphrase,
+					   bss->param.bss_config.wpa_cfg.
+					   passphrase,
+					   bss->param.bss_config.wpa_cfg.length,
+					   bss->param.bss_config.wpa_cfg.
+					   length);
+				cmd_size +=
+					sizeof(MrvlIEtypesHeader_t) +
+					bss->param.bss_config.wpa_cfg.length;
+				tlv += sizeof(MrvlIEtypesHeader_t) +
+					bss->param.bss_config.wpa_cfg.length;
+			}
+
+			if (bss->param.bss_config.wpa_cfg.gk_rekey_time <
+			    MAX_GRP_TIMER) {
+				tlv_rekey_time =
+					(MrvlIEtypes_group_rekey_time_t *)tlv;
+				tlv_rekey_time->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_GRP_REKEY_TIME);
+				tlv_rekey_time->header.len =
+					wlan_cpu_to_le16(sizeof(t_u32));
+				tlv_rekey_time->gk_rekey_time =
+					wlan_cpu_to_le32(bss->param.bss_config.
+							 wpa_cfg.gk_rekey_time);
+				cmd_size +=
+					sizeof(MrvlIEtypes_group_rekey_time_t);
+				tlv += sizeof(MrvlIEtypes_group_rekey_time_t);
+			}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		}
+#endif
+	} else {
+		if ((bss->param.bss_config.wep_cfg.key0.length) &&
+		    ((bss->param.bss_config.wep_cfg.key0.length == 5) ||
+		     (bss->param.bss_config.wep_cfg.key0.length == 10) ||
+		     (bss->param.bss_config.wep_cfg.key0.length == 13) ||
+		     (bss->param.bss_config.wep_cfg.key0.length == 26))) {
+			tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+			tlv_wep_key->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+			tlv_wep_key->header.len =
+				wlan_cpu_to_le16(2 +
+						 bss->param.bss_config.wep_cfg.
+						 key0.length);
+			tlv_wep_key->key_index =
+				bss->param.bss_config.wep_cfg.key0.key_index;
+			tlv_wep_key->is_default =
+				bss->param.bss_config.wep_cfg.key0.is_default;
+			memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+				   bss->param.bss_config.wep_cfg.key0.key,
+				   bss->param.bss_config.wep_cfg.key0.length,
+				   bss->param.bss_config.wep_cfg.key0.length);
+			cmd_size +=
+				sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key0.length;
+			tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key0.length;
+		}
+
+		if ((bss->param.bss_config.wep_cfg.key1.length) &&
+		    ((bss->param.bss_config.wep_cfg.key1.length == 5) ||
+		     (bss->param.bss_config.wep_cfg.key1.length == 10) ||
+		     (bss->param.bss_config.wep_cfg.key1.length == 13) ||
+		     (bss->param.bss_config.wep_cfg.key1.length == 26))) {
+			tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+			tlv_wep_key->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+			tlv_wep_key->header.len =
+				wlan_cpu_to_le16(2 +
+						 bss->param.bss_config.wep_cfg.
+						 key1.length);
+			tlv_wep_key->key_index =
+				bss->param.bss_config.wep_cfg.key1.key_index;
+			tlv_wep_key->is_default =
+				bss->param.bss_config.wep_cfg.key1.is_default;
+			memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+				   bss->param.bss_config.wep_cfg.key1.key,
+				   bss->param.bss_config.wep_cfg.key1.length,
+				   bss->param.bss_config.wep_cfg.key1.length);
+			cmd_size +=
+				sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key1.length;
+			tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key1.length;
+		}
+
+		if ((bss->param.bss_config.wep_cfg.key2.length) &&
+		    ((bss->param.bss_config.wep_cfg.key2.length == 5) ||
+		     (bss->param.bss_config.wep_cfg.key2.length == 10) ||
+		     (bss->param.bss_config.wep_cfg.key2.length == 13) ||
+		     (bss->param.bss_config.wep_cfg.key2.length == 26))) {
+			tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+			tlv_wep_key->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+			tlv_wep_key->header.len =
+				wlan_cpu_to_le16(2 +
+						 bss->param.bss_config.wep_cfg.
+						 key2.length);
+			tlv_wep_key->key_index =
+				bss->param.bss_config.wep_cfg.key2.key_index;
+			tlv_wep_key->is_default =
+				bss->param.bss_config.wep_cfg.key2.is_default;
+			memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+				   bss->param.bss_config.wep_cfg.key2.key,
+				   bss->param.bss_config.wep_cfg.key2.length,
+				   bss->param.bss_config.wep_cfg.key2.length);
+			cmd_size +=
+				sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key2.length;
+			tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key2.length;
+		}
+
+		if ((bss->param.bss_config.wep_cfg.key3.length) &&
+		    ((bss->param.bss_config.wep_cfg.key3.length == 5) ||
+		     (bss->param.bss_config.wep_cfg.key3.length == 10) ||
+		     (bss->param.bss_config.wep_cfg.key3.length == 13) ||
+		     (bss->param.bss_config.wep_cfg.key3.length == 26))) {
+			tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+			tlv_wep_key->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+			tlv_wep_key->header.len =
+				wlan_cpu_to_le16(2 +
+						 bss->param.bss_config.wep_cfg.
+						 key3.length);
+			tlv_wep_key->key_index =
+				bss->param.bss_config.wep_cfg.key3.key_index;
+			tlv_wep_key->is_default =
+				bss->param.bss_config.wep_cfg.key3.is_default;
+			memcpy_ext(pmpriv->adapter, tlv_wep_key->key,
+				   bss->param.bss_config.wep_cfg.key3.key,
+				   bss->param.bss_config.wep_cfg.key3.length,
+				   bss->param.bss_config.wep_cfg.key3.length);
+			cmd_size +=
+				sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key3.length;
+			tlv += sizeof(MrvlIEtypesHeader_t) + 2 +
+				bss->param.bss_config.wep_cfg.key3.length;
+		}
+	}
+	if (bss->param.bss_config.ht_cap_info) {
+		tlv_htcap = (MrvlIETypes_HTCap_t *)tlv;
+		tlv_htcap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
+		tlv_htcap->header.len = wlan_cpu_to_le16(sizeof(HTCap_t));
+		tlv_htcap->ht_cap.ht_cap_info =
+			wlan_cpu_to_le16(bss->param.bss_config.ht_cap_info);
+		tlv_htcap->ht_cap.ampdu_param =
+			bss->param.bss_config.ampdu_param;
+		memcpy_ext(pmpriv->adapter, tlv_htcap->ht_cap.supported_mcs_set,
+			   bss->param.bss_config.supported_mcs_set, 16,
+			   sizeof(tlv_htcap->ht_cap.supported_mcs_set));
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(SD9097) || defined(USB9097)
+		if (IS_CARD9098(pmpriv->adapter->card_type) ||
+		    IS_CARD9097(pmpriv->adapter->card_type)) {
+			if (bss->param.bss_config.supported_mcs_set[0]) {
+				if (bss->param.bss_config.bandcfg.chanBand ==
+				    BAND_5GHZ)
+					rx_mcs_supp =
+						GET_RXMCSSUPP(pmpriv->adapter->
+							      user_htstream >>
+							      8);
+				else
+					rx_mcs_supp =
+						GET_RXMCSSUPP(pmpriv->adapter->
+							      user_htstream);
+
+				if (rx_mcs_supp == 0x1) {
+					tlv_htcap->ht_cap.supported_mcs_set[0] =
+						0xFF;
+					tlv_htcap->ht_cap.supported_mcs_set[1] =
+						0;
+				} else if (rx_mcs_supp == 0x2) {
+					tlv_htcap->ht_cap.supported_mcs_set[0] =
+						0xFF;
+					tlv_htcap->ht_cap.supported_mcs_set[1] =
+						0xFF;
+				}
+			}
+		}
+#endif
+		tlv_htcap->ht_cap.ht_ext_cap =
+			wlan_cpu_to_le16(bss->param.bss_config.ht_ext_cap);
+		tlv_htcap->ht_cap.tx_bf_cap =
+			wlan_cpu_to_le32(bss->param.bss_config.tx_bf_cap);
+		tlv_htcap->ht_cap.asel = bss->param.bss_config.asel;
+		cmd_size += sizeof(MrvlIETypes_HTCap_t);
+		tlv += sizeof(MrvlIETypes_HTCap_t);
+	}
+	if (bss->param.bss_config.mgmt_ie_passthru_mask < (MAX_VALID_DWORD)) {
+		tlv_mgmt_ie_passthru = (MrvlIEtypes_mgmt_ie_passthru_t *)tlv;
+		tlv_mgmt_ie_passthru->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK);
+		tlv_mgmt_ie_passthru->header.len =
+			wlan_cpu_to_le16(sizeof(t_u32));
+		/* keep copy in private data */
+		pmpriv->mgmt_frame_passthru_mask =
+			bss->param.bss_config.mgmt_ie_passthru_mask;
+		tlv_mgmt_ie_passthru->mgmt_ie_mask =
+			wlan_cpu_to_le32(bss->param.bss_config.
+					 mgmt_ie_passthru_mask);
+		cmd_size += sizeof(MrvlIEtypes_mgmt_ie_passthru_t);
+		tlv += sizeof(MrvlIEtypes_mgmt_ie_passthru_t);
+	}
+	if ((bss->param.bss_config.enable_2040coex == 0) ||
+	    (bss->param.bss_config.enable_2040coex == 1)) {
+		tlv_2040_coex_enable = (MrvlIEtypes_2040_coex_enable_t *)tlv;
+		tlv_2040_coex_enable->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_2040_BSS_COEX_CONTROL);
+		tlv_2040_coex_enable->header.len =
+			wlan_cpu_to_le16(sizeof(t_u8));
+		tlv_2040_coex_enable->enable_2040coex =
+			bss->param.bss_config.enable_2040coex;
+		cmd_size += sizeof(MrvlIEtypes_2040_coex_enable_t);
+		tlv += sizeof(MrvlIEtypes_2040_coex_enable_t);
+	}
+	if ((bss->param.bss_config.uap_host_based_config == MTRUE) ||
+	    (bss->param.bss_config.wmm_para.qos_info & 0x80 ||
+	     bss->param.bss_config.wmm_para.qos_info == 0x00)) {
+		tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)tlv;
+		tlv_wmm_parameter->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_VENDOR_SPECIFIC_IE);
+		tlv_wmm_parameter->header.len =
+			wlan_cpu_to_le16(sizeof
+					 (bss->param.bss_config.wmm_para));
+		memcpy_ext(pmpriv->adapter, tlv_wmm_parameter->wmm_para.ouitype,
+			   bss->param.bss_config.wmm_para.ouitype,
+			   sizeof(tlv_wmm_parameter->wmm_para.ouitype),
+			   sizeof(tlv_wmm_parameter->wmm_para.ouitype));
+		tlv_wmm_parameter->wmm_para.ouisubtype =
+			bss->param.bss_config.wmm_para.ouisubtype;
+		tlv_wmm_parameter->wmm_para.version =
+			bss->param.bss_config.wmm_para.version;
+		tlv_wmm_parameter->wmm_para.qos_info =
+			bss->param.bss_config.wmm_para.qos_info;
+		for (ac = 0; ac < 4; ac++) {
+			tlv_wmm_parameter->wmm_para.ac_params[ac]
+				.aci_aifsn.aifsn =
+				bss->param.bss_config.wmm_para.ac_params[ac]
+				.aci_aifsn.aifsn;
+			tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn.
+				aci =
+				bss->param.bss_config.wmm_para.ac_params[ac]
+				.aci_aifsn.aci;
+			tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_max =
+				bss->param.bss_config.wmm_para.ac_params[ac]
+				.ecw.ecw_max;
+			tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_min =
+				bss->param.bss_config.wmm_para.ac_params[ac]
+				.ecw.ecw_min;
+			tlv_wmm_parameter->wmm_para.ac_params[ac].tx_op_limit =
+				wlan_cpu_to_le16(bss->param.bss_config.wmm_para.
+						 ac_params[ac]
+						 .tx_op_limit);
+		}
+		cmd_size += sizeof(MrvlIEtypes_wmm_parameter_t);
+		tlv += sizeof(MrvlIEtypes_wmm_parameter_t);
+	}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	if (!IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter))
+		AuthenticatorBssConfig(pmpriv->psapriv,
+				       (t_u8 *)&bss->param.bss_config, 0, 0, 0);
+#endif
+	if (pmpriv->adapter->pcard_info->v17_fw_api &&
+	    bss->param.bss_config.preamble_type) {
+		tlv_preamble = (MrvlIEtypes_preamble_t *)tlv;
+		tlv_preamble->header.type =
+			wlan_cpu_to_le16(TLV_TYPE_UAP_PREAMBLE_CTL);
+		tlv_preamble->header.len =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypes_preamble_t) -
+					 sizeof(MrvlIEtypesHeader_t));
+		tlv_preamble->preamble_type =
+			wlan_cpu_to_le16(bss->param.bss_config.preamble_type);
+
+		cmd_size += sizeof(MrvlIEtypes_preamble_t);
+		tlv += sizeof(MrvlIEtypes_preamble_t);
+	}
+	cmd->size = (t_u16)wlan_cpu_to_le16(cmd_size);
+	PRINTM(MCMND, "AP config: cmd_size=%d\n", cmd_size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of sys_config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_cmd_sys_configure(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *cmd,
+			   t_u16 cmd_action,
+			   pmlan_ioctl_req pioctl_buf, t_void *pdata_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config;
+	MrvlIEtypes_MacAddr_t *mac_tlv = MNULL;
+	MrvlIEtypes_channel_band_t *pdat_tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *bcn_pd_tlv = MNULL,
+		*pdat_tlv_bcnpd = MNULL;
+	MrvlIEtypes_dtim_period_t *dtim_pd_tlv = MNULL,
+		*pdat_tlv_dtimpd = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	MrvlIEtypes_channel_band_t *chan_band_tlv = MNULL;
+	MrvlIEtypes_chan_bw_oper_t *poper_class_tlv = MNULL;
+	t_u8 length = 0;
+	t_u8 curr_oper_class = 1;
+	t_u8 *oper_class_ie = (t_u8 *)sys_config->tlv_buffer;
+	t_u16 i = 0;
+	t_u8 ac = 0;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypesHeader_t *ie_header =
+		(MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+	MrvlIEtypesHeader_t *pdata_header = (MrvlIEtypesHeader_t *)pdata_buf;
+	t_u8 *ie = (t_u8 *)sys_config->tlv_buffer + sizeof(MrvlIEtypesHeader_t);
+	t_u16 req_len = 0, travel_len = 0;
+	custom_ie *cptr = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	MrvlIEtypes_wacp_mode_t *tlv_wacp_mode = MNULL;
+	MrvlIEtypes_action_chan_switch_t *tlv_chan_switch = MNULL;
+	IEEEtypes_ChanSwitchAnn_t *csa_ie = MNULL;
+	IEEEtypes_ExtChanSwitchAnn_t *ecsa_ie = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
+	sys_config->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+	if (pioctl_buf == MNULL) {
+		if (pdata_buf) {
+			switch (pdata_header->type) {
+			case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+				pdat_tlv_cb =
+					(MrvlIEtypes_channel_band_t *)pdata_buf;
+				chan_band_tlv = (MrvlIEtypes_channel_band_t *)
+					sys_config->tlv_buffer;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_channel_band_t));
+				chan_band_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				chan_band_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					chan_band_tlv->bandcfg =
+						pdat_tlv_cb->bandcfg;
+					chan_band_tlv->channel =
+						pdat_tlv_cb->channel;
+				}
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_UAP_BEACON_PERIOD:
+				pdat_tlv_bcnpd = (MrvlIEtypes_beacon_period_t *)
+					pdata_buf;
+				bcn_pd_tlv = (MrvlIEtypes_beacon_period_t *)
+					sys_config->tlv_buffer;
+				cmd->size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 +
+					S_DS_GEN +
+					sizeof(MrvlIEtypes_beacon_period_t);
+				bcn_pd_tlv->header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_BEACON_PERIOD);
+				bcn_pd_tlv->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_beacon_period_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				if (cmd_action) {
+					bcn_pd_tlv->beacon_period =
+						wlan_cpu_to_le16
+						(pdat_tlv_bcnpd->beacon_period);
+				}
+				/* Add TLV_UAP_DTIM_PERIOD if it follws in
+				 * pdata_buf */
+				pdat_tlv_dtimpd =
+					(MrvlIEtypes_dtim_period_t
+					 *)(((t_u8 *)pdata_buf) +
+					    sizeof
+					    (MrvlIEtypes_beacon_period_t));
+				if (TLV_TYPE_UAP_DTIM_PERIOD ==
+				    pdat_tlv_dtimpd->header.type) {
+					dtim_pd_tlv =
+						(MrvlIEtypes_dtim_period_t
+						 *)(sys_config->tlv_buffer +
+						    sizeof
+						    (MrvlIEtypes_beacon_period_t));
+					cmd->size +=
+						sizeof
+						(MrvlIEtypes_dtim_period_t);
+					dtim_pd_tlv->header.type =
+						wlan_cpu_to_le16
+						(TLV_TYPE_UAP_DTIM_PERIOD);
+					dtim_pd_tlv->header.len =
+						wlan_cpu_to_le16(sizeof
+								 (MrvlIEtypes_dtim_period_t)
+								 -
+								 sizeof
+								 (MrvlIEtypesHeader_t));
+					if (cmd_action) {
+						dtim_pd_tlv->dtim_period =
+							pdat_tlv_dtimpd->
+							dtim_period;
+					}
+				}
+				/* Finalize cmd size */
+				cmd->size = wlan_cpu_to_le16(cmd->size);
+				ret = MLAN_STATUS_SUCCESS;
+				break;
+			case TLV_TYPE_MGMT_IE:
+				cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypesHeader_t) +
+							 cust_ie->len);
+				ie_header->type =
+					wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+				ie_header->len = wlan_cpu_to_le16(cust_ie->len);
+
+				if (ie) {
+					req_len = cust_ie->len;
+					travel_len = 0;
+					/* conversion for index, mask, len */
+					if (req_len == sizeof(t_u16))
+						cust_ie->ie_data_list[0]
+							.ie_index =
+							wlan_cpu_to_le16
+							(cust_ie->
+							 ie_data_list[0]
+							 .ie_index);
+					while (req_len > sizeof(t_u16)) {
+						cptr = (custom_ie
+							*)(((t_u8 *)&cust_ie->
+							    ie_data_list) +
+							   travel_len);
+						travel_len +=
+							cptr->ie_length +
+							sizeof(custom_ie) -
+							MAX_IE_SIZE;
+						req_len -=
+							cptr->ie_length +
+							sizeof(custom_ie) -
+							MAX_IE_SIZE;
+						cptr->ie_index =
+							wlan_cpu_to_le16(cptr->
+									 ie_index);
+						cptr->mgmt_subtype_mask =
+							wlan_cpu_to_le16(cptr->
+									 mgmt_subtype_mask);
+						cptr->ie_length =
+							wlan_cpu_to_le16(cptr->
+									 ie_length);
+					}
+					memcpy_ext(pmpriv->adapter, ie,
+						   cust_ie->ie_data_list,
+						   cust_ie->len, cust_ie->len);
+				}
+				break;
+			case REGULATORY_CLASS:
+				poper_class_tlv =
+					(MrvlIEtypes_chan_bw_oper_t *)
+					pdata_buf;
+				ret = wlan_get_curr_oper_class(pmpriv,
+							       poper_class_tlv->
+							       ds_chan_bw_oper.
+							       channel,
+							       poper_class_tlv->
+							       ds_chan_bw_oper.
+							       bandwidth,
+							       &curr_oper_class);
+				if (ret != MLAN_STATUS_SUCCESS) {
+					PRINTM(MERROR,
+					       "Can not get current oper class! bandwidth = %d, channel = %d\n",
+					       poper_class_tlv->ds_chan_bw_oper.
+					       bandwidth,
+					       poper_class_tlv->ds_chan_bw_oper.
+					       channel);
+				}
+
+				if (cmd_action == HostCmd_ACT_GEN_SET)
+					length = wlan_add_supported_oper_class_ie(pmpriv, &oper_class_ie, curr_oper_class);
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 length);
+				break;
+			case TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP:
+				memcpy_ext(pmpriv->adapter,
+					   sys_config->tlv_buffer, pdata_buf,
+					   sizeof
+					   (MrvlIEtypes_uap_max_sta_cnt_t),
+					   sizeof
+					   (MrvlIEtypes_uap_max_sta_cnt_t));
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_uap_max_sta_cnt_t));
+				break;
+			default:
+				PRINTM(MERROR,
+				       "Wrong data, or missing TLV_TYPE 0x%04x handler.\n",
+				       *(t_u16 *)pdata_buf);
+				break;
+			}
+			goto done;
+		} else {
+			mac_tlv =
+				(MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypes_MacAddr_t));
+			mac_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+			mac_tlv->header.len =
+				wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+			ret = MLAN_STATUS_SUCCESS;
+			goto done;
+		}
+	}
+	if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) {
+			mac_tlv =
+				(MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypes_MacAddr_t));
+			mac_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+			mac_tlv->header.len =
+				wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
+			if (cmd_action == HostCmd_ACT_GEN_SET)
+				memcpy_ext(pmpriv->adapter, mac_tlv->mac,
+					   &bss->param.mac_addr,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+		} else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM) {
+			tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)
+				sys_config->tlv_buffer;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof
+						 (MrvlIEtypes_wmm_parameter_t));
+			tlv_wmm_parameter->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_AP_WMM_PARAM);
+			tlv_wmm_parameter->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (bss->param.ap_wmm_para));
+			if (cmd_action == HostCmd_ACT_GEN_SET) {
+				for (ac = 0; ac < 4; ac++) {
+					tlv_wmm_parameter->wmm_para.
+						ac_params[ac]
+						.aci_aifsn.aifsn =
+						bss->param.ap_wmm_para.
+						ac_params[ac]
+						.aci_aifsn.aifsn;
+					tlv_wmm_parameter->wmm_para.
+						ac_params[ac]
+						.aci_aifsn.aci =
+						bss->param.ap_wmm_para.
+						ac_params[ac]
+						.aci_aifsn.aci;
+					tlv_wmm_parameter->wmm_para.
+						ac_params[ac]
+						.ecw.ecw_max =
+						bss->param.ap_wmm_para.
+						ac_params[ac]
+						.ecw.ecw_max;
+					tlv_wmm_parameter->wmm_para.
+						ac_params[ac]
+						.ecw.ecw_min =
+						bss->param.ap_wmm_para.
+						ac_params[ac]
+						.ecw.ecw_min;
+					tlv_wmm_parameter->wmm_para.
+						ac_params[ac]
+						.tx_op_limit =
+						wlan_cpu_to_le16(bss->param.
+								 ap_wmm_para.
+								 ac_params[ac]
+								 .tx_op_limit);
+				}
+			}
+		} else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS) {
+			tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)
+				sys_config->tlv_buffer;
+			tlv_chan_list->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+			if (bss->param.ap_scan_channels.num_of_chan &&
+			    bss->param.ap_scan_channels.num_of_chan <=
+			    MLAN_MAX_CHANNEL) {
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof(tlv_chan_list->
+								header) +
+							 sizeof
+							 (ChanScanParamSet_t) *
+							 bss->param.
+							 ap_scan_channels.
+							 num_of_chan);
+				tlv_chan_list->header.len =
+					wlan_cpu_to_le16((t_u16)
+							 (sizeof
+							  (ChanScanParamSet_t) *
+							  bss->param.
+							  ap_scan_channels.
+							  num_of_chan));
+				pscan_chan = tlv_chan_list->chan_scan_param;
+				for (i = 0;
+				     i <
+				     bss->param.ap_scan_channels.num_of_chan;
+				     i++) {
+					pscan_chan->chan_number =
+						bss->param.ap_scan_channels.
+						chan_list[i]
+						.chan_number;
+					pscan_chan->bandcfg =
+						bss->param.ap_scan_channels.
+						chan_list[i]
+						.bandcfg;
+					pscan_chan++;
+				}
+				PRINTM(MCMND,
+				       "Set AP scan channel list =  %d\n",
+				       bss->param.ap_scan_channels.num_of_chan);
+			} else {
+				tlv_chan_list->header.len = wlan_cpu_to_le16((t_u16)(sizeof(ChanScanParamSet_t) * MLAN_MAX_CHANNEL));
+				cmd->size =
+					wlan_cpu_to_le16(sizeof
+							 (HostCmd_DS_SYS_CONFIG)
+							 - 1 + S_DS_GEN +
+							 sizeof
+							 (MrvlIEtypes_ChanListParamSet_t)
+							 +
+							 sizeof
+							 (ChanScanParamSet_t) *
+							 MLAN_MAX_CHANNEL);
+			}
+		} else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+			chan_band_tlv = (MrvlIEtypes_channel_band_t *)
+				sys_config->tlv_buffer;
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof
+						 (MrvlIEtypes_channel_band_t));
+			chan_band_tlv->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+			chan_band_tlv->header.len =
+				wlan_cpu_to_le16(sizeof
+						 (MrvlIEtypes_channel_band_t) -
+						 sizeof(MrvlIEtypesHeader_t));
+			if (cmd_action == HostCmd_ACT_GEN_SET) {
+				chan_band_tlv->bandcfg =
+					bss->param.ap_channel.bandcfg;
+				chan_band_tlv->channel =
+					bss->param.ap_channel.channel;
+				PRINTM(MCMND,
+				       "Set AP channel, band=%d, channel=%d\n",
+				       bss->param.ap_channel.bandcfg,
+				       bss->param.ap_channel.channel);
+			}
+		} else if (bss->sub_command == MLAN_OID_ACTION_CHAN_SWITCH) {
+			cmd->size =
+				sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN +
+				sizeof(MrvlIEtypes_action_chan_switch_t);
+			tlv_chan_switch = (MrvlIEtypes_action_chan_switch_t *)
+				sys_config->tlv_buffer;
+			tlv_chan_switch->header.type =
+				wlan_cpu_to_le16
+				(MRVL_ACTION_CHAN_SWITCH_ANNOUNCE);
+			//mode reserve for future use
+			tlv_chan_switch->mode = 0;
+			if (bss->param.chanswitch.new_oper_class) {
+				tlv_chan_switch->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_action_chan_switch_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t) +
+							 sizeof
+							 (IEEEtypes_ExtChanSwitchAnn_t));
+				ecsa_ie =
+					(IEEEtypes_ExtChanSwitchAnn_t *)
+					tlv_chan_switch->ie_buf;
+				ecsa_ie->element_id = EXTEND_CHANNEL_SWITCH_ANN;
+				ecsa_ie->len =
+					sizeof(IEEEtypes_ExtChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				ecsa_ie->chan_switch_mode =
+					bss->param.chanswitch.chan_switch_mode;
+				ecsa_ie->chan_switch_count =
+					bss->param.chanswitch.chan_switch_count;
+				ecsa_ie->new_channel_num =
+					bss->param.chanswitch.new_channel_num;
+				ecsa_ie->new_oper_class =
+					bss->param.chanswitch.new_oper_class;
+				cmd->size +=
+					sizeof(IEEEtypes_ExtChanSwitchAnn_t);
+			} else {
+				tlv_chan_switch->header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_action_chan_switch_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t) +
+							 sizeof
+							 (IEEEtypes_ChanSwitchAnn_t));
+				csa_ie = (IEEEtypes_ChanSwitchAnn_t *)
+					tlv_chan_switch->ie_buf;
+				csa_ie->element_id = CHANNEL_SWITCH_ANN;
+				csa_ie->len =
+					sizeof(IEEEtypes_ChanSwitchAnn_t) -
+					sizeof(IEEEtypes_Header_t);
+				csa_ie->chan_switch_mode =
+					bss->param.chanswitch.chan_switch_mode;
+				csa_ie->chan_switch_count =
+					bss->param.chanswitch.chan_switch_count;
+				csa_ie->new_channel_num =
+					bss->param.chanswitch.new_channel_num;
+				cmd->size += sizeof(IEEEtypes_ChanSwitchAnn_t);
+			}
+			cmd->size = wlan_cpu_to_le16(cmd->size);
+		} else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) &&
+			   (cmd_action == HostCmd_ACT_GEN_SET)) {
+			ret = wlan_uap_cmd_ap_config(pmpriv, cmd, cmd_action,
+						     pioctl_buf);
+			goto done;
+		}
+	} else if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		if ((misc->sub_command == MLAN_OID_MISC_GEN_IE) &&
+		    (misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE)) {
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypesHeader_t) +
+						 misc->param.gen_ie.len);
+			ie_header->type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE);
+			ie_header->len =
+				wlan_cpu_to_le16(misc->param.gen_ie.len);
+			if (cmd_action == HostCmd_ACT_GEN_SET)
+				memcpy_ext(pmpriv->adapter, ie,
+					   misc->param.gen_ie.ie_data,
+					   misc->param.gen_ie.len,
+					   misc->param.gen_ie.len);
+		}
+		if ((misc->sub_command == MLAN_OID_MISC_CUSTOM_IE) &&
+		    (misc->param.cust_ie.type == TLV_TYPE_MGMT_IE)) {
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof(MrvlIEtypesHeader_t) +
+						 misc->param.cust_ie.len);
+			ie_header->type = wlan_cpu_to_le16(TLV_TYPE_MGMT_IE);
+			ie_header->len =
+				wlan_cpu_to_le16(misc->param.cust_ie.len);
+
+			if (ie) {
+				req_len = misc->param.cust_ie.len;
+				travel_len = 0;
+				/* conversion for index, mask, len */
+				if (req_len == sizeof(t_u16))
+					misc->param.cust_ie.ie_data_list[0]
+						.ie_index =
+						wlan_cpu_to_le16(misc->param.
+								 cust_ie.
+								 ie_data_list[0]
+								 .ie_index);
+				while (req_len > sizeof(t_u16)) {
+					cptr = (custom_ie
+						*)(((t_u8 *)&misc->param.
+						    cust_ie.ie_data_list) +
+						   travel_len);
+					travel_len +=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					req_len -=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					cptr->ie_index =
+						wlan_cpu_to_le16(cptr->
+								 ie_index);
+					cptr->mgmt_subtype_mask =
+						wlan_cpu_to_le16(cptr->
+								 mgmt_subtype_mask);
+					cptr->ie_length =
+						wlan_cpu_to_le16(cptr->
+								 ie_length);
+				}
+				if (misc->param.cust_ie.len)
+					memcpy_ext(pmpriv->adapter, ie,
+						   misc->param.cust_ie.
+						   ie_data_list,
+						   misc->param.cust_ie.len,
+						   misc->param.cust_ie.len);
+			}
+		}
+		if (misc->sub_command == MLAN_OID_MISC_WACP_MODE) {
+			tlv_wacp_mode =
+				(MrvlIEtypes_wacp_mode_t *) sys_config->
+				tlv_buffer;
+			tlv_wacp_mode->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_UAP_WACP_MODE);
+			tlv_wacp_mode->header.len =
+				wlan_cpu_to_le16(sizeof(t_u8));
+			if (cmd_action == HostCmd_ACT_GEN_SET) {
+				tlv_wacp_mode->wacp_mode =
+					misc->param.wacp_mode;
+			}
+			cmd->size =
+				wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) -
+						 1 + S_DS_GEN +
+						 sizeof
+						 (MrvlIEtypes_wacp_mode_t));
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles command resp for get uap settings
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_cmd_ap_config(pmlan_private pmpriv,
+			   HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+	mlan_ds_bss *bss = MNULL;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	t_u16 tlv_buf_left = 0;
+	t_u16 tlv_type = 0;
+	t_u16 tlv_len = 0;
+	MrvlIEtypes_MacAddr_t *tlv_mac = MNULL;
+	MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
+	MrvlIEtypes_beacon_period_t *tlv_beacon_period = MNULL;
+	MrvlIEtypes_dtim_period_t *tlv_dtim_period = MNULL;
+	MrvlIEtypes_RatesParamSet_t *tlv_rates = MNULL;
+	MrvlIEtypes_tx_rate_t *tlv_txrate = MNULL;
+	MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = MNULL;
+	MrvlIEtypes_tx_power_t *tlv_tx_power = MNULL;
+	MrvlIEtypes_bcast_ssid_t *tlv_bcast_ssid = MNULL;
+	MrvlIEtypes_antenna_mode_t *tlv_antenna = MNULL;
+	MrvlIEtypes_pkt_forward_t *tlv_pkt_forward = MNULL;
+	MrvlIEtypes_max_sta_count_t *tlv_sta_count = MNULL;
+	MrvlIEtypes_sta_ageout_t *tlv_sta_ageout = MNULL;
+	MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout = MNULL;
+	MrvlIEtypes_rts_threshold_t *tlv_rts_threshold = MNULL;
+	MrvlIEtypes_frag_threshold_t *tlv_frag_threshold = MNULL;
+	MrvlIEtypes_retry_limit_t *tlv_retry_limit = MNULL;
+	MrvlIEtypes_eapol_pwk_hsk_timeout_t *tlv_pairwise_timeout = MNULL;
+	MrvlIEtypes_eapol_pwk_hsk_retries_t *tlv_pairwise_retries = MNULL;
+	MrvlIEtypes_eapol_gwk_hsk_timeout_t *tlv_groupwise_timeout = MNULL;
+	MrvlIEtypes_eapol_gwk_hsk_retries_t *tlv_groupwise_retries = MNULL;
+	MrvlIEtypes_mgmt_ie_passthru_t *tlv_mgmt_ie_passthru = MNULL;
+	MrvlIEtypes_2040_coex_enable_t *tlv_2040_coex_enable = MNULL;
+	MrvlIEtypes_mac_filter_t *tlv_mac_filter = MNULL;
+	MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	MrvlIEtypes_auth_type_t *tlv_auth_type = MNULL;
+	MrvlIEtypes_encrypt_protocol_t *tlv_encrypt_protocol = MNULL;
+	MrvlIEtypes_akmp_t *tlv_akmp = MNULL;
+	MrvlIEtypes_pwk_cipher_t *tlv_pwk_cipher = MNULL;
+	MrvlIEtypes_gwk_cipher_t *tlv_gwk_cipher = MNULL;
+	MrvlIEtypes_rsn_replay_prot_t *tlv_rsn_prot = MNULL;
+	MrvlIEtypes_passphrase_t *tlv_passphrase = MNULL;
+#ifdef WIFI_DIRECT_SUPPORT
+	MrvlIEtypes_psk_t *tlv_psk = MNULL;
+#endif /* WIFI_DIRECT_SUPPORT */
+	MrvlIEtypes_group_rekey_time_t *tlv_rekey_time = MNULL;
+	MrvlIEtypes_wep_key_t *tlv_wep_key = MNULL;
+	MrvlIEtypes_preamble_t *tlv_preamble = MNULL;
+	MrvlIEtypes_bss_status_t *tlv_bss_status = MNULL;
+	MrvlIETypes_HTCap_t *tlv_htcap = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL;
+
+	wep_key *pkey = MNULL;
+	t_u16 i;
+	t_u16 ac;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+	tlv = (MrvlIEtypesHeader_t *)sys_config->tlv_buffer;
+	tlv_buf_left =
+		resp->size - (sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN);
+
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+
+		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
+			PRINTM(MERROR,
+			       "Error processing uAP sys config TLVs, bytes left < TLV length\n");
+			break;
+		}
+
+		switch (tlv_type) {
+		case TLV_TYPE_UAP_MAC_ADDRESS:
+			tlv_mac = (MrvlIEtypes_MacAddr_t *)tlv;
+			memcpy_ext(pmpriv->adapter,
+				   &bss->param.bss_config.mac_addr,
+				   tlv_mac->mac, MLAN_MAC_ADDR_LENGTH,
+				   MLAN_MAC_ADDR_LENGTH);
+			break;
+		case TLV_TYPE_SSID:
+			tlv_ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv;
+			bss->param.bss_config.ssid.ssid_len =
+				MIN(MLAN_MAX_SSID_LENGTH, tlv_len);
+			memcpy_ext(pmpriv->adapter,
+				   bss->param.bss_config.ssid.ssid,
+				   tlv_ssid->ssid, tlv_len,
+				   MLAN_MAX_SSID_LENGTH);
+			break;
+		case TLV_TYPE_UAP_BEACON_PERIOD:
+			tlv_beacon_period = (MrvlIEtypes_beacon_period_t *)tlv;
+			bss->param.bss_config.beacon_period =
+				wlan_le16_to_cpu(tlv_beacon_period->
+						 beacon_period);
+			pmpriv->uap_state_chan_cb.beacon_period =
+				wlan_le16_to_cpu(tlv_beacon_period->
+						 beacon_period);
+			break;
+		case TLV_TYPE_UAP_DTIM_PERIOD:
+			tlv_dtim_period = (MrvlIEtypes_dtim_period_t *)tlv;
+			bss->param.bss_config.dtim_period =
+				tlv_dtim_period->dtim_period;
+			pmpriv->uap_state_chan_cb.dtim_period =
+				tlv_dtim_period->dtim_period;
+			break;
+		case TLV_TYPE_RATES:
+			tlv_rates = (MrvlIEtypes_RatesParamSet_t *)tlv;
+			memcpy_ext(pmpriv->adapter, bss->param.bss_config.rates,
+				   tlv_rates->rates, tlv_len, MAX_DATA_RATES);
+			break;
+		case TLV_TYPE_UAP_TX_DATA_RATE:
+			tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+			bss->param.bss_config.tx_data_rate =
+				wlan_le16_to_cpu(tlv_txrate->tx_data_rate);
+			break;
+		case TLV_TYPE_UAP_TX_BEACON_RATE:
+			tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv;
+			bss->param.bss_config.tx_beacon_rate =
+				wlan_le16_to_cpu(tlv_txrate->tx_data_rate);
+			break;
+		case TLV_TYPE_UAP_MCBC_DATA_RATE:
+			tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)tlv;
+			bss->param.bss_config.mcbc_data_rate =
+				wlan_le16_to_cpu(tlv_mcbc_rate->mcbc_data_rate);
+			break;
+		case TLV_TYPE_UAP_TX_POWER:
+			tlv_tx_power = (MrvlIEtypes_tx_power_t *)tlv;
+			bss->param.bss_config.tx_power_level =
+				tlv_tx_power->tx_power;
+			break;
+		case TLV_TYPE_UAP_BCAST_SSID_CTL:
+			tlv_bcast_ssid = (MrvlIEtypes_bcast_ssid_t *)tlv;
+			bss->param.bss_config.bcast_ssid_ctl =
+				tlv_bcast_ssid->bcast_ssid_ctl;
+			break;
+		case TLV_TYPE_UAP_ANTENNA_CTL:
+			tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv;
+			if (tlv_antenna->which_antenna == TX_ANTENNA)
+				bss->param.bss_config.tx_antenna =
+					tlv_antenna->antenna_mode;
+			else if (tlv_antenna->which_antenna == RX_ANTENNA)
+				bss->param.bss_config.rx_antenna =
+					tlv_antenna->antenna_mode;
+			break;
+		case TLV_TYPE_UAP_PKT_FWD_CTL:
+			tlv_pkt_forward = (MrvlIEtypes_pkt_forward_t *)tlv;
+			bss->param.bss_config.pkt_forward_ctl =
+				tlv_pkt_forward->pkt_forward_ctl;
+			break;
+		case TLV_TYPE_UAP_MAX_STA_CNT:
+			tlv_sta_count = (MrvlIEtypes_max_sta_count_t *)tlv;
+			bss->param.bss_config.max_sta_count =
+				wlan_le16_to_cpu(tlv_sta_count->max_sta_count);
+			break;
+		case TLV_TYPE_UAP_STA_AGEOUT_TIMER:
+			tlv_sta_ageout = (MrvlIEtypes_sta_ageout_t *)tlv;
+			bss->param.bss_config.sta_ageout_timer =
+				wlan_le32_to_cpu(tlv_sta_ageout->
+						 sta_ageout_timer);
+			break;
+		case TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER:
+			tlv_ps_sta_ageout = (MrvlIEtypes_ps_sta_ageout_t *)tlv;
+			bss->param.bss_config.ps_sta_ageout_timer =
+				wlan_le32_to_cpu(tlv_ps_sta_ageout->
+						 ps_sta_ageout_timer);
+			break;
+		case TLV_TYPE_UAP_RTS_THRESHOLD:
+			tlv_rts_threshold = (MrvlIEtypes_rts_threshold_t *)tlv;
+			bss->param.bss_config.rts_threshold =
+				wlan_le16_to_cpu(tlv_rts_threshold->
+						 rts_threshold);
+			break;
+		case TLV_TYPE_UAP_FRAG_THRESHOLD:
+			tlv_frag_threshold =
+				(MrvlIEtypes_frag_threshold_t *)tlv;
+			bss->param.bss_config.frag_threshold =
+				wlan_le16_to_cpu(tlv_frag_threshold->
+						 frag_threshold);
+			break;
+		case TLV_TYPE_UAP_RETRY_LIMIT:
+			tlv_retry_limit = (MrvlIEtypes_retry_limit_t *)tlv;
+			bss->param.bss_config.retry_limit =
+				tlv_retry_limit->retry_limit;
+			break;
+		case TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT:
+			tlv_pairwise_timeout =
+				(MrvlIEtypes_eapol_pwk_hsk_timeout_t *)tlv;
+			bss->param.bss_config.pairwise_update_timeout =
+				wlan_le32_to_cpu(tlv_pairwise_timeout->
+						 pairwise_update_timeout);
+			break;
+		case TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES:
+			tlv_pairwise_retries =
+				(MrvlIEtypes_eapol_pwk_hsk_retries_t *)tlv;
+			bss->param.bss_config.pwk_retries =
+				wlan_le32_to_cpu(tlv_pairwise_retries->
+						 pwk_retries);
+			break;
+		case TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT:
+			tlv_groupwise_timeout =
+				(MrvlIEtypes_eapol_gwk_hsk_timeout_t *)tlv;
+			bss->param.bss_config.groupwise_update_timeout =
+				wlan_le32_to_cpu(tlv_groupwise_timeout->
+						 groupwise_update_timeout);
+			break;
+		case TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES:
+			tlv_groupwise_retries =
+				(MrvlIEtypes_eapol_gwk_hsk_retries_t *)tlv;
+			bss->param.bss_config.gwk_retries =
+				wlan_le32_to_cpu(tlv_groupwise_retries->
+						 gwk_retries);
+			break;
+		case TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK:
+			tlv_mgmt_ie_passthru =
+				(MrvlIEtypes_mgmt_ie_passthru_t *)tlv;
+			bss->param.bss_config.mgmt_ie_passthru_mask =
+				wlan_le32_to_cpu(tlv_mgmt_ie_passthru->
+						 mgmt_ie_mask);
+			break;
+		case TLV_TYPE_2040_BSS_COEX_CONTROL:
+			tlv_2040_coex_enable =
+				(MrvlIEtypes_2040_coex_enable_t *)tlv;
+			bss->param.bss_config.enable_2040coex =
+				tlv_2040_coex_enable->enable_2040coex;
+			break;
+		case TLV_TYPE_UAP_STA_MAC_ADDR_FILTER:
+			tlv_mac_filter = (MrvlIEtypes_mac_filter_t *)tlv;
+			bss->param.bss_config.filter.mac_count =
+				MIN(MAX_MAC_FILTER_NUM, tlv_mac_filter->count);
+			bss->param.bss_config.filter.filter_mode =
+				tlv_mac_filter->filter_mode;
+			memcpy_ext(pmpriv->adapter,
+				   (t_u8 *)bss->param.bss_config.filter.
+				   mac_list, tlv_mac_filter->mac_address,
+				   MLAN_MAC_ADDR_LENGTH *
+				   bss->param.bss_config.filter.mac_count,
+				   sizeof(bss->param.bss_config.filter.
+					  mac_list));
+			break;
+		case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+			tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv;
+			bss->param.bss_config.bandcfg = tlv_chan_band->bandcfg;
+			bss->param.bss_config.channel = tlv_chan_band->channel;
+			pmpriv->uap_state_chan_cb.bandcfg =
+				tlv_chan_band->bandcfg;
+			pmpriv->uap_state_chan_cb.channel =
+				tlv_chan_band->channel;
+			break;
+		case TLV_TYPE_CHANLIST:
+			tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
+			bss->param.bss_config.num_of_chan =
+				tlv_len / sizeof(ChanScanParamSet_t);
+			pscan_chan = tlv_chan_list->chan_scan_param;
+			for (i = 0; i < bss->param.bss_config.num_of_chan; i++) {
+				bss->param.bss_config.chan_list[i].chan_number =
+					pscan_chan->chan_number;
+				bss->param.bss_config.chan_list[i].bandcfg =
+					pscan_chan->bandcfg;
+				pscan_chan++;
+			}
+			break;
+		case TLV_TYPE_AUTH_TYPE:
+			tlv_auth_type = (MrvlIEtypes_auth_type_t *)tlv;
+			bss->param.bss_config.auth_mode =
+				tlv_auth_type->auth_type;
+			break;
+		case TLV_TYPE_UAP_ENCRYPT_PROTOCOL:
+			tlv_encrypt_protocol =
+				(MrvlIEtypes_encrypt_protocol_t *)tlv;
+			bss->param.bss_config.protocol =
+				wlan_le16_to_cpu(tlv_encrypt_protocol->
+						 protocol);
+			break;
+		case TLV_TYPE_UAP_AKMP:
+			tlv_akmp = (MrvlIEtypes_akmp_t *)tlv;
+			bss->param.bss_config.key_mgmt =
+				wlan_le16_to_cpu(tlv_akmp->key_mgmt);
+			if (tlv_len > sizeof(t_u16))
+				bss->param.bss_config.key_mgmt_operation =
+					wlan_le16_to_cpu(tlv_akmp->
+							 key_mgmt_operation);
+			break;
+		case TLV_TYPE_PWK_CIPHER:
+			tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv;
+			if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) &
+			    PROTOCOL_WPA)
+				bss->param.bss_config.wpa_cfg.
+					pairwise_cipher_wpa =
+					tlv_pwk_cipher->pairwise_cipher;
+			if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) &
+			    PROTOCOL_WPA2)
+				bss->param.bss_config.wpa_cfg.
+					pairwise_cipher_wpa2 =
+					tlv_pwk_cipher->pairwise_cipher;
+			if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) &
+			    PROTOCOL_WPA3_SAE)
+				bss->param.bss_config.wpa_cfg.
+					pairwise_cipher_wpa2 =
+					tlv_pwk_cipher->pairwise_cipher;
+			break;
+		case TLV_TYPE_GWK_CIPHER:
+			tlv_gwk_cipher = (MrvlIEtypes_gwk_cipher_t *)tlv;
+			bss->param.bss_config.wpa_cfg.group_cipher =
+				tlv_gwk_cipher->group_cipher;
+			break;
+		case TLV_TYPE_UAP_RSN_REPLAY_PROTECT:
+			tlv_rsn_prot = (MrvlIEtypes_rsn_replay_prot_t *)tlv;
+			bss->param.bss_config.wpa_cfg.rsn_protection =
+				tlv_rsn_prot->rsn_replay_prot;
+			break;
+		case TLV_TYPE_UAP_WPA_PASSPHRASE:
+			tlv_passphrase = (MrvlIEtypes_passphrase_t *)tlv;
+			bss->param.bss_config.wpa_cfg.length =
+				MIN(MLAN_PMK_HEXSTR_LENGTH, tlv_len);
+			memcpy_ext(pmpriv->adapter,
+				   bss->param.bss_config.wpa_cfg.passphrase,
+				   tlv_passphrase->passphrase,
+				   bss->param.bss_config.wpa_cfg.length,
+				   sizeof(bss->param.bss_config.wpa_cfg.
+					  passphrase));
+			break;
+#ifdef WIFI_DIRECT_SUPPORT
+		case TLV_TYPE_UAP_PSK:
+			tlv_psk = (MrvlIEtypes_psk_t *)tlv;
+			memcpy_ext(pmpriv->adapter, bss->param.bss_config.psk,
+				   tlv_psk->psk, tlv_len, MLAN_MAX_KEY_LENGTH);
+			break;
+#endif /* WIFI_DIRECT_SUPPORT */
+		case TLV_TYPE_UAP_GRP_REKEY_TIME:
+			tlv_rekey_time = (MrvlIEtypes_group_rekey_time_t *)tlv;
+			bss->param.bss_config.wpa_cfg.gk_rekey_time =
+				wlan_le32_to_cpu(tlv_rekey_time->gk_rekey_time);
+			break;
+		case TLV_TYPE_UAP_WEP_KEY:
+			tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv;
+			pkey = MNULL;
+			if (tlv_wep_key->key_index == 0)
+				pkey = &bss->param.bss_config.wep_cfg.key0;
+			else if (tlv_wep_key->key_index == 1)
+				pkey = &bss->param.bss_config.wep_cfg.key1;
+			else if (tlv_wep_key->key_index == 2)
+				pkey = &bss->param.bss_config.wep_cfg.key2;
+			else if (tlv_wep_key->key_index == 3)
+				pkey = &bss->param.bss_config.wep_cfg.key3;
+			if (pkey) {
+				pkey->key_index = tlv_wep_key->key_index;
+				pkey->is_default = tlv_wep_key->is_default;
+				pkey->length =
+					MIN(MAX_WEP_KEY_SIZE, (tlv_len - 2));
+				memcpy_ext(pmpriv->adapter, pkey->key,
+					   tlv_wep_key->key, pkey->length,
+					   pkey->length);
+			}
+			break;
+		case TLV_TYPE_UAP_PREAMBLE_CTL:
+			tlv_preamble = (MrvlIEtypes_preamble_t *)tlv;
+			bss->param.bss_config.preamble_type =
+				tlv_preamble->preamble_type;
+			break;
+		case TLV_TYPE_BSS_STATUS:
+			tlv_bss_status = (MrvlIEtypes_bss_status_t *)tlv;
+			bss->param.bss_config.bss_status =
+				wlan_le16_to_cpu(tlv_bss_status->bss_status);
+			pmpriv->uap_bss_started =
+				(bss->param.bss_config.bss_status) ? MTRUE :
+				MFALSE;
+			break;
+		case TLV_TYPE_HT_CAPABILITY:
+			tlv_htcap = (MrvlIETypes_HTCap_t *)tlv;
+			bss->param.bss_config.ht_cap_info =
+				wlan_le16_to_cpu(tlv_htcap->ht_cap.ht_cap_info);
+			bss->param.bss_config.ampdu_param =
+				tlv_htcap->ht_cap.ampdu_param;
+			memcpy_ext(pmpriv->adapter,
+				   bss->param.bss_config.supported_mcs_set,
+				   tlv_htcap->ht_cap.supported_mcs_set, 16,
+				   sizeof(bss->param.bss_config.
+					  supported_mcs_set));
+			bss->param.bss_config.ht_ext_cap =
+				wlan_le16_to_cpu(tlv_htcap->ht_cap.ht_ext_cap);
+			bss->param.bss_config.tx_bf_cap =
+				wlan_le32_to_cpu(tlv_htcap->ht_cap.tx_bf_cap);
+			bss->param.bss_config.asel = tlv_htcap->ht_cap.asel;
+			break;
+		case TLV_TYPE_VENDOR_SPECIFIC_IE:
+			tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)tlv;
+			bss->param.bss_config.wmm_para.qos_info =
+				tlv_wmm_parameter->wmm_para.qos_info;
+			for (ac = 0; ac < 4; ac++) {
+				bss->param.bss_config.wmm_para.ac_params[ac]
+					.aci_aifsn.aifsn =
+					tlv_wmm_parameter->wmm_para.
+					ac_params[ac]
+					.aci_aifsn.aifsn;
+				bss->param.bss_config.wmm_para.ac_params[ac]
+					.aci_aifsn.aci =
+					tlv_wmm_parameter->wmm_para.
+					ac_params[ac]
+					.aci_aifsn.aci;
+				bss->param.bss_config.wmm_para.ac_params[ac]
+					.ecw.ecw_max =
+					tlv_wmm_parameter->wmm_para.
+					ac_params[ac]
+					.ecw.ecw_max;
+				bss->param.bss_config.wmm_para.ac_params[ac]
+					.ecw.ecw_min =
+					tlv_wmm_parameter->wmm_para.
+					ac_params[ac]
+					.ecw.ecw_min;
+				bss->param.bss_config.wmm_para.ac_params[ac]
+					.tx_op_limit =
+					wlan_le16_to_cpu(tlv_wmm_parameter->
+							 wmm_para.ac_params[ac]
+							 .tx_op_limit);
+			}
+			break;
+		}
+
+		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	if (!IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter))
+		AuthenticatorBssConfig(pmpriv->psapriv,
+				       (t_u8 *)&bss->param.bss_config, 0, 0, 1);
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sys_reset
+ *         Clear various private state variables used by DFS.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_sys_reset(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	ENTER();
+
+	memset(pmpriv->adapter, &(pmpriv->uap_state_chan_cb.bandcfg), 0,
+	       sizeof(pmpriv->uap_state_chan_cb.bandcfg));
+	pmpriv->uap_state_chan_cb.channel = 0;
+	pmpriv->uap_state_chan_cb.beacon_period = 0;
+	pmpriv->uap_state_chan_cb.dtim_period = 0;
+
+	/* assume default 11d/11h states are off, should check with FW */
+	/* currently don't clear domain_info... global, could be from STA */
+	wlan_11d_priv_init(pmpriv);
+	wlan_11h_priv_init(pmpriv);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of sys_config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_sys_config(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	int resp_len = 0, travel_len = 0;
+	t_u32 i = 0;
+	custom_ie *cptr;
+	HostCmd_DS_SYS_CONFIG *sys_config =
+		(HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	MrvlIEtypes_MacAddr_t *tlv =
+		(MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer;
+	mlan_ds_misc_custom_ie *cust_ie = MNULL;
+	tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL;
+	MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter =
+		(MrvlIEtypes_wmm_parameter_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list =
+		(MrvlIEtypes_ChanListParamSet_t *)sys_config->tlv_buffer;
+	MrvlIEtypes_channel_band_t *chan_band_tlv =
+		(MrvlIEtypes_channel_band_t *)sys_config->tlv_buffer;
+	ChanScanParamSet_t *pscan_chan = MNULL;
+	t_u8 ac = 0;
+	MrvlIEtypes_channel_band_t *tlv_cb = MNULL;
+	MrvlIEtypes_beacon_period_t *tlv_bcnpd = MNULL;
+	MrvlIEtypes_dtim_period_t *tlv_dtimpd = MNULL;
+	MrvlIEtypes_uap_max_sta_cnt_t *tlv_uap_max_sta = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		if (pioctl_buf->req_id == MLAN_IOCTL_BSS) {
+			bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+			if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) {
+				if (TLV_TYPE_UAP_MAC_ADDRESS ==
+				    wlan_le16_to_cpu(tlv->header.type)) {
+					memcpy_ext(pmpriv->adapter,
+						   &bss->param.mac_addr,
+						   tlv->mac,
+						   MLAN_MAC_ADDR_LENGTH,
+						   MLAN_MAC_ADDR_LENGTH);
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_CFG_WMM_PARAM) {
+				if (TLV_TYPE_AP_WMM_PARAM ==
+				    wlan_le16_to_cpu(tlv_wmm_parameter->header.
+						     type)) {
+					if (wlan_le16_to_cpu
+					    (tlv_wmm_parameter->header.len) <
+					    sizeof(bss->param.ap_wmm_para)) {
+						PRINTM(MCMND,
+						       "FW don't support AP WMM PARAM\n");
+					} else {
+						bss->param.ap_wmm_para.
+							reserved =
+							MLAN_STATUS_COMPLETE;
+						for (ac = 0; ac < 4; ac++) {
+							bss->param.ap_wmm_para.
+								ac_params[ac]
+								.aci_aifsn.
+								aifsn =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac]
+								.aci_aifsn.
+								aifsn;
+							bss->param.ap_wmm_para.
+								ac_params[ac]
+								.aci_aifsn.aci =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac]
+								.aci_aifsn.aci;
+							bss->param.ap_wmm_para.
+								ac_params[ac]
+								.ecw.ecw_max =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac]
+								.ecw.ecw_max;
+							bss->param.ap_wmm_para.
+								ac_params[ac]
+								.ecw.ecw_min =
+								tlv_wmm_parameter->
+								wmm_para.
+								ac_params[ac]
+								.ecw.ecw_min;
+							bss->param.ap_wmm_para.
+								ac_params[ac]
+								.tx_op_limit =
+								wlan_le16_to_cpu
+								(tlv_wmm_parameter->
+								 wmm_para.
+								 ac_params[ac]
+								 .tx_op_limit);
+							PRINTM(MCMND,
+							       "ac=%d, aifsn=%d, aci=%d, ecw_max=%d, ecw_min=%d, tx_op=%d\n",
+							       ac,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac]
+							       .aci_aifsn.aifsn,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac]
+							       .aci_aifsn.aci,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac]
+							       .ecw.ecw_max,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac]
+							       .ecw.ecw_min,
+							       bss->param.
+							       ap_wmm_para.
+							       ac_params[ac]
+							       .tx_op_limit);
+						}
+					}
+				}
+			} else if (bss->sub_command ==
+				   MLAN_OID_UAP_SCAN_CHANNELS) {
+				if (TLV_TYPE_CHANLIST ==
+				    wlan_le16_to_cpu(tlv_chan_list->header.
+						     type)) {
+					pscan_chan =
+						tlv_chan_list->chan_scan_param;
+					bss->param.ap_scan_channels.
+						num_of_chan = 0;
+					for (i = 0;
+					     i <
+					     (int)
+					     wlan_le16_to_cpu(tlv_chan_list->
+							      header.len) /
+					     sizeof(ChanScanParamSet_t); i++) {
+						if (bss->param.ap_scan_channels.
+						    remove_nop_channel &&
+						    wlan_11h_is_channel_under_nop
+						    (pmpriv->adapter,
+						     pscan_chan->chan_number)) {
+							bss->param.
+								ap_scan_channels.
+								num_remvoed_channel++;
+							PRINTM(MCMND,
+							       "Remove nop channel=%d\n",
+							       pscan_chan->
+							       chan_number);
+							pscan_chan++;
+							continue;
+						}
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan]
+							.chan_number =
+							pscan_chan->chan_number;
+						bss->param.ap_scan_channels.
+							chan_list[bss->param.
+								  ap_scan_channels.
+								  num_of_chan]
+							.bandcfg =
+							pscan_chan->bandcfg;
+						bss->param.ap_scan_channels.
+							num_of_chan++;
+						pscan_chan++;
+					}
+					PRINTM(MCMND,
+					       "AP scan channel list=%d\n",
+					       bss->param.ap_scan_channels.
+					       num_of_chan);
+				}
+			} else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) {
+				if (TLV_TYPE_UAP_CHAN_BAND_CONFIG ==
+				    wlan_le16_to_cpu(chan_band_tlv->header.
+						     type)) {
+					bss->param.ap_channel.bandcfg =
+						chan_band_tlv->bandcfg;
+					bss->param.ap_channel.channel =
+						chan_band_tlv->channel;
+					bss->param.ap_channel.is_11n_enabled =
+						pmpriv->is_11n_enabled;
+					bss->param.ap_channel.is_dfs_chan =
+						wlan_11h_radar_detect_required
+						(pmpriv,
+						 bss->param.ap_channel.channel);
+					if (chan_band_tlv->bandcfg.chanWidth ==
+					    CHAN_BW_80MHZ)
+						bss->param.ap_channel.
+							center_chan =
+							wlan_get_center_freq_idx
+							(pmpriv, BAND_AAC,
+							 chan_band_tlv->channel,
+							 CHANNEL_BW_80MHZ);
+					PRINTM(MCMND,
+					       "AP channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n",
+					       bss->param.ap_channel.bandcfg,
+					       bss->param.ap_channel.channel,
+					       bss->param.ap_channel.
+					       is_11n_enabled,
+					       bss->param.ap_channel.
+					       center_chan);
+				}
+			} else if ((bss->sub_command ==
+				    MLAN_OID_UAP_BSS_CONFIG) &&
+				   (pioctl_buf->action == MLAN_ACT_GET)) {
+				wlan_uap_ret_cmd_ap_config(pmpriv, resp,
+							   pioctl_buf);
+			}
+		}
+		if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) {
+			misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+			cust_ie = (mlan_ds_misc_custom_ie *)
+				sys_config->tlv_buffer;
+			if ((pioctl_buf->action == MLAN_ACT_GET ||
+			     pioctl_buf->action == MLAN_ACT_SET) &&
+			    (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) {
+				cust_ie->type = wlan_le16_to_cpu(cust_ie->type);
+				resp_len = cust_ie->len =
+					wlan_le16_to_cpu(cust_ie->len);
+				travel_len = 0;
+				/* conversion for index, mask, len */
+				if (resp_len == sizeof(t_u16))
+					cust_ie->ie_data_list[0].ie_index =
+						wlan_cpu_to_le16(cust_ie->
+								 ie_data_list[0]
+								 .ie_index);
+
+				while (resp_len > (int)sizeof(t_u16)) {
+					cptr = (custom_ie
+						*)(((t_u8 *)cust_ie->
+						    ie_data_list) + travel_len);
+					cptr->ie_index =
+						wlan_le16_to_cpu(cptr->
+								 ie_index);
+					cptr->mgmt_subtype_mask =
+						wlan_le16_to_cpu(cptr->
+								 mgmt_subtype_mask);
+					cptr->ie_length =
+						wlan_le16_to_cpu(cptr->
+								 ie_length);
+					travel_len +=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+					resp_len -=
+						cptr->ie_length +
+						sizeof(custom_ie) - MAX_IE_SIZE;
+				}
+				memcpy_ext(pmpriv->adapter,
+					   &misc->param.cust_ie, cust_ie,
+					   cust_ie->len +
+					   sizeof(MrvlIEtypesHeader_t),
+					   sizeof(mlan_ds_misc_custom_ie) -
+					   sizeof(tlvbuf_max_mgmt_ie));
+				max_mgmt_ie =
+					(tlvbuf_max_mgmt_ie
+					 *)(sys_config->tlv_buffer +
+					    cust_ie->len +
+					    sizeof(MrvlIEtypesHeader_t));
+				if (max_mgmt_ie) {
+					max_mgmt_ie->type =
+						wlan_le16_to_cpu(max_mgmt_ie->
+								 type);
+					if (max_mgmt_ie->type ==
+					    TLV_TYPE_MAX_MGMT_IE) {
+						max_mgmt_ie->len =
+							wlan_le16_to_cpu
+							(max_mgmt_ie->len);
+						max_mgmt_ie->count =
+							wlan_le16_to_cpu
+							(max_mgmt_ie->count);
+						for (i = 0;
+						     i < max_mgmt_ie->count;
+						     i++) {
+							max_mgmt_ie->info[i]
+								.buf_size =
+								wlan_le16_to_cpu
+								(max_mgmt_ie->
+								 info[i]
+								 .buf_size);
+							max_mgmt_ie->info[i]
+								.buf_count =
+								wlan_le16_to_cpu
+								(max_mgmt_ie->
+								 info[i]
+								 .buf_count);
+						}
+						/* Append max_mgmt_ie TLV after
+						 * custom_ie */
+						memcpy_ext(pmpriv->adapter,
+							   (t_u8 *)&misc->param.
+							   cust_ie +
+							   (cust_ie->len +
+							    sizeof
+							    (MrvlIEtypesHeader_t)),
+							   max_mgmt_ie,
+							   max_mgmt_ie->len +
+							   sizeof
+							   (MrvlIEtypesHeader_t),
+							   sizeof
+							   (tlvbuf_max_mgmt_ie));
+					}
+				}
+			}
+		}
+	} else {		/* no ioctl: driver generated get/set */
+		switch (wlan_le16_to_cpu(tlv->header.type)) {
+		case TLV_TYPE_UAP_MAC_ADDRESS:
+			memcpy_ext(pmpriv->adapter, pmpriv->curr_addr, tlv->mac,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+			break;
+		case TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP:
+			tlv_uap_max_sta = (MrvlIEtypes_uap_max_sta_cnt_t *) tlv;
+			pmpriv->adapter->max_sta_conn =
+				wlan_le16_to_cpu(tlv_uap_max_sta->uap_max_sta);
+			PRINTM(MCMND, "Uap max_sta per chip=%d\n",
+			       wlan_le16_to_cpu(tlv_uap_max_sta->uap_max_sta));
+			break;
+		case TLV_TYPE_UAP_CHAN_BAND_CONFIG:
+			tlv_cb = (MrvlIEtypes_channel_band_t *)tlv;
+			pmpriv->uap_state_chan_cb.bandcfg = tlv_cb->bandcfg;
+			pmpriv->uap_state_chan_cb.channel = tlv_cb->channel;
+			/* call callback waiting for channel info */
+			if (pmpriv->uap_state_chan_cb.get_chan_callback)
+				pmpriv->uap_state_chan_cb.
+					get_chan_callback(pmpriv);
+			break;
+		case TLV_TYPE_UAP_BEACON_PERIOD:
+			tlv_bcnpd = (MrvlIEtypes_beacon_period_t *)tlv;
+			pmpriv->uap_state_chan_cb.beacon_period =
+				wlan_le16_to_cpu(tlv_bcnpd->beacon_period);
+			/* copy dtim_period as well if it follows */
+			tlv_dtimpd =
+				(MrvlIEtypes_dtim_period_t
+				 *)(((t_u8 *)tlv) +
+				    sizeof(MrvlIEtypes_beacon_period_t));
+			if (TLV_TYPE_UAP_DTIM_PERIOD ==
+			    wlan_le16_to_cpu(tlv_dtimpd->header.type))
+				pmpriv->uap_state_chan_cb.dtim_period =
+					tlv_dtimpd->dtim_period;
+			/* call callback waiting for beacon/dtim info */
+			if (pmpriv->uap_state_chan_cb.get_chan_callback)
+				pmpriv->uap_state_chan_cb.
+					get_chan_callback(pmpriv);
+			break;
+		case TLV_TYPE_MGMT_IE:
+			if ((pmpriv->adapter->state_rdh.stage ==
+			     RDH_SET_CUSTOM_IE) ||
+			    (pmpriv->adapter->state_rdh.stage ==
+			     RDH_REM_CUSTOM_IE)) {
+				if (!pmpriv->adapter->ecsa_enable)
+					wlan_11h_radar_detected_callback((t_void
+									  *)
+									 pmpriv);
+			}
+			break;
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of snmp_mib
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param cmd_oid      Cmd oid: treated as sub command
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @param pdata_buf    A pointer to information buffer
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_cmd_snmp_mib(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *cmd,
+		      t_u16 cmd_action, t_u32 cmd_oid,
+		      pmlan_ioctl_req pioctl_buf, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.smib;
+	HostCmd_DS_UAP_802_11_SNMP_MIB *puap_snmp_mib = &cmd->params.uap_smib;
+
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *psnmp_oid = MNULL;
+	t_u32 ul_temp;
+	t_u8 i;
+
+	t_u8 snmp_oids[] = {
+		tkip_mic_failures,
+		ccmp_decrypt_errors,
+		wep_undecryptable_count,
+		wep_icv_error_count,
+		decrypt_failure_count,
+		dot11_mcast_tx_count,
+		dot11_failed_count,
+		dot11_retry_count,
+		dot11_multi_retry_count,
+		dot11_frame_dup_count,
+		dot11_rts_success_count,
+		dot11_rts_failure_count,
+		dot11_ack_failure_count,
+		dot11_rx_fragment_count,
+		dot11_mcast_rx_frame_count,
+		dot11_fcs_error_count,
+		dot11_tx_frame_count,
+		dot11_rsna_tkip_cm_invoked,
+		dot11_rsna_4way_hshk_failures,
+	};
+
+	ENTER();
+
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+		psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+		if (cmd_oid == StopDeauth_i) {
+			psnmp_mib->oid = wlan_cpu_to_le16((t_u16)StopDeauth_i);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+			cmd->size =
+				wlan_cpu_to_le16(sizeof
+						 (HostCmd_DS_802_11_SNMP_MIB) +
+						 S_DS_GEN);
+		} else {
+			cmd->size = wlan_cpu_to_le16(sizeof(t_u16) + S_DS_GEN +
+						     sizeof(snmp_oids) *
+						     sizeof
+						     (MrvlIEtypes_snmp_oid_t));
+			psnmp_oid = (t_u8 *)&puap_snmp_mib->snmp_data;
+			for (i = 0; i < sizeof(snmp_oids); i++) {
+				/* SNMP OID header type */
+				*(t_u16 *)psnmp_oid =
+					wlan_cpu_to_le16(snmp_oids[i]);
+				psnmp_oid += sizeof(t_u16);
+				/* SNMP OID header length */
+				*(t_u16 *)psnmp_oid =
+					wlan_cpu_to_le16(sizeof(t_u32));
+				psnmp_oid += sizeof(t_u16) + sizeof(t_u32);
+			}
+		}
+	} else {		/* cmd_action == ACT_SET */
+		cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+		cmd->size = sizeof(HostCmd_DS_802_11_SNMP_MIB) - 1 + S_DS_GEN;
+		psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+
+		switch (cmd_oid) {
+		case Dot11D_i:
+		case Dot11H_i:
+			psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16));
+			ul_temp = *(t_u32 *)pdata_buf;
+			*((t_u16 *)(psnmp_mib->value)) =
+				wlan_cpu_to_le16((t_u16)ul_temp);
+			cmd->size += sizeof(t_u16);
+			break;
+		case ECSAEnable_i:
+			psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+			psnmp_mib->value[0] = *((t_u8 *)pdata_buf);
+			cmd->size += sizeof(t_u8);
+			break;
+		case StopDeauth_i:
+			psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid);
+			psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
+			psnmp_mib->value[0] = *((t_u8 *)pdata_buf);
+			cmd->size += sizeof(t_u8);
+			break;
+		default:
+			PRINTM(MERROR, "Unsupported OID.\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		cmd->size = wlan_cpu_to_le16(cmd->size);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of get_log.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_802_11_get_log(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd)
+{
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of bss_start.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_bss_start(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd)
+{
+	MrvlIEtypes_HostMlme_t *tlv;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_BSS_START);
+	cmd->size = S_DS_GEN;
+	if (pmpriv->uap_host_based & UAP_FLAG_HOST_MLME) {
+		tlv = (MrvlIEtypes_HostMlme_t *) ((t_u8 *)cmd + cmd->size);
+		tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_HOST_MLME);
+		tlv->header.len = wlan_cpu_to_le16(sizeof(tlv->host_mlme));
+		tlv->host_mlme = MTRUE;
+		cmd->size += sizeof(MrvlIEtypes_HostMlme_t);
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of snmp_mib
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_snmp_mib(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	HostCmd_DS_802_11_SNMP_MIB *psnmp_mib =
+		(HostCmd_DS_802_11_SNMP_MIB *)&resp->params.smib;
+	mlan_ds_get_info *info;
+	mlan_ds_snmp_mib *mib = MNULL;
+	t_u16 oid = wlan_le16_to_cpu(psnmp_mib->oid);
+	t_u8 *psnmp_oid = MNULL;
+	t_u32 data;
+	t_u16 tlv_buf_left = 0;
+	t_u16 tlv_type = 0;
+	t_u16 query_type = wlan_le16_to_cpu(psnmp_mib->query_type);
+
+	ENTER();
+	if (query_type == HostCmd_ACT_GEN_GET) {
+		if (!pioctl_buf) {
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+		if (oid == StopDeauth_i) {
+			mib = (mlan_ds_snmp_mib *)pioctl_buf->pbuf;
+			if (mib)
+				mib->param.deauthctrl = psnmp_mib->value[0];
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		tlv_buf_left = resp->size - (sizeof(t_u16) + S_DS_GEN);
+		psnmp_oid = (t_u8 *)&psnmp_mib->oid;
+		while (tlv_buf_left >= sizeof(MrvlIEtypes_snmp_oid_t)) {
+			tlv_type = wlan_le16_to_cpu(*(t_u16 *)psnmp_oid);
+			psnmp_oid += sizeof(t_u16) + sizeof(t_u16);
+			memcpy_ext(pmadapter, &data, psnmp_oid, sizeof(t_u32),
+				   sizeof(t_u32));
+			switch (tlv_type) {
+			case tkip_mic_failures:
+				info->param.ustats.tkip_mic_failures =
+					wlan_le32_to_cpu(data);
+				break;
+			case ccmp_decrypt_errors:
+				info->param.ustats.ccmp_decrypt_errors =
+					wlan_le32_to_cpu(data);
+				break;
+			case wep_undecryptable_count:
+				info->param.ustats.wep_undecryptable_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case wep_icv_error_count:
+				info->param.ustats.wep_icv_error_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case decrypt_failure_count:
+				info->param.ustats.decrypt_failure_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_mcast_tx_count:
+				info->param.ustats.mcast_tx_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_failed_count:
+				info->param.ustats.failed_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_retry_count:
+				info->param.ustats.retry_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_multi_retry_count:
+				info->param.ustats.multi_retry_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_frame_dup_count:
+				info->param.ustats.frame_dup_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_rts_success_count:
+				info->param.ustats.rts_success_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_rts_failure_count:
+				info->param.ustats.rts_failure_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_ack_failure_count:
+				info->param.ustats.ack_failure_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_rx_fragment_count:
+				info->param.ustats.rx_fragment_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_mcast_rx_frame_count:
+				info->param.ustats.mcast_rx_frame_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_fcs_error_count:
+				info->param.ustats.fcs_error_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_tx_frame_count:
+				info->param.ustats.tx_frame_count =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_rsna_tkip_cm_invoked:
+				info->param.ustats.rsna_tkip_cm_invoked =
+					wlan_le32_to_cpu(data);
+				break;
+			case dot11_rsna_4way_hshk_failures:
+				info->param.ustats.rsna_4way_hshk_failures =
+					wlan_le32_to_cpu(data);
+				break;
+			}
+			tlv_buf_left -= sizeof(MrvlIEtypes_snmp_oid_t);
+			psnmp_oid += sizeof(t_u32);
+		}
+	} else {		/* ACT_SET */
+		switch (wlan_le16_to_cpu(psnmp_mib->oid)) {
+		case Dot11D_i:
+			data = wlan_le16_to_cpu(*((t_u16 *)(psnmp_mib->value)));
+			/* Set 11d state to private */
+			pmpriv->state_11d.enable_11d = data;
+			/* Set user enable flag if called from ioctl */
+			if (pioctl_buf)
+				pmpriv->state_11d.user_enable_11d = data;
+			break;
+		case Dot11H_i:
+			data = wlan_le16_to_cpu(*((t_u16 *)(psnmp_mib->value)));
+			/* Set 11h state to priv */
+			pmpriv->intf_state_11h.is_11h_active =
+				(data & ENABLE_11H_MASK);
+			/* Set radar_det state to adapter */
+			pmpriv->adapter->state_11h.is_master_radar_det_active =
+				(data & MASTER_RADAR_DET_MASK) ? MTRUE : MFALSE;
+			pmpriv->adapter->state_11h.is_slave_radar_det_active =
+				(data & SLAVE_RADAR_DET_MASK) ? MTRUE : MFALSE;
+			break;
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of get_log
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_get_log(pmlan_private pmpriv,
+		     HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_GET_LOG *pget_log =
+		(HostCmd_DS_802_11_GET_LOG *)&resp->params.get_log;
+	mlan_ds_get_info *pget_info = MNULL;
+	int i = 0;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		pget_info->param.stats.mcast_tx_frame =
+			wlan_le32_to_cpu(pget_log->mcast_tx_frame);
+		pget_info->param.stats.failed =
+			wlan_le32_to_cpu(pget_log->failed);
+		pget_info->param.stats.retry =
+			wlan_le32_to_cpu(pget_log->retry);
+		pget_info->param.stats.multi_retry =
+			wlan_le32_to_cpu(pget_log->multiretry);
+		pget_info->param.stats.frame_dup =
+			wlan_le32_to_cpu(pget_log->frame_dup);
+		pget_info->param.stats.rts_success =
+			wlan_le32_to_cpu(pget_log->rts_success);
+		pget_info->param.stats.rts_failure =
+			wlan_le32_to_cpu(pget_log->rts_failure);
+		pget_info->param.stats.ack_failure =
+			wlan_le32_to_cpu(pget_log->ack_failure);
+		pget_info->param.stats.rx_frag =
+			wlan_le32_to_cpu(pget_log->rx_frag);
+		pget_info->param.stats.mcast_rx_frame =
+			wlan_le32_to_cpu(pget_log->mcast_rx_frame);
+		pget_info->param.stats.fcs_error =
+			wlan_le32_to_cpu(pget_log->fcs_error);
+		pget_info->param.stats.tx_frame =
+			wlan_le32_to_cpu(pget_log->tx_frame);
+		pget_info->param.stats.wep_icv_error[0] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[0]);
+		pget_info->param.stats.wep_icv_error[1] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[1]);
+		pget_info->param.stats.wep_icv_error[2] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]);
+		pget_info->param.stats.wep_icv_error[3] =
+			wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]);
+		pget_info->param.stats.bcn_rcv_cnt =
+			wlan_le32_to_cpu(pget_log->bcn_rcv_cnt);
+		pget_info->param.stats.bcn_miss_cnt =
+			wlan_le32_to_cpu(pget_log->bcn_miss_cnt);
+		pget_info->param.stats.amsdu_rx_cnt = pmpriv->amsdu_rx_cnt;
+		pget_info->param.stats.msdu_in_rx_amsdu_cnt =
+			pmpriv->msdu_in_rx_amsdu_cnt;
+		pget_info->param.stats.amsdu_tx_cnt = pmpriv->amsdu_tx_cnt;
+		pget_info->param.stats.msdu_in_tx_amsdu_cnt =
+			pmpriv->msdu_in_tx_amsdu_cnt;
+		pget_info->param.stats.rx_stuck_issue_cnt[0] =
+			wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[0]);
+		pget_info->param.stats.rx_stuck_issue_cnt[1] =
+			wlan_le32_to_cpu(pget_log->rx_stuck_issue_cnt[1]);
+		pget_info->param.stats.rx_stuck_recovery_cnt =
+			wlan_le32_to_cpu(pget_log->rx_stuck_recovery_cnt);
+		pget_info->param.stats.rx_stuck_tsf[0] =
+			wlan_le64_to_cpu(pget_log->rx_stuck_tsf[0]);
+		pget_info->param.stats.rx_stuck_tsf[1] =
+			wlan_le64_to_cpu(pget_log->rx_stuck_tsf[1]);
+		pget_info->param.stats.tx_watchdog_recovery_cnt =
+			wlan_le32_to_cpu(pget_log->tx_watchdog_recovery_cnt);
+		pget_info->param.stats.tx_watchdog_tsf[0] =
+			wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[0]);
+		pget_info->param.stats.tx_watchdog_tsf[1] =
+			wlan_le64_to_cpu(pget_log->tx_watchdog_tsf[1]);
+		pget_info->param.stats.channel_switch_ann_sent =
+			wlan_le32_to_cpu(pget_log->channel_switch_ann_sent);
+		pget_info->param.stats.channel_switch_state =
+			wlan_le32_to_cpu(pget_log->channel_switch_state);
+		pget_info->param.stats.reg_class =
+			wlan_le32_to_cpu(pget_log->reg_class);
+		pget_info->param.stats.channel_number =
+			wlan_le32_to_cpu(pget_log->channel_number);
+		pget_info->param.stats.channel_switch_mode =
+			wlan_le32_to_cpu(pget_log->channel_switch_mode);
+		pget_info->param.stats.rx_reset_mac_recovery_cnt =
+			wlan_le32_to_cpu(pget_log->rx_reset_mac_recovery_cnt);
+		pget_info->param.stats.rx_Isr2_NotDone_Cnt =
+			wlan_le32_to_cpu(pget_log->rx_Isr2_NotDone_Cnt);
+		pget_info->param.stats.gdma_abort_cnt =
+			wlan_le32_to_cpu(pget_log->gdma_abort_cnt);
+		pget_info->param.stats.g_reset_rx_mac_cnt =
+			wlan_le32_to_cpu(pget_log->g_reset_rx_mac_cnt);
+		//Ownership error counters
+		pget_info->param.stats.dwCtlErrCnt =
+			wlan_le32_to_cpu(pget_log->dwCtlErrCnt);
+		pget_info->param.stats.dwBcnErrCnt =
+			wlan_le32_to_cpu(pget_log->dwBcnErrCnt);
+		pget_info->param.stats.dwMgtErrCnt =
+			wlan_le32_to_cpu(pget_log->dwMgtErrCnt);
+		pget_info->param.stats.dwDatErrCnt =
+			wlan_le32_to_cpu(pget_log->dwDatErrCnt);
+		pget_info->param.stats.bigtk_mmeGoodCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_mmeGoodCnt);
+		pget_info->param.stats.bigtk_replayErrCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_replayErrCnt);
+		pget_info->param.stats.bigtk_micErrCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_micErrCnt);
+		pget_info->param.stats.bigtk_mmeNotFoundCnt =
+			wlan_le32_to_cpu(pget_log->bigtk_mmeNotFoundCnt);
+
+		if (pmpriv->adapter->getlog_enable) {
+			pget_info->param.stats.tx_frag_cnt =
+				wlan_le32_to_cpu(pget_log->tx_frag_cnt);
+			for (i = 0; i < 8; i++) {
+				pget_info->param.stats.qos_tx_frag_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_tx_frag_cnt[i]);
+				pget_info->param.stats.qos_failed_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_failed_cnt[i]);
+				pget_info->param.stats.qos_retry_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_retry_cnt[i]);
+				pget_info->param.stats.qos_multi_retry_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_multi_retry_cnt
+							 [i]);
+				pget_info->param.stats.qos_frm_dup_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_frm_dup_cnt[i]);
+				pget_info->param.stats.qos_rts_suc_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_rts_suc_cnt[i]);
+				pget_info->param.stats.qos_rts_failure_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_rts_failure_cnt
+							 [i]);
+				pget_info->param.stats.qos_ack_failure_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_ack_failure_cnt
+							 [i]);
+				pget_info->param.stats.qos_rx_frag_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_rx_frag_cnt[i]);
+				pget_info->param.stats.qos_tx_frm_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_tx_frm_cnt[i]);
+				pget_info->param.stats.
+					qos_discarded_frm_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_discarded_frm_cnt
+							 [i]);
+				pget_info->param.stats.qos_mpdus_rx_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_mpdus_rx_cnt[i]);
+				pget_info->param.stats.qos_retries_rx_cnt[i] =
+					wlan_le32_to_cpu(pget_log->
+							 qos_retries_rx_cnt[i]);
+			}
+			pget_info->param.stats.mgmt_ccmp_replays =
+				wlan_le32_to_cpu(pget_log->mgmt_ccmp_replays);
+			pget_info->param.stats.tx_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->tx_amsdu_cnt);
+			pget_info->param.stats.failed_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->failed_amsdu_cnt);
+			pget_info->param.stats.retry_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->retry_amsdu_cnt);
+			pget_info->param.stats.multi_retry_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 multi_retry_amsdu_cnt);
+			pget_info->param.stats.tx_octets_in_amsdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 tx_octets_in_amsdu_cnt);
+			pget_info->param.stats.amsdu_ack_failure_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 amsdu_ack_failure_cnt);
+			pget_info->param.stats.rx_amsdu_cnt =
+				wlan_le32_to_cpu(pget_log->rx_amsdu_cnt);
+			pget_info->param.stats.rx_octets_in_amsdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 rx_octets_in_amsdu_cnt);
+			pget_info->param.stats.tx_ampdu_cnt =
+				wlan_le32_to_cpu(pget_log->tx_ampdu_cnt);
+			pget_info->param.stats.tx_mpdus_in_ampdu_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 tx_mpdus_in_ampdu_cnt);
+			pget_info->param.stats.tx_octets_in_ampdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 tx_octets_in_ampdu_cnt);
+			pget_info->param.stats.ampdu_rx_cnt =
+				wlan_le32_to_cpu(pget_log->ampdu_rx_cnt);
+			pget_info->param.stats.mpdu_in_rx_ampdu_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 mpdu_in_rx_ampdu_cnt);
+			pget_info->param.stats.rx_octets_in_ampdu_cnt =
+				wlan_le64_to_cpu(pget_log->
+						 rx_octets_in_ampdu_cnt);
+			pget_info->param.stats.ampdu_delimiter_crc_error_cnt =
+				wlan_le32_to_cpu(pget_log->
+						 ampdu_delimiter_crc_error_cnt);
+
+			/* Indicate ioctl complete */
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_get_info);
+		} else
+			pioctl_buf->data_read_written =
+				sizeof(mlan_ds_get_stats_org) +
+				sizeof(pget_info->sub_command);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of deauth station
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_sta_deauth(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	HostCmd_DS_STA_DEAUTH *pcmd_sta_deauth =
+		(HostCmd_DS_STA_DEAUTH *)&cmd->params.sta_deauth;
+	mlan_deauth_param *deauth = (mlan_deauth_param *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_STA_DEAUTH);
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_STA_DEAUTH));
+	memcpy_ext(pmpriv->adapter, pcmd_sta_deauth->mac, deauth->mac_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	pcmd_sta_deauth->reason = wlan_cpu_to_le16(deauth->reason_code);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of report mic_err
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_report_mic(pmlan_private pmpriv,
+			HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	HostCmd_DS_REPORT_MIC *pcmd_report_mic =
+		(HostCmd_DS_REPORT_MIC *)&cmd->params.report_mic;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_REPORT_MIC);
+	cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REPORT_MIC));
+	memcpy_ext(pmpriv->adapter, pcmd_report_mic->mac, pdata_buf,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of key material
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param cmd_oid      OID: ENABLE or DISABLE
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_key_material(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd,
+			  t_u16 cmd_action, t_u16 cmd_oid, t_void *pdata_buf)
+{
+	HostCmd_DS_802_11_KEY_MATERIAL *pkey_material =
+		&cmd->params.key_material;
+	mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *)pdata_buf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	sta_node *sta_ptr = MNULL;
+
+	ENTER();
+	if (!pkey) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+	pkey_material->action = wlan_cpu_to_le16(cmd_action);
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		cmd->size = wlan_cpu_to_le16(sizeof(pkey_material->action) +
+					     S_DS_GEN);
+		goto done;
+	}
+	memset(pmpriv->adapter, &pkey_material->key_param_set, 0,
+	       sizeof(MrvlIEtype_KeyParamSetV2_t));
+	if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) {
+		pkey_material->action =
+			wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE);
+		pkey_material->key_param_set.type =
+			wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
+		pkey_material->key_param_set.key_idx =
+			pkey->key_index & KEY_INDEX_MASK;
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(KEY_INFO_MCAST_KEY |
+					 KEY_INFO_UCAST_KEY);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.mac_addr,
+			   pkey->mac_addr, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Remove Key\n");
+		goto done;
+	}
+	pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+	pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK;
+	pkey_material->key_param_set.type =
+		wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
+	pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY;
+	memcpy_ext(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
+		   pkey->mac_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	if (pkey->key_len <= MAX_WEP_KEY_SIZE) {
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(wep_param_t));
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_WEP;
+		pkey_material->key_param_set.key_info |=
+			KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY;
+		if (pkey_material->key_param_set.key_idx ==
+		    (pmpriv->wep_key_curr_index & KEY_INDEX_MASK))
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_DEFAULT_KEY;
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+		pkey_material->key_param_set.key_params.wep.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.wep.key,
+			   pkey->key_material, pkey->key_len, MAX_WEP_KEY_SIZE);
+		cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					     S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					     sizeof(wep_param_t) +
+					     sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set WEP Key\n");
+		goto done;
+	}
+	if (pkey->key_flags & KEY_FLAG_GROUP_KEY)
+		pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY;
+	else
+		pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY;
+	if (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)
+		pkey_material->key_param_set.key_info |= KEY_INFO_CMAC_AES_KEY;
+	if (pkey->key_flags & KEY_FLAG_SET_TX_KEY)
+		pkey_material->key_param_set.key_info |=
+			KEY_INFO_TX_KEY | KEY_INFO_RX_KEY;
+	else
+		pkey_material->key_param_set.key_info |= KEY_INFO_TX_KEY;
+	if (pkey->is_wapi_key) {
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_WAPI;
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.wapi.pn,
+			   pkey->pn, PN_SIZE, PN_SIZE);
+		pkey_material->key_param_set.key_params.wapi.key_len =
+			wlan_cpu_to_le16(MIN(WAPI_KEY_SIZE, pkey->key_len));
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.wapi.key,
+			   pkey->key_material, pkey->key_len, WAPI_KEY_SIZE);
+		if (!pmpriv->sec_info.wapi_key_on)
+			pkey_material->key_param_set.key_info |=
+				KEY_INFO_DEFAULT_KEY;
+		if (pkey->key_flags & KEY_FLAG_GROUP_KEY) {
+			pmpriv->sec_info.wapi_key_on = MTRUE;
+		} else {
+			/* WAPI pairwise key: unicast */
+			sta_ptr =
+				wlan_add_station_entry(pmpriv, pkey->mac_addr);
+			if (sta_ptr) {
+				PRINTM(MCMND, "station: wapi_key_on\n");
+				sta_ptr->wapi_key_on = MTRUE;
+			}
+		}
+		pkey_material->key_param_set.key_info =
+			wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(wapi_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(wapi_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set WAPI Key\n");
+		goto done;
+	}
+	pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY;
+	pkey_material->key_param_set.key_info =
+		wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
+	if (pkey->key_len == WPA_AES_KEY_LEN &&
+	    !(pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+		if (pkey->key_flags &
+		    (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy_ext(pmpriv->adapter,
+				   pkey_material->key_param_set.key_params.aes.
+				   pn, pkey->pn, SEQ_MAX_SIZE, WPA_PN_SIZE);
+		pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES;
+		pkey_material->key_param_set.key_params.aes.key_len =
+			wlan_cpu_to_le16(pkey->key_len);
+		memcpy_ext(pmpriv->adapter,
+			   pkey_material->key_param_set.key_params.aes.key,
+			   pkey->key_material, pkey->key_len, WPA_AES_KEY_LEN);
+		pkey_material->key_param_set.length =
+			wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN +
+					 sizeof(aes_param));
+		cmd->size =
+			wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					 S_DS_GEN + KEY_PARAMS_FIXED_LEN +
+					 sizeof(aes_param) +
+					 sizeof(pkey_material->action));
+		PRINTM(MCMND, "Set AES Key\n");
+		goto done;
+	}
+	if (pkey->key_len == WPA_IGTK_KEY_LEN &&
+	    (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) {
+		if (pkey->key_flags &
+		    (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID))
+			memcpy_ext(pmpriv->adapter,
+				   pkey_material->key_param_set.key_params.
+				   cmac_aes.ipn, pkey->pn, SEQ_MAX_SIZE,
+				   IGTK_PN_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		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.
+				   cmac_aes.ipn, pkey->pn, SEQ_MAX_SIZE,
+				   IGTK_PN_SIZE);
+		pkey_material->key_param_set.key_info &=
+			~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY));
+		pkey_material->key_param_set.key_info |=
+			wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK);
+		pkey_material->key_param_set.key_type =
+			KEY_TYPE_ID_BIP_GMAC_256;
+		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,
+			   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 handles the command response of sta_list
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_sta_list(pmlan_private pmpriv,
+		      HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_STA_LIST *sta_list =
+		(HostCmd_DS_STA_LIST *)&resp->params.sta_list;
+	mlan_ds_get_info *info;
+	MrvlIEtypes_sta_info_t *tlv = MNULL;
+	t_u8 i = 0;
+	sta_node *sta_ptr;
+	t_u8 tlv_len = 0;
+	t_u8 *buf = MNULL;
+	t_u8 *ie_buf = MNULL;
+
+	ENTER();
+	if (pioctl_buf) {
+		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
+		info->param.sta_list.sta_count =
+			wlan_le16_to_cpu(sta_list->sta_count);
+		buf = sta_list->tlv_buf;
+		tlv = (MrvlIEtypes_sta_info_t *)buf;
+		info->param.sta_list.sta_count =
+			MIN(info->param.sta_list.sta_count, MAX_NUM_CLIENTS);
+		ie_buf = (t_u8 *)&info->param.sta_list.info[0];
+		ie_buf += sizeof(sta_info_data) *
+			info->param.sta_list.sta_count;
+		pioctl_buf->data_read_written = sizeof(mlan_ds_sta_list) -
+			sizeof(sta_info_data) * MAX_NUM_CLIENTS;
+		for (i = 0; i < info->param.sta_list.sta_count; i++) {
+			tlv_len = wlan_le16_to_cpu(tlv->header.len);
+			memcpy_ext(pmpriv->adapter,
+				   info->param.sta_list.info[i].mac_address,
+				   tlv->mac_address, MLAN_MAC_ADDR_LENGTH,
+				   MLAN_MAC_ADDR_LENGTH);
+			info->param.sta_list.info[i].ie_len =
+				tlv_len + sizeof(MrvlIEtypesHeader_t) -
+				sizeof(MrvlIEtypes_sta_info_t);
+			if (info->param.sta_list.info[i].ie_len) {
+				memcpy_ext(pmpriv->adapter,
+					   ie_buf,
+					   tlv->ie_buf,
+					   info->param.sta_list.info[i].ie_len,
+					   info->param.sta_list.info[i].ie_len);
+				ie_buf += info->param.sta_list.info[i].ie_len;
+			}
+			info->param.sta_list.info[i].power_mgmt_status =
+				tlv->power_mgmt_status;
+			info->param.sta_list.info[i].rssi = tlv->rssi;
+			sta_ptr = wlan_get_station_entry(pmpriv,
+							 tlv->mac_address);
+			if (sta_ptr) {
+				info->param.sta_list.info[i].bandmode =
+					sta_ptr->bandmode;
+				memcpy_ext(pmpriv->adapter,
+					   &(info->param.sta_list.info[i].
+					     stats), &(sta_ptr->stats),
+					   sizeof(sta_stats),
+					   sizeof(sta_stats));
+			} else
+				info->param.sta_list.info[i].bandmode = 0xFF;
+			pioctl_buf->data_read_written +=
+				sizeof(sta_info_data) +
+				info->param.sta_list.info[i].ie_len;
+			buf += sizeof(MrvlIEtypes_sta_info_t) +
+				info->param.sta_list.info[i].ie_len;
+			tlv = (MrvlIEtypes_sta_info_t *)buf;
+		}
+		PRINTM(MCMND, "Total sta_list size=%d\n",
+		       pioctl_buf->data_read_written);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/** Fixed size of bss start event */
+#define BSS_START_EVENT_FIX_SIZE 12
+
+/**
+ *  @brief This function will search for the specific ie
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to event buf
+ *
+ *  @return	       N/A
+ */
+static void
+wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent)
+{
+	t_u16 tlv_type, tlv_len;
+	int tlv_buf_left = pevent->data_len - BSS_START_EVENT_FIX_SIZE;
+	MrvlIEtypesHeader_t *tlv =
+		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+					BSS_START_EVENT_FIX_SIZE);
+
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	IEEEtypes_WmmParameter_t wmm_param_ie;
+	MrvlIEtypes_channel_band_t *pchan_info;
+	t_u8 event_buf[100];
+	mlan_event *event = (mlan_event *)event_buf;
+	chan_band_info *pchan_band_info = (chan_band_info *) event->event_buf;
+	MrvlIEtypes_He_cap_t *pext_tlv = MNULL;
+
+	ENTER();
+	priv->wmm_enabled = MFALSE;
+	priv->pkt_fwd = MFALSE;
+	priv->is_11n_enabled = MFALSE;
+	priv->is_11ac_enabled = MFALSE;
+	priv->is_11ax_enabled = MFALSE;
+
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		if (tlv_type == HT_CAPABILITY) {
+			DBG_HEXDUMP(MCMD_D, "HT_CAP tlv", tlv,
+				    tlv_len + sizeof(MrvlIEtypesHeader_t));
+			priv->is_11n_enabled = MTRUE;
+		}
+		if (tlv_type == VHT_CAPABILITY) {
+			DBG_HEXDUMP(MCMD_D, "VHT_CAP tlv", tlv,
+				    tlv_len + sizeof(MrvlIEtypesHeader_t));
+			priv->is_11ac_enabled = MTRUE;
+		}
+		if (tlv_type == EXTENSION) {
+			pext_tlv = (MrvlIEtypes_He_cap_t *) tlv;
+			if (pext_tlv->ext_id == HE_CAPABILITY) {
+				DBG_HEXDUMP(MCMD_D, "HE_CAP tlv", tlv,
+					    tlv_len +
+					    sizeof(MrvlIEtypesHeader_t));
+				priv->is_11ax_enabled = MTRUE;
+			}
+		}
+
+		if (tlv_type == VENDOR_SPECIFIC_221) {
+			if (!memcmp(priv->adapter,
+				    (t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t),
+				    wmm_oui, sizeof(wmm_oui))) {
+				DBG_HEXDUMP(MCMD_D, "wmm ie tlv", tlv,
+					    tlv_len +
+					    sizeof(MrvlIEtypesHeader_t));
+				priv->wmm_enabled = MFALSE;
+				wlan_wmm_setup_ac_downgrade(priv);
+				priv->wmm_enabled = MTRUE;
+				memcpy_ext(priv->adapter, &wmm_param_ie,
+					   ((t_u8 *)tlv + 2),
+					   sizeof(IEEEtypes_WmmParameter_t),
+					   sizeof(IEEEtypes_WmmParameter_t));
+				wmm_param_ie.vend_hdr.len = (t_u8)tlv_len;
+				wmm_param_ie.vend_hdr.element_id = WMM_IE;
+				wlan_wmm_setup_queue_priorities(priv,
+								&wmm_param_ie);
+			}
+		}
+		if (tlv_type == TLV_TYPE_UAP_PKT_FWD_CTL) {
+			DBG_HEXDUMP(MCMD_D, "pkt_fwd tlv", tlv,
+				    tlv_len + sizeof(MrvlIEtypesHeader_t));
+			priv->pkt_fwd =
+				*((t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t));
+			PRINTM(MCMND, "pkt_fwd FW: 0x%x\n", priv->pkt_fwd);
+			if (priv->pkt_fwd & PKT_FWD_FW_BIT)
+				priv->pkt_fwd = MFALSE;
+			else
+				priv->pkt_fwd |= PKT_FWD_ENABLE_BIT;
+			PRINTM(MCMND, "pkt_fwd DRV: 0x%x\n", priv->pkt_fwd);
+		}
+		if (tlv_type == TLV_TYPE_UAP_CHAN_BAND_CONFIG) {
+			DBG_HEXDUMP(MCMD_D, "chan_band_config tlv", tlv,
+				    tlv_len + sizeof(MrvlIEtypesHeader_t));
+			pchan_info = (MrvlIEtypes_channel_band_t *)tlv;
+			priv->uap_channel = pchan_info->channel;
+			PRINTM(MCMND, "uap_channel FW: 0x%x\n",
+			       priv->uap_channel);
+			event->bss_index = priv->bss_index;
+			event->event_id = MLAN_EVENT_ID_DRV_UAP_CHAN_INFO;
+			event->event_len = sizeof(chan_band_info);
+			memcpy_ext(priv->adapter,
+				   (t_u8 *)&pchan_band_info->bandcfg,
+				   (t_u8 *)&pchan_info->bandcfg, tlv_len,
+				   tlv_len);
+			if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
+				pchan_band_info->center_chan =
+					wlan_get_center_freq_idx(priv, BAND_AAC,
+								 pchan_info->
+								 channel,
+								 CHANNEL_BW_80MHZ);
+			if (priv->adapter->ecsa_enable) {
+				int ret;
+				t_u8 bandwidth = BW_20MHZ;
+
+				MrvlIEtypes_chan_bw_oper_t chan_bw_oper;
+				chan_bw_oper.header.type = REGULATORY_CLASS;
+				chan_bw_oper.header.len =
+					sizeof(MrvlIEtypes_chan_bw_oper_t);
+				chan_bw_oper.ds_chan_bw_oper.channel =
+					pchan_info->channel;
+
+				if (pchan_band_info->bandcfg.chanWidth ==
+				    CHAN_BW_40MHZ)
+					bandwidth = BW_40MHZ;
+				else if (pchan_band_info->bandcfg.chanWidth ==
+					 CHAN_BW_80MHZ)
+					bandwidth = BW_80MHZ;
+				chan_bw_oper.ds_chan_bw_oper.bandwidth =
+					bandwidth;
+
+				ret = wlan_prepare_cmd(priv,
+						       HOST_CMD_APCMD_SYS_CONFIGURE,
+						       HostCmd_ACT_GEN_SET, 0,
+						       MNULL, &chan_bw_oper);
+				if (ret != MLAN_STATUS_SUCCESS &&
+				    ret != MLAN_STATUS_PENDING) {
+					PRINTM(MERROR,
+					       "%s(): Could not set supported operating class IE for priv=%p [priv_bss_idx=%d]!\n",
+					       __func__, priv, priv->bss_index);
+				}
+			}
+		}
+
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+	if (priv->wmm_enabled == MFALSE) {
+		/* Since WMM is not enabled, setup the queues with the defaults
+		 */
+		wlan_wmm_setup_queues(priv);
+	}
+	if (event->event_id == MLAN_EVENT_ID_DRV_UAP_CHAN_INFO) {
+		pchan_band_info->is_11n_enabled = priv->is_11n_enabled;
+		wlan_recv_event(priv, MLAN_EVENT_ID_DRV_UAP_CHAN_INFO, event);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will update WAPI PN in statation assoc event
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to event buf
+ *
+ *  @return	       MFALSE
+ */
+static t_u32
+wlan_update_wapi_info_tlv(pmlan_private priv, pmlan_buffer pevent)
+{
+	t_u32 ret = MFALSE;
+	t_u16 tlv_type, tlv_len;
+	t_u32 tx_pn[4];
+	t_u32 i = 0;
+	int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
+	MrvlIEtypesHeader_t *tlv =
+		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
+					ASSOC_EVENT_FIX_SIZE);
+	MrvlIEtypes_wapi_info_t *wapi_tlv = MNULL;
+
+	ENTER();
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		if (tlv_type == TLV_TYPE_AP_WAPI_INFO) {
+			wapi_tlv = (MrvlIEtypes_wapi_info_t *)tlv;
+			DBG_HEXDUMP(MCMD_D, "Fw:multicast_PN",
+				    wapi_tlv->multicast_PN, PN_SIZE);
+			memcpy_ext(priv->adapter, (t_u8 *)tx_pn,
+				   wapi_tlv->multicast_PN, PN_SIZE,
+				   sizeof(tx_pn));
+			for (i = 0; i < 4; i++)
+				tx_pn[i] = mlan_ntohl(tx_pn[i]);
+			memcpy_ext(priv->adapter, wapi_tlv->multicast_PN,
+				   (t_u8 *)tx_pn, PN_SIZE,
+				   sizeof(wapi_tlv->multicast_PN));
+			DBG_HEXDUMP(MCMD_D, "Host:multicast_PN",
+				    wapi_tlv->multicast_PN, PN_SIZE);
+			break;
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+	LEAVE();
+
+	return ret;
+}
+
+/**
+ *  @brief This function send sta_assoc_event to moal
+ *          payload with sta mac address and assoc ie.
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to mlan_event buffer
+ *  @param pbuf    A pointer to mlan_buffer which has event content.
+ *
+ *  @return	       MFALSE
+ */
+static t_u32
+wlan_process_sta_assoc_event(pmlan_private priv,
+			     mlan_event *pevent, pmlan_buffer pmbuf)
+{
+	t_u32 ret = MFALSE;
+	t_u16 tlv_type, tlv_len;
+	t_u16 frame_control, frame_sub_type = 0;
+	t_u8 *assoc_req_ie = MNULL;
+	t_u8 ie_len = 0, assoc_ie_len = 0;
+	int tlv_buf_left = pmbuf->data_len - ASSOC_EVENT_FIX_SIZE;
+	MrvlIEtypesHeader_t *tlv =
+		(MrvlIEtypesHeader_t *)(pmbuf->pbuf + pmbuf->data_offset +
+					ASSOC_EVENT_FIX_SIZE);
+	MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
+
+	ENTER();
+	pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_CONNECT;
+	pevent->bss_index = priv->bss_index;
+	pevent->event_len = MLAN_MAC_ADDR_LENGTH;
+	memcpy_ext(priv->adapter, pevent->event_buf,
+		   pmbuf->pbuf + pmbuf->data_offset + 6, pevent->event_len,
+		   pevent->event_len);
+	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
+		tlv_type = wlan_le16_to_cpu(tlv->type);
+		tlv_len = wlan_le16_to_cpu(tlv->len);
+		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
+		    (unsigned int)tlv_buf_left) {
+			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+			       tlv_len, tlv_buf_left);
+			break;
+		}
+		if (tlv_type == TLV_TYPE_MGMT_FRAME) {
+			mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
+			memcpy_ext(priv->adapter, &frame_control,
+				   (t_u8 *)&(mgmt_tlv->frame_control),
+				   sizeof(frame_control),
+				   sizeof(frame_control));
+			frame_sub_type =
+				IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE
+				(frame_control);
+			if ((mgmt_tlv->frame_control.type == 0) &&
+			    ((frame_sub_type == SUBTYPE_ASSOC_REQUEST) ||
+			     (frame_sub_type == SUBTYPE_REASSOC_REQUEST))) {
+				if (frame_sub_type == SUBTYPE_ASSOC_REQUEST)
+					assoc_ie_len =
+						sizeof(IEEEtypes_AssocRqst_t);
+				else if (frame_sub_type ==
+					 SUBTYPE_REASSOC_REQUEST)
+					assoc_ie_len =
+						sizeof(IEEEtypes_ReAssocRqst_t);
+
+				ie_len = tlv_len -
+					sizeof(IEEEtypes_FrameCtl_t) -
+					assoc_ie_len;
+				assoc_req_ie =
+					(t_u8 *)tlv +
+					sizeof(MrvlIETypes_MgmtFrameSet_t) +
+					assoc_ie_len;
+				memcpy_ext(priv->adapter,
+					   pevent->event_buf +
+					   pevent->event_len,
+					   assoc_req_ie, ie_len, ie_len);
+				pevent->event_len += ie_len;
+				break;
+			}
+		}
+		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
+					      sizeof(MrvlIEtypesHeader_t));
+	}
+	PRINTM(MEVENT, "STA assoc event len=%d\n", pevent->event_len);
+	DBG_HEXDUMP(MCMD_D, "STA assoc event", pevent->event_buf,
+		    pevent->event_len);
+	wlan_recv_event(priv, pevent->event_id, pevent);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles repsonse of acs_scan.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_ret_cmd_uap_acs_scan(pmlan_private pmpriv,
+			  const HostCmd_DS_COMMAND *resp,
+			  mlan_ioctl_req *pioctl_buf)
+{
+	HostCMD_DS_APCMD_ACS_SCAN *acs_scan =
+		(HostCMD_DS_APCMD_ACS_SCAN *) & resp->params.acs_scan;
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+	PRINTM(MCMND, "ACS scan done: bandcfg=%x, channel=%d\n",
+	       acs_scan->bandcfg, acs_scan->chan);
+	if (pioctl_buf) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		bss->param.ap_acs_scan.chan = acs_scan->chan;
+		bss->param.ap_acs_scan.bandcfg = acs_scan->bandcfg;
+		pioctl_buf->data_read_written = sizeof(mlan_ds_bss);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of uap operation control
+ *
+ *  @param pmpriv		A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_cmd_oper_ctrl(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd,
+		       t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+		(HostCmd_DS_UAP_OPER_CTRL *) & cmd->params.uap_oper_ctrl;
+	mlan_ds_bss *bss = (mlan_ds_bss *)pdata_buf;
+	mlan_uap_oper_ctrl *uap_oper_ctrl = &bss->param.ap_oper_ctrl;
+	Band_Config_t *bandcfg = MNULL;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_OPER_CTRL);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_UAP_OPER_CTRL) + S_DS_GEN);
+	poper_ctl->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		poper_ctl->ctrl = wlan_cpu_to_le16(uap_oper_ctrl->ctrl_value);
+		if (uap_oper_ctrl->ctrl_value == 2) {
+			poper_ctl->chan_opt =
+				wlan_cpu_to_le16(uap_oper_ctrl->chan_opt);
+			if (uap_oper_ctrl->chan_opt == 3) {
+				poper_ctl->channel_band.header.type =
+					wlan_cpu_to_le16
+					(TLV_TYPE_UAP_CHAN_BAND_CONFIG);
+				poper_ctl->channel_band.header.len =
+					wlan_cpu_to_le16(sizeof
+							 (MrvlIEtypes_channel_band_t)
+							 -
+							 sizeof
+							 (MrvlIEtypesHeader_t));
+				bandcfg = &poper_ctl->channel_band.bandcfg;
+				if (uap_oper_ctrl->channel > 14)
+					bandcfg->chanBand = BAND_5GHZ;
+				bandcfg->chanWidth = uap_oper_ctrl->band_cfg;
+				if (bandcfg->chanWidth)
+					bandcfg->chan2Offset =
+						wlan_get_second_channel_offset
+						(pmpriv,
+						 uap_oper_ctrl->channel);
+				bandcfg->scanMode = SCAN_MODE_MANUAL;
+				poper_ctl->channel_band.channel =
+					uap_oper_ctrl->channel;
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of uap operation control
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+wlan_uap_ret_oper_ctrl(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_UAP_OPER_CTRL *poper_ctl =
+		(HostCmd_DS_UAP_OPER_CTRL *) & resp->params.uap_oper_ctrl;
+	mlan_ds_bss *bss = MNULL;
+	mlan_uap_oper_ctrl *uap_oper_ctrl = MNULL;
+	Band_Config_t *bandcfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf && pioctl_buf->action == MLAN_ACT_GET) {
+		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+		uap_oper_ctrl =
+			(mlan_uap_oper_ctrl *) & bss->param.ap_oper_ctrl;
+		uap_oper_ctrl->ctrl_value = wlan_le16_to_cpu(poper_ctl->ctrl);
+		uap_oper_ctrl->chan_opt = wlan_le16_to_cpu(poper_ctl->chan_opt);
+		uap_oper_ctrl->channel = poper_ctl->channel_band.channel;
+		bandcfg = &poper_ctl->channel_band.bandcfg;
+		uap_oper_ctrl->band_cfg = bandcfg->chanWidth;
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief	Check 11B support Rates
+ *
+ *
+ *  @param pmadapter	Private mlan adapter structure
+ *
+ *  @return MTRUE/MFALSE
+ *
+ */
+static t_u8
+wlan_check_11B_support_rates(MrvlIEtypes_RatesParamSet_t *prates_tlv)
+{
+	int i;
+	t_u8 rate;
+	t_u8 ret = MTRUE;
+	for (i = 0; i < prates_tlv->header.len; i++) {
+		rate = prates_tlv->rates[i] & 0x7f;
+		if ((rate != 0x02) && (rate != 0x04) && (rate != 0x0b) &&
+		    (rate != 0x16)) {
+			ret = MFALSE;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of sys_config
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   cmd action
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_cmd_add_station(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd,
+			 t_u16 cmd_action, pmlan_ioctl_req pioctl_buf)
+{
+	mlan_ds_bss *bss = MNULL;
+	HostCmd_DS_ADD_STATION *new_sta =
+		(HostCmd_DS_ADD_STATION *) & cmd->params.sta_info;
+	sta_node *sta_ptr = MNULL;
+	t_u16 tlv_buf_left;
+	t_u8 *pos = MNULL;
+	t_u8 *tlv_buf = MNULL;
+	t_u16 travel_len = 0;
+	MrvlIEtypesHeader_t *tlv;
+	t_u16 tlv_len = 0;
+	t_u8 b_only = MFALSE;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	MrvlIETypes_HTCap_t *phtcap;
+	MrvlIETypes_VHTCap_t *pvhtcap;
+	MrvlIEtypes_Extension_t *pext_tlv = MNULL;
+	MrvlIEtypes_StaFlag_t *pstaflag;
+	int i;
+
+	ENTER();
+
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	bss = (mlan_ds_bss *)pioctl_buf->pbuf;
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ADD_NEW_STATION);
+	new_sta->action = wlan_cpu_to_le16(cmd_action);
+	cmd->size = sizeof(HostCmd_DS_ADD_STATION) + S_DS_GEN;
+	if (cmd_action == HostCmd_ACT_ADD_STA) {
+		sta_ptr = wlan_get_station_entry(pmpriv,
+						 bss->param.sta_info.peer_mac);
+		if (!sta_ptr)
+			sta_ptr =
+				wlan_add_station_entry(pmpriv,
+						       bss->param.sta_info.
+						       peer_mac);
+	} else {
+		sta_ptr = wlan_add_station_entry(pmpriv,
+						 bss->param.sta_info.peer_mac);
+	}
+	if (!sta_ptr) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	memcpy_ext(pmadapter, new_sta->peer_mac, bss->param.sta_info.peer_mac,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	if (cmd_action != HostCmd_ACT_ADD_STA)
+		goto done;
+	new_sta->aid = wlan_cpu_to_le16(bss->param.sta_info.aid);
+	new_sta->listen_interval =
+		wlan_cpu_to_le32(bss->param.sta_info.listen_interval);
+	if (bss->param.sta_info.cap_info)
+		new_sta->cap_info =
+			wlan_cpu_to_le16(bss->param.sta_info.cap_info);
+	else
+		new_sta->cap_info = wlan_cpu_to_le16(sta_ptr->capability);
+	tlv_buf_left = bss->param.sta_info.tlv_len;
+	pos = new_sta->tlv;
+	tlv_buf = bss->param.sta_info.tlv;
+	tlv = (MrvlIEtypesHeader_t *)tlv_buf;
+	if (bss->param.sta_info.sta_flags & STA_FLAG_WME) {
+		PRINTM(MCMND, "STA flags supports wmm \n");
+		sta_ptr->is_wmm_enabled = MTRUE;
+	}
+	// append sta_flag_flags.
+	pstaflag = (MrvlIEtypes_StaFlag_t *) pos;
+	pstaflag->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS);
+	pstaflag->header.len = wlan_cpu_to_le16(sizeof(t_u32));
+	pstaflag->sta_flags = wlan_cpu_to_le32(bss->param.sta_info.sta_flags);
+	pos += sizeof(MrvlIEtypes_StaFlag_t);
+	cmd->size += sizeof(MrvlIEtypes_StaFlag_t);
+
+	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
+		if (tlv_buf_left < (sizeof(MrvlIEtypesHeader_t) + tlv->len))
+			break;
+		switch (tlv->type) {
+		case EXT_CAPABILITY:
+			break;
+		case SUPPORTED_RATES:
+			b_only = wlan_check_11B_support_rates((MrvlIEtypes_RatesParamSet_t *)tlv);
+			break;
+		case QOS_INFO:
+			PRINTM(MCMND, "STA supports wmm\n");
+			sta_ptr->is_wmm_enabled = MTRUE;
+			break;
+		case HT_CAPABILITY:
+			PRINTM(MCMND, "STA supports 11n\n");
+			sta_ptr->is_11n_enabled = MTRUE;
+			phtcap = (MrvlIETypes_HTCap_t *)tlv;
+			if (sta_ptr->HTcap.ieee_hdr.element_id == HT_CAPABILITY) {
+				if (GETHT_40MHZ_INTOLARANT
+				    (sta_ptr->HTcap.ht_cap.ht_cap_info)) {
+					PRINTM(MCMND,
+					       "SETHT_40MHZ_INTOLARANT\n");
+					SETHT_40MHZ_INTOLARANT(phtcap->ht_cap.
+							       ht_cap_info);
+				}
+			}
+			if (GETHT_MAXAMSDU(phtcap->ht_cap.ht_cap_info))
+				sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+			else
+				sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+			break;
+		case VHT_CAPABILITY:
+			PRINTM(MCMND, "STA supports 11ac\n");
+			sta_ptr->is_11ac_enabled = MTRUE;
+			pvhtcap = (MrvlIETypes_VHTCap_t *)tlv;
+			if (GET_VHTCAP_MAXMPDULEN(pvhtcap->vht_cap.vht_cap_info)
+			    == 2)
+				sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_12K;
+			else if (GET_VHTCAP_MAXMPDULEN
+				 (pvhtcap->vht_cap.vht_cap_info) == 1)
+				sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K;
+			else
+				sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
+			break;
+		case OPER_MODE_NTF:
+			break;
+		case EXTENSION:
+			pext_tlv = (MrvlIEtypes_Extension_t *) tlv;
+			if (pext_tlv->ext_id == HE_CAPABILITY) {
+				sta_ptr->is_11ax_enabled = MTRUE;
+				PRINTM(MCMND, "STA supports 11ax\n");
+			} else {
+				pext_tlv = MNULL;
+			}
+			break;
+		default:
+			break;
+		}
+		tlv_len = tlv->len;
+		tlv->type = wlan_cpu_to_le16(tlv->type);
+		tlv->len = wlan_cpu_to_le16(tlv->len);
+		memcpy_ext(pmadapter, pos, (t_u8 *)tlv,
+			   sizeof(MrvlIEtypesHeader_t) + tlv_len,
+			   sizeof(MrvlIEtypesHeader_t) + tlv_len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv_len;
+		tlv_buf += sizeof(MrvlIEtypesHeader_t) + tlv_len;
+		tlv = (MrvlIEtypesHeader_t *)tlv_buf;
+		travel_len += sizeof(MrvlIEtypesHeader_t) + tlv_len;
+		tlv_buf_left -= sizeof(MrvlIEtypesHeader_t) + tlv_len;
+	}
+	if (sta_ptr->is_11ax_enabled) {
+		if (pext_tlv == MNULL) {
+			tlv = (MrvlIEtypesHeader_t *)pos;
+			tlv->type = wlan_cpu_to_le16(EXTENSION);
+			tlv->len =
+				wlan_cpu_to_le16(MIN
+						 (sta_ptr->he_cap.ieee_hdr.len,
+						  sizeof(IEEEtypes_HECap_t) -
+						  sizeof(IEEEtypes_Header_t)));
+
+			pos += sizeof(MrvlIEtypesHeader_t);
+			memcpy_ext(pmadapter, pos,
+				   (t_u8 *)&sta_ptr->he_cap.ext_id,
+				   tlv->len, tlv->len);
+			travel_len += sizeof(MrvlIEtypesHeader_t) + tlv->len;
+		}
+	}
+
+	if (sta_ptr->is_11n_enabled) {
+		if (pmpriv->uap_channel <= 14)
+			sta_ptr->bandmode = BAND_GN;
+		else
+			sta_ptr->bandmode = BAND_AN;
+	} else if (!b_only) {
+		if (pmpriv->uap_channel <= 14)
+			sta_ptr->bandmode = BAND_G;
+		else
+			sta_ptr->bandmode = BAND_A;
+	} else
+		sta_ptr->bandmode = BAND_B;
+	if (sta_ptr->is_11ac_enabled) {
+		if (pmpriv->uap_channel <= 14)
+			sta_ptr->bandmode = BAND_GAC;
+		else
+			sta_ptr->bandmode = BAND_AAC;
+	}
+	if (sta_ptr->is_11ax_enabled) {
+		if (pmpriv->uap_channel <= 14)
+			sta_ptr->bandmode = BAND_GAX;
+		else
+			sta_ptr->bandmode = BAND_AAX;
+	}
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		if (sta_ptr->is_11n_enabled)
+			sta_ptr->ampdu_sta[i] =
+				pmpriv->aggr_prio_tbl[i].ampdu_user;
+		else
+			sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
+	}
+	memset(pmadapter, sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
+done:
+	cmd->size += travel_len;
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *  @brief This function prepare the command before sending to firmware.
+ *
+ *  @param priv       A pointer to mlan_private structure
+ *  @param cmd_no       Command number
+ *  @param cmd_action   Command action: GET or SET
+ *  @param cmd_oid      Cmd oid: treated as sub command
+ *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
+ *  @param pdata_buf    A pointer to information buffer
+ *  @param pcmd_buf      A pointer to cmd buf
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
+			 t_u16 cmd_action, t_u32 cmd_oid,
+			 t_void *pioctl_buf,
+			 t_void *pdata_buf, t_void *pcmd_buf)
+{
+	HostCmd_DS_COMMAND *cmd_ptr = (HostCmd_DS_COMMAND *)pcmd_buf;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
+
+	ENTER();
+
+	/* Prepare command */
+	switch (cmd_no) {
+	case HostCMD_APCMD_ACS_SCAN:
+	case HostCmd_CMD_SOFT_RESET:
+	case HOST_CMD_APCMD_BSS_STOP:
+	case HOST_CMD_APCMD_SYS_INFO:
+	case HOST_CMD_APCMD_SYS_RESET:
+	case HOST_CMD_APCMD_STA_LIST:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HOST_CMD_APCMD_BSS_START:
+		ret = wlan_uap_cmd_bss_start(pmpriv, cmd_ptr);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if (IsAuthenticatorEnabled(pmpriv->psapriv))
+			AuthenticatorBssConfig(pmpriv->psapriv, MNULL, 1, 0, 0);
+#endif
+		break;
+	case HOST_CMD_APCMD_SYS_CONFIGURE:
+		ret = wlan_uap_cmd_sys_configure(pmpriv, cmd_ptr, cmd_action,
+						 (pmlan_ioctl_req)pioctl_buf,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_PS_MODE_ENH:
+		ret = wlan_cmd_enh_power_mode(pmpriv, cmd_ptr, cmd_action,
+					      (t_u16)cmd_oid, pdata_buf);
+		break;
+#if defined(SDIO)
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_FUNC_INIT:
+		if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
+			pmpriv->adapter->hw_status =
+				WlanHardwareStatusInitializing;
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+		pmpriv->adapter->hw_status = WlanHardwareStatusReset;
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		break;
+	case HostCmd_CMD_CFG_DATA:
+		ret = wlan_cmd_cfg_data(pmpriv, cmd_ptr, cmd_action, cmd_oid,
+					pdata_buf);
+		break;
+	case HostCmd_CMD_MAC_CONTROL:
+		ret = wlan_cmd_mac_control(pmpriv, cmd_ptr, cmd_action,
+					   pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_SNMP_MIB:
+		ret = wlan_uap_cmd_snmp_mib(pmpriv, cmd_ptr, cmd_action,
+					    cmd_oid,
+					    (pmlan_ioctl_req)pioctl_buf,
+					    pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_GET_LOG:
+		ret = wlan_uap_cmd_802_11_get_log(pmpriv, cmd_ptr);
+		break;
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action);
+		break;
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		ret = wlan_11h_cmd_process(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HOST_CMD_APCMD_STA_DEAUTH:
+		ret = wlan_uap_cmd_sta_deauth(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HOST_CMD_APCMD_REPORT_MIC:
+		ret = wlan_uap_cmd_report_mic(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_KEY_MATERIAL:
+		ret = wlan_uap_cmd_key_material(pmpriv, cmd_ptr, cmd_action,
+						cmd_oid, pdata_buf);
+		break;
+	case HostCmd_CMD_GET_HW_SPEC:
+		ret = wlan_cmd_get_hw_spec(pmpriv, cmd_ptr);
+		break;
+#ifdef SDIO
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_802_11_HS_CFG_ENH:
+		ret = wlan_uap_cmd_802_11_hs_cfg(pmpriv, cmd_ptr, cmd_action,
+						 (hs_config_param *)pdata_buf);
+		break;
+	case HostCmd_CMD_HS_WAKEUP_REASON:
+		ret = wlan_cmd_hs_wakeup_reason(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		ret = wlan_cmd_robustcoex(pmpriv, cmd_ptr, cmd_action,
+					  (t_u16 *)pdata_buf);
+		break;
+	case HostCmd_CMD_DMCS_CONFIG:
+		ret = wlan_cmd_dmcs_config(pmpriv, cmd_ptr, cmd_action,
+					   pdata_buf);
+		break;
+	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+		ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
+					    pdata_buf);
+		break;
+	case HostCmd_CMD_AMSDU_AGGR_CTRL:
+		ret = wlan_cmd_amsdu_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_11N_CFG:
+		ret = wlan_cmd_11n_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_ADDBA_REQ:
+		ret = wlan_cmd_11n_addba_req(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_DELBA:
+		ret = wlan_cmd_11n_delba(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11N_ADDBA_RSP:
+		ret = wlan_cmd_11n_addba_rspgen(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_REJECT_ADDBA_REQ:
+		ret = wlan_cmd_reject_addba_req(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HostCmd_CMD_TX_BF_CFG:
+		ret = wlan_cmd_tx_bf_cfg(pmpriv, cmd_ptr, cmd_action,
+					 pdata_buf);
+		break;
+#if defined(WIFI_DIRECT_SUPPORT)
+	case HostCmd_CMD_SET_BSS_MODE:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		if (pdata_buf)
+			cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
+		else
+			cmd_ptr->params.bss_mode.con_type =
+				BSS_MODE_WIFIDIRECT_GO;
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_SET_BSS_MODE) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+#endif
+	case HostCmd_CMD_VERSION_EXT:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->params.verext.version_str_sel =
+			(t_u8)(*((t_u32 *)pdata_buf));
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_VERSION_EXT) +
+					 S_DS_GEN);
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->params.rx_mgmt_ind.action =
+			wlan_cpu_to_le16(cmd_action);
+		cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask =
+			(t_u32)(*((t_u32 *)pdata_buf));
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_MGMT_IND) +
+					 S_DS_GEN);
+		break;
+	case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+		ret = wlan_uap_cmd_txdatapause(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_cmd_802_11_radio_control(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_TX_RATE_CFG:
+		ret = wlan_cmd_tx_rate_cfg(pmpriv, cmd_ptr, cmd_action,
+					   pdata_buf, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		cmd_ptr->command =
+			wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) +
+						 S_DS_GEN);
+		pmpriv->tx_rate = 0;
+		ret = MLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_cmd_p2p_params_config(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#endif
+	case HOST_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_802_11_RF_ANTENNA:
+		ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf);
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_DYN_BW:
+		ret = wlan_cmd_config_dyn_bw(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_MAC_REG_ACCESS:
+	case HostCmd_CMD_BBP_REG_ACCESS:
+	case HostCmd_CMD_RF_REG_ACCESS:
+	case HostCmd_CMD_CAU_REG_ACCESS:
+	case HostCmd_CMD_TARGET_ACCESS:
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:
+	case HostCmd_CMD_BCA_REG_ACCESS:
+		ret = wlan_cmd_reg_access(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
+	case HostCmd_CMD_MEM_ACCESS:
+		ret = wlan_cmd_mem_access(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_WMM_QUEUE_CONFIG:
+		ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf);
+		break;
+#ifdef RX_PACKET_COALESCE
+	case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+		ret = wlan_cmd_rx_pkt_coalesce_cfg(pmpriv, cmd_ptr, cmd_action,
+						   pdata_buf);
+		break;
+#endif
+	case HOST_CMD_APCMD_OPER_CTRL:
+		ret = wlan_uap_cmd_oper_ctrl(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+
+	case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+		ret = wlan_cmd_ind_rst_cfg(cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_GET_TSF:
+		ret = wlan_cmd_get_tsf(pmpriv, cmd_ptr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+		ret = wlan_cmd_ps_inactivity_timeout(pmpriv, cmd_ptr,
+						     cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
+		cmd_ptr->size =
+			wlan_cpu_to_le16(sizeof(HostCmd_DS_CHAN_REGION_CFG) +
+					 S_DS_GEN);
+		cmd_ptr->params.reg_cfg.action = wlan_cpu_to_le16(cmd_action);
+		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+		ret = wlan_cmd_packet_aggr_ctrl(pmpriv, cmd_ptr, cmd_action,
+						pdata_buf);
+		break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+	case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+		ret = wlan_cmd_pcie_host_buf_cfg(pmpriv, cmd_ptr, cmd_action,
+						 pdata_buf);
+		break;
+#endif
+#endif
+	case HOST_CMD_TX_RX_PKT_STATS:
+		ret = wlan_cmd_tx_rx_pkt_stats(pmpriv, cmd_ptr,
+					       (pmlan_ioctl_req)pioctl_buf,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_FW_DUMP_EVENT:
+		ret = wlan_cmd_fw_dump_event(pmpriv, cmd_ptr, cmd_action,
+					     pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_LINK_STATS:
+		ret = wlan_cmd_802_11_link_statistic(pmpriv, cmd_ptr,
+						     cmd_action, pioctl_buf);
+		break;
+	case HostCmd_CMD_ADD_NEW_STATION:
+		ret = wlan_uap_cmd_add_station(pmpriv, cmd_ptr, cmd_action,
+					       (pmlan_ioctl_req)pioctl_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_cmd_boot_sleep(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+	case HostCmd_CMD_CRYPTO:
+		ret = wlan_cmd_crypto(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+#endif
+	case HostCmd_CMD_11AX_CFG:
+		ret = wlan_cmd_11ax_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_11AX_CMD:
+		ret = wlan_cmd_11ax_cmd(pmpriv, cmd_ptr, cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_RANGE_EXT:
+		ret = wlan_cmd_range_ext(pmpriv, cmd_ptr, cmd_action,
+					 pdata_buf);
+		break;
+	case HostCmd_CMD_RX_ABORT_CFG:
+		ret = wlan_cmd_rxabortcfg(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
+	case HostCmd_CMD_RX_ABORT_CFG_EXT:
+		ret = wlan_cmd_rxabortcfg_ext(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+		ret = wlan_cmd_tx_ampdu_prot_mode(pmpriv, cmd_ptr, cmd_action,
+						  pdata_buf);
+		break;
+	case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+		ret = wlan_cmd_dot11mc_unassoc_ftm_cfg(pmpriv, cmd_ptr,
+						       cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_RATE_ADAPT_CFG:
+		ret = wlan_cmd_rate_adapt_cfg(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
+	case HostCmd_CMD_CCK_DESENSE_CFG:
+		ret = wlan_cmd_cck_desense_cfg(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_cmd_get_chan_trpc_config(pmpriv, cmd_ptr, cmd_action,
+						    pdata_buf);
+		break;
+	case HostCmd_CMD_LOW_POWER_MODE_CFG:
+		ret = wlan_cmd_set_get_low_power_mode_cfg(pmpriv, cmd_ptr,
+							  cmd_action,
+							  pdata_buf);
+		break;
+	case HostCmd_CMD_802_11_BAND_STEERING:
+		ret = wlan_cmd_set_get_band_steering_cfg(pmpriv, cmd_ptr,
+							 cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_UAP_BEACON_STUCK_CFG:
+		ret = wlan_cmd_set_get_beacon_stuck_cfg(pmpriv, cmd_ptr,
+							cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_HAL_PHY_CFG:
+		ret = wlan_cmd_hal_phy_cfg(pmpriv, cmd_ptr, cmd_action,
+					   pdata_buf);
+		break;
+	default:
+		PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
+		if (pioctl_req)
+			pioctl_req->status_code = MLAN_ERROR_CMD_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the AP mode command response
+ *
+ *  @param priv             A pointer to mlan_private structure
+ *  @param cmdresp_no       cmd no
+ *  @param pcmd_buf         cmdresp buf
+ *  @param pioctl           A pointer to ioctl buf
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
+			     t_void *pcmd_buf, t_void *pioctl)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *)pcmd_buf;
+	mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *)pioctl;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+#ifdef SDIO
+	int ctr;
+#endif
+	wlan_dfs_device_state_t *pstate_dfs =
+		(wlan_dfs_device_state_t *)&pmpriv->adapter->state_dfs;
+	t_u32 sec, usec;
+	ENTER();
+
+	/* If the command is not successful, cleanup and return failure */
+	if (resp->result != HostCmd_RESULT_OK) {
+		ret = uap_process_cmdresp_error(pmpriv, resp, pioctl_buf);
+		LEAVE();
+		return ret;
+	}
+
+	/* Command successful, handle response */
+	switch (cmdresp_no) {
+	case HOST_CMD_APCMD_BSS_STOP:
+		pmpriv->uap_bss_started = MFALSE;
+		/* Timestamp update is required because bss_start after skip_cac
+		 * enabled should not select non-current channel just because
+		 * timestamp got expired
+		 */
+		if (!pmpriv->intf_state_11h.is_11h_host &&
+		    !pstate_dfs->dfs_check_pending &&
+		    pstate_dfs->dfs_check_channel) {
+			pmpriv->adapter->callbacks.moal_get_system_time(pmpriv->
+									adapter->
+									pmoal_handle,
+									&sec,
+									&usec);
+			pstate_dfs->dfs_report_time_sec = sec;
+		}
+		if (pmpriv->intf_state_11h.is_11h_host)
+			pmpriv->intf_state_11h.tx_disabled = MFALSE;
+		else {
+			if (pmpriv->adapter->ecsa_enable)
+				wlan_11h_remove_custom_ie(pmpriv->adapter,
+							  pmpriv);
+			wlan_11h_check_update_radar_det_state(pmpriv);
+		}
+
+		if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS)
+			wlan_11h_radar_detected_callback((t_void *)pmpriv);
+		wlan_coex_ampdu_rxwinsize(pmadapter);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if (IsAuthenticatorEnabled(pmpriv->psapriv)) {
+			AuthenticatorBssConfig(pmpriv->psapriv, MNULL, 0, 1, 0);
+			AuthenticatorkeyClear(pmpriv->psapriv);
+		}
+#endif
+		pmpriv->uap_host_based = 0;
+		break;
+	case HOST_CMD_APCMD_BSS_START:
+		if (!pmpriv->intf_state_11h.is_11h_host &&
+		    pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS)
+			wlan_11h_radar_detected_callback((t_void *)pmpriv);
+		/* Stop pps_uapsd_mode once bss_start */
+		pmpriv->adapter->tx_lock_flag = MFALSE;
+		pmpriv->adapter->pps_uapsd_mode = MFALSE;
+		pmpriv->adapter->delay_null_pkt = MFALSE;
+		/* Clear AMSDU statistics */
+		pmpriv->amsdu_rx_cnt = 0;
+		pmpriv->amsdu_tx_cnt = 0;
+		pmpriv->msdu_in_rx_amsdu_cnt = 0;
+		pmpriv->msdu_in_tx_amsdu_cnt = 0;
+		break;
+	case HOST_CMD_APCMD_SYS_RESET:
+		pmpriv->uap_bss_started = MFALSE;
+		pmpriv->uap_host_based = 0;
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		AuthenitcatorInitBssConfig(pmpriv->psapriv);
+#endif
+		ret = wlan_uap_ret_sys_reset(pmpriv, resp, pioctl_buf);
+		wlan_11h_check_update_radar_det_state(pmpriv);
+		wlan_coex_ampdu_rxwinsize(pmadapter);
+		break;
+	case HOST_CMD_APCMD_SYS_INFO:
+		break;
+	case HOST_CMD_APCMD_SYS_CONFIGURE:
+		ret = wlan_uap_ret_sys_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_PS_MODE_ENH:
+		ret = wlan_ret_enh_power_mode(pmpriv, resp, pioctl_buf);
+		break;
+#if defined(SDIO)
+	case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
+		break;
+#endif
+	case HostCmd_CMD_FUNC_INIT:
+	case HostCmd_CMD_FUNC_SHUTDOWN:
+		break;
+	case HostCmd_CMD_802_11_SNMP_MIB:
+		ret = wlan_uap_ret_snmp_mib(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_GET_LOG:
+		ret = wlan_uap_ret_get_log(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		ret = wlan_ret_802_11d_domain_info(pmpriv, resp);
+		break;
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		ret = wlan_11h_cmdresp_process(pmpriv, resp);
+		break;
+	case HOST_CMD_APCMD_STA_DEAUTH:
+		break;
+	case HOST_CMD_APCMD_REPORT_MIC:
+		break;
+	case HostCmd_CMD_802_11_KEY_MATERIAL:
+		break;
+	case HOST_CMD_APCMD_STA_LIST:
+		ret = wlan_uap_ret_sta_list(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_GET_HW_SPEC:
+		ret = wlan_ret_get_hw_spec(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef SDIO
+	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
+		ret = wlan_ret_sdio_rx_aggr_cfg(pmpriv, resp);
+		break;
+#endif
+	case HostCmd_CMD_CFG_DATA:
+		ret = wlan_ret_cfg_data(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MAC_CONTROL:
+		ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_HS_CFG_ENH:
+		ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_HS_WAKEUP_REASON:
+		ret = wlan_ret_hs_wakeup_reason(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_ROBUSTCOEX:
+		break;
+	case HostCmd_CMD_DMCS_CONFIG:
+		ret = wlan_ret_dmcs_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11N_ADDBA_REQ:
+		ret = wlan_ret_11n_addba_req(pmpriv, resp);
+		break;
+	case HostCmd_CMD_11N_DELBA:
+		ret = wlan_ret_11n_delba(pmpriv, resp);
+		break;
+	case HostCmd_CMD_11N_ADDBA_RSP:
+		ret = wlan_ret_11n_addba_resp(pmpriv, resp);
+		break;
+	case HostCmd_CMD_SET_BSS_MODE:
+		break;
+	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
+		wlan_set_tx_pause_flag(pmpriv, MFALSE);
+
+		pmadapter->tx_buf_size =
+			(t_u16)wlan_le16_to_cpu(resp->params.tx_buf.buff_size);
+#ifdef SDIO
+		if (IS_SD(pmadapter->card_type)) {
+			pmadapter->tx_buf_size = (pmadapter->tx_buf_size /
+						  MLAN_SDIO_BLOCK_SIZE) *
+				MLAN_SDIO_BLOCK_SIZE;
+			pmadapter->pcard_sd->mp_end_port =
+				wlan_le16_to_cpu(resp->params.tx_buf.
+						 mp_end_port);
+			pmadapter->pcard_sd->mp_data_port_mask =
+				pmadapter->pcard_sd->reg->data_port_mask;
+
+			for (ctr = 1;
+			     ctr <=
+			     pmadapter->pcard_sd->max_ports -
+			     pmadapter->pcard_sd->mp_end_port; ctr++) {
+				pmadapter->pcard_sd->mp_data_port_mask &=
+					~(1 <<
+					  (pmadapter->pcard_sd->max_ports -
+					   ctr));
+			}
+
+			pmadapter->pcard_sd->curr_wr_port =
+				pmadapter->pcard_sd->reg->start_wr_port;
+			pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
+				MIN(pmadapter->pcard_sd->mp_aggr_pkt_limit,
+				    (pmadapter->pcard_sd->mp_end_port >> 1));
+			PRINTM(MCMND, "end port %d, data port mask %x\n",
+			       wlan_le16_to_cpu(resp->params.tx_buf.
+						mp_end_port),
+			       pmadapter->pcard_sd->mp_data_port_mask);
+		}
+#endif
+		pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size;
+		PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n",
+		       pmadapter->max_tx_buf_size, pmadapter->tx_buf_size);
+		break;
+	case HostCmd_CMD_AMSDU_AGGR_CTRL:
+		ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11N_CFG:
+		ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_REJECT_ADDBA_REQ:
+		ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_BF_CFG:
+		ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_VERSION_EXT:
+		ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_MGMT_IND:
+		ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CFG_TX_DATA_PAUSE:
+		ret = wlan_uap_ret_txdatapause(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_RATE_CFG:
+		ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
+		ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+	case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
+		ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_P2P_PARAMS_CONFIG:
+		ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG:
+		ret = wlan_ret_gpio_tsf_latch(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_MIMO_SWITCH:
+		break;
+	case HostCmd_CMD_11AC_CFG:
+		ret = wlan_ret_11ac_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DYN_BW:
+		ret = wlan_ret_dyn_bw(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MAC_REG_ACCESS:
+	case HostCmd_CMD_BBP_REG_ACCESS:
+	case HostCmd_CMD_RF_REG_ACCESS:
+	case HostCmd_CMD_CAU_REG_ACCESS:
+	case HostCmd_CMD_TARGET_ACCESS:
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:
+	case HostCmd_CMD_BCA_REG_ACCESS:
+		ret = wlan_ret_reg_access(pmpriv->adapter, cmdresp_no, resp,
+					  pioctl_buf);
+		break;
+	case HostCmd_CMD_MEM_ACCESS:
+		ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_WMM_QUEUE_CONFIG:
+		ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf);
+		break;
+#ifdef RX_PACKET_COALESCE
+	case HostCmd_CMD_RX_PKT_COALESCE_CFG:
+		ret = wlan_ret_rx_pkt_coalesce_cfg(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCMD_APCMD_ACS_SCAN:
+		ret = wlan_ret_cmd_uap_acs_scan(pmpriv, resp, pioctl_buf);
+		break;
+	case HOST_CMD_APCMD_OPER_CTRL:
+		ret = wlan_uap_ret_oper_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_INDEPENDENT_RESET_CFG:
+		ret = wlan_ret_ind_rst_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT:
+		break;
+	case HostCmd_CMD_GET_TSF:
+		ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf);
+		break;
+
+	case HostCmd_CMD_CHAN_REGION_CFG:
+		ret = wlan_ret_chan_region_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_PACKET_AGGR_CTRL:
+		ret = wlan_ret_packet_aggr_ctrl(pmpriv, resp, pioctl_buf);
+		break;
+#if defined(PCIE)
+#if defined(PCIE8997) || defined(PCIE8897)
+	case HostCmd_CMD_PCIE_HOST_BUF_DETAILS:
+		PRINTM(MINFO, "PCIE host buffer configuration successful.\n");
+		break;
+#endif
+#endif
+	case HOST_CMD_TX_RX_PKT_STATS:
+		ret = wlan_ret_tx_rx_pkt_stats(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_LINK_STATS:
+		ret = wlan_ret_get_link_statistic(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_BOOT_SLEEP:
+		ret = wlan_ret_boot_sleep(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_ADD_NEW_STATION:
+		break;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+	case HostCmd_CMD_CRYPTO:
+		ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf);
+		break;
+#endif
+	case HostCmd_CMD_11AX_CFG:
+		ret = wlan_ret_11ax_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_11AX_CMD:
+		ret = wlan_ret_11ax_cmd(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RANGE_EXT:
+		ret = wlan_ret_range_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_ABORT_CFG:
+		ret = wlan_ret_rxabortcfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RX_ABORT_CFG_EXT:
+		ret = wlan_ret_rxabortcfg_ext(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_TX_AMPDU_PROT_MODE:
+		ret = wlan_ret_tx_ampdu_prot_mode(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG:
+		ret = wlan_ret_dot11mc_unassoc_ftm_cfg(pmpriv, resp,
+						       pioctl_buf);
+		break;
+	case HostCmd_CMD_HAL_PHY_CFG:
+		ret = wlan_ret_hal_phy_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_RATE_ADAPT_CFG:
+		ret = wlan_ret_rate_adapt_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_CCK_DESENSE_CFG:
+		ret = wlan_ret_cck_desense_cfg(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CHANNEL_TRPC_CONFIG:
+		ret = wlan_ret_get_chan_trpc_config(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_LOW_POWER_MODE_CFG:
+		ret = wlan_ret_set_get_low_power_mode_cfg(pmpriv, resp,
+							  pioctl_buf);
+		break;
+	case HostCmd_CMD_802_11_BAND_STEERING:
+		ret = wlan_ret_set_get_band_steering_cfg(pmpriv, resp,
+							 pioctl_buf);
+		break;
+	case HostCmd_CMD_UAP_BEACON_STUCK_CFG:
+		ret = wlan_ret_set_get_beacon_stuck_cfg(pmpriv, resp,
+							pioctl_buf);
+		break;
+	default:
+		PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n",
+		       resp->command);
+		if (pioctl_buf)
+			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles events generated by firmware
+ *
+ *  @param priv		A pointer to mlan_private structure
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_uap_process_event(t_void *priv)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 eventcause = pmadapter->event_cause;
+	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
+	t_u8 *event_buf = MNULL;
+	mlan_event *pevent = MNULL;
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	sta_node *sta_ptr = MNULL;
+	t_u8 i = 0;
+	t_u8 channel = 0;
+	MrvlIEtypes_channel_band_t *pchan_info = MNULL;
+	chan_band_info *pchan_band_info = MNULL;
+	event_exceed_max_p2p_conn *event_excd_p2p = MNULL;
+	t_u16 enable;
+
+	ENTER();
+
+	if (!pmbuf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Event length check */
+	if (pmbuf && (pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) {
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate memory for event buffer */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
+			       MAX_EVENT_SIZE + sizeof(mlan_event),
+			       MLAN_MEM_DEF, &event_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
+		PRINTM(MERROR, "Could not allocate buffer for event buf\n");
+		if (pmbuf)
+			pmbuf->status_code = MLAN_ERROR_NO_MEM;
+		goto done;
+	}
+	pevent = (pmlan_event)event_buf;
+	memset(pmadapter, &pevent->event_id, 0, sizeof(pevent->event_id));
+
+	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
+	    pmbuf->data_len > sizeof(eventcause))
+		DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset,
+			    pmbuf->data_len);
+
+	switch (eventcause) {
+	case EVENT_MICRO_AP_BSS_START:
+		PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_START\n");
+		pmpriv->uap_bss_started = MTRUE;
+		pmpriv->is_data_rate_auto = MTRUE;
+		memcpy_ext(pmadapter, pmpriv->curr_addr,
+			   pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_START;
+		wlan_check_uap_capability(pmpriv, pmbuf);
+		wlan_coex_ampdu_rxwinsize(pmadapter);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		if (IsAuthenticatorEnabled(pmpriv->psapriv)) {
+			pmadapter->authenticator_priv = pmpriv;
+			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK,
+					MNULL);
+		}
+#endif
+		break;
+	case EVENT_MICRO_AP_BSS_ACTIVE:
+		PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_ACTIVE\n");
+		pmpriv->media_connected = MTRUE;
+		pmpriv->port_open = MTRUE;
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE;
+		break;
+	case EVENT_MICRO_AP_BSS_IDLE:
+		PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_IDLE\n");
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_IDLE;
+		pmpriv->media_connected = MFALSE;
+		wlan_clean_txrx(pmpriv);
+		wlan_notify_station_deauth(pmpriv);
+		wlan_delete_station_list(pmpriv);
+		pmpriv->port_open = MFALSE;
+		pmpriv->amsdu_disable = MFALSE;
+		pmpriv->tx_pause = MFALSE;
+		break;
+	case EVENT_MICRO_AP_MIC_COUNTERMEASURES:
+		PRINTM(MEVENT, "EVENT: MICRO_AP_MIC_COUNTERMEASURES\n");
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES;
+		break;
+	case EVENT_PS_AWAKE:
+		PRINTM(MINFO, "EVENT: AWAKE\n");
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "||");
+		/* Handle unexpected PS AWAKE event */
+		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+			break;
+		pmadapter->pm_wakeup_card_req = MFALSE;
+		pmadapter->pm_wakeup_fw_try = MFALSE;
+		pmadapter->ps_state = PS_STATE_AWAKE;
+
+		break;
+	case EVENT_PS_SLEEP:
+		PRINTM(MINFO, "EVENT: SLEEP\n");
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "__");
+		/* Handle unexpected PS SLEEP event */
+		if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
+			break;
+		pmadapter->ps_state = PS_STATE_PRE_SLEEP;
+		wlan_check_ps_cond(pmadapter);
+		break;
+	case EVENT_MICRO_AP_STA_ASSOC:
+		wlan_process_sta_assoc_event(pmpriv, pevent, pmbuf);
+		memcpy_ext(pmadapter, sta_addr, pmadapter->event_body + 2,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		sta_ptr = wlan_add_station_entry(pmpriv, sta_addr);
+		PRINTM_NETINTF(MMSG, pmpriv);
+		PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_ASSOC " MACSTR "\n",
+		       MAC2STR(sta_addr));
+		if (!sta_ptr)
+			break;
+		if (pmpriv->is_11n_enabled
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		    || IsAuthenticatorEnabled(pmpriv->psapriv)
+#endif
+			) {
+			wlan_check_sta_capability(pmpriv, pmbuf, sta_ptr);
+			for (i = 0; i < MAX_NUM_TID; i++) {
+				if (sta_ptr->is_11n_enabled)
+					sta_ptr->ampdu_sta[i] =
+						pmpriv->aggr_prio_tbl[i]
+					.ampdu_user;
+				else
+					sta_ptr->ampdu_sta[i] =
+						BA_STREAM_NOT_ALLOWED;
+			}
+			memset(pmadapter, sta_ptr->rx_seq, 0xff,
+			       sizeof(sta_ptr->rx_seq));
+		}
+		if (pmpriv->sec_info.wapi_enabled)
+			wlan_update_wapi_info_tlv(pmpriv, pmbuf);
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+		/**enter authenticator*/
+		if (IsAuthenticatorEnabled(pmpriv->psapriv))
+			AuthenticatorSendEapolPacket(pmpriv->psapriv,
+						     sta_ptr->
+						     cm_connectioninfo);
+#endif
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		break;
+	case EVENT_MICRO_AP_STA_DEAUTH:
+		pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT;
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_len = pmbuf->data_len - 4;
+		/* skip event length field */
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset + 4,
+			   pevent->event_len, pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		memcpy_ext(pmadapter, sta_addr, pmadapter->event_body + 2,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		PRINTM_NETINTF(MMSG, pmpriv);
+		PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_DEAUTH " MACSTR "\n",
+		       MAC2STR(sta_addr));
+		if (pmpriv->is_11n_enabled) {
+			wlan_cleanup_reorder_tbl(pmpriv, sta_addr);
+			wlan_11n_cleanup_txbastream_tbl(pmpriv, sta_addr);
+		}
+		wlan_wmm_delete_peer_ralist(pmpriv, sta_addr);
+		wlan_delete_station_entry(pmpriv, sta_addr);
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		break;
+	case EVENT_HS_ACT_REQ:
+		PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_HS_CFG_ENH, 0,
+				       0, MNULL, MNULL);
+		break;
+	case EVENT_ADDBA:
+		PRINTM(MEVENT, "EVENT: ADDBA Request\n");
+		if (pmpriv->media_connected == MTRUE)
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_11N_ADDBA_RSP,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       pmadapter->event_body);
+		else
+			PRINTM(MERROR,
+			       "Ignore ADDBA Request event in BSS idle state\n");
+		break;
+	case EVENT_DELBA:
+		PRINTM(MEVENT, "EVENT: DELBA Request\n");
+		if (pmpriv->media_connected == MTRUE)
+			wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
+		else
+			PRINTM(MERROR,
+			       "Ignore DELBA Request event in BSS idle state\n");
+		break;
+	case EVENT_BA_STREAM_TIMEOUT:
+		PRINTM(MEVENT, "EVENT:  BA Stream timeout\n");
+		if (pmpriv->media_connected == MTRUE)
+			wlan_11n_ba_stream_timeout(pmpriv,
+						   (HostCmd_DS_11N_BATIMEOUT *)
+						   pmadapter->event_body);
+		else
+			PRINTM(MERROR,
+			       "Ignore BA Stream timeout event in BSS idle state\n");
+		break;
+	case EVENT_RXBA_SYNC:
+		PRINTM(MEVENT, "EVENT:  RXBA_SYNC\n");
+		wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body,
+					 pmbuf->data_len - sizeof(eventcause));
+		break;
+	case EVENT_AMSDU_AGGR_CTRL:
+		PRINTM(MEVENT, "EVENT:  AMSDU_AGGR_CTRL %d\n",
+		       *(t_u16 *)pmadapter->event_body);
+		pmadapter->tx_buf_size =
+			MIN(pmadapter->curr_tx_buf_size,
+			    wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body));
+		if (pmbuf->data_len == sizeof(eventcause) + sizeof(t_u32)) {
+			enable = wlan_le16_to_cpu(*(t_u16 *)
+						  (pmadapter->event_body +
+						   sizeof(t_u16)));
+			if (enable)
+				pmpriv->amsdu_disable = MFALSE;
+			else
+				pmpriv->amsdu_disable = MTRUE;
+			PRINTM(MEVENT, "amsdu_disable=%d\n",
+			       pmpriv->amsdu_disable);
+		}
+		PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size);
+		break;
+	case EVENT_TX_DATA_PAUSE:
+		PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n");
+		wlan_process_tx_pause_event(priv, pmbuf);
+		break;
+	case EVENT_RADAR_DETECTED:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: Radar Detected\n");
+		if (pmpriv->adapter->dfs_test_params.cac_restart &&
+		    pmpriv->adapter->state_dfs.dfs_check_pending) {
+			wlan_11h_cancel_radar_detect(pmpriv);
+			wlan_11h_issue_radar_detect(pmpriv, MNULL,
+						    pmpriv->adapter->
+						    dfs_test_params.chan,
+						    pmpriv->adapter->
+						    dfs_test_params.bandcfg);
+			pevent->event_id = 0;
+			break;
+		}
+		/* Send as passthru first, this event can cause other events */
+		memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pevent->event_id = 0;	/* clear to avoid resending at end of fcn
+					 */
+
+		/* Print event data */
+		pevent->event_id = MLAN_EVENT_ID_FW_RADAR_DETECTED;
+		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause),
+			   pevent->event_len, pevent->event_len);
+		wlan_11h_print_event_radar_detected(pmpriv, pevent, &channel);
+		*((t_u8 *)pevent->event_buf) = channel;
+		if (!pmpriv->intf_state_11h.is_11h_host) {
+			if (pmadapter->state_rdh.stage == RDH_OFF) {
+				pmadapter->state_rdh.stage = RDH_CHK_INTFS;
+				wlan_11h_radar_detected_handling(pmadapter,
+								 pmpriv);
+				if (pmpriv->uap_host_based)
+					wlan_recv_event(priv,
+							MLAN_EVENT_ID_FW_RADAR_DETECTED,
+							pevent);
+			} else {
+				PRINTM(MEVENT,
+				       "Ignore Event Radar Detected - handling"
+				       " already in progress.\n");
+			}
+		} else {
+			if (pmpriv->adapter->dfs_test_params.
+			    no_channel_change_on_radar ||
+			    pmpriv->adapter->dfs_test_params.
+			    fixed_new_channel_on_radar) {
+				if (pmadapter->state_rdh.stage == RDH_OFF ||
+				    pmadapter->state_rdh.stage ==
+				    RDH_SET_CUSTOM_IE) {
+					pmadapter->state_rdh.stage =
+						RDH_CHK_INTFS;
+					wlan_11h_radar_detected_handling
+						(pmadapter, pmpriv);
+				} else
+					PRINTM(MEVENT,
+					       "Ignore Event Radar Detected - handling already in progress.\n");
+			} else {
+				pmpriv->intf_state_11h.tx_disabled = MTRUE;
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_FW_RADAR_DETECTED,
+						pevent);
+
+			}
+		}
+
+		pevent->event_id = 0;	/* clear to avoid resending at end of fcn
+					 */
+		break;
+	case EVENT_CHANNEL_REPORT_RDY:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
+		pmpriv->adapter->dfs_test_params.cac_restart = MFALSE;
+		memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+		/* Setup event buffer */
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY;
+		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+		/* Copy event data */
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause),
+			   pevent->event_len, pevent->event_len);
+		/* Handle / pass event data, and free buffer */
+		ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent,
+							  &channel);
+		if (pmpriv->intf_state_11h.is_11h_host) {
+			*((t_u8 *)pevent->event_buf) =
+				pmpriv->adapter->state_dfs.dfs_radar_found;
+			*((t_u8 *)pevent->event_buf + 1) = channel;
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY,
+					pevent);
+		} else {
+			/* Send up this Event to unblock MOAL waitqueue */
+			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT,
+					MNULL);
+		}
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		break;
+	case EVENT_CHANNEL_SWITCH:
+		pchan_info =
+			(MrvlIEtypes_channel_band_t *)(pmadapter->event_body);
+		channel = pchan_info->channel;
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: CHANNEL_SWITCH new channel %d\n",
+		       channel);
+		pmpriv->uap_channel = channel;
+		pmpriv->uap_state_chan_cb.channel = pchan_info->channel;
+		pmpriv->uap_state_chan_cb.bandcfg = pchan_info->bandcfg;
+		if (wlan_11h_radar_detect_required(pmpriv, pchan_info->channel)) {
+			if (!wlan_11h_is_active(pmpriv)) {
+				/* active 11h extention in Fw */
+				ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+				ret = wlan_11h_config_master_radar_det(pmpriv,
+								       MTRUE);
+				ret = wlan_11h_check_update_radar_det_state
+					(pmpriv);
+			}
+			if (pmpriv->uap_host_based)
+				pmpriv->intf_state_11h.is_11h_host = MTRUE;
+			wlan_11h_set_dfs_check_chan(pmpriv,
+						    pchan_info->channel);
+		}
+		if ((pmpriv->adapter->state_rdh.stage != RDH_OFF &&
+		     !pmpriv->intf_state_11h.is_11h_host)
+		    || pmpriv->adapter->dfs_test_params.
+		    no_channel_change_on_radar ||
+		    pmpriv->adapter->dfs_test_params.
+		    fixed_new_channel_on_radar) {
+			/* Handle embedded DFS */
+			if (pmpriv->adapter->state_rdh.stage ==
+			    RDH_SET_CUSTOM_IE) {
+				pmadapter->state_rdh.stage =
+					RDH_RESTART_TRAFFIC;
+				wlan_11h_radar_detected_handling(pmadapter,
+								 pmpriv);
+			}
+
+		} else {
+			/* Handle Host-based DFS and non-DFS(normal uap) case */
+			pmpriv->intf_state_11h.tx_disabled = MFALSE;
+			memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+			/* Setup event buffer */
+			pevent->bss_index = pmpriv->bss_index;
+			pevent->event_id =
+				MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE;
+			pevent->event_len = sizeof(chan_band_info);
+			pchan_band_info = (chan_band_info *) pevent->event_buf;
+			/* Copy event data */
+			memcpy_ext(pmadapter, (t_u8 *)&pchan_band_info->bandcfg,
+				   (t_u8 *)&pchan_info->bandcfg,
+				   sizeof(pchan_info->bandcfg),
+				   sizeof(pchan_info->bandcfg));
+			pchan_band_info->channel = pchan_info->channel;
+			if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ)
+				pchan_band_info->center_chan =
+					wlan_get_center_freq_idx(priv, BAND_AAC,
+								 pchan_info->
+								 channel,
+								 CHANNEL_BW_80MHZ);
+			pchan_band_info->is_11n_enabled =
+				pmpriv->is_11n_enabled;
+			wlan_recv_event(pmpriv,
+					MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE,
+					pevent);
+			pevent->event_id = 0;
+		}
+		break;
+	case EVENT_REMAIN_ON_CHANNEL_EXPIRED:
+		PRINTM_NETINTF(MEVENT, pmpriv);
+		PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n",
+		       *(t_u16 *)pmadapter->event_body);
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
+		pevent->event_id = MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED;
+		break;
+
+	case EVENT_FW_DEBUG_INFO:
+		memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE);
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO;
+		pevent->event_len = pmbuf->data_len - sizeof(eventcause);
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause),
+			   pevent->event_len, pevent->event_len);
+		PRINTM(MEVENT, "EVENT: FW Debug Info %s\n",
+		       (t_u8 *)pevent->event_buf);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+		pevent->event_id = 0;	/* clear to avoid resending at end of fcn
+					 */
+		break;
+	case EVENT_TX_STATUS_REPORT:
+		PRINTM(MINFO, "EVENT: TX_STATUS\n");
+		pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS;
+		break;
+	case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+		PRINTM(MEVENT, "EVENT: BT coex wlan param update\n");
+		wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf);
+		break;
+	case EVENT_EXCEED_MAX_P2P_CONN:
+		event_excd_p2p =
+			(event_exceed_max_p2p_conn *) (pmbuf->pbuf +
+						       pmbuf->data_offset);
+		PRINTM(MEVENT, "EVENT: EXCEED MAX P2P CONNECTION\n");
+		PRINTM(MEVENT, "REQUEST P2P MAC: " MACSTR "\n",
+		       MAC2STR(event_excd_p2p->peer_mac_addr));
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		break;
+	case EVENT_VDLL_IND:
+		wlan_process_vdll_event(pmpriv, pmbuf);
+		break;
+
+	case EVENT_FW_HANG_REPORT:
+		if (pmbuf->data_len < (sizeof(eventcause) + sizeof(t_u16))) {
+			PRINTM(MEVENT,
+			       "EVENT: EVENT_FW_HANG_REPORT skip for len too short: %d\n",
+			       pmbuf->data_len);
+			break;
+		}
+		PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT reasoncode=%d\n",
+		       wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+						   pmbuf->data_offset +
+						   sizeof(eventcause))));
+		pmadapter->fw_hang_report = MTRUE;
+		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
+		break;
+	case EVENT_WATCHDOG_TMOUT:
+		PRINTM(MEVENT, "EVENT: EVENT_WATCHDOG_TMOUT reasoncode=%d\n",
+		       wlan_le16_to_cpu(*(t_u16 *)
+					(pmbuf->pbuf + pmbuf->data_offset +
+					 sizeof(eventcause))));
+		pevent->event_id = MLAN_EVENT_ID_DRV_WIFI_STATUS;
+		pevent->event_len = sizeof(pevent->event_id) + sizeof(t_u16);
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset +
+			   sizeof(eventcause), sizeof(t_u16), sizeof(t_u16));
+		break;
+	default:
+		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
+		break;
+	}
+
+	if (pevent->event_id) {
+		pevent->bss_index = pmpriv->bss_index;
+		pevent->event_len = pmbuf->data_len;
+		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
+			   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len,
+			   pevent->event_len);
+		wlan_recv_event(pmpriv, pevent->event_id, pevent);
+	}
+done:
+	if (event_buf)
+		pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues commands to set uap max sta number
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param uap_max_sta  Max station number uAP can supported (per chip)
+ *
+ *  @return   MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_set_uap_max_sta(pmlan_private pmpriv, t_u8 uap_max_sta)
+{
+	MrvlIEtypes_uap_max_sta_cnt_t tlv_uap_max_sta;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(pmpriv->adapter, &tlv_uap_max_sta, 0, sizeof(tlv_uap_max_sta));
+	tlv_uap_max_sta.header.type =
+		wlan_cpu_to_le16(TLV_TYPE_UAP_MAX_STA_CNT_PER_CHIP);
+	tlv_uap_max_sta.header.len = wlan_cpu_to_le16(sizeof(t_u16));
+	tlv_uap_max_sta.uap_max_sta = wlan_cpu_to_le16(uap_max_sta);
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_SET, 0, MNULL, &tlv_uap_max_sta);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function issues commands to initialize firmware
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param first_bss    flag for first BSS
+ *
+ *  @return   MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_uap_init_cmd(t_void *priv, t_u8 first_bss)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = (pmlan_private)priv;
+	t_u16 last_cmd = 0;
+
+	ENTER();
+	if (!pmpriv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (first_bss) {
+		if (wlan_adapter_init_cmd(pmpriv->adapter) ==
+		    MLAN_STATUS_FAILURE) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+	if (pmpriv->adapter->init_para.uap_max_sta &&
+	    (pmpriv->adapter->init_para.uap_max_sta <= MAX_STA_COUNT))
+		wlan_uap_set_uap_max_sta(pmpriv,
+					 pmpriv->adapter->init_para.
+					 uap_max_sta);
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+	if (ret) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	last_cmd = HOST_CMD_APCMD_SYS_CONFIGURE;
+	/** set last_init_cmd */
+	if (last_cmd) {
+		pmpriv->adapter->last_init_cmd = last_cmd;
+		ret = MLAN_STATUS_PENDING;
+	}
+done:
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_uap_ioctl.c b/wlan_sd8987/mlan/mlan_uap_ioctl.c
new file mode 100755
index 0000000..16eef40
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap_ioctl.c
@@ -0,0 +1,2295 @@
+/** @file mlan_uap_ioctl.c
+ *
+ *  @brief This file contains the handling of AP mode ioctls
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_main.h"
+#include "mlan_uap.h"
+#include "mlan_11n.h"
+#include "mlan_fw.h"
+#include "mlan_11h.h"
+#include "mlan_11ac.h"
+#include "mlan_11ax.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief Stop BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_stop(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+static t_bool
+wlan_can_radar_det_skip(mlan_private *priv)
+{
+	mlan_private *priv_list[MLAN_MAX_BSS_NUM];
+	mlan_private *pmpriv;
+	mlan_adapter *pmadapter = priv->adapter;
+	t_u8 pcount, i;
+
+	/* In MBSS environment, if one of the BSS is already beaconing and DRCS
+	 * is off then 11n_radar detection is not required for subsequent BSSes
+	 * since they will follow the primary bss.
+	 */
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)) {
+		memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
+		pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
+						priv_list);
+		for (i = 0; i < pcount; i++) {
+			pmpriv = priv_list[i];
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
+				return MTRUE;
+		}
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief Callback to finish BSS IOCTL START
+ *  Not to be called directly to initiate bss_start
+ *
+ *  @param priv A pointer to mlan_private structure (cast from t_void*)
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ *  @sa         wlan_uap_bss_ioctl_start
+ */
+static mlan_status
+wlan_uap_callback_bss_ioctl_start(t_void *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+	t_u8 old_channel;
+	t_bool under_nop = MFALSE;
+	ENTER();
+	/* clear callback now that we're here */
+	puap_state_chan_cb->get_chan_callback = MNULL;
+
+	/*
+	 * Check if the region and channel requires we check for radar.
+	 */
+	if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+	    !wlan_can_radar_det_skip(pmpriv) &&
+	    wlan_11h_radar_detect_required(pmpriv,
+					   puap_state_chan_cb->channel)) {
+		/* If DFS repeater mode is on then before starting the uAP
+		 * make sure that mlan0 is connected to some external AP
+		 * for DFS channel operations.
+		 */
+		if (pmpriv->adapter->dfs_repeater) {
+			pmlan_private tmpriv = MNULL;
+			tmpriv = wlan_get_priv(pmpriv->adapter,
+					       MLAN_BSS_ROLE_STA);
+
+			if (tmpriv && !tmpriv->media_connected) {
+				PRINTM(MERROR,
+				       "BSS start is blocked when DFS-repeater\n"
+				       "mode is on and STA is not connected\n");
+				pcb->moal_ioctl_complete(pmpriv->adapter->
+							 pmoal_handle,
+							 puap_state_chan_cb->
+							 pioctl_req_curr,
+							 MLAN_STATUS_FAILURE);
+				goto done;
+			} else {
+				/* STA is connected.
+				 * Skip DFS check for bss_start since its a
+				 * repeater mode
+				 */
+				goto prep_bss_start;
+			}
+		}
+
+		/* first check if channel is under NOP */
+		if (wlan_11h_is_channel_under_nop
+		    (pmpriv->adapter, puap_state_chan_cb->channel)) {
+			/* recently we've seen radar on this channel */
+			ret = MLAN_STATUS_FAILURE;
+			under_nop = MTRUE;
+		}
+
+		/* Check cached radar check on the channel */
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = wlan_11h_check_chan_report(pmpriv,
+							 puap_state_chan_cb->
+							 channel);
+
+		/* Found radar: try to switch to a non-dfs channel */
+		if (ret != MLAN_STATUS_SUCCESS) {
+			old_channel = puap_state_chan_cb->channel;
+			ret = wlan_11h_switch_non_dfs_chan(pmpriv,
+							   &puap_state_chan_cb->
+							   channel);
+
+			if (ret == MLAN_STATUS_SUCCESS) {
+				wlan_11h_update_bandcfg(pmpriv,
+							&pmpriv->
+							uap_state_chan_cb.
+							bandcfg,
+							puap_state_chan_cb->
+							channel);
+				PRINTM(MCMD_D,
+				       "NOP: uap band config:0x%x  channel=%d\n",
+				       pmpriv->uap_state_chan_cb.bandcfg,
+				       puap_state_chan_cb->channel);
+
+				ret = wlan_uap_set_channel(pmpriv,
+							   pmpriv->
+							   uap_state_chan_cb.
+							   bandcfg,
+							   puap_state_chan_cb->
+							   channel);
+				if (ret == MLAN_STATUS_SUCCESS) {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switched to new channel %d successfully.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+				} else {
+					if (under_nop) {
+						PRINTM(MMSG,
+						       "Channel %d under NOP,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					} else {
+						PRINTM(MMSG,
+						       "Radar found on channel %d,"
+						       " switch to new channel %d failed.\n",
+						       old_channel,
+						       puap_state_chan_cb->
+						       channel);
+					}
+					pcb->moal_ioctl_complete(pmpriv->
+								 adapter->
+								 pmoal_handle,
+								 puap_state_chan_cb->
+								 pioctl_req_curr,
+								 MLAN_STATUS_FAILURE);
+					goto done;
+				}
+			} else {
+				if (under_nop) {
+					PRINTM(MMSG,
+					       "Channel %d under NOP, no switch channel available.\n",
+					       old_channel);
+				} else {
+					PRINTM(MMSG,
+					       "Radar found on channel %d, no switch channel available.\n",
+					       old_channel);
+				}
+				/* No command sent with the ioctl, need manually
+				 * signal completion */
+				pcb->moal_ioctl_complete(pmpriv->adapter->
+							 pmoal_handle,
+							 puap_state_chan_cb->
+							 pioctl_req_curr,
+							 MLAN_STATUS_FAILURE);
+				goto done;
+			}
+		} else {
+			PRINTM(MINFO, "No Radar found on channel %d\n",
+			       puap_state_chan_cb->channel);
+		}
+	}
+
+prep_bss_start:
+	/* else okay to send command:  not DFS channel or no radar */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
+			       HostCmd_ACT_GEN_SET, 0,
+			       (t_void *)puap_state_chan_cb->pioctl_req_curr,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+done:
+	puap_state_chan_cb->pioctl_req_curr = MNULL;	/* prevent re-use */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Start BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+/**
+ *  @sa         wlan_uap_callback_bss_ioctl_start
+ */
+static mlan_status
+wlan_uap_bss_ioctl_start(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	pmpriv->uap_host_based = bss->param.host_based;
+	if (!pmpriv->intf_state_11h.is_11h_host &&
+	    pmpriv->intf_state_11h.is_11h_active) {
+		/* if FW supports ACS+DFS then sequence is different */
+
+		/* First check channel report, defer BSS_START CMD to callback.
+		 */
+		/* store params, issue command to get UAP channel, whose
+		 * CMD_RESP will callback remainder of bss_start handling */
+		pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+		pmpriv->uap_state_chan_cb.get_chan_callback =
+			wlan_uap_callback_bss_ioctl_start;
+		pmpriv->intf_state_11h.is_11h_host = MFALSE;
+		ret = wlan_uap_get_channel(pmpriv);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
+				       HostCmd_ACT_GEN_SET, 0,
+				       (t_void *)pioctl_req, MNULL);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief reset BSS
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_reset(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	t_u8 i = 0;
+
+	ENTER();
+
+	/*
+	 * Reset any uap private parameters here
+	 */
+	for (i = 0; i < pmadapter->max_mgmt_ie_index; i++)
+		memset(pmadapter, &pmpriv->mgmt_ie[i], 0, sizeof(custom_ie));
+	pmpriv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+	pmpriv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+	pmpriv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+	pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
+		pmpriv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
+		pmpriv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT;
+	}
+	pmpriv->aggr_prio_tbl[6].amsdu = BA_STREAM_NOT_ALLOWED;
+	pmpriv->aggr_prio_tbl[7].amsdu = BA_STREAM_NOT_ALLOWED;
+
+	pmpriv->aggr_prio_tbl[6].ampdu_user =
+		pmpriv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED;
+	pmpriv->addba_reject[6] = pmpriv->addba_reject[7] =
+		ADDBA_RSP_STATUS_REJECT;
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_RESET,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function to process add station.
+ *
+ *  @param pmadapter       A pointer to pmadapter.
+ *
+ *  @param pioctl_req      A pointer to pioctl_req
+ *
+ *  @return            	  MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_uap_bss_ioctl_add_station(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ADD_NEW_STATION,
+			       HostCmd_ACT_ADD_STA, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get MAC address
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_mac_address(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		memcpy_ext(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		cmd_action = HostCmd_ACT_GEN_SET;
+	} else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get wmm param
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_wmm_param(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle channel switch
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_action_chan_switch(pmlan_adapter pmadapter,
+				      pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	cmd_action = HostCmd_ACT_GEN_SET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get scan channels
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_scan_channels(pmlan_adapter pmadapter,
+				     pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP channel
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_channel(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get UAP operation control vaule
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_uap_oper_ctrl(pmlan_adapter pmadapter,
+				 pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pmadapter->fw_ver == HOST_API_VERSION_V15 &&
+	    pmadapter->fw_min_ver >= FW_MINOR_VERSION_1) {
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else
+			cmd_action = HostCmd_ACT_GEN_GET;
+		/* Send request to firmware */
+		ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_OPER_CTRL,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       (t_void *)pioctl_req->pbuf);
+
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		PRINTM(MMSG, "FW don't support uap oper ctrl\n");
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Uap statistics
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_stats(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Uap MIB counters
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_stats_log(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (pioctl_req != MNULL) {
+		pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	} else {
+		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Check information buffer length of MLAN IOCTL */
+	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
+		PRINTM(MWARN,
+		       "MLAN IOCTL information buffer length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		ret = MLAN_STATUS_RESOURCE;
+		goto exit;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_GET_LOG,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get AP config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_config(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
+			       0, (t_void *)pioctl_req, MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief deauth sta
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_deauth_sta(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_bss *bss = MNULL;
+
+	ENTER();
+
+	bss = (mlan_ds_bss *)pioctl_req->pbuf;
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_STA_DEAUTH,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       (t_void *)&bss->param.deauth_param);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get station list
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_get_sta_list(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_STA_LIST,
+			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief soft_reset
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_misc_ioctl_soft_reset(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Tx data pause
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_misc_ioctl_txdatapause(pmlan_adapter pmadapter,
+				pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CFG_TX_DATA_PAUSE,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &(pmisc->param.tx_datapause));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Power mode
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_pm_ioctl_mode(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pm = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+	t_u32 cmd_oid = 0;
+
+	ENTER();
+
+	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		if (pm->param.ps_mgmt.ps_mode == PS_MODE_INACTIVITY) {
+			cmd_action = EN_AUTO_PS;
+			cmd_oid = BITMAP_UAP_INACT_PS;
+		} else if (pm->param.ps_mgmt.ps_mode == PS_MODE_PERIODIC_DTIM) {
+			cmd_action = EN_AUTO_PS;
+			cmd_oid = BITMAP_UAP_DTIM_PS;
+		} else {
+			cmd_action = DIS_AUTO_PS;
+			cmd_oid = BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS;
+		}
+	} else {
+		cmd_action = GET_PS;
+		cmd_oid = BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS;
+	}
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+			       cmd_action, cmd_oid, (t_void *)pioctl_req,
+			       (t_void *)&pm->param.ps_mgmt);
+	if ((ret == MLAN_STATUS_SUCCESS) &&
+	    (pioctl_req->action == MLAN_ACT_SET) &&
+	    (cmd_action == DIS_AUTO_PS)) {
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+				       GET_PS, 0, MNULL, MNULL);
+	}
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set WAPI IE
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_set_wapi_ie(mlan_private *priv, pmlan_ioctl_req pioctl_req)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (misc->param.gen_ie.len) {
+		if (misc->param.gen_ie.len > sizeof(priv->wapi_ie)) {
+			PRINTM(MWARN, "failed to copy WAPI IE, too big\n");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		memcpy_ext(priv->adapter, priv->wapi_ie,
+			   misc->param.gen_ie.ie_data, misc->param.gen_ie.len,
+			   sizeof(priv->wapi_ie));
+		priv->wapi_ie_len = misc->param.gen_ie.len;
+		PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len,
+		       priv->wapi_ie[0]);
+		DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie,
+			    priv->wapi_ie_len);
+		if (priv->wapi_ie[0] == WAPI_IE)
+			priv->sec_info.wapi_enabled = MTRUE;
+	} else {
+		memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie));
+		priv->wapi_ie_len = misc->param.gen_ie.len;
+		PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
+		       priv->wapi_ie_len, priv->wapi_ie[0]);
+		priv->sec_info.wapi_enabled = MFALSE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(priv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set generic IE
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_uap_misc_ioctl_gen_ie(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *misc = MNULL;
+	IEEEtypes_VendorHeader_t *pvendor_ie = MNULL;
+
+	ENTER();
+
+	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	if ((misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE) &&
+	    (pioctl_req->action == MLAN_ACT_SET)) {
+		if (misc->param.gen_ie.len) {
+			pvendor_ie = (IEEEtypes_VendorHeader_t *)
+				misc->param.gen_ie.ie_data;
+			if (pvendor_ie->element_id == WAPI_IE) {
+				/* IE is a WAPI IE so call set_wapi function */
+				ret = wlan_uap_set_wapi_ie(pmpriv, pioctl_req);
+			}
+		} else {
+			/* clear WAPI IE */
+			ret = wlan_uap_set_wapi_ie(pmpriv, pioctl_req);
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get WAPI status
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_uap_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		if (pmpriv->wapi_ie_len)
+			sec->param.wapi_enabled = MTRUE;
+		else
+			sec->param.wapi_enabled = MFALSE;
+	} else {
+		if (sec->param.wapi_enabled == MFALSE) {
+			memset(pmpriv->adapter, pmpriv->wapi_ie, 0,
+			       sizeof(pmpriv->wapi_ie));
+			pmpriv->wapi_ie_len = 0;
+			PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
+			       pmpriv->wapi_ie_len, pmpriv->wapi_ie[0]);
+			pmpriv->sec_info.wapi_enabled = MFALSE;
+		}
+	}
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief report mic error
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_sec_ioctl_report_mic_error(pmlan_adapter pmadapter,
+				    pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	ENTER();
+
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_REPORT_MIC,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       (t_void *)sec->param.sta_mac);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set encrypt key
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+static mlan_status
+wlan_uap_sec_ioctl_set_encrypt_key(pmlan_adapter pmadapter,
+				   pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_sec_cfg *sec = MNULL;
+
+	ENTER();
+	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action != MLAN_ACT_SET) {
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (!sec->param.encrypt_key.key_remove &&
+	    !sec->param.encrypt_key.key_len) {
+		PRINTM(MCMND, "Skip set key with key_len = 0\n");
+		LEAVE();
+		return ret;
+	}
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
+			       HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+			       (t_void *)pioctl_req, &sec->param.encrypt_key);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get BSS information
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_uap_get_bss_info(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_info *info;
+
+	ENTER();
+
+	info = (mlan_ds_get_info *)pioctl_req->pbuf;
+	/* Connection status */
+	info->param.bss_info.media_connected = pmpriv->media_connected;
+
+	/* Radio status */
+	info->param.bss_info.radio_on = pmadapter->radio_on;
+
+	/* BSSID */
+	memcpy_ext(pmadapter, &info->param.bss_info.bssid, pmpriv->curr_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	info->param.bss_info.scan_block = pmadapter->scan_block;
+
+	info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured;
+	info->param.bss_info.is_11h_active =
+		pmpriv->intf_state_11h.is_11h_active;
+	info->param.bss_info.dfs_check_channel =
+		pmpriv->adapter->state_dfs.dfs_check_channel;
+	pioctl_req->data_read_written =
+		sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Host Sleep configurations
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success, otherwise
+ * fail
+ */
+static mlan_status
+wlan_uap_pm_ioctl_deepsleep(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_pm_cfg *pm = MNULL;
+	mlan_ds_auto_ds auto_ds;
+	t_u32 mode;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		if (pmadapter->is_deep_sleep) {
+			pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
+			pm->param.auto_deep_sleep.idletime =
+				pmadapter->idle_time;
+		} else
+			pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
+	} else {
+		if (pmadapter->is_deep_sleep &&
+		    pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
+			PRINTM(MMSG, "uAP already in deep sleep mode\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+		    ->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
+			auto_ds.auto_ds = DEEP_SLEEP_ON;
+			mode = EN_AUTO_PS;
+			PRINTM(MINFO, "Auto Deep Sleep: on\n");
+		} else {
+			mode = DIS_AUTO_PS;
+			auto_ds.auto_ds = DEEP_SLEEP_OFF;
+			PRINTM(MINFO, "Auto Deep Sleep: off\n");
+		}
+		if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+		    ->param.auto_deep_sleep.idletime)
+			auto_ds.idletime = ((mlan_ds_pm_cfg *)pioctl_req->pbuf)
+				->param.auto_deep_sleep.idletime;
+		else
+			auto_ds.idletime = pmadapter->idle_time;
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
+				       (t_u16)mode, BITMAP_AUTO_DS,
+				       (t_void *)pioctl_req, &auto_ds);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Band Steering configurations
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success, otherwise
+ * fail
+ */
+static mlan_status
+wlan_misc_band_steering_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pm = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_band_steer_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_band_steer_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	pm = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_BAND_STEERING,
+			       (t_u16)pm->param.band_steer_cfg.action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&pm->param.band_steer_cfg);
+	LEAVE();
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	return ret;
+}
+
+/**
+ *  @brief Set Beacon Stuck Detect Mechanism Configurations
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return            MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_misc_beacon_stuck_cfg(IN pmlan_adapter pmadapter,
+			   IN pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pm = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_beacon_stuck_param_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed =
+			sizeof(mlan_ds_beacon_stuck_param_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	pm = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_UAP_BEACON_STUCK_CFG,
+			       (t_u16)pm->param.beacon_stuck_cfg.action, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&pm->param.beacon_stuck_cfg);
+
+	LEAVE();
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	return ret;
+}
+
+/**
+ *  @brief Set SNMP MIB for 11D
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_snmp_mib_11d(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_snmp_mib *snmp = MNULL;
+	state_11d_t flag;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
+		PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if ((pioctl_req->action == MLAN_ACT_SET) && pmpriv->uap_bss_started) {
+		PRINTM(MIOCTL,
+		       "11D setting cannot be changed while UAP bss is started.\n");
+		pioctl_req->data_read_written = 0;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+	flag = (snmp->param.oid_value) ? ENABLE_11D : DISABLE_11D;
+
+	ret = wlan_11d_enable(pmpriv, (t_void *)pioctl_req, flag);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Callback to finish domain_info handling
+ *  Not to be called directly to initiate domain_info setting.
+ *
+ *  @param pmpriv   A pointer to mlan_private structure (cast from t_void*)
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ *  @sa         wlan_uap_domain_info
+ */
+static mlan_status
+wlan_uap_callback_domain_info(t_void *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+	mlan_ds_11d_cfg *cfg11d;
+	t_u8 band;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+	/* clear callback now that we're here */
+	puap_state_chan_cb->get_chan_callback = MNULL;
+
+	if (!puap_state_chan_cb->pioctl_req_curr) {
+		PRINTM(MERROR, "pioctl_req_curr is null\n");
+		LEAVE();
+		return ret;
+	}
+	cfg11d = (mlan_ds_11d_cfg *)puap_state_chan_cb->pioctl_req_curr->pbuf;
+	band = (puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) ? BAND_A :
+		BAND_B;
+
+	ret = wlan_11d_handle_uap_domain_info(pmpriv, band,
+					      cfg11d->param.domain_tlv,
+					      puap_state_chan_cb->
+					      pioctl_req_curr);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	else {
+		puap_state_chan_cb->pioctl_req_curr->status_code =
+			MLAN_STATUS_FAILURE;
+		pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
+					 puap_state_chan_cb->pioctl_req_curr,
+					 MLAN_STATUS_FAILURE);
+	}
+
+	puap_state_chan_cb->pioctl_req_curr = MNULL;	/* prevent re-use */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Domain Info for 11D
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ *  @sa         wlan_uap_callback_domain_info
+ */
+static mlan_status
+wlan_uap_domain_info(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) {
+		PRINTM(MWARN, "MLAN 11d_cfg IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+
+	if ((pioctl_req->action == MLAN_ACT_SET) && pmpriv->uap_bss_started) {
+		PRINTM(MIOCTL,
+		       "Domain_info cannot be changed while UAP bss is started.\n");
+		pioctl_req->data_read_written = 0;
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* store params, issue command to get UAP channel, whose CMD_RESP will
+	 * callback remainder of domain_info handling */
+	pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+	pmpriv->uap_state_chan_cb.get_chan_callback =
+		wlan_uap_callback_domain_info;
+
+	ret = wlan_uap_get_channel(pmpriv);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Callback to finish 11H channel check handling.
+ *  Not to be called directly to initiate channel check.
+ *
+ *  @param priv A pointer to mlan_private structure (cast from t_void*)
+ *
+ *  @return     MLAN_STATUS_SUCCESS/PENDING --success, otherwise fail
+ *  @sa         wlan_uap_11h_channel_check_req
+ */
+static mlan_status
+wlan_uap_callback_11h_channel_check_req(t_void *priv)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+	Band_Config_t *pband_cfg = &puap_state_chan_cb->bandcfg;
+	/* keep copy as local variable */
+	pmlan_ioctl_req pioctl = puap_state_chan_cb->pioctl_req_curr;
+	ENTER();
+	/* clear callback now that we're here */
+	puap_state_chan_cb->get_chan_callback = MNULL;
+	/* clear early to avoid race condition */
+	puap_state_chan_cb->pioctl_req_curr = MNULL;
+
+	/*
+	 * Check if the region and channel requires a channel availability
+	 * check.
+	 */
+	if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+	    !wlan_can_radar_det_skip(pmpriv) &&
+	    wlan_11h_radar_detect_required(pmpriv,
+					   puap_state_chan_cb->channel) &&
+	    !wlan_11h_is_channel_under_nop(pmpriv->adapter,
+					   puap_state_chan_cb->channel)) {
+		/*
+		 * Radar detection is required for this channel, make sure
+		 * 11h is activated in the firmware
+		 */
+		ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+		ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+		ret = wlan_11h_check_update_radar_det_state(pmpriv);
+
+		/* Check for radar on the channel */
+		ret = wlan_11h_issue_radar_detect(pmpriv, pioctl,
+						  puap_state_chan_cb->channel,
+						  *pband_cfg);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		/* No command sent with the ioctl, need manually signal
+		 * completion */
+		pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, pioctl,
+					 MLAN_STATUS_COMPLETE);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief 802.11h uap start channel check
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ *  @sa         wlan_uap_callback_11h_channel_check_req
+ */
+static mlan_status
+wlan_uap_11h_channel_check_req(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_11h_cfg *p11h_cfg;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) {
+		PRINTM(MWARN, "MLAN 11h_cfg IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg);
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	p11h_cfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+	pmpriv->intf_state_11h.is_11h_host =
+		p11h_cfg->param.chan_rpt_req.host_based;
+
+	if (!pmpriv->intf_state_11h.is_11h_host) {
+		/* store params, issue command to get UAP channel, whose
+		 * CMD_RESP will callback remainder of 11H channel check
+		 * handling */
+		pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+		pmpriv->uap_state_chan_cb.get_chan_callback =
+			wlan_uap_callback_11h_channel_check_req;
+
+		ret = wlan_uap_get_channel(pmpriv);
+		if (ret == MLAN_STATUS_SUCCESS)
+			ret = MLAN_STATUS_PENDING;
+	} else {
+		if (!wlan_11h_is_active(pmpriv)) {
+			/* active 11h extention in Fw */
+			ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
+			ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+			ret = wlan_11h_check_update_radar_det_state(pmpriv);
+		}
+		if (p11h_cfg->param.chan_rpt_req.millisec_dwell_time) {
+			if (pmpriv->adapter->dfs_test_params.
+			    user_cac_period_msec) {
+				PRINTM(MCMD_D,
+				       "cfg80211 dfs_testing - user CAC period=%d (msec)\n",
+				       pmpriv->adapter->dfs_test_params.
+				       user_cac_period_msec);
+				p11h_cfg->param.chan_rpt_req.
+					millisec_dwell_time =
+					pmpriv->adapter->dfs_test_params.
+					user_cac_period_msec;
+			}
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_CHAN_REPORT_REQUEST,
+					       HostCmd_ACT_GEN_SET, 0,
+					       (t_void *)pioctl_req,
+					       (t_void *)&p11h_cfg->param.
+					       chan_rpt_req);
+
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Callback to finish 11H handling
+ *  Not to be called directly to initiate 11H setting.
+ *
+ *  @param pmpriv   A pointer to mlan_private structure (cast from t_void*)
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ *  @sa         wlan_uap_snmp_mib_11h
+ */
+static mlan_status
+wlan_uap_callback_snmp_mib_11h(t_void *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = (mlan_private *)priv;
+	wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
+	mlan_ds_snmp_mib *snmp;
+	t_bool enable_11h;
+
+	ENTER();
+	/* clear callback now that we're here */
+	puap_state_chan_cb->get_chan_callback = MNULL;
+
+	snmp = (mlan_ds_snmp_mib *)puap_state_chan_cb->pioctl_req_curr->pbuf;
+	enable_11h = (snmp->param.oid_value) ? MTRUE : MFALSE;
+
+	if (enable_11h) {
+		if ((puap_state_chan_cb->bandcfg.chanBand == BAND_5GHZ) &&
+		    !wlan_can_radar_det_skip(pmpriv) &&
+		    wlan_11h_radar_detect_required(pmpriv,
+						   puap_state_chan_cb->
+						   channel)) {
+			if (!wlan_11h_is_master_radar_det_active(pmpriv))
+				wlan_11h_config_master_radar_det(pmpriv, MTRUE);
+		} else {
+			puap_state_chan_cb->pioctl_req_curr->status_code =
+				MLAN_STATUS_SUCCESS;
+			pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle,
+						 puap_state_chan_cb->
+						 pioctl_req_curr,
+						 MLAN_STATUS_SUCCESS);
+			goto done;
+		}
+	}
+
+	ret = wlan_11h_activate(pmpriv,
+				(t_void *)puap_state_chan_cb->pioctl_req_curr,
+				enable_11h);
+	wlan_11h_check_update_radar_det_state(pmpriv);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+done:
+	puap_state_chan_cb->pioctl_req_curr = MNULL;	/* prevent re-use */
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set SNMP MIB for 11H
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_PENDING --success, otherwise fail
+ *  @sa         wlan_uap_callback_snmp_mib_11h
+ */
+static mlan_status
+wlan_uap_snmp_mib_11h(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_snmp_mib *snmp = MNULL;
+	t_bool enable;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
+		PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+	enable = (snmp->param.oid_value) ? MTRUE : MFALSE;
+
+	if (enable) {
+		/* first enable 11D if it is not enabled */
+		if (!wlan_fw_11d_is_enabled(pmpriv)) {
+			ret = wlan_11d_enable(pmpriv, MNULL, ENABLE_11D);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "Failed to first enable 11D before enabling 11H.\n");
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+
+	/* store params, issue command to get UAP channel, whose CMD_RESP will
+	 * callback remainder of 11H handling (and radar detect if DFS chan) */
+	pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req;
+	pmpriv->uap_state_chan_cb.get_chan_callback =
+		wlan_uap_callback_snmp_mib_11h;
+
+	ret = wlan_uap_get_channel(pmpriv);
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief ACS scan
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_bss_ioctl_acs_scan(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (pmadapter->uap_fw_ver < UAP_FW_VERSION_2) {
+		PRINTM(MIOCTL, "FW don't support ACS SCAN API\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCMD_APCMD_ACS_SCAN,
+			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
+			       MNULL);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Issue CMD to UAP firmware to get current channel
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_uap_get_channel(pmlan_private pmpriv)
+{
+	MrvlIEtypes_channel_band_t tlv_chan_band;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(pmpriv->adapter, &tlv_chan_band, 0, sizeof(tlv_chan_band));
+	tlv_chan_band.header.type = TLV_TYPE_UAP_CHAN_BAND_CONFIG;
+	tlv_chan_band.header.len = sizeof(MrvlIEtypes_channel_band_t) -
+		sizeof(MrvlIEtypesHeader_t);
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, &tlv_chan_band);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Issue CMD to UAP firmware to set current channel
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param uap_band_cfg UAP band configuration
+ *  @param channel      New channel
+ *
+ *  @return         MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_uap_set_channel(pmlan_private pmpriv,
+		     Band_Config_t uap_band_cfg, t_u8 channel)
+{
+	MrvlIEtypes_channel_band_t tlv_chan_band;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(pmpriv->adapter, &tlv_chan_band, 0, sizeof(tlv_chan_band));
+	tlv_chan_band.header.type = TLV_TYPE_UAP_CHAN_BAND_CONFIG;
+	tlv_chan_band.header.len = sizeof(MrvlIEtypes_channel_band_t) -
+		sizeof(MrvlIEtypesHeader_t);
+	tlv_chan_band.bandcfg = uap_band_cfg;
+	tlv_chan_band.channel = channel;
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_SET, 0, MNULL, &tlv_chan_band);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Issue CMD to UAP firmware to get current beacon and dtim periods
+ *
+ *  @param pmpriv   A pointer to mlan_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_uap_get_beacon_dtim(pmlan_private pmpriv)
+{
+	t_u8 tlv_buffer[sizeof(MrvlIEtypes_beacon_period_t) +
+			sizeof(MrvlIEtypes_dtim_period_t)];
+	MrvlIEtypes_beacon_period_t *ptlv_beacon_pd;
+	MrvlIEtypes_dtim_period_t *ptlv_dtim_pd;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(pmpriv->adapter, &tlv_buffer, 0, sizeof(tlv_buffer));
+	ptlv_beacon_pd = (MrvlIEtypes_beacon_period_t *)tlv_buffer;
+	ptlv_beacon_pd->header.type = TLV_TYPE_UAP_BEACON_PERIOD;
+	ptlv_beacon_pd->header.len = sizeof(MrvlIEtypes_beacon_period_t) -
+		sizeof(MrvlIEtypesHeader_t);
+
+	ptlv_dtim_pd =
+		(MrvlIEtypes_dtim_period_t
+		 *)(tlv_buffer + sizeof(MrvlIEtypes_beacon_period_t));
+	ptlv_dtim_pd->header.type = TLV_TYPE_UAP_DTIM_PERIOD;
+	ptlv_dtim_pd->header.len =
+		sizeof(MrvlIEtypes_dtim_period_t) - sizeof(MrvlIEtypesHeader_t);
+
+	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE,
+			       HostCmd_ACT_GEN_GET, 0, MNULL, tlv_buffer);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get deauth control.
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_uap_snmp_mib_ctrl_deauth(pmlan_adapter pmadapter,
+			      pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_snmp_mib *mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET) {
+		cmd_action = HostCmd_ACT_GEN_SET;
+	} else {
+		cmd_action = HostCmd_ACT_GEN_GET;
+	}
+
+	/* Send command to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
+			       StopDeauth_i, (t_void *)pioctl_req,
+			       &mib->param.deauthctrl);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief MLAN uap ioctl handler
+ *
+ *  @param adapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = MNULL;
+	mlan_ds_get_info *pget_info = MNULL;
+	mlan_ds_misc_cfg *misc = MNULL;
+	mlan_ds_sec_cfg *sec = MNULL;
+	mlan_ds_power_cfg *power = MNULL;
+	mlan_ds_pm_cfg *pm = MNULL;
+	mlan_ds_11d_cfg *cfg11d = MNULL;
+	mlan_ds_snmp_mib *snmp = MNULL;
+	mlan_ds_11h_cfg *cfg11h = MNULL;
+	mlan_ds_radio_cfg *radiocfg = MNULL;
+	mlan_ds_rate *rate = MNULL;
+	mlan_ds_reg_mem *reg_mem = MNULL;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	pmlan_ds_scan pscan;
+#endif
+
+	ENTER();
+	switch (pioctl_req->req_id) {
+	case MLAN_IOCTL_BSS:
+		bss = (mlan_ds_bss *)pioctl_req->pbuf;
+		if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR)
+			status = wlan_uap_bss_ioctl_mac_address(pmadapter,
+								pioctl_req);
+		else if (bss->sub_command == MLAN_OID_BSS_STOP)
+			status = wlan_uap_bss_ioctl_stop(pmadapter, pioctl_req);
+		else if (bss->sub_command == MLAN_OID_BSS_START)
+			status = wlan_uap_bss_ioctl_start(pmadapter,
+							  pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_BSS_CONFIG)
+			status = wlan_uap_bss_ioctl_config(pmadapter,
+							   pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_DEAUTH_STA)
+			status = wlan_uap_bss_ioctl_deauth_sta(pmadapter,
+							       pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_BSS_RESET)
+			status = wlan_uap_bss_ioctl_reset(pmadapter,
+							  pioctl_req);
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		else if (bss->sub_command == MLAN_OID_BSS_ROLE) {
+			util_enqueue_list_tail(pmadapter->pmoal_handle,
+					       &pmadapter->ioctl_pending_q,
+					       (pmlan_linked_list)pioctl_req,
+					       pmadapter->callbacks.
+					       moal_spin_lock,
+					       pmadapter->callbacks.
+					       moal_spin_unlock);
+			pmadapter->pending_ioctl = MTRUE;
+			status = MLAN_STATUS_PENDING;
+		}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		else if (bss->sub_command == MLAN_OID_WIFI_DIRECT_MODE)
+			status = wlan_bss_ioctl_wifi_direct_mode(pmadapter,
+								 pioctl_req);
+#endif
+		else if (bss->sub_command == MLAN_OID_BSS_REMOVE)
+			status = wlan_bss_ioctl_bss_remove(pmadapter,
+							   pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM)
+			status = wlan_uap_bss_ioctl_uap_wmm_param(pmadapter,
+								  pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS)
+			status = wlan_uap_bss_ioctl_uap_scan_channels(pmadapter,
+								      pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_CHANNEL)
+			status = wlan_uap_bss_ioctl_uap_channel(pmadapter,
+								pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_ACS_SCAN)
+			status = wlan_uap_bss_ioctl_acs_scan(pmadapter,
+							     pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_OPER_CTRL)
+			status = wlan_uap_bss_ioctl_uap_oper_ctrl(pmadapter,
+								  pioctl_req);
+		else if (bss->sub_command == MLAN_OID_UAP_ADD_STATION)
+			status = wlan_uap_bss_ioctl_add_station(pmadapter,
+								pioctl_req);
+		else if (bss->sub_command == MLAN_OID_ACTION_CHAN_SWITCH)
+			status = wlan_uap_bss_ioctl_action_chan_switch
+				(pmadapter, pioctl_req);
+		break;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	case MLAN_IOCTL_SCAN:
+		pscan = (mlan_ds_scan *)pioctl_req->pbuf;
+		if ((pscan->sub_command == MLAN_OID_SCAN_NORMAL) &&
+		    (pioctl_req->action == MLAN_ACT_GET)) {
+			PRINTM(MIOCTL, "Get scan table in uap\n");
+			pscan->param.scan_resp.pscan_table =
+				(t_u8 *)pmadapter->pscan_table;
+			pscan->param.scan_resp.num_in_scan_table =
+				pmadapter->num_in_scan_table;
+			pscan->param.scan_resp.age_in_secs =
+				pmadapter->age_in_secs;
+			pioctl_req->data_read_written =
+				sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
+			pscan->param.scan_resp.pchan_stats =
+				(t_u8 *)pmadapter->pchan_stats;
+			pscan->param.scan_resp.num_in_chan_stats =
+				pmadapter->num_in_chan_stats;
+		}
+		break;
+#endif
+	case MLAN_IOCTL_GET_INFO:
+		pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
+		if (pget_info->sub_command == MLAN_OID_GET_VER_EXT)
+			status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_DEBUG_INFO)
+			status = wlan_get_info_debug_info(pmadapter,
+							  pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_STATS)
+			status = wlan_uap_get_stats(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_UAP_STATS_LOG)
+			status = wlan_uap_get_stats_log(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_UAP_STA_LIST)
+			status = wlan_uap_get_sta_list(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_BSS_INFO)
+			status = wlan_uap_get_bss_info(pmadapter, pioctl_req);
+		else if (pget_info->sub_command == MLAN_OID_GET_FW_INFO) {
+			pioctl_req->data_read_written =
+				sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
+			memcpy_ext(pmadapter,
+				   &pget_info->param.fw_info.mac_addr,
+				   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
+				   MLAN_MAC_ADDR_LENGTH);
+			pget_info->param.fw_info.fw_ver =
+				pmadapter->fw_release_number;
+			pget_info->param.fw_info.hotfix_version =
+				pmadapter->fw_hotfix_ver;
+			pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
+			pget_info->param.fw_info.ecsa_enable =
+				pmadapter->ecsa_enable;
+			pget_info->param.fw_info.getlog_enable =
+				pmadapter->getlog_enable;
+			pget_info->param.fw_info.hw_dev_mcs_support =
+				pmadapter->hw_dev_mcs_support;
+			pget_info->param.fw_info.hw_dot_11n_dev_cap =
+				pmadapter->hw_dot_11n_dev_cap;
+			pget_info->param.fw_info.usr_dev_mcs_support =
+				pmpriv->usr_dev_mcs_support;
+			if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
+				pget_info->param.fw_info.prohibit_80mhz = MTRUE;
+			else
+				pget_info->param.fw_info.prohibit_80mhz =
+					MFALSE;
+			pget_info->param.fw_info.hw_dot_11ac_mcs_support =
+				pmadapter->hw_dot_11ac_mcs_support;
+			pget_info->param.fw_info.hw_dot_11ac_dev_cap =
+				pmadapter->hw_dot_11ac_dev_cap;
+			pget_info->param.fw_info.usr_dot_11ac_dev_cap_bg =
+				pmpriv->usr_dot_11ac_dev_cap_bg;
+			pget_info->param.fw_info.usr_dot_11ac_mcs_support =
+				pmpriv->usr_dot_11ac_mcs_support;
+			pget_info->param.fw_info.usr_dot_11ac_dev_cap_a =
+				pmpriv->usr_dot_11ac_dev_cap_a;
+			pget_info->param.fw_info.hw_hecap_len =
+				pmadapter->hw_hecap_len;
+			pget_info->param.fw_info.hw_2g_hecap_len =
+				pmadapter->hw_2g_hecap_len;
+			memcpy_ext(pmadapter,
+				   pget_info->param.fw_info.hw_he_cap,
+				   pmadapter->hw_he_cap,
+				   pmadapter->hw_hecap_len,
+				   sizeof(pget_info->param.fw_info.hw_he_cap));
+			memcpy_ext(pmadapter,
+				   pget_info->param.fw_info.hw_2g_he_cap,
+				   pmadapter->hw_2g_he_cap,
+				   pmadapter->hw_2g_hecap_len,
+				   sizeof(pget_info->param.fw_info.
+					  hw_2g_he_cap));
+			pget_info->param.fw_info.region_code =
+				pmadapter->region_code;
+			if (pmadapter->otp_region &&
+			    pmadapter->otp_region->force_reg)
+				pget_info->param.fw_info.force_reg = MTRUE;
+			else
+				pget_info->param.fw_info.force_reg = MFALSE;
+			pget_info->param.fw_info.fw_supplicant_support =
+				IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 :
+				0x00;
+			pget_info->param.fw_info.antinfo = pmadapter->antinfo;
+			pget_info->param.fw_info.max_ap_assoc_sta =
+				pmadapter->max_sta_conn;
+		} else if (pget_info->sub_command == MLAN_OID_LINK_STATS)
+			status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
+		break;
+	case MLAN_IOCTL_MISC_CFG:
+		misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+		if (misc->sub_command == MLAN_OID_MISC_INIT_SHUTDOWN)
+			status = wlan_misc_ioctl_init_shutdown(pmadapter,
+							       pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_SOFT_RESET)
+			status = wlan_uap_misc_ioctl_soft_reset(pmadapter,
+								pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_HOST_CMD)
+			status = wlan_misc_ioctl_host_cmd(pmadapter,
+							  pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_REGION)
+			status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GEN_IE)
+			status = wlan_uap_misc_ioctl_gen_ie(pmadapter,
+							    pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)
+			status = wlan_misc_ioctl_custom_ie_list(pmadapter,
+								pioctl_req,
+								MTRUE);
+		if (misc->sub_command == MLAN_OID_MISC_TX_DATAPAUSE)
+			status = wlan_uap_misc_ioctl_txdatapause(pmadapter,
+								 pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_RX_MGMT_IND)
+			status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req);
+#ifdef DEBUG_LEVEL1
+		if (misc->sub_command == MLAN_OID_MISC_DRVDBG)
+			status = wlan_set_drvdbg(pmadapter, pioctl_req);
+#endif
+
+		if (misc->sub_command == MLAN_OID_MISC_TXCONTROL)
+			status = wlan_misc_ioctl_txcontrol(pmadapter,
+							   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_MAC_CONTROL)
+			status = wlan_misc_ioctl_mac_control(pmadapter,
+							     pioctl_req);
+#ifdef RX_PACKET_COALESCE
+		if (misc->sub_command == MLAN_OID_MISC_RX_PACKET_COALESCE)
+			status = wlan_misc_ioctl_rx_pkt_coalesce_config
+				(pmadapter, pioctl_req);
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		if (misc->sub_command == MLAN_OID_MISC_WIFI_DIRECT_CONFIG)
+			status = wlan_misc_p2p_config(pmadapter, pioctl_req);
+#endif
+		if (misc->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH)
+			status = wlan_misc_gpio_tsf_latch_config(pmadapter,
+								 pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_TSF_INFO)
+			status = wlan_misc_get_tsf_info(pmadapter, pioctl_req);
+
+		if (misc->sub_command == MLAN_OID_MISC_DFS_REAPTER_MODE) {
+			mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+			misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+			misc_cfg->param.dfs_repeater.mode =
+				pmadapter->dfs_repeater;
+			pioctl_req->data_read_written =
+				sizeof(mlan_ds_misc_dfs_repeater);
+
+			status = MLAN_STATUS_SUCCESS;
+		}
+		if (misc->sub_command == MLAN_OID_MISC_IND_RST_CFG)
+			status = wlan_misc_ioctl_ind_rst_cfg(pmadapter,
+							     pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_TSF)
+			status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_CHAN_REGION_CFG)
+			status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS_CHECK)
+			status = wlan_misc_ioctl_operclass_validation(pmadapter,
+								      pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS)
+			status = wlan_misc_ioctl_oper_class(pmadapter,
+							    pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_AGGR_CTRL)
+			status = wlan_misc_ioctl_aggr_ctrl(pmadapter,
+							   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_PER_PKT_CFG)
+			status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_FW_DUMP_EVENT)
+			status = wlan_misc_ioctl_fw_dump_event(pmadapter,
+							       pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_RX_ABORT_CFG)
+			status = wlan_misc_ioctl_rxabortcfg(pmadapter,
+							    pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_RX_ABORT_CFG_EXT)
+			status = wlan_misc_ioctl_rxabortcfg_ext(pmadapter,
+								pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_TX_AMPDU_PROT_MODE)
+			status = wlan_misc_ioctl_tx_ampdu_prot_mode(pmadapter,
+								    pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG)
+			status = wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg
+				(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_HAL_PHY_CFG)
+			status = wlan_misc_hal_phy_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_RATE_ADAPT_CFG)
+			status = wlan_misc_ioctl_rate_adapt_cfg(pmadapter,
+								pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_CCK_DESENSE_CFG)
+			status = wlan_misc_ioctl_cck_desense_cfg(pmadapter,
+								 pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_ROBUSTCOEX)
+			status = wlan_misc_robustcoex(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_DMCS_CONFIG)
+			status = wlan_misc_dmcs_config(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_TX_RX_HISTOGRAM)
+			status = wlan_get_tx_rx_histogram(pmadapter,
+							  pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_CFP_INFO)
+			status = wlan_get_cfpinfo(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_BOOT_SLEEP)
+			status = wlan_misc_bootsleep(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_DYN_BW)
+			status = wlan_misc_ioctl_dyn_bw(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_CHAN_TRPC_CFG)
+			status = wlan_get_chan_trpc_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_BAND_STEERING)
+			status = wlan_misc_band_steering_cfg(pmadapter,
+							     pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_BEACON_STUCK)
+			status = wlan_misc_beacon_stuck_cfg(pmadapter,
+							    pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG)
+			status = wlan_get_rgchnpwr_cfg(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_CFP_TABLE)
+			status = wlan_get_cfp_table(pmadapter, pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_RANGE_EXT)
+			status = wlan_misc_ioctl_range_ext(pmadapter,
+							   pioctl_req);
+		if (misc->sub_command == MLAN_OID_MISC_WACP_MODE)
+			status = wlan_misc_ioctl_wacp_mode(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_IOCTL_POWER_CFG:
+		power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
+		if (power->sub_command == MLAN_OID_POWER_LOW_POWER_MODE)
+			status = wlan_power_ioctl_set_get_lpm(pmadapter,
+							      pioctl_req);
+		break;
+	case MLAN_IOCTL_PM_CFG:
+		pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+		if (pm->sub_command == MLAN_OID_PM_CFG_PS_MODE)
+			status = wlan_uap_pm_ioctl_mode(pmadapter, pioctl_req);
+		if (pm->sub_command == MLAN_OID_PM_CFG_DEEP_SLEEP)
+			status = wlan_uap_pm_ioctl_deepsleep(pmadapter,
+							     pioctl_req);
+		if (pm->sub_command == MLAN_OID_PM_CFG_HS_CFG)
+			status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req);
+		if (pm->sub_command == MLAN_OID_PM_HS_WAKEUP_REASON)
+			status = wlan_get_hs_wakeup_reason(pmadapter,
+							   pioctl_req);
+		if (pm->sub_command == MLAN_OID_PM_MGMT_FILTER)
+			status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
+		if (pm->sub_command == MLAN_OID_PM_INFO)
+			status = wlan_get_pm_info(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_SNMP_MIB:
+		snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
+		if (snmp->sub_command == MLAN_OID_SNMP_MIB_CTRL_DEAUTH)
+			status = wlan_uap_snmp_mib_ctrl_deauth(pmadapter,
+							       pioctl_req);
+		if (snmp->sub_command == MLAN_OID_SNMP_MIB_DOT11D)
+			status = wlan_uap_snmp_mib_11d(pmadapter, pioctl_req);
+		if (snmp->sub_command == MLAN_OID_SNMP_MIB_DOT11H)
+			status = wlan_uap_snmp_mib_11h(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_SEC_CFG:
+		sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
+		if (sec->sub_command == MLAN_OID_SEC_CFG_ENCRYPT_KEY)
+			status = wlan_uap_sec_ioctl_set_encrypt_key(pmadapter,
+								    pioctl_req);
+		if (sec->sub_command == MLAN_OID_SEC_CFG_WAPI_ENABLED)
+			status = wlan_uap_sec_ioctl_wapi_enable(pmadapter,
+								pioctl_req);
+		if (sec->sub_command == MLAN_OID_SEC_CFG_REPORT_MIC_ERR)
+			status = wlan_uap_sec_ioctl_report_mic_error(pmadapter,
+								     pioctl_req);
+		break;
+	case MLAN_IOCTL_11N_CFG:
+		status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11D_CFG:
+		cfg11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
+		if (cfg11d->sub_command == MLAN_OID_11D_DOMAIN_INFO)
+			status = wlan_uap_domain_info(pmadapter, pioctl_req);
+		else if (cfg11d->sub_command == MLAN_OID_11D_DOMAIN_INFO_EXT)
+			status = wlan_11d_cfg_domain_info(pmadapter,
+							  pioctl_req);
+		break;
+	case MLAN_IOCTL_11H_CFG:
+		cfg11h = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
+		if (cfg11h->sub_command == MLAN_OID_11H_CHANNEL_CHECK)
+			status = wlan_uap_11h_channel_check_req(pmadapter,
+								pioctl_req);
+		if (cfg11h->sub_command == MLAN_OID_11H_DFS_TESTING)
+			status = wlan_11h_ioctl_dfs_testing(pmadapter,
+							    pioctl_req);
+		if (cfg11h->sub_command == MLAN_OID_11H_CHAN_NOP_INFO)
+			status = wlan_11h_ioctl_get_channel_nop_info(pmadapter,
+								     pioctl_req);
+		if (cfg11h->sub_command == MLAN_OID_11H_CHAN_REPORT_REQUEST)
+			status = wlan_11h_ioctl_dfs_chan_report(pmpriv,
+								pioctl_req);
+		if (cfg11h->sub_command == MLAN_OID_11H_CHAN_SWITCH_COUNT)
+			status = wlan_11h_ioctl_chan_switch_count(pmadapter,
+								  pioctl_req);
+		if (cfg11h->sub_command == MLAN_OID_11H_DFS_W53_CFG)
+			status = wlan_11h_ioctl_dfs_w53_cfg(pmadapter,
+							    pioctl_req);
+		break;
+	case MLAN_IOCTL_RADIO_CFG:
+		radiocfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
+		if (radiocfg->sub_command == MLAN_OID_MIMO_SWITCH)
+			status = wlan_radio_ioctl_mimo_switch_cfg(pmadapter,
+								  pioctl_req);
+		if (radiocfg->sub_command == MLAN_OID_RADIO_CTRL)
+			status = wlan_radio_ioctl_radio_ctl(pmadapter,
+							    pioctl_req);
+		if (radiocfg->sub_command == MLAN_OID_REMAIN_CHAN_CFG)
+			status = wlan_radio_ioctl_remain_chan_cfg(pmadapter,
+								  pioctl_req);
+		if (radiocfg->sub_command == MLAN_OID_ANT_CFG)
+			status = wlan_radio_ioctl_ant_cfg(pmadapter,
+							  pioctl_req);
+		if (radiocfg->sub_command == MLAN_OID_BAND_CFG)
+			status = wlan_radio_ioctl_band_cfg(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_IOCTL_RATE:
+		rate = (mlan_ds_rate *)pioctl_req->pbuf;
+		if (rate->sub_command == MLAN_OID_RATE_CFG)
+			status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
+		else if (rate->sub_command == MLAN_OID_GET_DATA_RATE)
+			status = wlan_rate_ioctl_get_data_rate(pmadapter,
+							       pioctl_req);
+		break;
+	case MLAN_IOCTL_11AC_CFG:
+		status = wlan_11ac_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_11AX_CFG:
+		status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	case MLAN_IOCTL_REG_MEM:
+		reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
+		if (reg_mem->sub_command == MLAN_OID_REG_RW)
+			status = wlan_reg_mem_ioctl_reg_rw(pmadapter,
+							   pioctl_req);
+		else if (reg_mem->sub_command == MLAN_OID_EEPROM_RD)
+			status = wlan_reg_mem_ioctl_read_eeprom(pmadapter,
+								pioctl_req);
+		else if (reg_mem->sub_command == MLAN_OID_MEM_RW)
+			status = wlan_reg_mem_ioctl_mem_rw(pmadapter,
+							   pioctl_req);
+		break;
+	case MLAN_IOCTL_WMM_CFG:
+		status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		break;
+	}
+	LEAVE();
+	return status;
+}
diff --git a/wlan_sd8987/mlan/mlan_uap_txrx.c b/wlan_sd8987/mlan/mlan_uap_txrx.c
new file mode 100755
index 0000000..3a98e52
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_uap_txrx.c
@@ -0,0 +1,871 @@
+/** @file mlan_uap_txrx.c
+ *
+ *  @brief This file contains AP mode transmit and receive functions
+ *
+ *
+ *  Copyright 2009-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/05/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_main.h"
+#include "mlan_uap.h"
+#include "mlan_wmm.h"
+#include "mlan_11n_aggr.h"
+#include "mlan_11n_rxreorder.h"
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+#include "authenticator_api.h"
+#endif
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief This function processes received packet and forwards it
+ *          to kernel/upper layer
+ *
+ *  @param pmadapter A pointer to mlan_adapter
+ *  @param pmbuf     A pointer to mlan_buffer which includes the received packet
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_upload_uap_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef DEBUG_LEVEL1
+	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+#endif
+	PRxPD prx_pd;
+	ENTER();
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+
+	/* Chop off RxPD */
+	pmbuf->data_len -= prx_pd->rx_pkt_offset;
+	pmbuf->data_offset += prx_pd->rx_pkt_offset;
+	pmbuf->pparent = MNULL;
+
+	DBG_HEXDUMP(MDAT_D, "uAP RxPD", (t_u8 *)prx_pd,
+		    MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
+	DBG_HEXDUMP(MDAT_D, "uAP Rx Payload",
+		    ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+		    MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->out_ts_sec,
+						  &pmbuf->out_ts_usec);
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
+	       pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
+	       prx_pd->priority);
+	ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+						    pmbuf);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR,
+		       "uAP Rx Error: moal_recv_packet returned error\n");
+		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+	}
+
+	if (ret != MLAN_STATUS_PENDING)
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+#ifdef USB
+	else if (IS_USB(pmadapter->card_type))
+		pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
+							MNULL,
+							pmadapter->rx_data_ep,
+							ret);
+#endif
+	LEAVE();
+
+	return ret;
+}
+
+/**
+ *  @brief This function will check if unicast packet need be dropped
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     mac address to find in station list table
+ *
+ *  @return	       MLAN_STATUS_FAILURE -- drop packet, otherwise forward to
+ * network stack
+ */
+static mlan_status
+wlan_check_unicast_packet(mlan_private *priv, t_u8 *mac)
+{
+	int j;
+	sta_node *sta_ptr = MNULL;
+	pmlan_adapter pmadapter = priv->adapter;
+	pmlan_private pmpriv = MNULL;
+	t_u8 pkt_type = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	for (j = 0; j < MLAN_MAX_BSS_NUM; ++j) {
+		pmpriv = pmadapter->priv[j];
+		if (pmpriv) {
+			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
+				continue;
+			sta_ptr = wlan_get_station_entry(pmpriv, mac);
+			if (sta_ptr) {
+				if (pmpriv == priv)
+					pkt_type = PKT_INTRA_UCAST;
+				else
+					pkt_type = PKT_INTER_UCAST;
+				break;
+			}
+		}
+	}
+	if ((pkt_type == PKT_INTRA_UCAST) &&
+	    (priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) {
+		PRINTM(MDATA, "Drop INTRA_UCAST packet\n");
+		ret = MLAN_STATUS_FAILURE;
+	} else if ((pkt_type == PKT_INTER_UCAST) &&
+		   (priv->pkt_fwd & PKT_FWD_INTER_UCAST)) {
+		PRINTM(MDATA, "Drop INTER_UCAST packet\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *  @brief This function fill the txpd for tx packet
+ *
+ *  @param priv	   A pointer to mlan_private structure
+ *  @param pmbuf   A pointer to the mlan_buffer for process
+ *
+ *  @return        headptr or MNULL
+ */
+t_void *
+wlan_ops_uap_process_txpd(t_void *priv, pmlan_buffer pmbuf)
+{
+	pmlan_private pmpriv = (pmlan_private)priv;
+	TxPD *plocal_tx_pd;
+	t_u8 *head_ptr = MNULL;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+	t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+
+	ENTER();
+
+	if (!pmbuf->data_len) {
+		PRINTM(MERROR, "uAP Tx Error: Invalid packet length: %d\n",
+		       pmbuf->data_len);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		goto done;
+	}
+	if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+		memcpy_ext(pmpriv->adapter, &pkt_type,
+			   pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type),
+			   sizeof(pkt_type));
+		memcpy_ext(pmpriv->adapter, &tx_control,
+			   pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+			   sizeof(tx_control), sizeof(tx_control));
+		pmbuf->data_offset += sizeof(pkt_type) + sizeof(tx_control);
+		pmbuf->data_len -= sizeof(pkt_type) + sizeof(tx_control);
+	}
+	if (pmbuf->data_offset <
+	    (sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT)) {
+		PRINTM(MERROR,
+		       "not enough space for TxPD: headroom=%d pkt_len=%d, required=%d\n",
+		       pmbuf->data_offset, pmbuf->data_len,
+		       sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT);
+		DBG_HEXDUMP(MDAT_D, "drop pkt",
+			    pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		goto done;
+	}
+
+	/* head_ptr should be aligned */
+	head_ptr = pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) -
+		pmpriv->intf_hr_len;
+	head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
+
+	plocal_tx_pd = (TxPD *)(head_ptr + pmpriv->intf_hr_len);
+	memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(TxPD));
+
+	/* Set the BSS number to TxPD */
+	plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv);
+	plocal_tx_pd->bss_type = pmpriv->bss_type;
+
+	plocal_tx_pd->tx_pkt_length = (t_u16)pmbuf->data_len;
+
+	plocal_tx_pd->priority = (t_u8)pmbuf->priority;
+	plocal_tx_pd->pkt_delay_2ms =
+		wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf);
+
+	if (plocal_tx_pd->priority <
+	    NELEMENTS(pmpriv->wmm.user_pri_pkt_tx_ctrl))
+		/*
+		 * Set the priority specific tx_control field, setting of 0 will
+		 *   cause the default value to be used later in this function
+		 */
+		plocal_tx_pd->tx_control =
+			pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->
+							 priority];
+
+	if (pmbuf->flags & MLAN_BUF_FLAG_TX_STATUS) {
+		plocal_tx_pd->tx_control_1 |= pmbuf->tx_seq_num << 8;
+		plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
+	}
+
+	/* Offset of actual data */
+	plocal_tx_pd->tx_pkt_offset = (t_u16)((t_ptr)pmbuf->pbuf +
+					      pmbuf->data_offset -
+					      (t_ptr)plocal_tx_pd);
+
+	if (!plocal_tx_pd->tx_control) {
+		/* TxCtrl set by user or default */
+		plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl;
+	}
+
+	if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+		plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type;
+		plocal_tx_pd->tx_control = tx_control;
+	}
+
+	if (pmbuf->flags & MLAN_BUF_FLAG_TX_CTRL) {
+		if (pmbuf->u.tx_info.data_rate) {
+			memcpy_ext(pmpriv->adapter, dst_mac,
+				   pmbuf->pbuf + pmbuf->data_offset,
+				   sizeof(dst_mac), sizeof(dst_mac));
+			plocal_tx_pd->tx_control |=
+				(wlan_ieee_rateid_to_mrvl_rateid
+				 (pmpriv, pmbuf->u.tx_info.data_rate, dst_mac)
+				 << 16);
+			plocal_tx_pd->tx_control |= TXPD_TXRATE_ENABLE;
+		}
+		plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.channel << 21;
+		if (pmbuf->u.tx_info.bw) {
+			plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.bw << 16;
+			plocal_tx_pd->tx_control_1 |= TXPD_BW_ENABLE;
+		}
+		if (pmbuf->u.tx_info.tx_power.tp.hostctl)
+			plocal_tx_pd->tx_control |=
+				(t_u32)pmbuf->u.tx_info.tx_power.val;
+		if (pmbuf->u.tx_info.retry_limit) {
+			plocal_tx_pd->tx_control |= pmbuf->u.tx_info.retry_limit
+				<< 8;
+			plocal_tx_pd->tx_control |= TXPD_RETRY_ENABLE;
+		}
+	}
+
+	endian_convert_TxPD(plocal_tx_pd);
+
+	/* Adjust the data offset and length to include TxPD in pmbuf */
+	pmbuf->data_len += pmbuf->data_offset;
+	pmbuf->data_offset = (t_u32)((t_ptr)head_ptr - (t_ptr)pmbuf->pbuf);
+	pmbuf->data_len -= pmbuf->data_offset;
+
+done:
+	LEAVE();
+	return head_ptr;
+}
+
+/**
+ *  @brief This function processes received packet and forwards it
+ *          to kernel/upper layer
+ *
+ *  @param adapter   A pointer to mlan_adapter
+ *  @param pmbuf     A pointer to mlan_buffer which includes the received packet
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_ops_uap_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	RxPD *prx_pd;
+	wlan_mgmt_pkt *puap_pkt_hdr = MNULL;
+
+	RxPacketHdr_t *prx_pkt;
+	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+	t_u16 rx_pkt_type = 0;
+	sta_node *sta_ptr = MNULL;
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	t_u8 eapol_type[2] = { 0x88, 0x8e };
+#endif
+	t_u16 adj_rx_rate = 0;
+	t_u8 antenna = 0;
+
+	t_u32 last_rx_sec = 0;
+	t_u32 last_rx_usec = 0;
+	t_u8 ext_rate_info = 0;
+
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	/* Endian conversion */
+	endian_convert_RxPD(prx_pd);
+
+	if (priv->adapter->pcard_info->v14_fw_api) {
+		t_u8 rxpd_rate_info_orig = prx_pd->rate_info;
+		prx_pd->rate_info =
+			wlan_convert_v14_rx_rate_info(priv,
+						      rxpd_rate_info_orig);
+		PRINTM(MINFO,
+		       "UAP RX: v14_fw_api=%d rx_rate =%d rxpd_rate_info=0x%x->0x%x\n",
+		       priv->adapter->pcard_info->v14_fw_api, prx_pd->rx_rate,
+		       rxpd_rate_info_orig, prx_pd->rate_info);
+	}
+
+	if (priv->rx_pkt_info) {
+		ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
+		pmbuf->u.rx_info.data_rate =
+			wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
+						prx_pd->rate_info,
+						ext_rate_info);
+		pmbuf->u.rx_info.channel =
+			(prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
+		pmbuf->u.rx_info.antenna = prx_pd->antenna;
+		pmbuf->u.rx_info.rssi = prx_pd->snr - prx_pd->nf;
+	}
+
+	rx_pkt_type = prx_pd->rx_pkt_type;
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+	PRINTM(MINFO,
+	       "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
+	       pmbuf->data_len, prx_pd->rx_pkt_offset,
+	       pmbuf->data_len - prx_pd->rx_pkt_offset);
+
+	if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) !=
+	    (t_u16)pmbuf->data_len) {
+		PRINTM(MERROR,
+		       "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
+		       " rx_pkt_length=%d\n",
+		       pmbuf->data_len, prx_pd->rx_pkt_offset,
+		       prx_pd->rx_pkt_length);
+		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
+		ret = MLAN_STATUS_FAILURE;
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+		goto done;
+	}
+	pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
+
+	if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask &&
+	    prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) {
+		/* Check if this is mgmt packet and needs to
+		 * forwarded to app as an event
+		 */
+		puap_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd +
+						 prx_pd->rx_pkt_offset);
+		puap_pkt_hdr->frm_len = wlan_le16_to_cpu(puap_pkt_hdr->frm_len);
+		if ((puap_pkt_hdr->wlan_header.frm_ctl &
+		     IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
+			wlan_process_802dot11_mgmt_pkt(pmadapter->
+						       priv[pmbuf->bss_index],
+						       (t_u8 *)&puap_pkt_hdr->
+						       wlan_header,
+						       puap_pkt_hdr->frm_len +
+						       sizeof(wlan_mgmt_pkt) -
+						       sizeof(puap_pkt_hdr->
+							      frm_len),
+						       (RxPD *)prx_pd);
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+		goto done;
+	}
+	if (rx_pkt_type != PKT_TYPE_BAR) {
+		priv->rxpd_rate = prx_pd->rx_rate;
+		priv->rxpd_rate_info = prx_pd->rate_info;
+		priv->rxpd_rx_info = (t_u8)(prx_pd->rx_info >> 16);
+
+		if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			antenna = wlan_adjust_antenna(priv, (RxPD *)prx_pd);
+			adj_rx_rate =
+				wlan_adjust_data_rate(priv, priv->rxpd_rate,
+						      priv->rxpd_rate_info);
+			pmadapter->callbacks.moal_hist_data_add(pmadapter->
+								pmoal_handle,
+								pmbuf->
+								bss_index,
+								adj_rx_rate,
+								prx_pd->snr,
+								prx_pd->nf,
+								antenna);
+		}
+	}
+
+	sta_ptr = wlan_get_station_entry(priv, prx_pkt->eth803_hdr.src_addr);
+	if (sta_ptr) {
+		sta_ptr->snr = prx_pd->snr;
+		sta_ptr->nf = prx_pd->nf;
+		pmadapter->callbacks.moal_get_system_time(pmadapter->
+							  pmoal_handle,
+							  &last_rx_sec,
+							  &last_rx_usec);
+		sta_ptr->stats.last_rx_in_msec =
+			(t_u64)last_rx_sec *1000 + (t_u64)last_rx_usec / 1000;
+	}
+#ifdef DRV_EMBEDDED_AUTHENTICATOR
+	/**process eapol packet for uap*/
+	if (IsAuthenticatorEnabled(priv->psapriv) &&
+	    (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type,
+		     sizeof(eapol_type)))) {
+		ret = AuthenticatorProcessEapolPacket(priv->psapriv,
+						      ((t_u8 *)prx_pd +
+						       prx_pd->rx_pkt_offset),
+						      prx_pd->rx_pkt_length);
+		if (ret == MLAN_STATUS_SUCCESS) {
+			pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+			goto done;
+		}
+	}
+#endif
+
+	pmbuf->priority |= prx_pd->priority;
+	memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
+		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) {
+		sta_ptr = wlan_get_station_entry(priv, ta);
+		if (sta_ptr) {
+			sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num;
+			sta_ptr->snr = prx_pd->snr;
+			sta_ptr->nf = prx_pd->nf;
+		}
+	}
+	/* check if UAP enable 11n */
+	if (!priv->is_11n_enabled ||
+	    (!wlan_11n_get_rxreorder_tbl((mlan_private *)priv, prx_pd->priority,
+					 ta)
+	     && (prx_pd->rx_pkt_type != PKT_TYPE_AMSDU)
+	    )
+		) {
+		if (priv->pkt_fwd)
+			wlan_process_uap_rx_packet(priv, pmbuf);
+		else
+			wlan_upload_uap_rx_packet(pmadapter, pmbuf);
+		goto done;
+	}
+	/* Reorder and send to OS */
+	ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
+				     ta, (t_u8)prx_pd->rx_pkt_type,
+				     (void *)pmbuf);
+	if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function processes received packet and forwards it
+ *          to kernel/upper layer or send back to firmware
+ *
+ *  @param priv      A pointer to mlan_private
+ *  @param pmbuf     A pointer to mlan_buffer which includes the received packet
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_uap_recv_packet(mlan_private *priv, pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	RxPacketHdr_t *prx_pkt;
+	pmlan_buffer newbuf = MNULL;
+
+	ENTER();
+
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)pmbuf->pbuf + pmbuf->data_offset);
+
+	DBG_HEXDUMP(MDAT_D, "uap_recv_packet", pmbuf->pbuf + pmbuf->data_offset,
+		    MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
+
+	PRINTM(MDATA, "AMSDU dest " MACSTR "\n",
+	       MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+
+	/* don't do packet forwarding in disconnected state */
+	if ((priv->media_connected == MFALSE) ||
+	    (pmbuf->data_len > MV_ETH_FRAME_LEN))
+		goto upload;
+
+	if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) {
+		if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) {
+			/* Multicast pkt */
+			newbuf = wlan_alloc_mlan_buffer(pmadapter,
+							MLAN_TX_DATA_BUF_SIZE_2K,
+							0, MOAL_MALLOC_BUFFER);
+			if (newbuf) {
+				newbuf->bss_index = pmbuf->bss_index;
+				newbuf->buf_type = pmbuf->buf_type;
+				newbuf->priority = pmbuf->priority;
+				newbuf->in_ts_sec = pmbuf->in_ts_sec;
+				newbuf->in_ts_usec = pmbuf->in_ts_usec;
+				newbuf->data_offset =
+					(sizeof(TxPD) + priv->intf_hr_len +
+					 DMA_ALIGNMENT);
+				util_scalar_increment(pmadapter->pmoal_handle,
+						      &pmadapter->
+						      pending_bridge_pkts,
+						      pmadapter->callbacks.
+						      moal_spin_lock,
+						      pmadapter->callbacks.
+						      moal_spin_unlock);
+
+				newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+
+				/* copy the data */
+				memcpy_ext(pmadapter,
+					   (t_u8 *)newbuf->pbuf +
+					   newbuf->data_offset,
+					   pmbuf->pbuf + pmbuf->data_offset,
+					   pmbuf->data_len,
+					   MLAN_TX_DATA_BUF_SIZE_2K);
+				newbuf->data_len = pmbuf->data_len;
+				wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
+				if (util_scalar_read(pmadapter->pmoal_handle,
+						     &pmadapter->
+						     pending_bridge_pkts,
+						     pmadapter->callbacks.
+						     moal_spin_lock,
+						     pmadapter->callbacks.
+						     moal_spin_unlock) >
+				    RX_HIGH_THRESHOLD)
+					wlan_drop_tx_pkts(priv);
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+			}
+		}
+	} else {
+		if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) &&
+		    (wlan_get_station_entry(priv,
+					    prx_pkt->eth803_hdr.dest_addr))) {
+			/* Intra BSS packet */
+			newbuf = wlan_alloc_mlan_buffer(pmadapter,
+							MLAN_TX_DATA_BUF_SIZE_2K,
+							0, MOAL_MALLOC_BUFFER);
+			if (newbuf) {
+				newbuf->bss_index = pmbuf->bss_index;
+				newbuf->buf_type = pmbuf->buf_type;
+				newbuf->priority = pmbuf->priority;
+				newbuf->in_ts_sec = pmbuf->in_ts_sec;
+				newbuf->in_ts_usec = pmbuf->in_ts_usec;
+				newbuf->data_offset =
+					(sizeof(TxPD) + priv->intf_hr_len +
+					 DMA_ALIGNMENT);
+				util_scalar_increment(pmadapter->pmoal_handle,
+						      &pmadapter->
+						      pending_bridge_pkts,
+						      pmadapter->callbacks.
+						      moal_spin_lock,
+						      pmadapter->callbacks.
+						      moal_spin_unlock);
+				newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+
+				/* copy the data */
+				memcpy_ext(pmadapter,
+					   (t_u8 *)newbuf->pbuf +
+					   newbuf->data_offset,
+					   pmbuf->pbuf + pmbuf->data_offset,
+					   pmbuf->data_len,
+					   MLAN_TX_DATA_BUF_SIZE_2K);
+				newbuf->data_len = pmbuf->data_len;
+				wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
+				if (util_scalar_read(pmadapter->pmoal_handle,
+						     &pmadapter->
+						     pending_bridge_pkts,
+						     pmadapter->callbacks.
+						     moal_spin_lock,
+						     pmadapter->callbacks.
+						     moal_spin_unlock) >
+				    RX_HIGH_THRESHOLD)
+					wlan_drop_tx_pkts(priv);
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+			}
+			goto done;
+		} else if (MLAN_STATUS_FAILURE ==
+			   wlan_check_unicast_packet(priv,
+						     prx_pkt->eth803_hdr.
+						     dest_addr)) {
+			/* drop packet */
+			PRINTM(MDATA, "Drop AMSDU dest " MACSTR "\n",
+			       MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+			goto done;
+		}
+	}
+upload:
+	/** send packet to moal */
+	ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+						    pmbuf);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function processes received packet and forwards it
+ *          to kernel/upper layer or send back to firmware
+ *
+ *  @param priv      A pointer to mlan_private
+ *  @param pmbuf     A pointer to mlan_buffer which includes the received packet
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_process_uap_rx_packet(mlan_private *priv, pmlan_buffer pmbuf)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	RxPD *prx_pd;
+	RxPacketHdr_t *prx_pkt;
+	pmlan_buffer newbuf = MNULL;
+
+	ENTER();
+
+	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
+	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
+
+	DBG_HEXDUMP(MDAT_D, "uAP RxPD", prx_pd,
+		    MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
+	DBG_HEXDUMP(MDAT_D, "uAP Rx Payload",
+		    ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
+		    MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
+
+	PRINTM(MINFO,
+	       "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
+	       pmbuf->data_len, prx_pd->rx_pkt_offset,
+	       pmbuf->data_len - prx_pd->rx_pkt_offset);
+	PRINTM(MDATA, "Rx dest " MACSTR "\n",
+	       MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+
+	/* don't do packet forwarding in disconnected state */
+	/* don't do packet forwarding when packet > 1514 */
+	if ((priv->media_connected == MFALSE) ||
+	    ((pmbuf->data_len - prx_pd->rx_pkt_offset) > MV_ETH_FRAME_LEN))
+		goto upload;
+
+	if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) {
+		if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) {
+			/* Multicast pkt */
+			newbuf = wlan_alloc_mlan_buffer(pmadapter,
+							MLAN_TX_DATA_BUF_SIZE_2K,
+							0, MOAL_MALLOC_BUFFER);
+			if (newbuf) {
+				newbuf->bss_index = pmbuf->bss_index;
+				newbuf->buf_type = pmbuf->buf_type;
+				newbuf->priority = pmbuf->priority;
+				newbuf->in_ts_sec = pmbuf->in_ts_sec;
+				newbuf->in_ts_usec = pmbuf->in_ts_usec;
+				newbuf->data_offset =
+					(sizeof(TxPD) + priv->intf_hr_len +
+					 DMA_ALIGNMENT);
+				util_scalar_increment(pmadapter->pmoal_handle,
+						      &pmadapter->
+						      pending_bridge_pkts,
+						      pmadapter->callbacks.
+						      moal_spin_lock,
+						      pmadapter->callbacks.
+						      moal_spin_unlock);
+				newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+
+				/* copy the data, skip rxpd */
+				memcpy_ext(pmadapter,
+					   (t_u8 *)newbuf->pbuf +
+					   newbuf->data_offset,
+					   pmbuf->pbuf + pmbuf->data_offset +
+					   prx_pd->rx_pkt_offset,
+					   pmbuf->data_len -
+					   prx_pd->rx_pkt_offset,
+					   MLAN_TX_DATA_BUF_SIZE_2K);
+				newbuf->data_len =
+					pmbuf->data_len - prx_pd->rx_pkt_offset;
+				wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
+				if (util_scalar_read(pmadapter->pmoal_handle,
+						     &pmadapter->
+						     pending_bridge_pkts,
+						     pmadapter->callbacks.
+						     moal_spin_lock,
+						     pmadapter->callbacks.
+						     moal_spin_unlock) >
+				    RX_HIGH_THRESHOLD)
+					wlan_drop_tx_pkts(priv);
+				wlan_recv_event(priv,
+						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+						MNULL);
+			}
+		}
+	} else {
+		if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) &&
+		    (wlan_get_station_entry(priv,
+					    prx_pkt->eth803_hdr.dest_addr))) {
+			/* Forwarding Intra-BSS packet */
+#ifdef USB
+			if (IS_USB(pmadapter->card_type)) {
+				if (pmbuf->flags & MLAN_BUF_FLAG_RX_DEAGGR) {
+					newbuf = wlan_alloc_mlan_buffer
+						(pmadapter,
+						 MLAN_TX_DATA_BUF_SIZE_2K, 0,
+						 MOAL_MALLOC_BUFFER);
+					if (newbuf) {
+						newbuf->bss_index =
+							pmbuf->bss_index;
+						newbuf->buf_type =
+							pmbuf->buf_type;
+						newbuf->priority =
+							pmbuf->priority;
+						newbuf->in_ts_sec =
+							pmbuf->in_ts_sec;
+						newbuf->in_ts_usec =
+							pmbuf->in_ts_usec;
+						newbuf->data_offset =
+							(sizeof(TxPD) +
+							 priv->intf_hr_len +
+							 DMA_ALIGNMENT);
+						util_scalar_increment
+							(pmadapter->
+							 pmoal_handle,
+							 &pmadapter->
+							 pending_bridge_pkts,
+							 pmadapter->callbacks.
+							 moal_spin_lock,
+							 pmadapter->callbacks.
+							 moal_spin_unlock);
+						newbuf->flags |=
+							MLAN_BUF_FLAG_BRIDGE_BUF;
+
+						/* copy the data, skip rxpd */
+						memcpy_ext(pmadapter,
+							   (t_u8 *)newbuf->
+							   pbuf +
+							   newbuf->data_offset,
+							   pmbuf->pbuf +
+							   pmbuf->data_offset +
+							   prx_pd->
+							   rx_pkt_offset,
+							   pmbuf->data_len -
+							   prx_pd->
+							   rx_pkt_offset,
+							   pmbuf->data_len -
+							   prx_pd->
+							   rx_pkt_offset);
+						newbuf->data_len =
+							pmbuf->data_len -
+							prx_pd->rx_pkt_offset;
+						wlan_wmm_add_buf_txqueue
+							(pmadapter, newbuf);
+						if (util_scalar_read
+						    (pmadapter->pmoal_handle,
+						     &pmadapter->
+						     pending_bridge_pkts,
+						     pmadapter->callbacks.
+						     moal_spin_lock,
+						     pmadapter->callbacks.
+						     moal_spin_unlock) >
+						    RX_HIGH_THRESHOLD)
+							wlan_drop_tx_pkts(priv);
+						wlan_recv_event(priv,
+								MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+								MNULL);
+					}
+					pmadapter->callbacks.
+						moal_recv_complete(pmadapter->
+								   pmoal_handle,
+								   pmbuf,
+								   pmadapter->
+								   rx_data_ep,
+								   ret);
+					goto done;
+				}
+			}
+#endif
+			pmbuf->data_len -= prx_pd->rx_pkt_offset;
+			pmbuf->data_offset += prx_pd->rx_pkt_offset;
+			pmbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
+			util_scalar_increment(pmadapter->pmoal_handle,
+					      &pmadapter->pending_bridge_pkts,
+					      pmadapter->callbacks.
+					      moal_spin_lock,
+					      pmadapter->callbacks.
+					      moal_spin_unlock);
+			wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
+			if (util_scalar_read(pmadapter->pmoal_handle,
+					     &pmadapter->pending_bridge_pkts,
+					     pmadapter->callbacks.
+					     moal_spin_lock,
+					     pmadapter->callbacks.
+					     moal_spin_unlock) >
+			    RX_HIGH_THRESHOLD)
+				wlan_drop_tx_pkts(priv);
+			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
+					MNULL);
+			goto done;
+		} else if (MLAN_STATUS_FAILURE ==
+			   wlan_check_unicast_packet(priv,
+						     prx_pkt->eth803_hdr.
+						     dest_addr)) {
+			PRINTM(MDATA, "Drop Pkts: Rx dest " MACSTR "\n",
+			       MAC2STR(prx_pkt->eth803_hdr.dest_addr));
+			pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+			pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+			goto done;
+		}
+	}
+
+upload:
+	/* Chop off RxPD */
+	pmbuf->data_len -= prx_pd->rx_pkt_offset;
+	pmbuf->data_offset += prx_pd->rx_pkt_offset;
+	pmbuf->pparent = MNULL;
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->out_ts_sec,
+						  &pmbuf->out_ts_usec);
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
+	       pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
+	       prx_pd->priority);
+
+	ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
+						    pmbuf);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR,
+		       "uAP Rx Error: moal_recv_packet returned error\n");
+		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
+	}
+
+	if (ret != MLAN_STATUS_PENDING)
+		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
+#ifdef USB
+	else if (IS_USB(pmadapter->card_type))
+		pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
+							MNULL,
+							pmadapter->rx_data_ep,
+							ret);
+#endif
+done:
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlan/mlan_usb.c b/wlan_sd8987/mlan/mlan_usb.c
new file mode 100755
index 0000000..98232f0
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_usb.c
@@ -0,0 +1,1302 @@
+/** @file mlan_usb.c
+ *
+ *  @brief This file contains USB specific code
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    04/21/2009: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_init.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+#ifdef USB8801
+static const struct _mlan_card_info mlan_card_info_usb8801 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
+	.v14_fw_api = 1,
+	.v16_fw_api = 0,
+	.supp_ps_handshake = 1,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
+};
+#endif
+#ifdef USB8897
+static const struct _mlan_card_info mlan_card_info_usb8897 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 0,
+	.supp_ps_handshake = 1,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB8997
+static const struct _mlan_card_info mlan_card_info_usb8997 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.supp_ps_handshake = 1,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB8978
+static const struct _mlan_card_info mlan_card_info_usb8978 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.supp_ps_handshake = 1,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB9098
+static const struct _mlan_card_info mlan_card_info_usb9098 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.supp_ps_handshake = 1,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+#ifdef USB9097
+static const struct _mlan_card_info mlan_card_info_usb9097 = {
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.supp_ps_handshake = 1,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+};
+#endif
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+#if defined(USB9098)
+/**
+ *  @This function checks the chip revision id
+ *
+ *  @param pmadapter  A pointer to mlan_adapter structure
+ *  @param rev_id         A pointer to chip revision id
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_usb_check_revision(mlan_adapter *pmadapter, t_u32 *rev_id)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	mlan_buffer mbuf;
+	t_u8 *tx_buff = MNULL;
+	t_u8 *recv_buff = MNULL;
+	t_u8 tx_size = 16;
+	FWSyncPkt syncpkt;
+
+	ENTER();
+	/* Allocate memory for transmit */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_TX_BUF_SIZE,
+			       MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&tx_buff);
+	if ((ret != MLAN_STATUS_SUCCESS) || !tx_buff) {
+		PRINTM(MERROR, "Could not allocate buffer for FW download\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Allocate memory for receive */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_RX_BUF_SIZE,
+			       MLAN_MEM_DEF | MLAN_MEM_DMA, &recv_buff);
+	if ((ret != MLAN_STATUS_SUCCESS) || !recv_buff) {
+		PRINTM(MERROR,
+		       "Could not allocate buffer for FW download response\n");
+		goto cleanup;
+	}
+	memset(pmadapter, &syncpkt, 0, sizeof(FWSyncPkt));
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = (t_u8 *)tx_buff;
+	mbuf.data_len = tx_size;
+	ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf,
+					pmadapter->tx_cmd_ep,
+					MLAN_USB_BULK_MSG_TIMEOUT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "check revision: write_data failed, ret %d\n",
+		       ret);
+		goto cleanup;
+	}
+	memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = (t_u8 *)recv_buff;
+	mbuf.data_len = 2048;
+	ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf,
+				       pmadapter->rx_cmd_ep,
+				       MLAN_USB_BULK_MSG_TIMEOUT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "check revision: read_data failed, ret %d\n",
+		       ret);
+		goto cleanup;
+	}
+	memcpy_ext(pmadapter, &syncpkt, recv_buff, sizeof(syncpkt),
+		   sizeof(syncpkt));
+	syncpkt.chip_rev = wlan_le32_to_cpu(syncpkt.chip_rev);
+	*rev_id = syncpkt.chip_rev & 0x000000ff;
+	PRINTM(MERROR, "chip_revision_id = %d\n", syncpkt.chip_rev);
+cleanup:
+	if (recv_buff)
+		pcb->moal_mfree(pmadapter->pmoal_handle, recv_buff);
+	if (tx_buff)
+		pcb->moal_mfree(pmadapter->pmoal_handle, tx_buff);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief  This function downloads FW blocks to device
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_usb_prog_fw_w_helper(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	t_u8 *firmware = pmfw->pfw_buf, *RecvBuff;
+	t_u32 retries = MAX_FW_RETRY, DataLength;
+	t_u32 FWSeqNum = 0, TotalBytes = 0, DnldCmd = 0;
+	t_u8 *TxBuff = MNULL;
+	FWData *fwdata = MNULL;
+	FWSyncHeader SyncFWHeader;
+	t_u8 check_winner = 1;
+	t_u8 check_fw_status = MFALSE;
+	t_u8 mic_retry = MAX_FW_RETRY;
+#if defined(USB9098)
+	t_u32 revision_id = 0;
+#endif
+
+	ENTER();
+
+	if (!firmware && !pcb->moal_get_fw_data) {
+		PRINTM(MMSG, "No firmware image found! Terminating download\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto fw_exit;
+	}
+
+	/* Allocate memory for transmit */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_TX_BUF_SIZE,
+			       MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&TxBuff);
+	if ((ret != MLAN_STATUS_SUCCESS) || !TxBuff) {
+		PRINTM(MERROR, "Could not allocate buffer for FW download\n");
+		goto fw_exit;
+	}
+	fwdata = (FWData *)TxBuff;
+
+	/* Allocate memory for receive */
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_RX_BUF_SIZE,
+			       MLAN_MEM_DEF | MLAN_MEM_DMA, &RecvBuff);
+	if ((ret != MLAN_STATUS_SUCCESS) || !RecvBuff) {
+		PRINTM(MERROR,
+		       "Could not allocate buffer for FW download response\n");
+		goto cleanup;
+	}
+
+	if (!IS_USB_NEW_INIT(pmadapter->feature_control))
+		check_winner = 0;
+#if defined(USB9098)
+	if (IS_USB9098(pmadapter->card_type)) {
+		ret = wlan_usb_check_revision(pmadapter, &revision_id);
+		if (ret != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR, "Failed to get USB chip revision ID\n");
+			goto cleanup;
+		}
+		/* Skyhawk A0, need to check both CRC and MIC error */
+		if (revision_id >= CHIP_9098_REV_A0)
+			check_fw_status = MTRUE;
+	}
+#endif
+#if defined(USB9097)
+	if (IS_USB9097(pmadapter->card_type))
+		check_fw_status = MTRUE;
+#endif
+	do {
+		/* Send pseudo data to check winner status first */
+		if (check_winner) {
+			memset(pmadapter, &fwdata->fw_header, 0,
+			       sizeof(FWHeader));
+			DataLength = 0;
+		} else {
+			/* Copy the header of the firmware data to get the
+			 * length */
+			if (firmware)
+				memcpy_ext(pmadapter, &fwdata->fw_header,
+					   &firmware[TotalBytes],
+					   sizeof(FWHeader),
+					   sizeof(fwdata->fw_header));
+			else
+				pcb->moal_get_fw_data(pmadapter->pmoal_handle,
+						      TotalBytes,
+						      sizeof(FWHeader),
+						      (t_u8 *)&fwdata->
+						      fw_header);
+
+			DataLength =
+				wlan_le32_to_cpu(fwdata->fw_header.data_length);
+			DnldCmd = wlan_le32_to_cpu(fwdata->fw_header.dnld_cmd);
+			TotalBytes += sizeof(FWHeader);
+
+			/** CMD 7 don't have data_length field */
+			if (DnldCmd == FW_CMD_4 || DnldCmd == FW_CMD_6 ||
+			    DnldCmd == FW_CMD_7 || DnldCmd == FW_CMD_10)
+				DataLength = 0;
+
+			if (DataLength >
+			    (FW_DNLD_TX_BUF_SIZE - sizeof(FWHeader))) {
+				PRINTM(MERROR,
+				       "Invalid Data Legth read from FW\n");
+				ret = MLAN_STATUS_FAILURE;
+				break;
+			}
+
+			/* Copy the firmware data */
+			if (firmware)
+				memcpy_ext(pmadapter, fwdata->data,
+					   &firmware[TotalBytes], DataLength,
+					   DataLength);
+			else
+				pcb->moal_get_fw_data(pmadapter->pmoal_handle,
+						      TotalBytes, DataLength,
+						      (t_u8 *)fwdata->data);
+
+			fwdata->seq_num = wlan_cpu_to_le32(FWSeqNum);
+			TotalBytes += DataLength;
+		}
+		/* If the send/receive fails or CRC occurs then retry */
+		while (retries) {
+			mlan_buffer mbuf;
+			int length = FW_DATA_XMIT_SIZE;
+			retries--;
+
+			memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+			mbuf.pbuf = (t_u8 *)fwdata;
+			mbuf.data_len = length;
+			/* Send the firmware block */
+			ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle,
+							&mbuf,
+							pmadapter->tx_cmd_ep,
+							MLAN_USB_BULK_MSG_TIMEOUT);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "fw_dnld: write_data failed, ret %d\n",
+				       ret);
+				continue;
+			}
+
+			memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer));
+			mbuf.pbuf = RecvBuff;
+			mbuf.data_len = FW_DNLD_RX_BUF_SIZE;
+
+			/* Receive the firmware block response */
+			ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle,
+						       &mbuf,
+						       pmadapter->rx_cmd_ep,
+						       MLAN_USB_BULK_MSG_TIMEOUT);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR,
+				       "fw_dnld: read_data failed, ret %d\n",
+				       ret);
+				continue;
+			}
+			memcpy_ext(pmadapter, &SyncFWHeader, RecvBuff,
+				   sizeof(FWSyncHeader), sizeof(SyncFWHeader));
+			endian_convert_syncfwheader(&SyncFWHeader);
+			/* Check the first firmware block response for highest
+			 * bit set */
+			if (check_winner) {
+				if (SyncFWHeader.cmd & 0x80000000) {
+					PRINTM(MMSG,
+					       "USB is not the winner 0x%x, returning success\n",
+					       SyncFWHeader.cmd);
+					ret = MLAN_STATUS_SUCCESS;
+					goto cleanup;
+				}
+				PRINTM(MINFO,
+				       "USB is the winner, start to download FW\n");
+				check_winner = 0;
+				break;
+			}
+
+			/* Check the firmware block response for CRC errors */
+			if (SyncFWHeader.cmd) {
+				/* Check firmware block response for CRC and MIC
+				 * errors */
+				if (check_fw_status) {
+					if (SyncFWHeader.status & MBIT(0)) {
+						PRINTM(MERROR,
+						       "FW received Blk with CRC error 0x%x offset=%d\n",
+						       SyncFWHeader.status,
+						       SyncFWHeader.offset);
+						ret = MLAN_STATUS_FAILURE;
+						continue;
+					}
+					if (SyncFWHeader.status &
+					    (MBIT(6) | MBIT(7))) {
+						PRINTM(MERROR,
+						       "FW received Blk with MIC error 0x%x offset\n",
+						       SyncFWHeader.status,
+						       SyncFWHeader.offset);
+						mic_retry--;
+						FWSeqNum = 0;
+						TotalBytes = 0;
+						ret = MLAN_STATUS_FAILURE;
+						continue;
+					}
+				} else {
+					PRINTM(MERROR,
+					       "FW received Blk with CRC error 0x%x\n",
+					       SyncFWHeader.cmd);
+					ret = MLAN_STATUS_FAILURE;
+					continue;
+				}
+			}
+
+			retries = MAX_FW_RETRY;
+			break;
+		}
+
+		FWSeqNum++;
+		PRINTM(MINFO, ".\n");
+
+	} while ((DnldCmd != FW_HAS_LAST_BLOCK) && retries && mic_retry);
+
+cleanup:
+	PRINTM(MMSG, "fw_dnld: %d bytes downloaded\n", TotalBytes);
+
+	if (RecvBuff)
+		pcb->moal_mfree(pmadapter->pmoal_handle, RecvBuff);
+	if (TxBuff)
+		pcb->moal_mfree(pmadapter->pmoal_handle, TxBuff);
+	if (retries && mic_retry) {
+		ret = MLAN_STATUS_SUCCESS;
+	}
+
+fw_exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get number of packets when deaggregated
+ *
+ *  @param pmadapter		A pointer to mlan_adapter
+ *  @param pdata			A pointer to packet data
+ *  @param aggr_pkt_len		Aggregate packet length
+ *
+ *  @return			Number of packets
+ */
+static int
+wlan_usb_deaggr_rx_num_pkts(pmlan_adapter pmadapter, t_u8 *pdata,
+			    int aggr_pkt_len)
+{
+	int pkt_count = 0, pkt_len;
+	RxPD *prx_pd;
+
+	ENTER();
+	while (aggr_pkt_len >= (int)sizeof(RxPD)) {
+		prx_pd = (RxPD *)pdata;
+		pkt_len = wlan_le16_to_cpu(prx_pd->rx_pkt_length) +
+			wlan_le16_to_cpu(prx_pd->rx_pkt_offset);
+		if (pkt_len == 0)	/* blank RxPD can be at the end */
+			break;
+
+		++pkt_count;
+		if (aggr_pkt_len == pkt_len)	/* last packet has no padding */
+			break;
+
+		/* skip padding and goto next */
+		if (pkt_len %
+		    pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align)
+			pkt_len +=
+				(pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+				 aggr_align -
+				 (pkt_len %
+				  pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+				  aggr_align));
+		aggr_pkt_len -= pkt_len;
+		pdata += pkt_len;
+	}
+	LEAVE();
+	return pkt_count;
+}
+
+static inline t_u32
+usb_tx_aggr_pad_len(t_u32 len, usb_tx_aggr_params *pusb_tx_aggr)
+{
+	return (len % pusb_tx_aggr->aggr_ctrl.aggr_align) ?
+		(len + (pusb_tx_aggr->aggr_ctrl.aggr_align -
+			(len % pusb_tx_aggr->aggr_ctrl.aggr_align))) : len;
+}
+
+/**
+ *  @brief Copy pmbuf to aggregation buffer
+ *
+ *  @param pmadapter	Pointer to mlan_adapter structure
+ *  @param pmbuf_aggr	Pointer to aggregation buffer
+ *  @param pmbuf		Pointer to buffer to copy
+ *  @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ *
+ *  @return   N/A
+ */
+static inline t_void
+wlan_usb_tx_copy_buf_to_aggr(pmlan_adapter pmadapter, pmlan_buffer pmbuf_aggr,
+			     pmlan_buffer pmbuf,
+			     usb_tx_aggr_params *pusb_tx_aggr)
+{
+	ENTER();
+	pmbuf_aggr->data_len =
+		usb_tx_aggr_pad_len(pmbuf_aggr->data_len, pusb_tx_aggr);
+	memcpy_ext(pmadapter,
+		   pmbuf_aggr->pbuf + pmbuf_aggr->data_offset +
+		   pmbuf_aggr->data_len,
+		   pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len,
+		   pmbuf->data_len);
+	pmbuf_aggr->data_len += pmbuf->data_len;
+	LEAVE();
+}
+
+#define MLAN_TYPE_AGGR_DATA_V2 11
+/**
+ *  @brief Copy pmbuf to aggregation buffer
+ *
+ *  @param pmadapter	Pointer to mlan_adapter structure
+ *  @param pmbuf_aggr	Pointer to aggregation buffer
+ *  @param pmbuf		Pointer to buffer to copy
+ *	@param last 		last packet flag
+ *  @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ *
+ *  @return   N/A
+ */
+static inline t_void
+wlan_usb_tx_copy_buf_to_aggr_v2(pmlan_adapter pmadapter,
+				pmlan_buffer pmbuf_aggr, pmlan_buffer pmbuf,
+				t_u8 last, usb_tx_aggr_params *pusb_tx_aggr)
+{
+	t_u8 *payload;
+	t_u16 offset;
+
+	ENTER();
+	pmbuf_aggr->data_len =
+		usb_tx_aggr_pad_len(pmbuf_aggr->data_len, pusb_tx_aggr);
+	memcpy_ext(pmadapter,
+		   pmbuf_aggr->pbuf + pmbuf_aggr->data_offset +
+		   pmbuf_aggr->data_len,
+		   pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len,
+		   pmbuf->data_len);
+	payload = pmbuf_aggr->pbuf + pmbuf_aggr->data_offset +
+		pmbuf_aggr->data_len;
+	if (last) {
+		offset = pmbuf->data_len;
+		*(t_u16 *)&payload[2] =
+			wlan_cpu_to_le16(MLAN_TYPE_AGGR_DATA_V2 | 0x80);
+	} else {
+		offset = usb_tx_aggr_pad_len(pmbuf->data_len, pusb_tx_aggr);
+		*(t_u16 *)&payload[2] =
+			wlan_cpu_to_le16(MLAN_TYPE_AGGR_DATA_V2);
+	}
+	*(t_u16 *)&payload[0] = wlan_cpu_to_le16(offset);
+	pmbuf_aggr->data_len += pmbuf->data_len;
+	PRINTM(MIF_D, "offset=%d len=%d\n", offset, pmbuf->data_len);
+	LEAVE();
+}
+
+/**
+ *  @brief Allocate Aggregation buffer and copy pending buffers to it.
+ *
+ *  @param pmadapter	Pointer to mlan_adapter structure
+ *  @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ *
+ *  @return			Aggregation buffer
+ */
+static inline pmlan_buffer
+wlan_usb_copy_buf_to_aggr(pmlan_adapter pmadapter,
+			  usb_tx_aggr_params *pusb_tx_aggr)
+{
+	pmlan_buffer pmbuf_aggr = MNULL;
+	t_u8 i, use_count;
+	pmlan_buffer pmbuf_curr, pmbuf_next;
+	pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter, pusb_tx_aggr->aggr_len,
+					    0, MOAL_MALLOC_BUFFER);
+	if (pmbuf_aggr) {
+		pmbuf_curr = pusb_tx_aggr->pmbuf_aggr;
+		pmbuf_aggr->bss_index = pmbuf_curr->bss_index;
+		pmbuf_aggr->buf_type = pmbuf_curr->buf_type;
+		pmbuf_aggr->priority = pmbuf_curr->priority;
+		pmbuf_aggr->data_len = 0;
+		PRINTM(MIF_D, "use_count=%d,aggr_len=%d\n",
+		       pmbuf_curr->use_count, pusb_tx_aggr->aggr_len);
+		use_count = pmbuf_curr->use_count;
+		for (i = 0; i <= use_count; i++) {
+			pmbuf_next = pmbuf_curr->pnext;
+			if (pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+			    MLAN_USB_AGGR_MODE_LEN_V2) {
+				if (i == use_count)
+					wlan_usb_tx_copy_buf_to_aggr_v2
+						(pmadapter, pmbuf_aggr,
+						 pmbuf_curr, MTRUE,
+						 pusb_tx_aggr);
+				else
+					wlan_usb_tx_copy_buf_to_aggr_v2
+						(pmadapter, pmbuf_aggr,
+						 pmbuf_curr, MFALSE,
+						 pusb_tx_aggr);
+			} else
+				wlan_usb_tx_copy_buf_to_aggr(pmadapter,
+							     pmbuf_aggr,
+							     pmbuf_curr,
+							     pusb_tx_aggr);
+			pmbuf_curr = pmbuf_next;
+		}
+		DBG_HEXDUMP(MIF_D, "USB AggrTx",
+			    pmbuf_aggr->pbuf + pmbuf_aggr->data_offset,
+			    pmbuf_aggr->data_len);
+	}
+	return pmbuf_aggr;
+}
+
+/**
+ *  @brief Link buffer into aggregate head buffer
+ *
+ *  @param pmbuf_aggr	Pointer to aggregation buffer
+ *  @param pmbuf		Pointer to buffer to add to the buffer list
+ *  @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ */
+static inline t_void
+wlan_usb_tx_link_buf_to_aggr(pmlan_buffer pmbuf_aggr, pmlan_buffer pmbuf,
+			     usb_tx_aggr_params *pusb_tx_aggr)
+{
+	/* link new buf at end of list */
+	pmbuf->pnext = pmbuf_aggr;
+	pmbuf->pprev = pmbuf_aggr->pprev;
+	pmbuf->pparent = pmbuf_aggr;
+	pmbuf_aggr->pprev->pnext = pmbuf;
+	pmbuf_aggr->pprev = pmbuf;
+	pmbuf_aggr->use_count++;
+	pusb_tx_aggr->aggr_len =
+		usb_tx_aggr_pad_len(pusb_tx_aggr->aggr_len, pusb_tx_aggr);
+	pusb_tx_aggr->aggr_len += pmbuf->data_len;
+}
+
+/**
+ *  @brief Send aggregated buffer
+ *
+ *  @param pmadapter	Pointer to mlan_adapter structure
+ *  @param pusb_tx_aggr Pointer to usb_tx_aggr_params
+ */
+static inline t_void
+wlan_usb_tx_send_aggr(pmlan_adapter pmadapter, usb_tx_aggr_params *pusb_tx_aggr)
+{
+	mlan_status ret;
+	pmlan_buffer pmbuf_aggr = pusb_tx_aggr->pmbuf_aggr;
+	ENTER();
+	if (!pusb_tx_aggr->pmbuf_aggr) {
+		LEAVE();
+		return;
+	}
+
+	if (pusb_tx_aggr->pmbuf_aggr->use_count) {
+		pmbuf_aggr = wlan_usb_copy_buf_to_aggr(pmadapter, pusb_tx_aggr);
+		/* allocate new buffer for aggregation if not exist */
+		if (!pmbuf_aggr) {
+			PRINTM(MERROR,
+			       "Error allocating [usb_tx] aggr mlan_buffer.\n");
+			pmadapter->dbg.num_tx_host_to_card_failure +=
+				pusb_tx_aggr->pmbuf_aggr->use_count;
+			wlan_write_data_complete(pmadapter,
+						 pusb_tx_aggr->pmbuf_aggr,
+						 MLAN_STATUS_FAILURE);
+			pusb_tx_aggr->pmbuf_aggr = MNULL;
+			pusb_tx_aggr->aggr_len = 0;
+			LEAVE();
+			return;
+		} else {
+			wlan_write_data_complete(pmadapter,
+						 pusb_tx_aggr->pmbuf_aggr,
+						 MLAN_STATUS_SUCCESS);
+			pusb_tx_aggr->pmbuf_aggr = MNULL;
+			pusb_tx_aggr->aggr_len = 0;
+		}
+	} else if (pusb_tx_aggr->aggr_ctrl.aggr_mode ==
+		   MLAN_USB_AGGR_MODE_LEN_V2) {
+		t_u8 *payload = pmbuf_aggr->pbuf + pmbuf_aggr->data_offset;
+		*(t_u16 *)&payload[0] = wlan_cpu_to_le16(pmbuf_aggr->data_len);
+		*(t_u16 *)&payload[2] =
+			wlan_cpu_to_le16(MLAN_TYPE_AGGR_DATA_V2 | 0x80);
+		PRINTM(MIF_D, "USB Send single packet len=%d\n",
+		       pmbuf_aggr->data_len);
+		DBG_HEXDUMP(MIF_D, "USB Tx",
+			    pmbuf_aggr->pbuf + pmbuf_aggr->data_offset,
+			    pmbuf_aggr->data_len);
+	}
+
+	if (pmbuf_aggr && pmbuf_aggr->data_len) {
+		pmadapter->data_sent = MTRUE;
+		ret = pmadapter->callbacks.moal_write_data_async(pmadapter->
+								 pmoal_handle,
+								 pmbuf_aggr,
+								 pusb_tx_aggr->
+								 port);
+		switch (ret) {
+		case MLAN_STATUS_PRESOURCE:
+			PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+			break;
+		case MLAN_STATUS_RESOURCE:
+			/* Shouldn't reach here due to next condition. */
+			/* TODO: (maybe) How to requeue the aggregate? */
+			/* It may occur when the pending tx urbs reach the high
+			 * mark */
+			/* Thus, block further pkts for a bit */
+			PRINTM(MERROR,
+			       "Error: moal_write_data_async failed: 0x%X\n",
+			       ret);
+			pmadapter->dbg.num_tx_host_to_card_failure++;
+			pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
+			wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+			break;
+		case MLAN_STATUS_FAILURE:
+			pmadapter->data_sent = MFALSE;
+			PRINTM(MERROR,
+			       "Error: moal_write_data_async failed: 0x%X\n",
+			       ret);
+			pmadapter->dbg.num_tx_host_to_card_failure++;
+			pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
+			wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+			break;
+		case MLAN_STATUS_PENDING:
+			pmadapter->data_sent = MFALSE;
+			break;
+		case MLAN_STATUS_SUCCESS:
+			wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
+			break;
+		default:
+			break;
+		}
+
+		/* aggr_buf now sent to bus, prevent others from using it */
+		pusb_tx_aggr->pmbuf_aggr = MNULL;
+		pusb_tx_aggr->aggr_len = 0;
+	}
+	LEAVE();
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *	@brief This function get pcie device from card type
+ *
+ *	@param pmadapter  A pointer to mlan_adapter structure
+ *	@return 		  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_get_usb_device(pmlan_adapter pmadapter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 card_type = pmadapter->card_type;
+
+	ENTER();
+
+	ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					       sizeof(mlan_usb_card),
+					       MLAN_MEM_DEF,
+					       (t_u8 **)&pmadapter->pcard_usb);
+	if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pcard_usb) {
+		PRINTM(MERROR, "Failed to allocate pcard_usb\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	switch (card_type) {
+#ifdef USB8801
+	case CARD_TYPE_USB8801:
+		pmadapter->pcard_info = &mlan_card_info_usb8801;
+		break;
+#endif
+#ifdef USB8897
+	case CARD_TYPE_USB8897:
+		pmadapter->pcard_info = &mlan_card_info_usb8897;
+		break;
+#endif
+#ifdef USB8997
+	case CARD_TYPE_USB8997:
+		pmadapter->pcard_info = &mlan_card_info_usb8997;
+		break;
+#endif
+#ifdef USB8978
+	case CARD_TYPE_USB8978:
+		pmadapter->pcard_info = &mlan_card_info_usb8978;
+		break;
+#endif
+#ifdef USB9098
+	case CARD_TYPE_USB9098:
+		pmadapter->pcard_info = &mlan_card_info_usb9098;
+		break;
+#endif
+#ifdef USB9097
+	case CARD_TYPE_USB9097:
+		pmadapter->pcard_info = &mlan_card_info_usb9097;
+		break;
+#endif
+	default:
+		PRINTM(MERROR, "can't get right USB card type \n");
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function downloads firmware to card
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmfw			A pointer to firmware image
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_usb_dnld_fw(pmlan_adapter pmadapter, pmlan_fw_image pmfw)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_usb_prog_fw_w_helper(pmadapter, pmfw);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function deaggregates USB RX Data Packet from device
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmbuf		A pointer to the received buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_usb_deaggr_rx_pkt(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+	const t_u8 zero_rx_pd[sizeof(RxPD)] = { 0 };
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 curr_pkt_len;
+	RxPD *prx_pd;
+	t_u8 *pdata;
+	t_s32 aggr_len;
+	pmlan_buffer pdeaggr_buf;
+
+	ENTER();
+
+	pdata = pmbuf->pbuf + pmbuf->data_offset;
+	prx_pd = (RxPD *)pdata;
+	curr_pkt_len = wlan_le16_to_cpu(prx_pd->rx_pkt_length) +
+		wlan_le16_to_cpu(prx_pd->rx_pkt_offset);
+	/* if non-aggregate, just send through, don’t process here */
+	aggr_len = pmbuf->data_len;
+	if ((aggr_len == (t_s32)curr_pkt_len) ||
+	    (wlan_usb_deaggr_rx_num_pkts(pmadapter, pdata, aggr_len) == 1) ||
+	    (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable != MTRUE)) {
+		ret = wlan_handle_rx_packet(pmadapter, pmbuf);
+		LEAVE();
+		return ret;
+	}
+
+	while (aggr_len >= (t_s32)sizeof(RxPD)) {
+		/* check for (all-zeroes) termination RxPD */
+		if (!memcmp(pmadapter, pdata, zero_rx_pd, sizeof(RxPD))) {
+			break;
+		}
+
+		/* make new buffer and copy packet to it (including RxPD).
+		 * Also, reserve headroom so that there must have space
+		 * to change RxPD to TxPD for bridge packet in uAP mode */
+		pdeaggr_buf = wlan_alloc_mlan_buffer(pmadapter, curr_pkt_len,
+						     MLAN_RX_HEADER_LEN,
+						     MOAL_ALLOC_MLAN_BUFFER);
+		if (pdeaggr_buf == MNULL) {
+			PRINTM(MERROR,
+			       "Error allocating [usb_rx] deaggr mlan_buffer\n");
+			ret = MLAN_STATUS_FAILURE;
+			break;
+		}
+		pdeaggr_buf->bss_index = pmbuf->bss_index;
+		pdeaggr_buf->buf_type = pmbuf->buf_type;
+		pdeaggr_buf->data_len = curr_pkt_len;
+		pdeaggr_buf->in_ts_sec = pmbuf->in_ts_sec;
+		pdeaggr_buf->in_ts_usec = pmbuf->in_ts_usec;
+		pdeaggr_buf->priority = pmbuf->priority;
+		memcpy_ext(pmadapter,
+			   pdeaggr_buf->pbuf + pdeaggr_buf->data_offset, pdata,
+			   curr_pkt_len, pdeaggr_buf->data_len);
+
+		/* send new packet to processing */
+		ret = wlan_handle_rx_packet(pmadapter, pdeaggr_buf);
+		if (ret == MLAN_STATUS_FAILURE) {
+			break;
+		}
+		/* last block has no padding bytes */
+		if (aggr_len == (t_s32)curr_pkt_len) {
+			break;
+		}
+
+		/* round up to next block boundary */
+		if (curr_pkt_len %
+		    pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.aggr_align)
+			curr_pkt_len +=
+				(pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+				 aggr_align -
+				 (curr_pkt_len %
+				  pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.
+				  aggr_align));
+		/* point to next packet */
+		aggr_len -= curr_pkt_len;
+		pdata += curr_pkt_len;
+		prx_pd = (RxPD *)pdata;
+		curr_pkt_len = wlan_le16_to_cpu(prx_pd->rx_pkt_length) +
+			wlan_le16_to_cpu(prx_pd->rx_pkt_offset);
+	}
+
+	/* free original pmbuf (since not sent for processing) */
+	pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+						pmadapter->rx_data_ep, ret);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function restore tx_pause flag
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pusb_tx_aggr A pointer to usb_tx_aggr_params
+ *
+ *  @return             MTRUE/MFALSE
+ */
+static t_u8
+wlan_is_port_tx_paused(pmlan_adapter pmadapter,
+		       usb_tx_aggr_params *pusb_tx_aggr)
+{
+	mlan_private *pmpriv = MNULL;
+	t_u8 i;
+	t_u8 ret = MFALSE;
+	for (i = 0; i < pmadapter->priv_num; i++) {
+		pmpriv = pmadapter->priv[i];
+		if (pmpriv && pmpriv->tx_pause &&
+		    (pmpriv->port == pusb_tx_aggr->port)) {
+			ret = MTRUE;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function handles the timeout of usb tx aggregation.
+ *  It will send the aggregate buffer being held.
+ *
+ *  @param function_context   A pointer to function_context
+ *  @return 	   N/A
+ */
+t_void
+wlan_usb_tx_aggr_timeout_func(t_void *function_context)
+{
+	usb_tx_aggr_params *pusb_tx_aggr =
+		(usb_tx_aggr_params *)function_context;
+	pmlan_adapter pmadapter = (mlan_adapter *)pusb_tx_aggr->phandle;
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+
+	ENTER();
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pusb_tx_aggr->paggr_lock);
+	pusb_tx_aggr->aggr_hold_timer_is_set = MFALSE;
+	if (pusb_tx_aggr->pmbuf_aggr && !pmadapter->data_sent
+	    && !wlan_is_port_tx_paused(pmadapter, pusb_tx_aggr)
+		)
+		wlan_usb_tx_send_aggr(pmadapter, pusb_tx_aggr);
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pusb_tx_aggr->paggr_lock);
+	LEAVE();
+}
+
+/**
+ *  @brief  This function aggregates USB TX Data Packet to send to device
+ *
+ *  @param pmadapter	A pointer to mlan_adapter
+ *  @param pmbuf		A pointer to the transmit buffer
+ *  @param tx_param 	A pointer to mlan_tx_param
+ *  @param pusb_tx_aggr A pointer to usb_tx_aggr_params
+ *
+ *  @return		MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+/*
+ *  Non Scatter-Gather code creates a new large buffer where each incoming
+ *     buffer's data contents are copied to (aligned to USB boundaries).
+ *  The individual buffers are ALSO linked to the large buffer,
+ *    in order to handle complete AFTER the aggregate is sent.
+ *  pmbuf_aggr->data_len is used to keep track of bytes aggregated so far.
+ */
+mlan_status
+wlan_usb_host_to_card_aggr(pmlan_adapter pmadapter,
+			   pmlan_buffer pmbuf,
+			   mlan_tx_param *tx_param,
+			   usb_tx_aggr_params *pusb_tx_aggr)
+{
+	pmlan_callbacks pcb = &pmadapter->callbacks;
+	pmlan_buffer pmbuf_aggr;
+	mlan_status ret = MLAN_STATUS_PENDING;
+	t_u32 next_pkt_len = (tx_param) ? tx_param->next_pkt_len : 0;
+	t_u32 aggr_len_counter = 0;
+	/* indicators */
+	t_u8 f_precopy_cur_buf = 0;
+	t_u8 f_send_aggr_buf = 0;
+	t_u8 f_postcopy_cur_buf = 0;
+	t_u32 max_aggr_size = 0, max_aggr_num = 0;
+
+	ENTER();
+
+	pcb->moal_spin_lock(pmadapter->pmoal_handle, pusb_tx_aggr->paggr_lock);
+
+	/* stop timer while we process */
+	if (pusb_tx_aggr->aggr_hold_timer_is_set) {
+		pcb->moal_stop_timer(pmadapter->pmoal_handle,
+				     pusb_tx_aggr->paggr_hold_timer);
+		pusb_tx_aggr->aggr_hold_timer_is_set = MFALSE;
+	}
+
+	pmbuf_aggr = pusb_tx_aggr->pmbuf_aggr;
+
+	if (pusb_tx_aggr->aggr_ctrl.aggr_tmo == MLAN_USB_TX_AGGR_TIMEOUT_DYN) {
+		if (!pmbuf_aggr) {
+			/* Start aggr from min timeout value in micro sec */
+			pusb_tx_aggr->hold_timeout_msec =
+				MLAN_USB_TX_MIN_AGGR_TIMEOUT;
+		} else {
+			/* Increase timeout in milisecond if pkts are
+			 * consecutive */
+			if (pusb_tx_aggr->hold_timeout_msec <
+			    MLAN_USB_TX_MAX_AGGR_TIMEOUT)
+				pusb_tx_aggr->hold_timeout_msec++;
+		}
+	} else {
+		if (pusb_tx_aggr->aggr_ctrl.aggr_tmo)
+			pusb_tx_aggr->hold_timeout_msec =
+				pusb_tx_aggr->aggr_ctrl.aggr_tmo / 1000;
+	}
+
+	max_aggr_size = max_aggr_num = pusb_tx_aggr->aggr_ctrl.aggr_max;
+	if (pusb_tx_aggr->aggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
+		max_aggr_size *= MAX(MLAN_USB_MAX_PKT_SIZE,
+				     pusb_tx_aggr->aggr_ctrl.aggr_align);
+	}
+	if (pusb_tx_aggr->aggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_LEN)
+		max_aggr_num /= pusb_tx_aggr->aggr_ctrl.aggr_align;
+	else if (pusb_tx_aggr->aggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_LEN_V2)
+		max_aggr_num = MLAN_USB_TX_AGGR_MAX_NUM;
+	if (!pmbuf_aggr) {
+		/* use this buf to start linked list, that's it */
+		pmbuf->pnext = pmbuf->pprev = pmbuf;
+		pmbuf_aggr = pmbuf;
+		pusb_tx_aggr->pmbuf_aggr = pmbuf_aggr;
+		pusb_tx_aggr->aggr_len = pmbuf->data_len;
+		pmbuf->flags |= MLAN_BUF_FLAG_USB_TX_AGGR;
+
+	} else {
+		/* DECIDE what to do */
+		aggr_len_counter = usb_tx_aggr_pad_len(pusb_tx_aggr->aggr_len,
+						       pusb_tx_aggr);
+
+		if ((aggr_len_counter + pmbuf->data_len) < max_aggr_size) {
+			f_precopy_cur_buf = 1;	/* can fit current packet in aggr
+						 */
+			if (next_pkt_len) {
+				aggr_len_counter +=
+					usb_tx_aggr_pad_len(pmbuf->data_len,
+							    pusb_tx_aggr);
+				if ((aggr_len_counter + next_pkt_len) >=
+				    max_aggr_size)
+					f_send_aggr_buf = 1;	/* can't fit next
+								   packet, send now
+								 */
+			}
+		} else {
+			/* can't fit current packet */
+			if (pusb_tx_aggr->aggr_len)
+				f_send_aggr_buf = 1;	/* send aggr first */
+			f_postcopy_cur_buf = 1;	/* then copy into new aggr_buf
+						 */
+		}
+	}
+
+	/* For zero timeout and zero next packet length send pkt now */
+	if (!pusb_tx_aggr->aggr_ctrl.aggr_tmo && !next_pkt_len)
+		f_send_aggr_buf = 1;
+
+	/* PERFORM ACTIONS as decided */
+	if (f_precopy_cur_buf) {
+		PRINTM(MIF_D, "%s: Precopy current buffer.\n", __FUNCTION__);
+		wlan_usb_tx_link_buf_to_aggr(pmbuf_aggr, pmbuf, pusb_tx_aggr);
+	}
+	if (pmbuf_aggr->use_count + 1 >= max_aggr_num)
+		f_send_aggr_buf = 1;
+
+	if (pmbuf->flags & MLAN_BUF_FLAG_NULL_PKT
+	    || pmbuf->flags & MLAN_BUF_FLAG_TCP_ACK)
+		f_send_aggr_buf = 1;
+
+	if (f_send_aggr_buf) {
+		PRINTM(MIF_D, "%s: Send aggregate buffer.\n", __FUNCTION__);
+		wlan_usb_tx_send_aggr(pmadapter, pusb_tx_aggr);
+		pmbuf_aggr = pusb_tx_aggr->pmbuf_aggr;	/* update ptr */
+	}
+
+	if (f_postcopy_cur_buf) {
+		PRINTM(MIF_D, "%s: Postcopy current buffer.\n", __FUNCTION__);
+		if (!pmbuf_aggr) {	/* this is possible if just sent (above) */
+			/* use this buf to start linked list */
+			pmbuf->pnext = pmbuf->pprev = pmbuf;
+			pmbuf_aggr = pmbuf;
+			pusb_tx_aggr->pmbuf_aggr = pmbuf_aggr;
+			pusb_tx_aggr->aggr_len = pmbuf->data_len;
+			pmbuf->flags |= MLAN_BUF_FLAG_USB_TX_AGGR;
+		}
+	}
+	/* (re)start timer if there is something in the aggregation buffer */
+	if (pmbuf_aggr && pmbuf_aggr->data_len) {
+		if (pusb_tx_aggr->aggr_ctrl.aggr_tmo) {
+			pcb->moal_start_timer(pmadapter->pmoal_handle,
+					      pusb_tx_aggr->paggr_hold_timer,
+					      MFALSE,
+					      pusb_tx_aggr->hold_timeout_msec);
+			pusb_tx_aggr->aggr_hold_timer_is_set = MTRUE;
+		}
+	}
+
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pusb_tx_aggr->paggr_lock);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function wakes up the card.
+ *
+ *  @param pmadapter		A pointer to mlan_adapter structure
+ *  @param timeout          set timeout flag
+ *
+ *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_pm_usb_wakeup_card(pmlan_adapter pmadapter, t_u8 timeout)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 age_ts_usec;
+
+	ENTER();
+	PRINTM(MEVENT, "Wakeup device...\n");
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmadapter->pm_wakeup_in_secs,
+						  &age_ts_usec);
+
+	/* Simulation of HS_AWAKE event */
+	pmadapter->pm_wakeup_fw_try = MFALSE;
+	pmadapter->pm_wakeup_card_req = MFALSE;
+	/* TODO USB suspend/resume */
+	pmadapter->ps_state = PS_STATE_AWAKE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function downloads data from driver to card.
+ *
+ *  Both commands and data packets are transferred to the card
+ *  by this function. This function adds the PCIE specific header
+ *  to the front of the buffer before transferring. The header
+ *  contains the length of the packet and the type. The firmware
+ *  handles the packets based upon this set type.
+ *
+ *  @param pmpriv    A pointer to pmlan_private structure
+ *  @param type      data or command
+ *  @param pmbuf     A pointer to mlan_buffer (pmbuf->data_len should include
+ * PCIE header)
+ *  @param tx_param  A pointer to mlan_tx_param (can be MNULL if type is
+ * command)
+ *
+ *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+wlan_usb_host_to_card(pmlan_private pmpriv, t_u8 type,
+		      mlan_buffer *pmbuf, mlan_tx_param *tx_param)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	usb_tx_aggr_params *pusb_tx_aggr = MNULL;
+	pmlan_adapter pmadapter = pmpriv->adapter;
+
+	ENTER();
+
+	if (!pmbuf) {
+		PRINTM(MERROR, "Passed NULL pmbuf to %s\n", __FUNCTION__);
+		return MLAN_STATUS_FAILURE;
+	}
+	if (type == MLAN_TYPE_CMD
+#if (defined(USB9098) || defined(USB9097))
+	    || type == MLAN_TYPE_VDLL
+#endif
+		) {
+		pmadapter->cmd_sent = MTRUE;
+		ret = pmadapter->callbacks.moal_write_data_async(pmadapter->
+								 pmoal_handle,
+								 pmbuf,
+								 pmadapter->
+								 tx_cmd_ep);
+		if (ret == MLAN_STATUS_FAILURE)
+			pmadapter->cmd_sent = MFALSE;
+		LEAVE();
+		return ret;
+	}
+	pusb_tx_aggr = wlan_get_usb_tx_aggr_params(pmadapter, pmpriv->port);
+	if (pusb_tx_aggr) {
+		ret = wlan_usb_host_to_card_aggr(pmadapter, pmbuf, tx_param,
+						 pusb_tx_aggr);
+	} else {
+		pmadapter->data_sent = MTRUE;
+		ret = pmadapter->callbacks.moal_write_data_async(pmadapter->
+								 pmoal_handle,
+								 pmbuf,
+								 pmpriv->port);
+		switch (ret) {
+		case MLAN_STATUS_PRESOURCE:
+			PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+			break;
+		case MLAN_STATUS_RESOURCE:
+
+			break;
+		case MLAN_STATUS_FAILURE:
+			pmadapter->data_sent = MFALSE;
+			break;
+		case MLAN_STATUS_PENDING:
+			pmadapter->data_sent = MFALSE;
+			break;
+		case MLAN_STATUS_SUCCESS:
+			break;
+		default:
+			break;
+		}
+
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle event/cmd complete
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the mlan_buffer
+ *  @return          N/A
+ */
+static mlan_status
+wlan_usb_cmdevt_complete(pmlan_adapter pmadapter,
+			 mlan_buffer *pmbuf, mlan_status status)
+{
+	ENTER();
+
+	pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+						pmadapter->rx_cmd_ep, status);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle data complete
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the mlan_buffer
+ *  @return          N/A
+ */
+static mlan_status
+wlan_usb_data_complete(pmlan_adapter pmadapter,
+		       mlan_buffer *pmbuf, mlan_status status)
+{
+	ENTER();
+
+	pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
+						pmadapter->rx_data_ep, status);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handle receive packet
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param pmbuf     A pointer to the mlan_buffer
+ *  @return
+ */
+static mlan_status
+wlan_usb_handle_rx_packet(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
+{
+	ENTER();
+
+	if (pmadapter->pcard_usb->usb_rx_deaggr.aggr_ctrl.enable == MTRUE)
+		return wlan_usb_deaggr_rx_pkt(pmadapter, pmbuf);
+	else
+		return wlan_handle_rx_packet(pmadapter, pmbuf);
+
+	LEAVE();
+}
+
+mlan_adapter_operations mlan_usb_ops = {
+	.dnld_fw = wlan_usb_dnld_fw,
+	.host_to_card = wlan_usb_host_to_card,
+	.wakeup_card = wlan_pm_usb_wakeup_card,
+	.event_complete = wlan_usb_cmdevt_complete,
+	.data_complete = wlan_usb_data_complete,
+	.cmdrsp_complete = wlan_usb_cmdevt_complete,
+	.handle_rx_packet = wlan_usb_handle_rx_packet,
+
+	.intf_header_len = USB_INTF_HEADER_LEN,
+};
diff --git a/wlan_sd8987/mlan/mlan_util.h b/wlan_sd8987/mlan/mlan_util.h
new file mode 100755
index 0000000..24657a1
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_util.h
@@ -0,0 +1,522 @@
+/** @file mlan_util.h
+ *
+ *  @brief This file contains wrappers for linked-list,
+ *  spinlock and timer defines.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/28/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_UTIL_H_
+#define _MLAN_UTIL_H_
+
+/** Circular doubly linked list */
+typedef struct _mlan_linked_list {
+	/** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+	/** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+} mlan_linked_list, *pmlan_linked_list;
+
+/** List head */
+typedef struct _mlan_list_head {
+	/** Pointer to previous node */
+	struct _mlan_linked_list *pprev;
+	/** Pointer to next node */
+	struct _mlan_linked_list *pnext;
+	/** Pointer to lock */
+	t_void *plock;
+} mlan_list_head, *pmlan_list_head;
+
+/** MLAN MNULL pointer */
+#define MNULL	((void *)0)
+
+/**
+ *  @brief This function initializes a list without locking
+ *
+ *  @param phead		List head
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list(pmlan_linked_list phead)
+{
+	/* Both next and prev point to self */
+	phead->pprev = phead->pnext = (pmlan_linked_list)phead;
+}
+
+/**
+ *  @brief This function initializes a list
+ *
+ *  @param phead		List head
+ *  @param lock_required	A flag for spinlock requirement
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_init_list_head(t_void *pmoal_handle, pmlan_list_head phead,
+		    t_u8 lock_required,
+		    mlan_status (*moal_init_lock) (t_void *handle,
+						   t_void **pplock))
+{
+	/* Both next and prev point to self */
+	util_init_list((pmlan_linked_list)phead);
+	if (lock_required)
+		moal_init_lock(pmoal_handle, &phead->plock);
+	else
+		phead->plock = MNULL;
+}
+
+/**
+ *  @brief This function frees a list
+ *
+ *  @param phead		List head
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_free_list_head(t_void *pmoal_handle, pmlan_list_head phead,
+		    mlan_status (*moal_free_lock) (t_void *handle,
+						   t_void *plock))
+{
+	phead->pprev = phead->pnext = MNULL;
+	if (phead->plock)
+		moal_free_lock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function peeks into a list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_peek_list(t_void *pmoal_handle, pmlan_list_head phead,
+	       mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+	       mlan_status (*moal_spin_unlock) (t_void *handle, t_void *plock))
+{
+	pmlan_linked_list pnode = MNULL;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	if (phead->pnext != (pmlan_linked_list)phead)
+		pnode = phead->pnext;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/**
+ *  @brief This function queues a node at the list tail
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to queue
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_tail(t_void *pmoal_handle, pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_last;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_last = phead->pprev;
+	pnode->pprev = pold_last;
+	pnode->pnext = (pmlan_linked_list)phead;
+
+	phead->pprev = pold_last->pnext = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function adds a node at the list head
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to add
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_enqueue_list_head(t_void *pmoal_handle, pmlan_list_head phead,
+		       pmlan_linked_list pnode,
+		       mlan_status (*moal_spin_lock) (t_void *handle,
+						      t_void *plock),
+		       mlan_status (*moal_spin_unlock) (t_void *handle,
+							t_void *plock))
+{
+	pmlan_linked_list pold_first;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pold_first = phead->pnext;
+	pnode->pprev = (pmlan_linked_list)phead;
+	pnode->pnext = pold_first;
+
+	phead->pnext = pold_first->pprev = pnode;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function removes a node from the list
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to remove
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_unlink_list(t_void *pmoal_handle, pmlan_list_head phead,
+		 pmlan_linked_list pnode,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	pmlan_linked_list pmy_prev;
+	pmlan_linked_list pmy_next;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pmy_prev = pnode->pprev;
+	pmy_next = pnode->pnext;
+	pmy_next->pprev = pmy_prev;
+	pmy_prev->pnext = pmy_next;
+
+	pnode->pnext = pnode->pprev = MNULL;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+}
+
+/**
+ *  @brief This function dequeues a node from the list
+ *
+ *  @param phead		List head
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list
+util_dequeue_list(t_void *pmoal_handle, pmlan_list_head phead,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	pmlan_linked_list pnode;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, phead->plock);
+	pnode = phead->pnext;
+	if (pnode && (pnode != (pmlan_linked_list)phead))
+		util_unlink_list(pmoal_handle, phead, pnode, MNULL, MNULL);
+	else
+		pnode = MNULL;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, phead->plock);
+	return pnode;
+}
+
+/** Access controlled scalar variable */
+typedef struct _mlan_scalar {
+	/** Value */
+	t_s32 value;
+	/** Pointer to lock */
+	t_void *plock;
+	/** Control flags */
+	t_u32 flags;
+} mlan_scalar, *pmlan_scalar;
+
+/** Flag to scalar lock acquired */
+#define MLAN_SCALAR_FLAG_UNIQUE_LOCK MBIT(16)
+
+/** scalar conditional value list */
+typedef enum _MLAN_SCALAR_CONDITIONAL {
+	MLAN_SCALAR_COND_EQUAL,
+	MLAN_SCALAR_COND_NOT_EQUAL,
+	MLAN_SCALAR_COND_GREATER_THAN,
+	MLAN_SCALAR_COND_GREATER_OR_EQUAL,
+	MLAN_SCALAR_COND_LESS_THAN,
+	MLAN_SCALAR_COND_LESS_OR_EQUAL
+} MLAN_SCALAR_CONDITIONAL;
+
+/**
+ *  @brief This function initializes a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Initial scalar value
+ *  @param plock_to_use		A new lock is created if NULL, else lock to use
+ *  @param moal_init_lock	A pointer to init lock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_init(t_void *pmoal_handle, pmlan_scalar pscalar, t_s32 val,
+		 t_void *plock_to_use,
+		 mlan_status (*moal_init_lock) (t_void *handle,
+						t_void **pplock))
+{
+	pscalar->value = val;
+	pscalar->flags = 0;
+	if (plock_to_use) {
+		pscalar->flags &= ~MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		pscalar->plock = plock_to_use;
+	} else {
+		pscalar->flags |= MLAN_SCALAR_FLAG_UNIQUE_LOCK;
+		moal_init_lock(pmoal_handle, &pscalar->plock);
+	}
+}
+
+/**
+ *  @brief This function frees a scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_free_lock	A pointer to free lock handler
+ *
+ *  @return			N/A
+ */
+static INLINE t_void
+util_scalar_free(t_void *pmoal_handle, pmlan_scalar pscalar,
+		 mlan_status (*moal_free_lock) (t_void *handle, t_void *plock))
+{
+	if (pscalar->flags & MLAN_SCALAR_FLAG_UNIQUE_LOCK)
+		moal_free_lock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function reads value from scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Stored value
+ */
+static INLINE t_s32
+util_scalar_read(t_void *pmoal_handle, pmlan_scalar pscalar,
+		 mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		 mlan_status (*moal_spin_unlock) (t_void *handle,
+						  t_void *plock))
+{
+	t_s32 val;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	val = pscalar->value;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return val;
+}
+
+/**
+ *  @brief This function writes value to scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param val				Value to write
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_write(t_void *pmoal_handle, pmlan_scalar pscalar, t_s32 val,
+		  mlan_status (*moal_spin_lock) (t_void *handle, t_void *plock),
+		  mlan_status (*moal_spin_unlock) (t_void *handle,
+						   t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value = val;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function increments the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_increment(t_void *pmoal_handle, pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value++;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function decrements the value in scalar
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					N/A
+ */
+static INLINE t_void
+util_scalar_decrement(t_void *pmoal_handle, pmlan_scalar pscalar,
+		      mlan_status (*moal_spin_lock) (t_void *handle,
+						     t_void *plock),
+		      mlan_status (*moal_spin_unlock) (t_void *handle,
+						       t_void *plock))
+{
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	pscalar->value--;
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+}
+
+/**
+ *  @brief This function adds an offset to the value in scalar,
+ *         and returns the new value
+ *
+ *  @param pscalar			Pointer to scalar
+ *  @param offset			Offset value (can be negative)
+ *  @param moal_spin_lock	A pointer to spin lock handler
+ *  @param moal_spin_unlock	A pointer to spin unlock handler
+ *
+ *  @return					Value after offset
+ */
+static INLINE t_s32
+util_scalar_offset(t_void *pmoal_handle, pmlan_scalar pscalar, t_s32 offset,
+		   mlan_status (*moal_spin_lock) (t_void *handle,
+						  t_void *plock),
+		   mlan_status (*moal_spin_unlock) (t_void *handle,
+						    t_void *plock))
+{
+	t_s32 newval;
+
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+	newval = (pscalar->value += offset);
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+
+	return newval;
+}
+
+/**
+ *  @brief This function writes the value to the scalar
+ *         if existing value compared with other value is true.
+ *
+ *  @param pscalar          Pointer to scalar
+ *  @param condition        Condition to check
+ *  @param val_compare      Value to compare against current value
+ *                          ((A X B), where B = val_compare)
+ *  @param val_to_set       Value to set if comparison is true
+ *  @param moal_spin_lock   A pointer to spin lock handler
+ *  @param moal_spin_unlock A pointer to spin unlock handler
+ *
+ *  @return                 Comparison result (MTRUE or MFALSE)
+ */
+static INLINE t_u8
+util_scalar_conditional_write(t_void *pmoal_handle, pmlan_scalar pscalar,
+			      MLAN_SCALAR_CONDITIONAL condition,
+			      t_s32 val_compare, t_s32 val_to_set,
+			      mlan_status (*moal_spin_lock) (t_void *handle,
+							     t_void *plock),
+			      mlan_status (*moal_spin_unlock) (t_void *handle,
+							       t_void *plock))
+{
+	t_u8 update;
+	if (moal_spin_lock)
+		moal_spin_lock(pmoal_handle, pscalar->plock);
+
+	switch (condition) {
+	case MLAN_SCALAR_COND_EQUAL:
+		update = (pscalar->value == val_compare);
+		break;
+	case MLAN_SCALAR_COND_NOT_EQUAL:
+		update = (pscalar->value != val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_THAN:
+		update = (pscalar->value > val_compare);
+		break;
+	case MLAN_SCALAR_COND_GREATER_OR_EQUAL:
+		update = (pscalar->value >= val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_THAN:
+		update = (pscalar->value < val_compare);
+		break;
+	case MLAN_SCALAR_COND_LESS_OR_EQUAL:
+		update = (pscalar->value <= val_compare);
+		break;
+	default:
+		update = MFALSE;
+		break;
+	}
+	if (update)
+		pscalar->value = val_to_set;
+
+	if (moal_spin_unlock)
+		moal_spin_unlock(pmoal_handle, pscalar->plock);
+	return (update) ? MTRUE : MFALSE;
+}
+
+/**
+ *  @brief This function counts the bits of unsigned int number
+ *
+ *  @param num  number
+ *  @return     number of bits
+ */
+static INLINE t_u32
+bitcount(t_u32 num)
+{
+	t_u32 count = 0;
+	static t_u32 nibblebits[] = { 0, 1, 1, 2, 1, 2, 2, 3,
+		1, 2, 2, 3, 2, 3, 3, 4
+	};
+	for (; num != 0; num >>= 4)
+		count += nibblebits[num & 0x0f];
+	return count;
+}
+
+#endif /* !_MLAN_UTIL_H_ */
diff --git a/wlan_sd8987/mlan/mlan_wmm.c b/wlan_sd8987/mlan/mlan_wmm.c
new file mode 100755
index 0000000..6709c7c
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_wmm.c
@@ -0,0 +1,3791 @@
+/** @file mlan_wmm.c
+ *
+ *  @brief This file contains functions for WMM.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/24/2008: initial version
+********************************************************/
+
+#include "mlan.h"
+#ifdef STA_SUPPORT
+#include "mlan_join.h"
+#endif
+#include "mlan_util.h"
+#include "mlan_fw.h"
+#include "mlan_main.h"
+#include "mlan_wmm.h"
+#include "mlan_11n.h"
+#ifdef SDIO
+#include "mlan_sdio.h"
+#endif /* SDIO */
+#ifdef PCIE
+#include "mlan_pcie.h"
+#endif /* PCIE */
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** WMM information IE */
+static const t_u8 wmm_info_ie[] = { WMM_IE, 0x07, 0x00, 0x50, 0xf2,
+	0x02, 0x00, 0x01, 0x00
+};
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _wmm_ac_e {
+	AC_BE,
+	AC_BK,
+	AC_VI,
+	AC_VO
+} MLAN_PACK_END wmm_ac_e;
+
+/**
+ * AC Priorities go from AC_BK to AC_VO.  The ACI enumeration for AC_BK (1)
+ *   is higher than the enumeration for AC_BE (0); hence the needed
+ *   mapping conversion for wmm AC to priority Queue Index
+ */
+static const t_u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
+	WMM_AC_VO
+};
+
+/**
+ * This table will be used to store the tid values based on ACs.
+ * It is initialized to default values per TID.
+ */
+static t_u8 tos_to_tid[] = {
+	/* TID        DSCP_P2   DSCP_P1  DSCP_P0   WMM_AC   */
+	0x01,			/*    0         1        0       AC_BK   */
+	0x02,			/*    0         0        0       AC_BK   */
+	0x00,			/*    0         0        1       AC_BE   */
+	0x03,			/*    0         1        1       AC_BE   */
+	0x04,			/*    1         0        0       AC_VI   */
+	0x05,			/*    1         0        1       AC_VI   */
+	0x06,			/*    1         1        0       AC_VO   */
+	0x07			/*    1         1        1       AC_VO   */
+};
+
+/**
+ * This table inverses the tos_to_tid operation to get a priority
+ * which is in sequential order, and can be compared.
+ * Use this to compare the priority of two different TIDs.
+ */
+t_u8 tos_to_tid_inv[] = { 0x02,	/* from tos_to_tid[2] = 0 */
+	0x00,			/* from tos_to_tid[0] = 1 */
+	0x01,			/* from tos_to_tid[1] = 2 */
+	0x03, 0x04, 0x05, 0x06, 0x07
+};
+
+/**
+ * This table will provide the tid value for given ac. This table does not
+ * change and will be used to copy back the default values to tos_to_tid in
+ * case of disconnect.
+ */
+t_u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} };
+
+/* Map of TOS UP values to WMM AC */
+static const mlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, WMM_AC_BK, WMM_AC_BK,
+	WMM_AC_BE, WMM_AC_VI, WMM_AC_VI,
+	WMM_AC_VO, WMM_AC_VO
+};
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+				    t_u8 *ra_addr);
+
+/********************************************************
+			Local Functions
+********************************************************/
+#ifdef DEBUG_LEVEL2
+/**
+ *  @brief Debug print function to display the priority parameters for a WMM AC
+ *
+ *  @param pac_param	Pointer to the AC parameters to display
+ *
+ *  @return		N/A
+ */
+static void
+wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t *pac_param)
+{
+	const char *ac_str[] = { "BK", "BE", "VI", "VO" };
+
+	ENTER();
+
+	PRINTM(MINFO,
+	       "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
+	       "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+	       ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]],
+	       pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm,
+	       pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min,
+	       pac_param->ecw.ecw_max,
+	       wlan_le16_to_cpu(pac_param->tx_op_limit));
+
+	LEAVE();
+}
+
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param)
+#else
+/** Print the WMM AC for debug purpose */
+#define PRINTM_AC(pac_param)
+#endif
+
+/**
+ *  @brief Allocate route address
+ *
+ *  @param pmadapter       Pointer to the mlan_adapter structure
+ *  @param ra              Pointer to the route address
+ *
+ *  @return         ra_list
+ */
+static raListTbl *
+wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter, t_u8 *ra)
+{
+	raListTbl *ra_list = MNULL;
+
+	ENTER();
+
+	if (pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					     sizeof(raListTbl), MLAN_MEM_DEF,
+					     (t_u8 **)&ra_list)) {
+		PRINTM(MERROR, "Fail to allocate ra_list\n");
+		goto done;
+	}
+	util_init_list((pmlan_linked_list)ra_list);
+	util_init_list_head((t_void *)pmadapter->pmoal_handle,
+			    &ra_list->buf_head, MFALSE,
+			    pmadapter->callbacks.moal_init_lock);
+
+	memcpy_ext(pmadapter, ra_list->ra, ra, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+
+	ra_list->del_ba_count = 0;
+	ra_list->total_pkts = 0;
+	ra_list->tx_pause = 0;
+	PRINTM(MINFO, "RAList: Allocating buffers for TID %p\n", ra_list);
+done:
+	LEAVE();
+	return ra_list;
+}
+
+/**
+ *  @brief Add packet to TDLS pending TX queue
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param pmbuf      Pointer to the mlan_buffer data struct
+ *
+ *  @return           N/A
+ */
+static t_void
+wlan_add_buf_tdls_txqueue(pmlan_private priv, pmlan_buffer pmbuf)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	ENTER();
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &priv->tdls_pending_txq,
+			       (pmlan_linked_list)pmbuf,
+			       pmadapter->callbacks.moal_spin_lock,
+			       pmadapter->callbacks.moal_spin_unlock);
+	LEAVE();
+}
+
+/**
+ *  @brief Clean up the tdls pending TX queue
+ *
+ *  @param priv		A pointer to mlan_private
+ *
+ *  @return      N/A
+ */
+static t_void
+wlan_cleanup_tdls_txq(pmlan_private priv)
+{
+	pmlan_buffer pmbuf;
+	mlan_adapter *pmadapter = priv->adapter;
+	ENTER();
+
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->tdls_pending_txq.plock);
+	while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &priv->tdls_pending_txq,
+						     MNULL, MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &priv->tdls_pending_txq,
+				 (pmlan_linked_list)pmbuf, MNULL, MNULL);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->tdls_pending_txq.plock);
+	LEAVE();
+}
+
+/**
+ * @brief Map ACs to TID
+ *
+ * @param priv             Pointer to the mlan_private driver data struct
+ * @param queue_priority   Queue_priority structure
+ *
+ * @return 	   N/A
+ */
+static void
+wlan_wmm_queue_priorities_tid(pmlan_private priv, t_u8 queue_priority[])
+{
+	int i;
+
+	ENTER();
+
+	for (i = 0; i < 4; ++i) {
+		tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1];
+		tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0];
+	}
+
+	for (i = 0; i < MAX_NUM_TID; i++)
+		tos_to_tid_inv[tos_to_tid[i]] = (t_u8)i;
+
+	/* in case priorities have changed, force highest priority so
+	 * next packet will check from top to re-establish the highest
+	 */
+	util_scalar_write(priv->adapter->pmoal_handle,
+			  &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+			  priv->adapter->callbacks.moal_spin_lock,
+			  priv->adapter->callbacks.moal_spin_unlock);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Evaluate whether or not an AC is to be downgraded
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *  @param eval_ac  AC to evaluate for downgrading
+ *
+ *  @return WMM AC  The eval_ac traffic is to be sent on.
+ */
+static mlan_wmm_ac_e
+wlan_wmm_eval_downgrade_ac(pmlan_private priv, mlan_wmm_ac_e eval_ac)
+{
+	int down_ac;
+	mlan_wmm_ac_e ret_ac;
+	WmmAcStatus_t *pac_status;
+
+	ENTER();
+
+	pac_status = &priv->wmm.ac_status[eval_ac];
+
+	if (pac_status->disabled == MFALSE) {
+		LEAVE();
+		/* Okay to use this AC, its enabled */
+		return eval_ac;
+	}
+
+	/* Setup a default return value of the lowest priority */
+	ret_ac = WMM_AC_BK;
+
+	/*
+	 * Find the highest AC that is enabled and does not require admission
+	 * control.  The spec disallows downgrading to an AC, which is enabled
+	 * due to a completed admission control.  Unadmitted traffic is not
+	 * to be sent on an AC with admitted traffic.
+	 */
+	for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) {
+		pac_status = &priv->wmm.ac_status[down_ac];
+
+		if ((pac_status->disabled == MFALSE) &&
+		    (pac_status->flow_required == MFALSE))
+			/* AC is enabled and does not require admission control
+			 */
+			ret_ac = (mlan_wmm_ac_e)down_ac;
+	}
+
+	LEAVE();
+	return ret_ac;
+}
+
+/**
+ *  @brief Convert the IP TOS field to an WMM AC Queue assignment
+ *
+ *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param tos       IP TOS field
+ *
+ *  @return     WMM AC Queue mapping of the IP TOS field
+ */
+static INLINE mlan_wmm_ac_e
+wlan_wmm_convert_tos_to_ac(pmlan_adapter pmadapter, t_u32 tos)
+{
+	ENTER();
+
+	if (tos >= NELEMENTS(tos_to_ac)) {
+		LEAVE();
+		return WMM_AC_BE;
+	}
+
+	LEAVE();
+	return tos_to_ac[tos];
+}
+
+/**
+ *  @brief  Evaluate a given TID and downgrade it to a lower TID if the
+ *          WMM Parameter IE received from the AP indicates that the AP
+ *          is disabled (due to call admission control (ACM bit). Mapping
+ *          of TID to AC is taken care internally
+ *
+ *  @param priv		Pointer to the mlan_private data struct
+ *  @param tid      tid to evaluate for downgrading
+ *
+ *  @return       Same tid as input if downgrading not required or
+ *                the tid the traffic for the given tid should be downgraded to
+ */
+static INLINE t_u8
+wlan_wmm_downgrade_tid(pmlan_private priv, t_u32 tid)
+{
+	mlan_wmm_ac_e ac_down;
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	ac_down =
+		priv->wmm.
+		ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(pmadapter, tid)];
+	LEAVE();
+	/*
+	 * Send the index to tid array, picking from the array will be
+	 * taken care by dequeuing function
+	 */
+	if (tid == 1 || tid == 2)
+		return ac_to_tid[ac_down][(tid + 1) % 2];
+	else if (tid >= MAX_NUM_TID)
+		return ac_to_tid[ac_down][0];
+	else
+		return ac_to_tid[ac_down][tid % 2];
+}
+
+/**
+ *  @brief Delete packets in RA node
+ *
+ *  @param priv         Pointer to the mlan_private driver data struct
+ *  @param ra_list      Pointer to raListTbl
+ *
+ *  @return             N/A
+ */
+static INLINE void
+wlan_wmm_del_pkts_in_ralist_node(pmlan_private priv, raListTbl *ra_list)
+{
+	pmlan_buffer pmbuf;
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+	while ((pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &ra_list->buf_head, MNULL,
+						     MNULL))) {
+		util_unlink_list(pmadapter->pmoal_handle, &ra_list->buf_head,
+				 (pmlan_linked_list)pmbuf, MNULL, MNULL);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+	}
+	util_free_list_head((t_void *)pmadapter->pmoal_handle,
+			    &ra_list->buf_head,
+			    pmadapter->callbacks.moal_free_lock);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Delete packets in RA list
+ *
+ *  @param priv			Pointer to the mlan_private driver data struct
+ *  @param ra_list_head	ra list header
+ *
+ *  @return		N/A
+ */
+static INLINE void
+wlan_wmm_del_pkts_in_ralist(pmlan_private priv, mlan_list_head *ra_list_head)
+{
+	raListTbl *ra_list;
+
+	ENTER();
+
+	ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					      ra_list_head, MNULL, MNULL);
+
+	while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+		wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
+
+		ra_list = ra_list->pnext;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Clean up the wmm queue
+ *
+ *  @param priv  Pointer to the mlan_private driver data struct
+ *
+ *  @return      N/A
+ */
+static void
+wlan_wmm_cleanup_queues(pmlan_private priv)
+{
+	int i;
+
+	ENTER();
+
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		wlan_wmm_del_pkts_in_ralist(priv,
+					    &priv->wmm.tid_tbl_ptr[i].ra_list);
+		priv->wmm.pkts_queued[i] = 0;
+		priv->wmm.pkts_paused[i] = 0;
+	}
+	util_scalar_write(priv->adapter->pmoal_handle,
+			  &priv->wmm.tx_pkts_queued, 0, MNULL, MNULL);
+	util_scalar_write(priv->adapter->pmoal_handle,
+			  &priv->wmm.highest_queued_prio, HIGH_PRIO_TID, MNULL,
+			  MNULL);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Delete all route address from RA list
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+static void
+wlan_wmm_delete_all_ralist(pmlan_private priv)
+{
+	raListTbl *ra_list;
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+
+	ENTER();
+
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		PRINTM(MINFO, "RAList: Freeing buffers for TID %d\n", i);
+		while ((ra_list =
+			(raListTbl *)util_peek_list(pmadapter->pmoal_handle,
+						    &priv->wmm.tid_tbl_ptr[i].
+						    ra_list, MNULL, MNULL))) {
+			util_unlink_list(pmadapter->pmoal_handle,
+					 &priv->wmm.tid_tbl_ptr[i].ra_list,
+					 (pmlan_linked_list)ra_list, MNULL,
+					 MNULL);
+
+			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+							(t_u8 *)ra_list);
+		}
+
+		util_init_list((pmlan_linked_list)&priv->wmm.tid_tbl_ptr[i].
+			       ra_list);
+		priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
+	}
+
+	LEAVE();
+}
+
+/**
+ *   @brief Get queue RA pointer
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param tid      TID
+ *   @param ra_addr  Pointer to the route address
+ *
+ *   @return         ra_list
+ */
+static raListTbl *
+wlan_wmm_get_queue_raptr(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
+{
+	raListTbl *ra_list;
+#ifdef UAP_SUPPORT
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+#endif
+
+	ENTER();
+	ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr);
+	if (ra_list) {
+		LEAVE();
+		return ra_list;
+	}
+#ifdef UAP_SUPPORT
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+	    (0 !=
+	     memcmp(priv->adapter, ra_addr, bcast_addr, sizeof(bcast_addr)))) {
+		if (MNULL == wlan_get_station_entry(priv, ra_addr)) {
+			PRINTM_NETINTF(MERROR, priv);
+			PRINTM(MERROR,
+			       "Drop packets to unknow station " MACSTR "\n",
+			       MAC2STR(ra_addr));
+			LEAVE();
+			return MNULL;
+		}
+	}
+#endif
+	wlan_ralist_add(priv, ra_addr);
+
+	ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr);
+	LEAVE();
+	return ra_list;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Sends wmmac host event
+ *
+ *  @param priv      Pointer to the mlan_private driver data struct
+ *  @param type_str  Type of host event
+ *  @param src_addr  Pointer to the source Address
+ *  @param tid       TID
+ *  @param up        User priority
+ *  @param status    Status code or Reason code
+ *
+ *  @return     N/A
+ */
+static void
+wlan_send_wmmac_host_event(pmlan_private priv, char *type_str,
+			   t_u8 *src_addr, t_u8 tid, t_u8 up, t_u8 status)
+{
+	t_u8 event_buf[100];
+	mlan_event *pevent;
+	t_u8 *pout_buf;
+
+	ENTER();
+
+	/* Format one of the following two output strings:
+	 **    - TSPEC:ADDTS_RSP:[<status code>]:TID=X:UP=Y
+	 **    - TSPEC:DELTS_RX:[<reason code>]:TID=X:UP=Y
+	 */
+	pevent = (mlan_event *)event_buf;
+	pout_buf = pevent->event_buf;
+
+	memcpy_ext(priv->adapter, pout_buf, (t_u8 *)"TSPEC:", 6, 6);
+	pout_buf += 6;
+
+	memcpy_ext(priv->adapter, pout_buf, (t_u8 *)type_str,
+		   wlan_strlen(type_str), wlan_strlen(type_str));
+	pout_buf += wlan_strlen(type_str);
+
+	*pout_buf++ = ':';
+	*pout_buf++ = '[';
+
+	if (status >= 100) {
+		*pout_buf++ = (status / 100) + '0';
+		status = (status % 100);
+	}
+
+	if (status >= 10) {
+		*pout_buf++ = (status / 10) + '0';
+		status = (status % 10);
+	}
+
+	*pout_buf++ = status + '0';
+
+	memcpy_ext(priv->adapter, pout_buf, (t_u8 *)"]:TID", 5, 5);
+	pout_buf += 5;
+	*pout_buf++ = tid + '0';
+
+	memcpy_ext(priv->adapter, pout_buf, (t_u8 *)":UP", 3, 3);
+	pout_buf += 3;
+	*pout_buf++ = up + '0';
+
+	*pout_buf = '\0';
+
+	pevent->bss_index = priv->bss_index;
+	pevent->event_id = MLAN_EVENT_ID_DRV_REPORT_STRING;
+	pevent->event_len = wlan_strlen((const char *)(pevent->event_buf));
+
+	wlan_recv_event(priv, MLAN_EVENT_ID_DRV_REPORT_STRING, pevent);
+	LEAVE();
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief This function gets the highest priority list pointer
+ *
+ *  @param pmadapter      A pointer to mlan_adapter
+ *  @param priv           A pointer to mlan_private
+ *  @param tid            A pointer to return tid
+ *
+ *  @return             raListTbl
+ */
+static raListTbl *
+wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter,
+				  pmlan_private *priv, int *tid)
+{
+	pmlan_private priv_tmp;
+	raListTbl *ptr, *head;
+	mlan_bssprio_node *bssprio_node, *bssprio_head;
+	tid_tbl_t *tid_ptr;
+	int i, j;
+	int next_prio = 0;
+	int next_tid = 0;
+	ENTER();
+
+	PRINTM(MDAT_D, "POP\n");
+	for (j = pmadapter->priv_num - 1; j >= 0; --j) {
+		if (!(util_peek_list(pmadapter->pmoal_handle,
+				     &pmadapter->bssprio_tbl[j].bssprio_head,
+				     MNULL, MNULL)))
+			continue;
+
+		if (pmadapter->bssprio_tbl[j].bssprio_cur ==
+		    (mlan_bssprio_node *)&pmadapter->bssprio_tbl[j]
+		    .bssprio_head) {
+			pmadapter->bssprio_tbl[j].bssprio_cur =
+				pmadapter->bssprio_tbl[j].bssprio_cur->pnext;
+		}
+
+		bssprio_head = bssprio_node =
+			pmadapter->bssprio_tbl[j].bssprio_cur;
+
+		do {
+			priv_tmp = bssprio_node->priv;
+			if ((priv_tmp->port_ctrl_mode == MTRUE) &&
+			    (priv_tmp->port_open == MFALSE)) {
+				PRINTM(MINFO,
+				       "get_highest_prio_ptr(): "
+				       "PORT_CLOSED Ignore pkts from BSS%d\n",
+				       priv_tmp->bss_index);
+				/* Ignore data pkts from a BSS if port is closed
+				 */
+				goto next_intf;
+			}
+			if (priv_tmp->tx_pause == MTRUE) {
+				PRINTM(MINFO,
+				       "get_highest_prio_ptr(): "
+				       "TX PASUE Ignore pkts from BSS%d\n",
+				       priv_tmp->bss_index);
+				/* Ignore data pkts from a BSS if tx pause */
+				goto next_intf;
+			}
+
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    priv_tmp->wmm.
+							    ra_list_spinlock);
+
+			for (i = util_scalar_read(pmadapter->pmoal_handle,
+						  &priv_tmp->wmm.
+						  highest_queued_prio, MNULL,
+						  MNULL); i >= LOW_PRIO_TID;
+			     --i) {
+				tid_ptr = &(priv_tmp)
+					->wmm.tid_tbl_ptr[tos_to_tid[i]];
+				if (!util_peek_list(pmadapter->pmoal_handle,
+						    &tid_ptr->ra_list, MNULL,
+						    MNULL))
+					continue;
+
+				/*
+				 * Always choose the next ra we transmitted
+				 * last time, this way we pick the ra's in
+				 * round robin fashion.
+				 */
+				head = ptr = tid_ptr->ra_list_curr->pnext;
+				if (ptr == (raListTbl *)&tid_ptr->ra_list)
+					head = ptr = ptr->pnext;
+
+				do {
+					if (!ptr->tx_pause &&
+					    util_peek_list(pmadapter->
+							   pmoal_handle,
+							   &ptr->buf_head,
+							   MNULL, MNULL)) {
+						/* Because WMM only support
+						 * BK/BE/VI/VO, we have 8 tid
+						 * We should balance the traffic
+						 * of the same AC */
+						if (i % 2)
+							next_prio = i - 1;
+						else
+							next_prio = i + 1;
+						next_tid =
+							tos_to_tid[next_prio];
+						if (priv_tmp->wmm.pkts_queued
+						    [next_tid] &&
+						    (priv_tmp->wmm.pkts_queued
+						     [next_tid] >
+						     priv_tmp->wmm.pkts_paused
+						     [next_tid]))
+							util_scalar_write
+								(pmadapter->
+								 pmoal_handle,
+								 &priv_tmp->wmm.
+								 highest_queued_prio,
+								 next_prio,
+								 MNULL, MNULL);
+						else
+							/* if
+							 * highest_queued_prio >
+							 * i, set it to i */
+							util_scalar_conditional_write
+								(pmadapter->
+								 pmoal_handle,
+								 &priv_tmp->wmm.
+								 highest_queued_prio,
+								 MLAN_SCALAR_COND_GREATER_THAN,
+								 i, i, MNULL,
+								 MNULL);
+						*priv = priv_tmp;
+						*tid = tos_to_tid[i];
+						/* hold priv->ra_list_spinlock
+						 * to maintain ptr */
+						PRINTM(MDAT_D,
+						       "get highest prio ptr %p, tid %d\n",
+						       ptr, *tid);
+						LEAVE();
+						return ptr;
+					}
+
+					ptr = ptr->pnext;
+					if (ptr ==
+					    (raListTbl *)&tid_ptr->ra_list)
+						ptr = ptr->pnext;
+				} while (ptr != head);
+			}
+
+			/* If priv still has packets queued, reset to
+			 * HIGH_PRIO_TID */
+			if (util_scalar_read(pmadapter->pmoal_handle,
+					     &priv_tmp->wmm.tx_pkts_queued,
+					     MNULL, MNULL))
+				util_scalar_write(pmadapter->pmoal_handle,
+						  &priv_tmp->wmm.
+						  highest_queued_prio,
+						  HIGH_PRIO_TID, MNULL, MNULL);
+			else
+				/* No packet at any TID for this priv.  Mark as
+				 * such to skip checking TIDs for this priv
+				 * (until pkt is added). */
+				util_scalar_write(pmadapter->pmoal_handle,
+						  &priv_tmp->wmm.
+						  highest_queued_prio,
+						  NO_PKT_PRIO_TID, MNULL,
+						  MNULL);
+
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv_tmp->wmm.
+							      ra_list_spinlock);
+
+next_intf:
+			bssprio_node = bssprio_node->pnext;
+			if (bssprio_node ==
+			    (mlan_bssprio_node *)&pmadapter->bssprio_tbl[j]
+			    .bssprio_head)
+				bssprio_node = bssprio_node->pnext;
+			pmadapter->bssprio_tbl[j].bssprio_cur = bssprio_node;
+		} while (bssprio_node != bssprio_head);
+	}
+
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief This function gets the number of packets in the Tx queue
+ *
+ *  @param priv           A pointer to mlan_private
+ *  @param ptr            A pointer to RA list table
+ *  @param max_buf_size   Maximum buffer size
+ *
+ *  @return             Packet count
+ */
+static int
+wlan_num_pkts_in_txq(mlan_private *priv, raListTbl *ptr, int max_buf_size)
+{
+	int count = 0, total_size = 0;
+	pmlan_buffer pmbuf;
+
+	ENTER();
+
+	for (pmbuf = (pmlan_buffer)ptr->buf_head.pnext;
+	     pmbuf != (pmlan_buffer)(&ptr->buf_head); pmbuf = pmbuf->pnext) {
+		total_size += pmbuf->data_len;
+		if (total_size < max_buf_size)
+			++count;
+		else
+			break;
+	}
+
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief This function sends a single packet
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param ptr          A pointer to RA list table
+ *  @param ptrindex     ptr's TID index
+ *
+ *  @return             N/A
+ */
+static INLINE void
+wlan_send_single_packet(pmlan_private priv, raListTbl *ptr, int ptrindex)
+{
+	pmlan_buffer pmbuf;
+	pmlan_buffer pmbuf_next;
+	mlan_tx_param tx_param;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+						&ptr->buf_head, MNULL, MNULL);
+	if (pmbuf) {
+		PRINTM(MINFO, "Dequeuing the packet %p %p\n", ptr, pmbuf);
+		priv->wmm.pkts_queued[ptrindex]--;
+		util_scalar_decrement(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		ptr->total_pkts--;
+		pmbuf_next =
+			(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &ptr->buf_head, MNULL,
+						     MNULL);
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+
+		tx_param.next_pkt_len =
+			((pmbuf_next) ? pmbuf_next->data_len + sizeof(TxPD) :
+			 0);
+		status = wlan_process_tx(priv, pmbuf, &tx_param);
+
+		if (status == MLAN_STATUS_RESOURCE) {
+			/** Queue the packet back at the head */
+			PRINTM(MDAT_D, "Queuing pkt back to raList %p %p\n",
+			       ptr, pmbuf);
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    priv->wmm.
+							    ra_list_spinlock);
+
+			if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 priv->wmm.
+							 ra_list_spinlock);
+				wlan_write_data_complete(pmadapter, pmbuf,
+							 MLAN_STATUS_FAILURE);
+				LEAVE();
+				return;
+			}
+			priv->wmm.pkts_queued[ptrindex]++;
+			util_scalar_increment(pmadapter->pmoal_handle,
+					      &priv->wmm.tx_pkts_queued, MNULL,
+					      MNULL);
+			util_enqueue_list_head(pmadapter->pmoal_handle,
+					       &ptr->buf_head,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+
+			ptr->total_pkts++;
+			pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+		} else {
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    priv->wmm.
+							    ra_list_spinlock);
+			if (wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+				priv->wmm.packets_out[ptrindex]++;
+				priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
+					ptr;
+			}
+			pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+				pmadapter->bssprio_tbl[priv->bss_priority]
+				.bssprio_cur->pnext;
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+		}
+	} else {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		PRINTM(MINFO, "Nothing to send\n");
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function checks if this mlan_buffer is already processed.
+ *
+ *  @param priv     A pointer to mlan_private
+ *  @param ptr      A pointer to RA list table
+ *
+ *  @return         MTRUE or MFALSE
+ */
+static INLINE int
+wlan_is_ptr_processed(mlan_private *priv, raListTbl *ptr)
+{
+	pmlan_buffer pmbuf;
+
+	pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
+					     &ptr->buf_head, MNULL, MNULL);
+	if (pmbuf && (pmbuf->flags & MLAN_BUF_FLAG_REQUEUED_PKT))
+		return MTRUE;
+
+	return MFALSE;
+}
+
+/**
+ *  @brief This function sends a single packet that has been processed
+ *
+ *  @param priv         A pointer to mlan_private
+ *  @param ptr          A pointer to RA list table
+ *  @param ptrindex     ptr's TID index
+ *
+ *  @return             N/A
+ */
+static INLINE void
+wlan_send_processed_packet(pmlan_private priv, raListTbl *ptr, int ptrindex)
+{
+	pmlan_buffer pmbuf_next = MNULL;
+	mlan_tx_param tx_param;
+	pmlan_buffer pmbuf;
+	pmlan_adapter pmadapter = priv->adapter;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
+						&ptr->buf_head, MNULL, MNULL);
+	if (pmbuf) {
+		pmbuf_next =
+			(pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &ptr->buf_head, MNULL,
+						     MNULL);
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		tx_param.next_pkt_len =
+			((pmbuf_next) ? pmbuf_next->data_len +
+			 sizeof(TxPD) : 0);
+
+		ret = pmadapter->ops.host_to_card(priv, MLAN_TYPE_DATA, pmbuf,
+						  &tx_param);
+		switch (ret) {
+#ifdef USB
+		case MLAN_STATUS_PRESOURCE:
+			PRINTM(MINFO, "MLAN_STATUS_PRESOURCE is returned\n");
+			break;
+#endif
+		case MLAN_STATUS_RESOURCE:
+			PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    priv->wmm.
+							    ra_list_spinlock);
+
+			if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 priv->wmm.
+							 ra_list_spinlock);
+				wlan_write_data_complete(pmadapter, pmbuf,
+							 MLAN_STATUS_FAILURE);
+				LEAVE();
+				return;
+			}
+			util_enqueue_list_head(pmadapter->pmoal_handle,
+					       &ptr->buf_head,
+					       (pmlan_linked_list)pmbuf, MNULL,
+					       MNULL);
+
+			pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			break;
+		case MLAN_STATUS_FAILURE:
+			PRINTM(MERROR, "Error: Failed to write data\n");
+			pmadapter->dbg.num_tx_host_to_card_failure++;
+			pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL;
+			wlan_write_data_complete(pmadapter, pmbuf, ret);
+			break;
+		case MLAN_STATUS_PENDING:
+			break;
+		case MLAN_STATUS_SUCCESS:
+			DBG_HEXDUMP(MDAT_D, "Tx",
+				    pmbuf->pbuf + pmbuf->data_offset,
+				    MIN(pmbuf->data_len + sizeof(TxPD),
+					MAX_DATA_DUMP_LEN));
+			wlan_write_data_complete(pmadapter, pmbuf, ret);
+			break;
+		default:
+			break;
+		}
+		if (ret != MLAN_STATUS_RESOURCE) {
+			pmadapter->callbacks.moal_spin_lock(pmadapter->
+							    pmoal_handle,
+							    priv->wmm.
+							    ra_list_spinlock);
+			if (wlan_is_ralist_valid(priv, ptr, ptrindex)) {
+				priv->wmm.packets_out[ptrindex]++;
+				priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
+					ptr;
+				ptr->total_pkts--;
+			}
+			pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
+				pmadapter->bssprio_tbl[priv->bss_priority]
+				.bssprio_cur->pnext;
+			priv->wmm.pkts_queued[ptrindex]--;
+			util_scalar_decrement(pmadapter->pmoal_handle,
+					      &priv->wmm.tx_pkts_queued, MNULL,
+					      MNULL);
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+		}
+	} else {
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+	}
+}
+
+/**
+ *  @brief This function dequeues a packet
+ *
+ *  @param pmadapter  A pointer to mlan_adapter
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+wlan_dequeue_tx_packet(pmlan_adapter pmadapter)
+{
+	raListTbl *ptr;
+	pmlan_private priv = MNULL;
+	int ptrindex = 0;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	int tid_del = 0;
+	int tid = 0;
+	mlan_buffer *pmbuf = MNULL;
+
+	ENTER();
+
+	ptr = wlan_wmm_get_highest_priolist_ptr(pmadapter, &priv, &ptrindex);
+	if (!ptr) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/*  Note:- Spinlock is locked in wlan_wmm_get_highest_priolist_ptr
+	 *  when it returns a pointer (for the priv it returns),
+	 *  and is unlocked in wlan_send_processed_packet,
+	 *  wlan_send_single_packet or wlan_11n_aggregate_pkt.
+	 *  The spinlock would be required for some parts of both of function.
+	 *  But, the the bulk of these function will execute w/o spinlock.
+	 *  Unlocking the spinlock inside these function will help us avoid
+	 *  taking the spinlock again, check to see if the ptr is still
+	 *  valid and then proceed. This is done purely to increase
+	 *  execution time. */
+
+	/* Note:- Also, anybody adding code which does not get into
+	 * wlan_send_processed_packet, wlan_send_single_packet, or
+	 * wlan_11n_aggregate_pkt should make sure ra_list_spinlock
+	 * is freed. Otherwise there would be a lock up. */
+
+	tid = wlan_get_tid(priv->adapter, ptr);
+	if (tid >= MAX_NUM_TID)
+		tid = wlan_wmm_downgrade_tid(priv, tid);
+
+	if (wlan_is_ptr_processed(priv, ptr)) {
+		wlan_send_processed_packet(priv, ptr, ptrindex);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	if (ptr->del_ba_count >= DEL_BA_THRESHOLD)
+		wlan_update_del_ba_count(priv, ptr);
+	if (pmadapter->tp_state_on) {
+		pmbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+						     &ptr->buf_head, MNULL,
+						     MNULL);
+		if (pmbuf) {
+			pmadapter->callbacks.moal_tp_accounting(pmadapter->
+								pmoal_handle,
+								pmbuf->pdesc,
+								3);
+			if (pmadapter->tp_state_drop_point == 3) {
+				pmbuf = (pmlan_buffer)
+					util_dequeue_list(pmadapter->
+							  pmoal_handle,
+							  &ptr->buf_head, MNULL,
+							  MNULL);
+				PRINTM(MERROR, "Dequeuing the packet %p %p\n",
+				       ptr, pmbuf);
+				priv->wmm.pkts_queued[ptrindex]--;
+				util_scalar_decrement(pmadapter->pmoal_handle,
+						      &priv->wmm.tx_pkts_queued,
+						      MNULL, MNULL);
+				ptr->total_pkts--;
+				pmadapter->callbacks.
+					moal_spin_unlock(pmadapter->
+							 pmoal_handle,
+							 priv->wmm.
+							 ra_list_spinlock);
+				wlan_write_data_complete(pmadapter, pmbuf,
+							 MLAN_STATUS_SUCCESS);
+				LEAVE();
+				return MLAN_STATUS_SUCCESS;
+			}
+		}
+	}
+	if (!ptr->is_11n_enabled ||
+	    (ptr->ba_status || ptr->del_ba_count >= DEL_BA_THRESHOLD)
+#ifdef STA_SUPPORT
+	    || priv->wps.session_enable
+#endif /* STA_SUPPORT */
+		) {
+		if (ptr->is_11n_enabled && ptr->ba_status &&
+		    ptr->amsdu_in_ampdu &&
+		    wlan_is_amsdu_allowed(priv, ptr, tid) &&
+		    (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >=
+		     MIN_NUM_AMSDU)) {
+			wlan_11n_aggregate_pkt(priv, ptr, priv->intf_hr_len,
+					       ptrindex);
+		} else
+			wlan_send_single_packet(priv, ptr, ptrindex);
+	} else {
+		if (wlan_is_ampdu_allowed(priv, ptr, tid) &&
+		    (ptr->packet_count > ptr->ba_packet_threshold)) {
+			if (wlan_is_bastream_avail(priv)) {
+				PRINTM(MINFO,
+				       "BA setup threshold %d reached. tid=%d\n",
+				       ptr->packet_count, tid);
+				if (!wlan_11n_get_txbastream_tbl
+				    (priv, tid, ptr->ra, MFALSE)) {
+					wlan_11n_create_txbastream_tbl(priv,
+								       ptr->ra,
+								       tid,
+								       BA_STREAM_SETUP_INPROGRESS);
+					wlan_send_addba(priv, tid, ptr->ra);
+				}
+			} else if (wlan_find_stream_to_delete(priv, ptr, tid,
+							      &tid_del, ra)) {
+				PRINTM(MDAT_D, "tid_del=%d tid=%d\n", tid_del,
+				       tid);
+				if (!wlan_11n_get_txbastream_tbl
+				    (priv, tid, ptr->ra, MFALSE)) {
+					wlan_11n_create_txbastream_tbl(priv,
+								       ptr->ra,
+								       tid,
+								       BA_STREAM_SETUP_INPROGRESS);
+					wlan_send_delba(priv, MNULL, tid_del,
+							ra, 1);
+				}
+			}
+		}
+		if (wlan_is_amsdu_allowed(priv, ptr, tid) &&
+		    (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >=
+		     MIN_NUM_AMSDU)) {
+			wlan_11n_aggregate_pkt(priv, ptr, priv->intf_hr_len,
+					       ptrindex);
+		} else {
+			wlan_send_single_packet(priv, ptr, ptrindex);
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief update tx_pause flag in ra_list
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param mac        peer mac address
+ *  @param tx_pause   tx_pause flag (0/1)
+ *
+ *
+ *  @return           packets queued for this mac
+ */
+t_u16
+wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause)
+{
+	raListTbl *ra_list;
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	t_u32 pkt_cnt = 0;
+	t_u32 tx_pkts_queued = 0;
+	ENTER();
+
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
+		if (ra_list && ra_list->tx_pause != tx_pause) {
+			pkt_cnt += ra_list->total_pkts;
+			ra_list->tx_pause = tx_pause;
+			if (tx_pause)
+				priv->wmm.pkts_paused[i] += ra_list->total_pkts;
+			else
+				priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
+		}
+	}
+	if (pkt_cnt) {
+		tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
+						  &priv->wmm.tx_pkts_queued,
+						  MNULL, MNULL);
+		if (tx_pause)
+			tx_pkts_queued -= pkt_cnt;
+		else
+			tx_pkts_queued += pkt_cnt;
+		util_scalar_write(priv->adapter->pmoal_handle,
+				  &priv->wmm.tx_pkts_queued, tx_pkts_queued,
+				  MNULL, MNULL);
+		util_scalar_write(priv->adapter->pmoal_handle,
+				  &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+				  MNULL, MNULL);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return pkt_cnt;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief update tx_pause flag in none tdls ra_list
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param mac        peer mac address
+ *  @param tx_pause   tx_pause flag (0/1)
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_update_non_tdls_ralist(mlan_private *priv, t_u8 *mac, t_u8 tx_pause)
+{
+	raListTbl *ra_list;
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	t_u32 pkt_cnt = 0;
+	t_u32 tx_pkts_queued = 0;
+	ENTER();
+
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ra_list =
+			(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						    &priv->wmm.tid_tbl_ptr[i].
+						    ra_list, MNULL, MNULL);
+		while (ra_list &&
+		       (ra_list !=
+			(raListTbl *)&priv->wmm.tid_tbl_ptr[i].ra_list)) {
+			if (memcmp
+			    (priv->adapter, ra_list->ra, mac,
+			     MLAN_MAC_ADDR_LENGTH) &&
+			    ra_list->tx_pause != tx_pause) {
+				pkt_cnt += ra_list->total_pkts;
+				ra_list->tx_pause = tx_pause;
+				if (tx_pause)
+					priv->wmm.pkts_paused[i] +=
+						ra_list->total_pkts;
+				else
+					priv->wmm.pkts_paused[i] -=
+						ra_list->total_pkts;
+			}
+			ra_list = ra_list->pnext;
+		}
+	}
+	if (pkt_cnt) {
+		tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
+						  &priv->wmm.tx_pkts_queued,
+						  MNULL, MNULL);
+		if (tx_pause)
+			tx_pkts_queued -= pkt_cnt;
+		else
+			tx_pkts_queued += pkt_cnt;
+		util_scalar_write(priv->adapter->pmoal_handle,
+				  &priv->wmm.tx_pkts_queued, tx_pkts_queued,
+				  MNULL, MNULL);
+		util_scalar_write(priv->adapter->pmoal_handle,
+				  &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+				  MNULL, MNULL);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief find tdls buffer from ralist
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param ralist     A pointer to ralistTbl
+ *  @param mac        TDLS peer mac address
+ *
+ *  @return           pmlan_buffer or MNULL
+ */
+static pmlan_buffer
+wlan_find_tdls_packets(mlan_private *priv, raListTbl *ra_list, t_u8 *mac)
+{
+	pmlan_buffer pmbuf = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	ENTER();
+	pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
+					     &ra_list->buf_head, MNULL, MNULL);
+	if (!pmbuf) {
+		LEAVE();
+		return MNULL;
+	}
+	while (pmbuf != (pmlan_buffer)&ra_list->buf_head) {
+		memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		if (!memcmp(priv->adapter, ra, mac, MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return pmbuf;
+		}
+		pmbuf = pmbuf->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief find tdls buffer from tdls pending queue
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param mac        TDLS peer mac address
+ *
+ *  @return           pmlan_buffer or MNULL
+ */
+static pmlan_buffer
+wlan_find_packets_tdls_txq(mlan_private *priv, t_u8 *mac)
+{
+	pmlan_buffer pmbuf = MNULL;
+	mlan_adapter *pmadapter = priv->adapter;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	ENTER();
+	pmbuf = (pmlan_buffer)util_peek_list(priv->adapter->pmoal_handle,
+					     &priv->tdls_pending_txq, MNULL,
+					     MNULL);
+	if (!pmbuf) {
+		LEAVE();
+		return MNULL;
+	}
+	while (pmbuf != (pmlan_buffer)&priv->tdls_pending_txq) {
+		memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		if (!memcmp(priv->adapter, ra, mac, MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return pmbuf;
+		}
+		pmbuf = pmbuf->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *  @brief Remove TDLS ralist and move packets to AP's ralist
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param mac        TDLS peer mac address
+ *
+ *  @return           N/A
+ */
+static t_void
+wlan_wmm_delete_tdls_ralist(pmlan_private priv, t_u8 *mac)
+{
+	raListTbl *ra_list;
+	raListTbl *ra_list_ap = MNULL;
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	pmlan_buffer pmbuf;
+	ENTER();
+
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
+		if (ra_list) {
+			PRINTM(MDATA, "delete TDLS ralist %p\n", ra_list);
+			ra_list_ap =
+				(raListTbl *)util_peek_list(pmadapter->
+							    pmoal_handle,
+							    &priv->wmm.
+							    tid_tbl_ptr[i].
+							    ra_list, MNULL,
+							    MNULL);
+			if (!ra_list_ap) {
+				LEAVE();
+				return;
+			}
+			while ((pmbuf =
+				(pmlan_buffer)util_peek_list(pmadapter->
+							     pmoal_handle,
+							     &ra_list->buf_head,
+							     MNULL, MNULL))) {
+				util_unlink_list(pmadapter->pmoal_handle,
+						 &ra_list->buf_head,
+						 (pmlan_linked_list)pmbuf,
+						 MNULL, MNULL);
+				util_enqueue_list_tail(pmadapter->pmoal_handle,
+						       &ra_list_ap->buf_head,
+						       (pmlan_linked_list)pmbuf,
+						       MNULL, MNULL);
+				ra_list_ap->total_pkts++;
+				ra_list_ap->packet_count++;
+			}
+			util_free_list_head((t_void *)pmadapter->pmoal_handle,
+					    &ra_list->buf_head,
+					    pmadapter->callbacks.
+					    moal_free_lock);
+
+			util_unlink_list(pmadapter->pmoal_handle,
+					 &priv->wmm.tid_tbl_ptr[i].ra_list,
+					 (pmlan_linked_list)ra_list, MNULL,
+					 MNULL);
+			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+							(t_u8 *)ra_list);
+			if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
+				priv->wmm.tid_tbl_ptr[i].ra_list_curr =
+					ra_list_ap;
+		}
+	}
+
+	LEAVE();
+}
+#endif /* STA_SUPPORT */
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Get the threshold value for BA setup using system time.
+ *
+ *  @param pmadapter       Pointer to the mlan_adapter structure
+ *
+ *  @return         threshold value.
+ */
+t_u8
+wlan_get_random_ba_threshold(pmlan_adapter pmadapter)
+{
+	t_u32 sec, usec;
+	t_u8 ba_threshold = 0;
+
+	ENTER();
+
+	/* setup ba_packet_threshold here random number between
+	   [BA_SETUP_PACKET_OFFSET,
+	   BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] */
+
+#define BA_SETUP_MAX_PACKET_THRESHOLD 16
+
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
+						  &usec);
+	sec = (sec & 0xFFFF) + (sec >> 16);
+	usec = (usec & 0xFFFF) + (usec >> 16);
+
+	ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) +
+		pmadapter->min_ba_threshold;
+	PRINTM(MINFO, "pmadapter->min_ba_threshold = %d\n",
+	       pmadapter->min_ba_threshold);
+	PRINTM(MINFO, "setup BA after %d packets\n", ba_threshold);
+
+	LEAVE();
+	return ba_threshold;
+}
+
+/**
+ *  @brief  This function cleans Tx/Rx queues
+ *
+ *  @param priv		A pointer to mlan_private
+ *
+ *  @return		N/A
+ */
+t_void
+wlan_clean_txrx(pmlan_private priv)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	t_u8 i = 0;
+
+	ENTER();
+	wlan_cleanup_bypass_txq(priv);
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		wlan_cleanup_tdls_txq(priv);
+	}
+	wlan_11n_cleanup_reorder_tbl(priv);
+	wlan_11n_deleteall_txbastream_tbl(priv);
+#if defined(USB)
+	if (IS_USB(pmadapter->card_type))
+		wlan_reset_usb_tx_aggr(priv->adapter);
+#endif
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type))
+		wlan_clean_pcie_ring_buf(priv->adapter);
+#endif
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	wlan_wmm_cleanup_queues(priv);
+	wlan_wmm_delete_all_ralist(priv);
+	memcpy_ext(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid),
+		   sizeof(tos_to_tid));
+	for (i = 0; i < MAX_NUM_TID; i++)
+		tos_to_tid_inv[tos_to_tid[i]] = (t_u8)i;
+#ifdef UAP_SUPPORT
+	priv->num_drop_pkts = 0;
+#endif
+#ifdef SDIO
+	if (IS_SD(pmadapter->card_type)) {
+		memset(pmadapter, pmadapter->pcard_sd->mpa_tx_count, 0,
+		       sizeof(pmadapter->pcard_sd->mpa_tx_count));
+		pmadapter->pcard_sd->mpa_sent_no_ports = 0;
+		pmadapter->pcard_sd->mpa_sent_last_pkt = 0;
+		memset(pmadapter, pmadapter->pcard_sd->mpa_rx_count, 0,
+		       sizeof(pmadapter->pcard_sd->mpa_rx_count));
+	}
+#endif
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+}
+
+/**
+ *  @brief Set the WMM queue priorities to their default values
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_default_queue_priorities(pmlan_private priv)
+{
+	ENTER();
+
+	/* Default queue priorities: VO->VI->BE->BK */
+	priv->wmm.queue_priority[0] = WMM_AC_VO;
+	priv->wmm.queue_priority[1] = WMM_AC_VI;
+	priv->wmm.queue_priority[2] = WMM_AC_BE;
+	priv->wmm.queue_priority[3] = WMM_AC_BK;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Initialize WMM priority queues
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *  @param pwmm_ie  Pointer to the IEEEtypes_WmmParameter_t data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_setup_queue_priorities(pmlan_private priv,
+				IEEEtypes_WmmParameter_t *pwmm_ie)
+{
+	t_u16 cw_min, avg_back_off, tmp[4];
+	t_u32 i, j, num_ac;
+	t_u8 ac_idx;
+
+	ENTER();
+
+	if (!pwmm_ie || priv->wmm_enabled == MFALSE) {
+		/* WMM is not enabled, just set the defaults and return */
+		wlan_wmm_default_queue_priorities(priv);
+		LEAVE();
+		return;
+	}
+	memset(priv->adapter, tmp, 0, sizeof(tmp));
+
+	HEXDUMP("WMM: setup_queue_priorities: param IE", (t_u8 *)pwmm_ie,
+		sizeof(IEEEtypes_WmmParameter_t));
+
+	PRINTM(MINFO,
+	       "WMM Parameter IE: version=%d, "
+	       "qos_info Parameter Set Count=%d, Reserved=%#x\n",
+	       pwmm_ie->vend_hdr.version, pwmm_ie->qos_info.para_set_count,
+	       pwmm_ie->reserved);
+
+	for (num_ac = 0; num_ac < NELEMENTS(pwmm_ie->ac_params); num_ac++) {
+		cw_min = (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_min) - 1;
+		avg_back_off = (cw_min >> 1) +
+			pwmm_ie->ac_params[num_ac].aci_aifsn.aifsn;
+
+		ac_idx = wmm_aci_to_qidx_map[pwmm_ie->ac_params[num_ac]
+					     .aci_aifsn.aci];
+		priv->wmm.queue_priority[ac_idx] = ac_idx;
+		tmp[ac_idx] = avg_back_off;
+
+		PRINTM(MCMND, "WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
+		       (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_max) - 1,
+		       cw_min, avg_back_off);
+		PRINTM_AC(&pwmm_ie->ac_params[num_ac]);
+	}
+
+	HEXDUMP("WMM: avg_back_off", (t_u8 *)tmp, sizeof(tmp));
+	HEXDUMP("WMM: queue_priority", priv->wmm.queue_priority,
+		sizeof(priv->wmm.queue_priority));
+
+	/* Bubble sort */
+	for (i = 0; i < num_ac; i++) {
+		for (j = 1; j < num_ac - i; j++) {
+			if (tmp[j - 1] > tmp[j]) {
+				SWAP_U16(tmp[j - 1], tmp[j]);
+				SWAP_U8(priv->wmm.queue_priority[j - 1],
+					priv->wmm.queue_priority[j]);
+			} else if (tmp[j - 1] == tmp[j]) {
+				if (priv->wmm.queue_priority[j - 1] <
+				    priv->wmm.queue_priority[j]) {
+					SWAP_U8(priv->wmm.queue_priority[j - 1],
+						priv->wmm.queue_priority[j]);
+				}
+			}
+		}
+	}
+
+	wlan_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority);
+
+	HEXDUMP("WMM: avg_back_off, sort", (t_u8 *)tmp, sizeof(tmp));
+	DBG_HEXDUMP(MCMD_D, "WMM: queue_priority, sort",
+		    priv->wmm.queue_priority, sizeof(priv->wmm.queue_priority));
+	LEAVE();
+}
+
+/**
+ *  @brief Downgrade WMM priority queue
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_setup_ac_downgrade(pmlan_private priv)
+{
+	int ac_val;
+
+	ENTER();
+
+	PRINTM(MINFO, "WMM: AC Priorities: BK(0), BE(1), VI(2), VO(3)\n");
+
+	if (priv->wmm_enabled == MFALSE) {
+		/* WMM is not enabled, default priorities */
+		for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
+			priv->wmm.ac_down_graded_vals[ac_val] =
+				(mlan_wmm_ac_e)ac_val;
+		}
+	} else {
+		for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
+			priv->wmm.ac_down_graded_vals[ac_val] =
+				wlan_wmm_eval_downgrade_ac(priv,
+							   (mlan_wmm_ac_e)
+							   ac_val);
+			PRINTM(MINFO, "WMM: AC PRIO %d maps to %d\n", ac_val,
+			       priv->wmm.ac_down_graded_vals[ac_val]);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief  Allocate and add a RA list for all TIDs with the given RA
+ *
+ *  @param priv  Pointer to the mlan_private driver data struct
+ *  @param ra	 Address of the receiver STA (AP in case of infra)
+ *
+ *  @return      N/A
+ */
+void
+wlan_ralist_add(mlan_private *priv, t_u8 *ra)
+{
+	int i;
+	raListTbl *ra_list;
+	pmlan_adapter pmadapter = priv->adapter;
+	tdlsStatus_e status;
+
+	ENTER();
+
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ra_list = wlan_wmm_allocate_ralist_node(pmadapter, ra);
+		PRINTM(MINFO, "Creating RA List %p for tid %d\n", ra_list, i);
+		if (!ra_list)
+			break;
+		ra_list->max_amsdu = 0;
+		ra_list->ba_status = BA_STREAM_NOT_SETUP;
+		ra_list->amsdu_in_ampdu = MFALSE;
+		if (queuing_ra_based(priv)) {
+			ra_list->is_11n_enabled = wlan_is_11n_enabled(priv, ra);
+			if (ra_list->is_11n_enabled)
+				ra_list->max_amsdu =
+					get_station_max_amsdu_size(priv, ra);
+			ra_list->tx_pause = wlan_is_tx_pause(priv, ra);
+		} else {
+			ra_list->is_tdls_link = MFALSE;
+			ra_list->tx_pause = MFALSE;
+			status = wlan_get_tdls_link_status(priv, ra);
+			if (MTRUE == wlan_is_tdls_link_setup(status)) {
+				ra_list->is_11n_enabled =
+					is_station_11n_enabled(priv, ra);
+				if (ra_list->is_11n_enabled)
+					ra_list->max_amsdu =
+						get_station_max_amsdu_size(priv,
+									   ra);
+				ra_list->is_tdls_link = MTRUE;
+			} else {
+				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+				if (ra_list->is_11n_enabled)
+					ra_list->max_amsdu = priv->max_amsdu;
+			}
+		}
+
+		PRINTM_NETINTF(MDATA, priv);
+		PRINTM(MDATA, "ralist %p: is_11n_enabled=%d max_amsdu=%d\n",
+		       ra_list, ra_list->is_11n_enabled, ra_list->max_amsdu);
+
+		if (ra_list->is_11n_enabled) {
+			ra_list->packet_count = 0;
+			ra_list->ba_packet_threshold =
+				wlan_get_random_ba_threshold(pmadapter);
+		}
+
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &priv->wmm.tid_tbl_ptr[i].ra_list,
+				       (pmlan_linked_list)ra_list, MNULL,
+				       MNULL);
+
+		if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr)
+			priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Initialize the WMM parameter.
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter data structure
+ *
+ *  @return         N/A
+ */
+t_void
+wlan_init_wmm_param(pmlan_adapter pmadapter)
+{
+	/* Reuse the same structure of WmmAcParameters_t for configuration
+	 * purpose here. the definition of acm bit is changed to ucm (user
+	 * configuration mode) FW will take the setting of
+	 * aifsn,ecw_max,ecw_min, tx_op_limit only when ucm is set to 1.
+	 * othewise the default setting/behavoir in firmware will be used.
+	 */
+	pmadapter->ac_params[AC_BE].aci_aifsn.acm = 0;
+	pmadapter->ac_params[AC_BE].aci_aifsn.aci = AC_BE;
+	pmadapter->ac_params[AC_BE].aci_aifsn.aifsn = 3;
+	pmadapter->ac_params[AC_BE].ecw.ecw_max = 10;
+	pmadapter->ac_params[AC_BE].ecw.ecw_min = 4;
+	pmadapter->ac_params[AC_BE].tx_op_limit = 0;
+
+	pmadapter->ac_params[AC_BK].aci_aifsn.acm = 0;
+	pmadapter->ac_params[AC_BK].aci_aifsn.aci = AC_BK;
+	pmadapter->ac_params[AC_BK].aci_aifsn.aifsn = 7;
+	pmadapter->ac_params[AC_BK].ecw.ecw_max = 10;
+	pmadapter->ac_params[AC_BK].ecw.ecw_min = 4;
+	pmadapter->ac_params[AC_BK].tx_op_limit = 0;
+
+	pmadapter->ac_params[AC_VI].aci_aifsn.acm = 0;
+	pmadapter->ac_params[AC_VI].aci_aifsn.aci = AC_VI;
+	pmadapter->ac_params[AC_VI].aci_aifsn.aifsn = 2;
+	pmadapter->ac_params[AC_VI].ecw.ecw_max = 4;
+	pmadapter->ac_params[AC_VI].ecw.ecw_min = 3;
+	pmadapter->ac_params[AC_VI].tx_op_limit = 188;
+
+	pmadapter->ac_params[AC_VO].aci_aifsn.acm = 0;
+	pmadapter->ac_params[AC_VO].aci_aifsn.aci = AC_VO;
+	pmadapter->ac_params[AC_VO].aci_aifsn.aifsn = 2;
+	pmadapter->ac_params[AC_VO].ecw.ecw_max = 3;
+	pmadapter->ac_params[AC_VO].ecw.ecw_min = 2;
+	pmadapter->ac_params[AC_VO].tx_op_limit = 102;
+}
+
+/**
+ *  @brief Initialize the WMM state information and the WMM data path queues.
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter data structure
+ *
+ *  @return         N/A
+ */
+t_void
+wlan_wmm_init(pmlan_adapter pmadapter)
+{
+	int i, j;
+	pmlan_private priv;
+
+	ENTER();
+
+	for (j = 0; j < pmadapter->priv_num; ++j) {
+		priv = pmadapter->priv[j];
+		if (priv) {
+			for (i = 0; i < MAX_NUM_TID; ++i) {
+				priv->aggr_prio_tbl[i].amsdu =
+					tos_to_tid_inv[i];
+				priv->aggr_prio_tbl[i].ampdu_ap =
+					priv->aggr_prio_tbl[i].ampdu_user =
+					tos_to_tid_inv[i];
+				priv->ibss_ampdu[i] =
+					priv->aggr_prio_tbl[i].ampdu_user;
+				priv->wmm.pkts_queued[i] = 0;
+				priv->wmm.pkts_paused[i] = 0;
+				priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
+			}
+			priv->wmm.drv_pkt_delay_max = WMM_DRV_DELAY_MAX;
+
+			priv->aggr_prio_tbl[6].amsdu = BA_STREAM_NOT_ALLOWED;
+			priv->aggr_prio_tbl[7].amsdu = BA_STREAM_NOT_ALLOWED;
+			priv->aggr_prio_tbl[6].ampdu_ap =
+				priv->aggr_prio_tbl[6].ampdu_user =
+				BA_STREAM_NOT_ALLOWED;
+			priv->ibss_ampdu[6] = BA_STREAM_NOT_ALLOWED;
+
+			priv->aggr_prio_tbl[7].ampdu_ap =
+				priv->aggr_prio_tbl[7].ampdu_user =
+				BA_STREAM_NOT_ALLOWED;
+			priv->ibss_ampdu[7] = BA_STREAM_NOT_ALLOWED;
+
+			priv->add_ba_param.timeout =
+				MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+#ifdef STA_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+				priv->add_ba_param.tx_win_size =
+					MLAN_STA_AMPDU_DEF_TXWINSIZE;
+				priv->add_ba_param.rx_win_size =
+					MLAN_STA_AMPDU_DEF_RXWINSIZE;
+			}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+				priv->add_ba_param.tx_win_size =
+					MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+				priv->add_ba_param.rx_win_size =
+					MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
+			}
+#endif
+#ifdef UAP_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+				priv->add_ba_param.tx_win_size =
+					MLAN_UAP_AMPDU_DEF_TXWINSIZE;
+				priv->add_ba_param.rx_win_size =
+					MLAN_UAP_AMPDU_DEF_RXWINSIZE;
+			}
+#endif
+			priv->user_rxwinsize = priv->add_ba_param.rx_win_size;
+			priv->add_ba_param.tx_amsdu = MTRUE;
+			priv->add_ba_param.rx_amsdu = MTRUE;
+			memset(priv->adapter, priv->rx_seq, 0xff,
+			       sizeof(priv->rx_seq));
+			wlan_wmm_default_queue_priorities(priv);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Setup the queue priorities and downgrade any queues as required
+ *         by the WMM info.  Setups default values if WMM is not active
+ *         for this association.
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+void
+wlan_wmm_setup_queues(pmlan_private priv)
+{
+	ENTER();
+	wlan_wmm_setup_queue_priorities(priv, MNULL);
+	wlan_wmm_setup_ac_downgrade(priv);
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief  Send a command to firmware to retrieve the current WMM status
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE
+ */
+mlan_status
+wlan_cmd_wmm_status_change(pmlan_private priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0,
+			       MNULL, MNULL);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Check if wmm TX queue is empty
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *
+ *  @return         MFALSE if not empty; MTRUE if empty
+ */
+int
+wlan_wmm_lists_empty(pmlan_adapter pmadapter)
+{
+	int j;
+	pmlan_private priv;
+
+	ENTER();
+
+	for (j = 0; j < pmadapter->priv_num; ++j) {
+		priv = pmadapter->priv[j];
+		if (priv) {
+			if ((priv->port_ctrl_mode == MTRUE) &&
+			    (priv->port_open == MFALSE)) {
+				PRINTM(MINFO,
+				       "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n",
+				       j);
+				continue;
+			}
+			if (priv->tx_pause)
+				continue;
+
+			if (util_scalar_read(pmadapter->pmoal_handle,
+					     &priv->wmm.tx_pkts_queued,
+					     pmadapter->callbacks.
+					     moal_spin_lock,
+					     pmadapter->callbacks.
+					     moal_spin_unlock)) {
+				LEAVE();
+				return MFALSE;
+			}
+		}
+	}
+
+	LEAVE();
+	return MTRUE;
+}
+
+/**
+ *   @brief Get ralist node
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param tid      TID
+ *   @param ra_addr  Pointer to the route address
+ *
+ *   @return         ra_list or MNULL
+ */
+raListTbl *
+wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
+{
+	raListTbl *ra_list;
+	ENTER();
+	ra_list =
+		(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[tid].ra_list,
+					    MNULL, MNULL);
+	while (ra_list &&
+	       (ra_list != (raListTbl *)&priv->wmm.tid_tbl_ptr[tid].ra_list)) {
+		if (!memcmp(priv->adapter, ra_list->ra, ra_addr,
+			    MLAN_MAC_ADDR_LENGTH)) {
+			LEAVE();
+			return ra_list;
+		}
+		ra_list = ra_list->pnext;
+	}
+	LEAVE();
+	return MNULL;
+}
+
+/**
+ *   @brief Check if RA list is valid or not
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param ra_list  Pointer to raListTbl
+ *   @param ptrindex TID pointer index
+ *
+ *   @return         MTRUE- valid. MFALSE- invalid.
+ */
+int
+wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int ptrindex)
+{
+	raListTbl *rlist;
+
+	ENTER();
+
+	rlist = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					    &priv->wmm.tid_tbl_ptr[ptrindex].
+					    ra_list, MNULL, MNULL);
+
+	while (rlist &&
+	       (rlist !=
+		(raListTbl *)&priv->wmm.tid_tbl_ptr[ptrindex].ra_list)) {
+		if (rlist == ra_list) {
+			LEAVE();
+			return MTRUE;
+		}
+
+		rlist = rlist->pnext;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief  Update an existing raList with a new RA and 11n capability
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *  @param old_ra   Old receiver address
+ *  @param new_ra   New receiver address
+ *
+ *  @return         integer count of updated nodes
+ */
+int
+wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
+{
+	t_u8 tid;
+	int update_count;
+	raListTbl *ra_list;
+
+	ENTER();
+
+	update_count = 0;
+
+	for (tid = 0; tid < MAX_NUM_TID; ++tid) {
+		ra_list = wlan_wmm_get_ralist_node(priv, tid, old_ra);
+
+		if (ra_list) {
+			update_count++;
+
+			if (queuing_ra_based(priv)) {
+				ra_list->is_11n_enabled =
+					wlan_is_11n_enabled(priv, new_ra);
+				if (ra_list->is_11n_enabled)
+					ra_list->max_amsdu =
+						get_station_max_amsdu_size(priv,
+									   new_ra);
+			} else {
+				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
+				if (ra_list->is_11n_enabled)
+					ra_list->max_amsdu = priv->max_amsdu;
+			}
+
+			ra_list->tx_pause = MFALSE;
+			ra_list->packet_count = 0;
+			ra_list->ba_packet_threshold =
+				wlan_get_random_ba_threshold(priv->adapter);
+			ra_list->amsdu_in_ampdu = MFALSE;
+			ra_list->ba_status = BA_STREAM_NOT_SETUP;
+			PRINTM(MINFO,
+			       "ralist_update: %p, %d, " MACSTR "-->" MACSTR
+			       "\n",
+			       ra_list, ra_list->is_11n_enabled,
+			       MAC2STR(ra_list->ra), MAC2STR(new_ra));
+
+			memcpy_ext(priv->adapter, ra_list->ra, new_ra,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		}
+	}
+
+	LEAVE();
+	return update_count;
+}
+
+/**
+ *  @brief Add packet to WMM queue
+ *
+ *  @param pmadapter  Pointer to the mlan_adapter driver data struct
+ *  @param pmbuf      Pointer to the mlan_buffer data struct
+ *
+ *  @return         N/A
+ */
+t_void
+wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
+{
+	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
+	t_u32 tid;
+	raListTbl *ra_list;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH], tid_down;
+	tdlsStatus_e status;
+#ifdef UAP_SUPPORT
+	psta_node sta_ptr = MNULL;
+#endif
+
+	ENTER();
+
+	pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+	if (!priv->media_connected) {
+		PRINTM_NETINTF(MWARN, priv);
+		PRINTM(MWARN, "Drop packet %p in disconnect state\n", pmbuf);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+		LEAVE();
+		return;
+	}
+	tid = pmbuf->priority;
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	tid_down = wlan_wmm_downgrade_tid(priv, tid);
+
+	/* In case of infra as we have already created the list during
+	   association we just don't have to call get_queue_raptr, we will have
+	   only 1 raptr for a tid in case of infra */
+	if (!queuing_ra_based(priv)) {
+		memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		status = wlan_get_tdls_link_status(priv, ra);
+		if (MTRUE == wlan_is_tdls_link_setup(status)) {
+			ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
+			pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
+		} else if (status == TDLS_SETUP_INPROGRESS) {
+			wlan_add_buf_tdls_txqueue(priv, pmbuf);
+			pmadapter->callbacks.moal_spin_unlock(pmadapter->
+							      pmoal_handle,
+							      priv->wmm.
+							      ra_list_spinlock);
+			LEAVE();
+			return;
+		} else
+			ra_list =
+				(raListTbl *)util_peek_list(pmadapter->
+							    pmoal_handle,
+							    &priv->wmm.
+							    tid_tbl_ptr
+							    [tid_down].ra_list,
+							    MNULL, MNULL);
+	} else {
+		memcpy_ext(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
+			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		/** put multicast/broadcast packet in the same ralist */
+		if (ra[0] & 0x01)
+			memset(pmadapter, ra, 0xff, sizeof(ra));
+#ifdef UAP_SUPPORT
+		else if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			sta_ptr = wlan_get_station_entry(priv, ra);
+			if (sta_ptr) {
+				if (!sta_ptr->is_wmm_enabled
+				    && !priv->is_11ac_enabled) {
+					tid_down = wlan_wmm_downgrade_tid(priv,
+									  0xff);
+				}
+			}
+		}
+#endif
+		ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, ra);
+	}
+
+	if (!ra_list) {
+		PRINTM_NETINTF(MWARN, priv);
+		PRINTM(MWARN,
+		       "Drop packet %p, ra_list=%p, media_connected=%d\n",
+		       pmbuf, ra_list, priv->media_connected);
+		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+						      priv->wmm.
+						      ra_list_spinlock);
+		wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE);
+		LEAVE();
+		return;
+	}
+
+	PRINTM_NETINTF(MDATA, priv);
+	PRINTM(MDATA,
+	       "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
+	       pmbuf, pmbuf->priority, tid_down, ra_list);
+	util_enqueue_list_tail(pmadapter->pmoal_handle, &ra_list->buf_head,
+			       (pmlan_linked_list)pmbuf, MNULL, MNULL);
+
+	ra_list->total_pkts++;
+	ra_list->packet_count++;
+
+	priv->wmm.pkts_queued[tid_down]++;
+	if (ra_list->tx_pause) {
+		priv->wmm.pkts_paused[tid_down]++;
+	} else {
+		util_scalar_increment(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		/* if highest_queued_prio < prio(tid_down), set it to
+		 * prio(tid_down) */
+		util_scalar_conditional_write(pmadapter->pmoal_handle,
+					      &priv->wmm.highest_queued_prio,
+					      MLAN_SCALAR_COND_LESS_THAN,
+					      tos_to_tid_inv[tid_down],
+					      tos_to_tid_inv[tid_down], MNULL,
+					      MNULL);
+	}
+	/* Record the current time the packet was queued; used to determine
+	 *   the amount of time the packet was queued in the driver before it
+	 *   was sent to the firmware.  The delay is then sent along with the
+	 *   packet to the firmware for aggregate delay calculation for stats
+	 *   and MSDU lifetime expiry.
+	 */
+	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
+						  &pmbuf->in_ts_sec,
+						  &pmbuf->in_ts_usec);
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Process the GET_WMM_STATUS command response from firmware
+ *
+ *  The GET_WMM_STATUS response may contain multiple TLVs for:
+ *      - AC Queue status TLVs
+ *      - Current WMM Parameter IE TLV
+ *      - Admission Control action frame TLVs
+ *
+ *  This function parses the TLVs and then calls further functions
+ *   to process any changes in the queue prioritize or state.
+ *
+ *  @param priv      Pointer to the mlan_private driver data struct
+ *  @param ptlv      Pointer to the tlv block returned in the response.
+ *  @param resp_len  Length of TLV block
+ *
+ *  @return MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv, int resp_len)
+{
+	t_u8 *pcurrent = ptlv;
+	t_u32 tlv_len;
+	t_u8 send_wmm_event;
+	MrvlIEtypes_Data_t *ptlv_hdr;
+	MrvlIEtypes_WmmQueueStatus_t *ptlv_wmm_q_status;
+	IEEEtypes_WmmParameter_t *pwmm_param_ie = MNULL;
+	WmmAcStatus_t *pac_status;
+
+	MrvlIETypes_ActionFrame_t *ptlv_action;
+	IEEEtypes_Action_WMM_AddTsRsp_t *padd_ts_rsp;
+	IEEEtypes_Action_WMM_DelTs_t *pdel_ts;
+
+	ENTER();
+
+	send_wmm_event = MFALSE;
+
+	PRINTM(MINFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", resp_len);
+	HEXDUMP("CMD_RESP: WMM_GET_STATUS", pcurrent, resp_len);
+
+	while (resp_len >= (int)sizeof(ptlv_hdr->header)) {
+		ptlv_hdr = (MrvlIEtypes_Data_t *)pcurrent;
+		tlv_len = wlan_le16_to_cpu(ptlv_hdr->header.len);
+		if ((int)(tlv_len + sizeof(ptlv_hdr->header)) > resp_len) {
+			PRINTM(MERROR,
+			       "WMM get status: Error in processing  TLV buffer\n");
+			resp_len = 0;
+			continue;
+		}
+
+		switch (wlan_le16_to_cpu(ptlv_hdr->header.type)) {
+		case TLV_TYPE_WMMQSTATUS:
+			ptlv_wmm_q_status =
+				(MrvlIEtypes_WmmQueueStatus_t *)ptlv_hdr;
+			PRINTM(MEVENT, "WMM_STATUS: QSTATUS TLV: %d\n",
+			       ptlv_wmm_q_status->queue_index);
+
+			PRINTM(MINFO,
+			       "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n",
+			       ptlv_wmm_q_status->queue_index,
+			       ptlv_wmm_q_status->flow_required,
+			       ptlv_wmm_q_status->disabled);
+
+			pac_status =
+				&priv->wmm.ac_status[ptlv_wmm_q_status->
+						     queue_index];
+			pac_status->disabled = ptlv_wmm_q_status->disabled;
+			pac_status->flow_required =
+				ptlv_wmm_q_status->flow_required;
+			pac_status->flow_created =
+				ptlv_wmm_q_status->flow_created;
+			break;
+
+		case TLV_TYPE_VENDOR_SPECIFIC_IE:	/* WMM_IE */
+			/*
+			 * Point the regular IEEE IE 2 bytes into the NXP IE
+			 *   and setup the IEEE IE type and length byte fields
+			 */
+
+			PRINTM(MEVENT, "WMM STATUS: WMM IE\n");
+
+			HEXDUMP("WMM: WMM TLV:", (t_u8 *)ptlv_hdr, tlv_len + 4);
+
+			pwmm_param_ie =
+				(IEEEtypes_WmmParameter_t *)(pcurrent + 2);
+			pwmm_param_ie->vend_hdr.len = (t_u8)tlv_len;
+			pwmm_param_ie->vend_hdr.element_id = WMM_IE;
+
+			PRINTM(MINFO,
+			       "CMD_RESP: WMM_GET_STATUS: WMM Parameter Set: %d\n",
+			       pwmm_param_ie->qos_info.para_set_count);
+
+			memcpy_ext(priv->adapter,
+				   (t_u8 *)&priv->curr_bss_params.
+				   bss_descriptor.wmm_ie, pwmm_param_ie,
+				   (pwmm_param_ie->vend_hdr.len + 2),
+				   sizeof(IEEEtypes_WmmParameter_t));
+			send_wmm_event = MTRUE;
+			break;
+
+		case TLV_TYPE_IEEE_ACTION_FRAME:
+			PRINTM(MEVENT, "WMM_STATUS: IEEE Action Frame\n");
+			ptlv_action = (MrvlIETypes_ActionFrame_t *)pcurrent;
+
+			ptlv_action->actionFrame.wmmAc.tspecAct.category =
+				wlan_le32_to_cpu(ptlv_action->actionFrame.wmmAc.
+						 tspecAct.category);
+			if (ptlv_action->actionFrame.wmmAc.tspecAct.category ==
+			    IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC) {
+				ptlv_action->actionFrame.wmmAc.tspecAct.action =
+					wlan_le32_to_cpu(ptlv_action->
+							 actionFrame.wmmAc.
+							 tspecAct.action);
+				switch (ptlv_action->actionFrame.wmmAc.tspecAct.
+					action) {
+				case TSPEC_ACTION_CODE_ADDTS_RSP:
+					padd_ts_rsp =
+						&ptlv_action->actionFrame.wmmAc.
+						addTsRsp;
+					wlan_send_wmmac_host_event(priv,
+								   "ADDTS_RSP",
+								   ptlv_action->
+								   srcAddr,
+								   padd_ts_rsp->
+								   tspecIE.
+								   TspecBody.
+								   TSInfo.TID,
+								   padd_ts_rsp->
+								   tspecIE.
+								   TspecBody.
+								   TSInfo.
+								   UserPri,
+								   padd_ts_rsp->
+								   statusCode);
+					break;
+
+				case TSPEC_ACTION_CODE_DELTS:
+					pdel_ts =
+						&ptlv_action->actionFrame.wmmAc.
+						delTs;
+					wlan_send_wmmac_host_event(priv,
+								   "DELTS_RX",
+								   ptlv_action->
+								   srcAddr,
+								   pdel_ts->
+								   tspecIE.
+								   TspecBody.
+								   TSInfo.TID,
+								   pdel_ts->
+								   tspecIE.
+								   TspecBody.
+								   TSInfo.
+								   UserPri,
+								   pdel_ts->
+								   reasonCode);
+					break;
+
+				case TSPEC_ACTION_CODE_ADDTS_REQ:
+				default:
+					break;
+				}
+			}
+			break;
+
+		default:
+			break;
+		}
+
+		pcurrent += (tlv_len + sizeof(ptlv_hdr->header));
+		resp_len -= (tlv_len + sizeof(ptlv_hdr->header));
+	}
+
+	wlan_wmm_setup_queue_priorities(priv, pwmm_param_ie);
+	wlan_wmm_setup_ac_downgrade(priv);
+
+	if (send_wmm_event) {
+		wlan_recv_event(priv, MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE,
+				MNULL);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Call back from the command module to allow insertion of a WMM TLV
+ *
+ *  If the BSS we are associating to supports WMM, add the required WMM
+ *    Information IE to the association request command buffer in the form
+ *    of a NXP extended IEEE IE.
+ *
+ *  @param priv         Pointer to the mlan_private driver data struct
+ *  @param ppassoc_buf  Output parameter: Pointer to the TLV output buffer,
+ *                      modified on return to point after the appended WMM TLV
+ *  @param pwmm_ie      Pointer to the WMM IE for the BSS we are joining
+ *  @param pht_cap      Pointer to the HT IE for the BSS we are joining
+ *
+ *  @return Length of data appended to the association tlv buffer
+ */
+t_u32
+wlan_wmm_process_association_req(pmlan_private priv, t_u8 **ppassoc_buf,
+				 IEEEtypes_WmmParameter_t *pwmm_ie,
+				 IEEEtypes_HTCap_t *pht_cap)
+{
+	MrvlIEtypes_WmmParamSet_t *pwmm_tlv;
+	t_u32 ret_len = 0;
+
+	ENTER();
+
+	/* Null checks */
+	if (!ppassoc_buf) {
+		LEAVE();
+		return 0;
+	}
+	if (!(*ppassoc_buf)) {
+		LEAVE();
+		return 0;
+	}
+
+	if (!pwmm_ie) {
+		LEAVE();
+		return 0;
+	}
+
+	PRINTM(MINFO, "WMM: process assoc req: bss->wmmIe=0x%x\n",
+	       pwmm_ie->vend_hdr.element_id);
+
+	if ((priv->wmm_required
+	     || (pht_cap && (pht_cap->ieee_hdr.element_id == HT_CAPABILITY) &&
+		 (priv->config_bands & BAND_GN || priv->config_bands & BAND_AN))
+	    )
+	    && pwmm_ie->vend_hdr.element_id == WMM_IE) {
+		pwmm_tlv = (MrvlIEtypes_WmmParamSet_t *)*ppassoc_buf;
+		pwmm_tlv->header.type = (t_u16)wmm_info_ie[0];
+		pwmm_tlv->header.type = wlan_cpu_to_le16(pwmm_tlv->header.type);
+		pwmm_tlv->header.len = (t_u16)wmm_info_ie[1];
+		memcpy_ext(priv->adapter, pwmm_tlv->wmm_ie, &wmm_info_ie[2],
+			   pwmm_tlv->header.len, pwmm_tlv->header.len);
+		if (pwmm_ie->qos_info.qos_uapsd)
+			memcpy_ext(priv->adapter,
+				   (t_u8 *)(pwmm_tlv->wmm_ie +
+					    pwmm_tlv->header.len -
+					    sizeof(priv->wmm_qosinfo)),
+				   &priv->wmm_qosinfo,
+				   sizeof(priv->wmm_qosinfo),
+				   sizeof(priv->wmm_qosinfo));
+
+		ret_len = sizeof(pwmm_tlv->header) + pwmm_tlv->header.len;
+		pwmm_tlv->header.len = wlan_cpu_to_le16(pwmm_tlv->header.len);
+
+		HEXDUMP("ASSOC_CMD: WMM IE", (t_u8 *)pwmm_tlv, ret_len);
+		*ppassoc_buf += ret_len;
+	}
+
+	LEAVE();
+	return ret_len;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *   @brief Compute the time delay in the driver queues for a given packet.
+ *
+ *   When the packet is received at the OS/Driver interface, the current
+ *     time is set in the packet structure.  The difference between the present
+ *     time and that received time is computed in this function and limited
+ *     based on pre-compiled limits in the driver.
+ *
+ *   @param priv   Ptr to the mlan_private driver data struct
+ *   @param pmbuf  Ptr to the mlan_buffer which has been previously timestamped
+ *
+ *   @return  Time delay of the packet in 2ms units after having limit applied
+ */
+t_u8
+wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+				     const pmlan_buffer pmbuf)
+{
+	t_u8 ret_val = 0;
+	t_u32 out_ts_sec, out_ts_usec;
+	t_s32 queue_delay;
+
+	ENTER();
+
+	priv->adapter->callbacks.moal_get_system_time(priv->adapter->
+						      pmoal_handle, &out_ts_sec,
+						      &out_ts_usec);
+	if (priv->adapter->tp_state_on) {
+		pmbuf->out_ts_sec = out_ts_sec;
+		pmbuf->out_ts_usec = out_ts_usec;
+		if (pmbuf->in_ts_sec)
+			priv->adapter->callbacks.moal_tp_accounting(priv->
+								    adapter->
+								    pmoal_handle,
+								    pmbuf, 11);
+	}
+	queue_delay = (t_s32)(out_ts_sec - pmbuf->in_ts_sec) * 1000;
+	queue_delay += (t_s32)(out_ts_usec - pmbuf->in_ts_usec) / 1000;
+
+	/*
+	 * Queue delay is passed as a uint8 in units of 2ms (ms shifted
+	 *  by 1). Min value (other than 0) is therefore 2ms, max is 510ms.
+	 *
+	 * Pass max value if queue_delay is beyond the uint8 range
+	 */
+	ret_val =
+		(t_u8)(MIN(queue_delay, (t_s32)priv->wmm.drv_pkt_delay_max) >>
+		       1);
+
+	PRINTM(MINFO, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n", queue_delay,
+	       ret_val);
+
+	LEAVE();
+	return ret_val;
+}
+
+/**
+ *  @brief Transmit the highest priority packet awaiting in the WMM Queues
+ *
+ *  @param pmadapter Pointer to the mlan_adapter driver data struct
+ *
+ *  @return        N/A
+ */
+void
+wlan_wmm_process_tx(pmlan_adapter pmadapter)
+{
+	ENTER();
+
+	do {
+		if (wlan_dequeue_tx_packet(pmadapter))
+			break;
+#ifdef SDIO
+		if (IS_SD(pmadapter->card_type) &&
+		    (pmadapter->ireg & UP_LD_CMD_PORT_HOST_INT_STATUS)) {
+			wlan_send_mp_aggr_buf(pmadapter);
+			break;
+		}
+#endif
+
+#ifdef PCIE
+		if (IS_PCIE(pmadapter->card_type) &&
+		    (pmadapter->ireg &
+		     pmadapter->pcard_pcie->reg->host_intr_event_rdy))
+			break;
+#endif
+#ifdef USB
+		if (IS_USB(pmadapter->card_type) && pmadapter->event_received)
+			break;
+#endif
+		/* Check if busy */
+	} while (!pmadapter->data_sent && !pmadapter->tx_lock_flag &&
+		 !wlan_wmm_lists_empty(pmadapter));
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief select wmm queue
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param tid          TID 0-7
+ *
+ *  @return             wmm_queue priority (0-3)
+ */
+t_u8
+wlan_wmm_select_queue(mlan_private *pmpriv, t_u8 tid)
+{
+	pmlan_adapter pmadapter = pmpriv->adapter;
+	t_u8 i;
+	mlan_wmm_ac_e ac_down =
+		pmpriv->wmm.
+		ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(pmadapter, tid)];
+
+	ENTER();
+
+	for (i = 0; i < 4; i++) {
+		if (pmpriv->wmm.queue_priority[i] == ac_down) {
+			LEAVE();
+			return i;
+		}
+	}
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Delete tx packets in RA list
+ *
+ *  @param priv			Pointer to the mlan_private driver data struct
+ *  @param ra_list_head	ra list header
+ *  @param tid          tid
+ *
+ *  @return		N/A
+ */
+static INLINE t_u8
+wlan_del_tx_pkts_in_ralist(pmlan_private priv,
+			   mlan_list_head *ra_list_head, int tid)
+{
+	raListTbl *ra_list = MNULL;
+	pmlan_adapter pmadapter = priv->adapter;
+	pmlan_buffer pmbuf = MNULL;
+	t_u8 ret = MFALSE;
+	ENTER();
+	ra_list = (raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+					      ra_list_head, MNULL, MNULL);
+	while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+		if (ra_list->total_pkts &&
+		    (ra_list->tx_pause ||
+		     (ra_list->total_pkts > RX_LOW_THRESHOLD))) {
+			pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->
+								pmoal_handle,
+								&ra_list->
+								buf_head, MNULL,
+								MNULL);
+			if (pmbuf) {
+				PRINTM(MDATA,
+				       "Drop pkts: tid=%d tx_pause=%d pkts=%d "
+				       MACSTR "\n", tid, ra_list->tx_pause,
+				       ra_list->total_pkts,
+				       MAC2STR(ra_list->ra));
+				wlan_write_data_complete(pmadapter, pmbuf,
+							 MLAN_STATUS_FAILURE);
+				priv->wmm.pkts_queued[tid]--;
+				priv->num_drop_pkts++;
+				ra_list->total_pkts--;
+				if (ra_list->tx_pause)
+					priv->wmm.pkts_paused[tid]--;
+				else
+					util_scalar_decrement(pmadapter->
+							      pmoal_handle,
+							      &priv->wmm.
+							      tx_pkts_queued,
+							      MNULL, MNULL);
+				ret = MTRUE;
+				break;
+			}
+		}
+		ra_list = ra_list->pnext;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Drop tx pkts
+ *
+ *  @param priv			Pointer to the mlan_private driver data struct
+ *
+ *  @return		N/A
+ */
+t_void
+wlan_drop_tx_pkts(pmlan_private priv)
+{
+	int j;
+	static int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	for (j = 0; j < MAX_NUM_TID; j++, i++) {
+		if (i == MAX_NUM_TID)
+			i = 0;
+		if (wlan_del_tx_pkts_in_ralist
+		    (priv, &priv->wmm.tid_tbl_ptr[i].ra_list, i)) {
+			i++;
+			break;
+		}
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	return;
+}
+
+/**
+ *  @brief Remove peer ralist
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param mac        peer mac address
+ *
+ *  @return           N/A
+ */
+t_void
+wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
+{
+	raListTbl *ra_list;
+	int i;
+	pmlan_adapter pmadapter = priv->adapter;
+	t_u32 pkt_cnt = 0;
+	t_u32 tx_pkts_queued = 0;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
+		if (ra_list) {
+			PRINTM(MINFO, "delete sta ralist %p\n", ra_list);
+			priv->wmm.pkts_queued[i] -= ra_list->total_pkts;
+			if (ra_list->tx_pause)
+				priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
+			else
+				pkt_cnt += ra_list->total_pkts;
+			wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
+
+			util_unlink_list(pmadapter->pmoal_handle,
+					 &priv->wmm.tid_tbl_ptr[i].ra_list,
+					 (pmlan_linked_list)ra_list, MNULL,
+					 MNULL);
+			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+							(t_u8 *)ra_list);
+			if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
+				priv->wmm.tid_tbl_ptr[i].ra_list_curr =
+					(raListTbl *)&priv->wmm.tid_tbl_ptr[i]
+					.ra_list;
+		}
+	}
+	if (pkt_cnt) {
+		tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
+						  &priv->wmm.tx_pkts_queued,
+						  MNULL, MNULL);
+		tx_pkts_queued -= pkt_cnt;
+		util_scalar_write(priv->adapter->pmoal_handle,
+				  &priv->wmm.tx_pkts_queued, tx_pkts_queued,
+				  MNULL, MNULL);
+		util_scalar_write(priv->adapter->pmoal_handle,
+				  &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
+				  MNULL, MNULL);
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Hold TDLS packets to tdls pending queue
+ *
+ *  @param priv		A pointer to mlan_private
+ *  @param mac      station mac address
+ *
+ *  @return      N/A
+ */
+t_void
+wlan_hold_tdls_packets(pmlan_private priv, t_u8 *mac)
+{
+	pmlan_buffer pmbuf;
+	mlan_adapter *pmadapter = priv->adapter;
+	raListTbl *ra_list = MNULL;
+	t_u8 i;
+
+	ENTER();
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+	PRINTM(MDATA, "wlan_hold_tdls_packets: " MACSTR "\n", MAC2STR(mac));
+	for (i = 0; i < MAX_NUM_TID; ++i) {
+		ra_list = (raListTbl *)util_peek_list(pmadapter->pmoal_handle,
+						      &priv->wmm.tid_tbl_ptr[i].
+						      ra_list, MNULL, MNULL);
+		if (ra_list) {
+			while ((pmbuf = wlan_find_tdls_packets(priv, ra_list,
+							       mac))) {
+				util_unlink_list(pmadapter->pmoal_handle,
+						 &ra_list->buf_head,
+						 (pmlan_linked_list)pmbuf,
+						 MNULL, MNULL);
+				ra_list->total_pkts--;
+				priv->wmm.pkts_queued[i]--;
+				util_scalar_decrement(pmadapter->pmoal_handle,
+						      &priv->wmm.tx_pkts_queued,
+						      MNULL, MNULL);
+				ra_list->packet_count--;
+				wlan_add_buf_tdls_txqueue(priv, pmbuf);
+				PRINTM(MDATA, "hold tdls packet=%p\n", pmbuf);
+			}
+		}
+	}
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+}
+
+/**
+ *  @brief move TDLS packets back to ralist
+ *
+ *  @param priv		  A pointer to mlan_private
+ *  @param mac        TDLS peer mac address
+ *  @param status     tdlsStatus
+ *
+ *  @return           pmlan_buffer or MNULL
+ */
+t_void
+wlan_restore_tdls_packets(pmlan_private priv, t_u8 *mac, tdlsStatus_e status)
+{
+	pmlan_buffer pmbuf;
+	mlan_adapter *pmadapter = priv->adapter;
+	raListTbl *ra_list = MNULL;
+	t_u32 tid;
+	t_u32 tid_down;
+
+	ENTER();
+	PRINTM(MDATA, "wlan_restore_tdls_packets: " MACSTR " status=%d\n",
+	       MAC2STR(mac), status);
+
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    priv->wmm.ra_list_spinlock);
+
+	while ((pmbuf = wlan_find_packets_tdls_txq(priv, mac))) {
+		util_unlink_list(pmadapter->pmoal_handle,
+				 &priv->tdls_pending_txq,
+				 (pmlan_linked_list)pmbuf, MNULL, MNULL);
+		tid = pmbuf->priority;
+		tid_down = wlan_wmm_downgrade_tid(priv, tid);
+		if (status == TDLS_SETUP_COMPLETE) {
+			ra_list = wlan_wmm_get_queue_raptr(priv, tid_down, mac);
+			pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
+		} else {
+			ra_list =
+				(raListTbl *)util_peek_list(pmadapter->
+							    pmoal_handle,
+							    &priv->wmm.
+							    tid_tbl_ptr
+							    [tid_down].ra_list,
+							    MNULL, MNULL);
+			pmbuf->flags &= ~MLAN_BUF_FLAG_TDLS;
+		}
+		if (!ra_list) {
+			PRINTM_NETINTF(MWARN, priv);
+			PRINTM(MWARN,
+			       "Drop packet %p, ra_list=%p media_connected=%d\n",
+			       pmbuf, ra_list, priv->media_connected);
+			wlan_write_data_complete(pmadapter, pmbuf,
+						 MLAN_STATUS_FAILURE);
+			continue;
+		}
+		PRINTM_NETINTF(MDATA, priv);
+		PRINTM(MDATA,
+		       "ADD TDLS pkt %p (priority=%d) back to ra_list %p\n",
+		       pmbuf, pmbuf->priority, ra_list);
+		util_enqueue_list_tail(pmadapter->pmoal_handle,
+				       &ra_list->buf_head,
+				       (pmlan_linked_list)pmbuf, MNULL, MNULL);
+		ra_list->total_pkts++;
+		ra_list->packet_count++;
+		priv->wmm.pkts_queued[tid_down]++;
+		util_scalar_increment(pmadapter->pmoal_handle,
+				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+		util_scalar_conditional_write(pmadapter->pmoal_handle,
+					      &priv->wmm.highest_queued_prio,
+					      MLAN_SCALAR_COND_LESS_THAN,
+					      tos_to_tid_inv[tid_down],
+					      tos_to_tid_inv[tid_down], MNULL,
+					      MNULL);
+	}
+	if (status != TDLS_SETUP_COMPLETE)
+		wlan_wmm_delete_tdls_ralist(priv, mac);
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      priv->wmm.ra_list_spinlock);
+	LEAVE();
+}
+
+/**
+ *  @brief This function prepares the command of ADDTS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wmm_addts_req(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_ds_wmm_addts *paddts = (mlan_ds_wmm_addts *)pdata_buf;
+	HostCmd_DS_WMM_ADDTS_REQ *pcmd_addts = &cmd->params.add_ts;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_ADDTS_REQ);
+	cmd->size = wlan_cpu_to_le16(sizeof(pcmd_addts->dialog_token) +
+				     sizeof(pcmd_addts->timeout_ms) +
+				     sizeof(pcmd_addts->command_result) +
+				     sizeof(pcmd_addts->ieee_status_code) +
+				     paddts->ie_data_len + S_DS_GEN);
+	cmd->result = 0;
+
+	pcmd_addts->timeout_ms = wlan_cpu_to_le32(paddts->timeout);
+	pcmd_addts->dialog_token = paddts->dialog_tok;
+	memcpy_ext(pmpriv->adapter, pcmd_addts->tspec_data, paddts->ie_data,
+		   paddts->ie_data_len, WMM_TSPEC_SIZE);
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of ADDTS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_addts_req(pmlan_private pmpriv,
+		       const HostCmd_DS_COMMAND *resp,
+		       mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_wmm_cfg *pwmm = MNULL;
+	mlan_ds_wmm_addts *paddts = MNULL;
+	const HostCmd_DS_WMM_ADDTS_REQ *presp_addts = &resp->params.add_ts;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+		paddts = (mlan_ds_wmm_addts *)&pwmm->param.addts;
+		paddts->result = wlan_le32_to_cpu(presp_addts->command_result);
+		paddts->dialog_tok = presp_addts->dialog_token;
+		paddts->status_code = (t_u32)presp_addts->ieee_status_code;
+
+		if (paddts->result == MLAN_CMD_RESULT_SUCCESS) {
+			/* The tspecData field is potentially variable in size
+			 * due to extra IEs that may have been in the ADDTS
+			 * response action frame. Calculate the data length from
+			 * the firmware command response.
+			 */
+			paddts->ie_data_len =
+				(t_u8)(resp->size -
+				       sizeof(presp_addts->command_result) -
+				       sizeof(presp_addts->timeout_ms) -
+				       sizeof(presp_addts->dialog_token) -
+				       sizeof(presp_addts->ieee_status_code) -
+				       S_DS_GEN);
+
+			/* Copy the TSPEC data include any extra IEs after the
+			 * TSPEC */
+			memcpy_ext(pmpriv->adapter, paddts->ie_data,
+				   presp_addts->tspec_data, paddts->ie_data_len,
+				   sizeof(paddts->ie_data));
+		} else {
+			paddts->ie_data_len = 0;
+		}
+		PRINTM(MINFO, "TSPEC: ADDTS ret = %d,%d sz=%d\n",
+		       paddts->result, paddts->status_code,
+		       paddts->ie_data_len);
+
+		HEXDUMP("TSPEC: ADDTS data", paddts->ie_data,
+			paddts->ie_data_len);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command of DELTS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wmm_delts_req(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_ds_wmm_delts *pdelts = (mlan_ds_wmm_delts *)pdata_buf;
+	HostCmd_DS_WMM_DELTS_REQ *pcmd_delts = &cmd->params.del_ts;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_DELTS_REQ);
+	cmd->size = wlan_cpu_to_le16(sizeof(pcmd_delts->dialog_token) +
+				     sizeof(pcmd_delts->command_result) +
+				     sizeof(pcmd_delts->ieee_reason_code) +
+				     pdelts->ie_data_len + S_DS_GEN);
+	cmd->result = 0;
+	pcmd_delts->ieee_reason_code = (t_u8)pdelts->status_code;
+	memcpy_ext(pmpriv->adapter, pcmd_delts->tspec_data, pdelts->ie_data,
+		   pdelts->ie_data_len, WMM_TSPEC_SIZE);
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of DELTS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_delts_req(pmlan_private pmpriv,
+		       const HostCmd_DS_COMMAND *resp,
+		       mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_wmm_cfg *pwmm;
+	IEEEtypes_WMM_TSPEC_t *ptspec_ie;
+	const HostCmd_DS_WMM_DELTS_REQ *presp_delts = &resp->params.del_ts;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+		pwmm->param.delts.result =
+			wlan_le32_to_cpu(presp_delts->command_result);
+
+		PRINTM(MINFO, "TSPEC: DELTS result = %d\n",
+		       presp_delts->command_result);
+
+		if (pwmm->param.delts.result == 0) {
+			ptspec_ie = (IEEEtypes_WMM_TSPEC_t *)
+				presp_delts->tspec_data;
+			wlan_send_wmmac_host_event(pmpriv, "DELTS_TX", MNULL,
+						   ptspec_ie->TspecBody.TSInfo.
+						   TID,
+						   ptspec_ie->TspecBody.TSInfo.
+						   UserPri,
+						   presp_delts->
+						   ieee_reason_code);
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command of WMM_QUEUE_STATS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wmm_queue_stats(pmlan_private pmpriv,
+			 HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_ds_wmm_queue_stats *pqstats = (mlan_ds_wmm_queue_stats *)pdata_buf;
+	HostCmd_DS_WMM_QUEUE_STATS *pcmd_qstats = &cmd->params.queue_stats;
+	t_u8 id;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_STATS);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_QUEUE_STATS) + S_DS_GEN);
+	cmd->result = 0;
+
+	pcmd_qstats->action = pqstats->action;
+	pcmd_qstats->select_is_userpri = 1;
+	pcmd_qstats->select_bin = pqstats->user_priority;
+	pcmd_qstats->pkt_count = wlan_cpu_to_le16(pqstats->pkt_count);
+	pcmd_qstats->pkt_loss = wlan_cpu_to_le16(pqstats->pkt_loss);
+	pcmd_qstats->avg_queue_delay =
+		wlan_cpu_to_le32(pqstats->avg_queue_delay);
+	pcmd_qstats->avg_tx_delay = wlan_cpu_to_le32(pqstats->avg_tx_delay);
+	pcmd_qstats->used_time = wlan_cpu_to_le16(pqstats->used_time);
+	pcmd_qstats->policed_time = wlan_cpu_to_le16(pqstats->policed_time);
+	for (id = 0; id < MLAN_WMM_STATS_PKTS_HIST_BINS; id++) {
+		pcmd_qstats->delay_histogram[id] =
+			wlan_cpu_to_le16(pqstats->delay_histogram[id]);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of WMM_QUEUE_STATS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_queue_stats(pmlan_private pmpriv,
+			 const HostCmd_DS_COMMAND *resp,
+			 mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_wmm_cfg *pwmm = MNULL;
+	mlan_ds_wmm_queue_stats *pqstats = MNULL;
+	const HostCmd_DS_WMM_QUEUE_STATS *presp_qstats =
+		&resp->params.queue_stats;
+	t_u8 id;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+		pqstats = (mlan_ds_wmm_queue_stats *)&pwmm->param.q_stats;
+
+		pqstats->action = presp_qstats->action;
+		pqstats->user_priority = presp_qstats->select_bin;
+		pqstats->pkt_count = wlan_le16_to_cpu(presp_qstats->pkt_count);
+		pqstats->pkt_loss = wlan_le16_to_cpu(presp_qstats->pkt_loss);
+		pqstats->avg_queue_delay =
+			wlan_le32_to_cpu(presp_qstats->avg_queue_delay);
+		pqstats->avg_tx_delay =
+			wlan_le32_to_cpu(presp_qstats->avg_tx_delay);
+		pqstats->used_time = wlan_le16_to_cpu(presp_qstats->used_time);
+		pqstats->policed_time =
+			wlan_le16_to_cpu(presp_qstats->policed_time);
+		for (id = 0; id < MLAN_WMM_STATS_PKTS_HIST_BINS; id++) {
+			pqstats->delay_histogram[id] =
+				wlan_le16_to_cpu(presp_qstats->
+						 delay_histogram[id]);
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command of WMM_TS_STATUS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wmm_ts_status(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_ds_wmm_ts_status *pts_status = (mlan_ds_wmm_ts_status *)pdata_buf;
+	HostCmd_DS_WMM_TS_STATUS *pcmd_ts_status = &cmd->params.ts_status;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_TS_STATUS);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_TS_STATUS) + S_DS_GEN);
+	cmd->result = 0;
+
+	memcpy_ext(pmpriv->adapter, (t_void *)pcmd_ts_status,
+		   (t_void *)pts_status, sizeof(HostCmd_DS_WMM_TS_STATUS),
+		   sizeof(HostCmd_DS_WMM_TS_STATUS));
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of WMM_TS_STATUS
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_ts_status(pmlan_private pmpriv,
+		       HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_wmm_cfg *pwmm = MNULL;
+	HostCmd_DS_WMM_TS_STATUS *presp_ts_status = &resp->params.ts_status;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+		presp_ts_status->medium_time =
+			wlan_le16_to_cpu(presp_ts_status->medium_time);
+		memcpy_ext(pmpriv->adapter, (t_void *)&pwmm->param.ts_status,
+			   (t_void *)presp_ts_status,
+			   sizeof(mlan_ds_wmm_ts_status),
+			   sizeof(mlan_ds_wmm_ts_status));
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get WMM status
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_wmm_ioctl_enable(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *wmm = MNULL;
+	ENTER();
+	wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_GET)
+		wmm->param.wmm_enable = (t_u32)pmpriv->wmm_required;
+	else
+		pmpriv->wmm_required = (t_u8)wmm->param.wmm_enable;
+	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get WMM QoS configuration
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_wmm_ioctl_qos(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *wmm = MNULL;
+
+	ENTER();
+
+	wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+	if (pioctl_req->action == MLAN_ACT_GET)
+		wmm->param.qos_cfg = pmpriv->wmm_qosinfo;
+	else {
+		pmpriv->wmm_qosinfo = wmm->param.qos_cfg;
+		pmpriv->saved_wmm_qosinfo = wmm->param.qos_cfg;
+	}
+
+	pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Request for add a TSPEC
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_wmm_ioctl_addts_req(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *cfg = MNULL;
+
+	ENTER();
+	cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_ADDTS_REQ, 0, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.addts);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Request for delete a TSPEC
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_wmm_ioctl_delts_req(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *cfg = MNULL;
+
+	ENTER();
+	cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_DELTS_REQ, 0, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.delts);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief To get and start/stop queue stats on a WMM AC
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_wmm_ioctl_queue_stats(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *cfg = MNULL;
+
+	ENTER();
+	cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_STATS, 0, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.q_stats);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the status of the WMM AC queues
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success
+ */
+static mlan_status
+wlan_wmm_ioctl_queue_status(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *cfg = MNULL;
+	mlan_ds_wmm_queue_status *pqstatus = MNULL;
+	WmmAcStatus_t *pac_status = MNULL;
+	mlan_wmm_ac_e ac_idx;
+
+	ENTER();
+
+	cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+	pqstatus = (mlan_ds_wmm_queue_status *)&cfg->param.q_status;
+
+	for (ac_idx = WMM_AC_BK; ac_idx <= WMM_AC_VO; ac_idx++) {
+		pac_status = &pmpriv->wmm.ac_status[ac_idx];
+
+		/* Firmware status */
+		pqstatus->ac_status[ac_idx].flow_required =
+			pac_status->flow_required;
+		pqstatus->ac_status[ac_idx].flow_created =
+			pac_status->flow_created;
+		pqstatus->ac_status[ac_idx].disabled = pac_status->disabled;
+
+		/* ACM bit reflected in firmware status (redundant) */
+		pqstatus->ac_status[ac_idx].wmm_acm = pac_status->flow_required;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get the status of the WMM Traffic Streams
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_wmm_ioctl_ts_status(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *cfg = MNULL;
+
+	ENTER();
+
+	cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_TS_STATUS, 0, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.ts_status);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief This function prepares the command of WMM_PARAM_CONFIG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   cmd action.
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wmm_param_config(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd,
+			  t_u8 cmd_action, t_void *pdata_buf)
+{
+	wmm_ac_parameters_t *ac_params = (wmm_ac_parameters_t *)pdata_buf;
+	HostCmd_DS_WMM_PARAM_CONFIG *pcmd_cfg = &cmd->params.param_config;
+	t_u8 i = 0;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_PARAM_CONFIG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_PARAM_CONFIG) +
+				     S_DS_GEN);
+	cmd->result = 0;
+
+	pcmd_cfg->action = cmd_action;
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		memcpy_ext(pmpriv->adapter, pcmd_cfg->ac_params, ac_params,
+			   sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES,
+			   sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
+		for (i = 0; i < MAX_AC_QUEUES; i++) {
+			pcmd_cfg->ac_params[i].tx_op_limit =
+				wlan_cpu_to_le16(pcmd_cfg->ac_params[i].
+						 tx_op_limit);
+		}
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of WMM_PARAM_CONFIG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_param_config(pmlan_private pmpriv,
+			  const HostCmd_DS_COMMAND *resp,
+			  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_wmm_cfg *pwmm = MNULL;
+	HostCmd_DS_WMM_PARAM_CONFIG *pcfg =
+		(HostCmd_DS_WMM_PARAM_CONFIG *) & resp->params.param_config;
+	t_u8 i;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+		for (i = 0; i < MAX_AC_QUEUES; i++) {
+			pcfg->ac_params[i].tx_op_limit =
+				wlan_le16_to_cpu(pcfg->ac_params[i].
+						 tx_op_limit);
+		}
+		memcpy_ext(pmpriv->adapter, pwmm->param.ac_params,
+			   pcfg->ac_params,
+			   sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES,
+			   sizeof(wmm_ac_parameters_t) * MAX_AC_QUEUES);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares the command of WMM_QUEUE_CONFIG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_cmd_wmm_queue_config(pmlan_private pmpriv,
+			  HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
+{
+	mlan_ds_wmm_queue_config *pqcfg = (mlan_ds_wmm_queue_config *)pdata_buf;
+	HostCmd_DS_WMM_QUEUE_CONFIG *pcmd_qcfg = &cmd->params.queue_config;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(pcmd_qcfg->action) +
+				 sizeof(pcmd_qcfg->access_category) +
+				 sizeof(pcmd_qcfg->msdu_lifetime_expiry) +
+				 S_DS_GEN);
+	cmd->result = 0;
+
+	pcmd_qcfg->action = pqcfg->action;
+	pcmd_qcfg->access_category = pqcfg->access_category;
+	pcmd_qcfg->msdu_lifetime_expiry =
+		wlan_cpu_to_le16(pqcfg->msdu_lifetime_expiry);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of WMM_QUEUE_CONFIG
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status
+wlan_ret_wmm_queue_config(pmlan_private pmpriv,
+			  const HostCmd_DS_COMMAND *resp,
+			  mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_wmm_cfg *pwmm = MNULL;
+	const HostCmd_DS_WMM_QUEUE_CONFIG *presp_qcfg =
+		&resp->params.queue_config;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		pwmm = (mlan_ds_wmm_cfg *)pioctl_buf->pbuf;
+		pwmm->param.q_cfg.action = wlan_le32_to_cpu(presp_qcfg->action);
+		pwmm->param.q_cfg.access_category =
+			wlan_le32_to_cpu(presp_qcfg->access_category);
+		pwmm->param.q_cfg.msdu_lifetime_expiry =
+			wlan_le16_to_cpu(presp_qcfg->msdu_lifetime_expiry);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get a specified AC Queue's parameters
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to ioctl request buffer
+ *
+ *  @return             MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status
+wlan_wmm_ioctl_queue_config(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_wmm_cfg *cfg = MNULL;
+
+	ENTER();
+	cfg = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_CONFIG, 0, 0,
+			       (t_void *)pioctl_req,
+			       (t_void *)&cfg->param.q_cfg);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief WMM configuration handler
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req A pointer to ioctl request buffer
+ *
+ *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status
+wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_wmm_cfg *wmm = MNULL;
+
+	ENTER();
+
+	if (pioctl_req->buf_len < sizeof(mlan_ds_wmm_cfg)) {
+		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
+		pioctl_req->data_read_written = 0;
+		pioctl_req->buf_len_needed = sizeof(mlan_ds_wmm_cfg);
+		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+		LEAVE();
+		return MLAN_STATUS_RESOURCE;
+	}
+	wmm = (mlan_ds_wmm_cfg *)pioctl_req->pbuf;
+	switch (wmm->sub_command) {
+#ifdef STA_SUPPORT
+	case MLAN_OID_WMM_CFG_ENABLE:
+		status = wlan_wmm_ioctl_enable(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_WMM_CFG_QOS:
+		status = wlan_wmm_ioctl_qos(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_WMM_CFG_ADDTS:
+		status = wlan_wmm_ioctl_addts_req(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_WMM_CFG_DELTS:
+		status = wlan_wmm_ioctl_delts_req(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_WMM_CFG_QUEUE_STATS:
+		status = wlan_wmm_ioctl_queue_stats(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_WMM_CFG_QUEUE_STATUS:
+		status = wlan_wmm_ioctl_queue_status(pmadapter, pioctl_req);
+		break;
+	case MLAN_OID_WMM_CFG_TS_STATUS:
+		status = wlan_wmm_ioctl_ts_status(pmadapter, pioctl_req);
+		break;
+#endif
+	case MLAN_OID_WMM_CFG_QUEUE_CONFIG:
+		status = wlan_wmm_ioctl_queue_config(pmadapter, pioctl_req);
+		break;
+	default:
+		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
+		status = MLAN_STATUS_FAILURE;
+		break;
+	}
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get ralist info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *  @param buf          A pointer to ralist_info structure
+ *  @return             number of ralist entry
+ *
+ */
+int
+wlan_get_ralist_info(mlan_private *priv, ralist_info *buf)
+{
+	ralist_info *plist = buf;
+	mlan_list_head *ra_list_head = MNULL;
+	raListTbl *ra_list;
+	int i;
+	int count = 0;
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
+		ra_list =
+			(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						    ra_list_head, MNULL, MNULL);
+		while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+			if (ra_list->total_pkts) {
+				plist->total_pkts = ra_list->total_pkts;
+				plist->tid = i;
+				plist->tx_pause = ra_list->tx_pause;
+				memcpy_ext(priv->adapter, plist->ra,
+					   ra_list->ra, MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+				plist++;
+				count++;
+				if (count >= MLAN_MAX_RALIST_NUM)
+					break;
+			}
+			ra_list = ra_list->pnext;
+		}
+	}
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief dump ralist info
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ *
+ */
+void
+wlan_dump_ralist(mlan_private *priv)
+{
+	mlan_list_head *ra_list_head = MNULL;
+	raListTbl *ra_list;
+	mlan_adapter *pmadapter = priv->adapter;
+	int i;
+	t_u32 tx_pkts_queued;
+
+	tx_pkts_queued =
+		util_scalar_read(pmadapter->pmoal_handle,
+				 &priv->wmm.tx_pkts_queued, MNULL, MNULL);
+	PRINTM(MERROR, "bss_index = %d, tx_pkts_queued = %d\n", priv->bss_index,
+	       tx_pkts_queued);
+	if (!tx_pkts_queued)
+		return;
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
+		ra_list =
+			(raListTbl *)util_peek_list(priv->adapter->pmoal_handle,
+						    ra_list_head, MNULL, MNULL);
+		while (ra_list && ra_list != (raListTbl *)ra_list_head) {
+			if (ra_list->total_pkts) {
+				PRINTM(MERROR,
+				       "ralist ra: %02x:%02x:%02x:%02x:%02x:%02x tid=%d pkts=%d pause=%d\n",
+				       ra_list->ra[0], ra_list->ra[1],
+				       ra_list->ra[2], ra_list->ra[3],
+				       ra_list->ra[4], ra_list->ra[5], i,
+				       ra_list->total_pkts, ra_list->tx_pause);
+			}
+			ra_list = ra_list->pnext;
+		}
+	}
+	return;
+}
+
+/**
+ *  @brief get tid down
+ *
+ *  @param priv         A pointer to mlan_private structure
+ * 	@param tid 			tid
+ *
+ *  @return             tid_down
+ *
+ */
+int
+wlan_get_wmm_tid_down(mlan_private *priv, int tid)
+{
+	return wlan_wmm_downgrade_tid(priv, tid);
+}
diff --git a/wlan_sd8987/mlan/mlan_wmm.h b/wlan_sd8987/mlan/mlan_wmm.h
new file mode 100755
index 0000000..73ce820
--- /dev/null
+++ b/wlan_sd8987/mlan/mlan_wmm.h
@@ -0,0 +1,249 @@
+/** @file mlan_wmm.h
+ *
+ *  @brief This file contains related macros, enum, and struct
+ *  of wmm functionalities
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/****************************************************
+Change log:
+    10/24/2008: initial version
+****************************************************/
+
+#ifndef _MLAN_WMM_H_
+#define _MLAN_WMM_H_
+
+/**
+ *  @brief This function gets the TID
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param ptr          A pointer to RA list table
+ *
+ *  @return             TID
+ */
+static INLINE t_u32
+wlan_get_tid(pmlan_adapter pmadapter, praListTbl ptr)
+{
+	pmlan_buffer mbuf;
+
+	ENTER();
+	mbuf = (pmlan_buffer)util_peek_list(pmadapter->pmoal_handle,
+					    &ptr->buf_head, MNULL, MNULL);
+	LEAVE();
+
+	if (!mbuf) {
+		return 0;	// The default TID,BE
+	} else
+		return mbuf->priority;
+}
+
+/**
+ *  @brief This function gets the length of a list
+ *
+ *  @param head         A pointer to mlan_list_head
+ *
+ *  @return             Length of list
+ */
+static INLINE t_u32
+wlan_wmm_list_len(pmlan_list_head head)
+{
+	pmlan_linked_list pos;
+	t_u32 count = 0;
+
+	ENTER();
+
+	pos = head->pnext;
+
+	while (pos != (pmlan_linked_list)head) {
+		++count;
+		pos = pos->pnext;
+	}
+
+	LEAVE();
+	return count;
+}
+
+/**
+ *  @brief This function requests a ralist lock
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+static INLINE t_void
+wlan_request_ralist_lock(pmlan_private priv)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	/* Call MOAL spin lock callback function */
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function releases a lock on ralist
+ *
+ *  @param priv         A pointer to mlan_private structure
+ *
+ *  @return             N/A
+ */
+static INLINE t_void
+wlan_release_ralist_lock(pmlan_private priv)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	/* Call MOAL spin unlock callback function */
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      priv->wmm.ra_list_spinlock);
+
+	LEAVE();
+	return;
+}
+
+/** Add buffer to WMM Tx queue */
+void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
+/** Add to RA list */
+void wlan_ralist_add(mlan_private *priv, t_u8 *ra);
+/** Update the RA list */
+int wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra);
+
+/** WMM status change command handler */
+mlan_status wlan_cmd_wmm_status_change(pmlan_private priv);
+/** Check if WMM lists are empty */
+int wlan_wmm_lists_empty(pmlan_adapter pmadapter);
+/** Process WMM transmission */
+t_void wlan_wmm_process_tx(pmlan_adapter pmadapter);
+/** Test to see if the ralist ptr is valid */
+int wlan_is_ralist_valid(mlan_private *priv, raListTbl *ra_list, int tid);
+
+raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid,
+				    t_u8 *ra_addr);
+t_u8 wlan_get_random_ba_threshold(pmlan_adapter pmadapter);
+
+/** Compute driver packet delay */
+t_u8 wlan_wmm_compute_driver_packet_delay(pmlan_private priv,
+					  const pmlan_buffer pmbuf);
+/** Initialize WMM */
+t_void wlan_wmm_init(pmlan_adapter pmadapter);
+/** Initialize WMM paramter */
+t_void wlan_init_wmm_param(pmlan_adapter pmadapter);
+/** Setup WMM queues */
+extern void wlan_wmm_setup_queues(pmlan_private priv);
+/* Setup default queues */
+void wlan_wmm_default_queue_priorities(pmlan_private priv);
+/* process wmm_param_config command */
+mlan_status wlan_cmd_wmm_param_config(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *cmd,
+				      t_u8 cmd_action, t_void *pdata_buf);
+
+/* process wmm_param_config command response */
+mlan_status wlan_ret_wmm_param_config(pmlan_private pmpriv,
+				      const HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf);
+
+#ifdef STA_SUPPORT
+/** Process WMM association request */
+extern t_u32 wlan_wmm_process_association_req(pmlan_private priv,
+					      t_u8 **ppAssocBuf,
+					      IEEEtypes_WmmParameter_t *pWmmIE,
+					      IEEEtypes_HTCap_t *pHTCap);
+#endif /* STA_SUPPORT */
+
+/** setup wmm queue priorities */
+void wlan_wmm_setup_queue_priorities(pmlan_private priv,
+				     IEEEtypes_WmmParameter_t *wmm_ie);
+
+/* Get tid_down from tid */
+int wlan_get_wmm_tid_down(mlan_private *priv, int tid);
+/** Downgrade WMM priority queue */
+void wlan_wmm_setup_ac_downgrade(pmlan_private priv);
+/** select WMM queue */
+t_u8 wlan_wmm_select_queue(mlan_private *pmpriv, t_u8 tid);
+t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac);
+
+#ifdef STA_SUPPORT
+/*
+ *  Functions used in the cmd handling routine
+ */
+/** WMM ADDTS request command handler */
+extern mlan_status wlan_cmd_wmm_addts_req(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *cmd,
+					  t_void *pdata_buf);
+/** WMM DELTS request command handler */
+extern mlan_status wlan_cmd_wmm_delts_req(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *cmd,
+					  t_void *pdata_buf);
+/** WMM QUEUE_STATS command handler */
+extern mlan_status wlan_cmd_wmm_queue_stats(pmlan_private pmpriv,
+					    HostCmd_DS_COMMAND *cmd,
+					    t_void *pdata_buf);
+/** WMM TS_STATUS command handler */
+extern mlan_status wlan_cmd_wmm_ts_status(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *cmd,
+					  t_void *pdata_buf);
+
+/*
+ *  Functions used in the cmdresp handling routine
+ */
+/** WMM get status command response handler */
+extern mlan_status wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv,
+					   int resp_len);
+/** WMM ADDTS request command response handler */
+extern mlan_status wlan_ret_wmm_addts_req(pmlan_private pmpriv,
+					  const HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf);
+/** WMM DELTS request command response handler */
+extern mlan_status wlan_ret_wmm_delts_req(pmlan_private pmpriv,
+					  const HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf);
+/** WMM QUEUE_STATS command response handler */
+extern mlan_status wlan_ret_wmm_queue_stats(pmlan_private pmpriv,
+					    const HostCmd_DS_COMMAND *resp,
+					    mlan_ioctl_req *pioctl_buf);
+/** WMM TS_STATUS command response handler */
+extern mlan_status wlan_ret_wmm_ts_status(pmlan_private pmpriv,
+					  HostCmd_DS_COMMAND *resp,
+					  mlan_ioctl_req *pioctl_buf);
+
+extern t_u8 tos_to_tid_inv[];
+extern t_u8 ac_to_tid[4][2];
+#endif /* STA_SUPPORT */
+
+/** WMM QUEUE_CONFIG command handler */
+extern mlan_status wlan_cmd_wmm_queue_config(pmlan_private pmpriv,
+					     HostCmd_DS_COMMAND *cmd,
+					     t_void *pdata_buf);
+
+/** WMM QUEUE_CONFIG command response handler */
+extern mlan_status wlan_ret_wmm_queue_config(pmlan_private pmpriv,
+					     const HostCmd_DS_COMMAND *resp,
+					     mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter,
+			       pmlan_ioctl_req pioctl_req);
+#endif /* !_MLAN_WMM_H_ */
diff --git a/wlan_sd8987/mlinux/mlan.h b/wlan_sd8987/mlinux/mlan.h
new file mode 100755
index 0000000..566ad50
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan.h
@@ -0,0 +1,37 @@
+/** @file mlan.h
+ *
+ *  @brief This file declares all APIs that will be called from MOAL module.
+ *  It also defines the data structures used for APIs between MLAN and MOAL.
+ *
+ *
+ *  Copyright 2008-2020 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    10/13/2008: initial version
+    11/07/2008: split mlan.h into mlan_decl.h & mlan_ioctl.h
+******************************************************/
+
+#ifndef _MLAN_H_
+#define _MLAN_H_
+
+#include "mlan_decl.h"
+#include "mlan_ioctl.h"
+#include "mlan_ieee.h"
+
+#endif /* !_MLAN_H_ */
diff --git a/wlan_sd8987/mlinux/mlan_decl.h b/wlan_sd8987/mlinux/mlan_decl.h
new file mode 100755
index 0000000..db7f060
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan_decl.h
@@ -0,0 +1,2288 @@
+/** @file mlan_decl.h
+ *
+ *  @brief This file declares the generic data structures and APIs.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+#ifndef _MLAN_DECL_H_
+#define _MLAN_DECL_H_
+
+/** MLAN release version */
+#define MLAN_RELEASE_VERSION "292.p10"
+
+/** Re-define generic data types for MLAN/MOAL */
+/** Signed char (1-byte) */
+typedef signed char t_s8, *t_ps8;
+/** Unsigned char (1-byte) */
+typedef unsigned char t_u8, *t_pu8;
+/** Signed short (2-bytes) */
+typedef short t_s16, *t_ps16;
+/** Unsigned short (2-bytes) */
+typedef unsigned short t_u16, *t_pu16;
+/** Signed long (4-bytes) */
+typedef int t_s32, *t_ps32;
+/** Unsigned long (4-bytes) */
+typedef unsigned int t_u32, *t_pu32;
+/** Signed long long 8-bytes) */
+typedef long long t_s64, *t_ps64;
+/** Unsigned long long 8-bytes) */
+typedef unsigned long long t_u64, *t_pu64;
+/** Void pointer (4-bytes) */
+typedef void t_void, *t_pvoid;
+/** Size type */
+typedef t_u32 t_size;
+/** Boolean type */
+typedef t_u8 t_bool;
+
+#ifdef MLAN_64BIT
+/** Pointer type (64-bit) */
+typedef t_u64 t_ptr;
+/** Signed value (64-bit) */
+typedef t_s64 t_sval;
+#else
+/** Pointer type (32-bit) */
+typedef t_u32 t_ptr;
+/** Signed value (32-bit) */
+typedef t_s32 t_sval;
+#endif
+
+/** Constants below */
+
+#ifdef __GNUC__
+/** Structure packing begins */
+#define MLAN_PACK_START
+/** Structure packeing end */
+#define MLAN_PACK_END __attribute__((packed))
+#else /* !__GNUC__ */
+#ifdef PRAGMA_PACK
+/** Structure packing begins */
+#define MLAN_PACK_START
+/** Structure packeing end */
+#define MLAN_PACK_END
+#else /* !PRAGMA_PACK */
+/** Structure packing begins */
+#define MLAN_PACK_START __packed
+/** Structure packing end */
+#define MLAN_PACK_END
+#endif /* PRAGMA_PACK */
+#endif /* __GNUC__ */
+
+#ifndef INLINE
+#ifdef __GNUC__
+/** inline directive */
+#define INLINE inline
+#else
+/** inline directive */
+#define INLINE __inline
+#endif
+#endif
+
+/** MLAN TRUE */
+#define MTRUE (1)
+/** MLAN FALSE */
+#define MFALSE (0)
+
+#ifndef MACSTR
+/** MAC address security format */
+#define MACSTR "%02x:XX:XX:XX:%02x:%02x"
+#endif
+
+#ifndef MAC2STR
+/** MAC address security print arguments */
+#define MAC2STR(a) (a)[0], (a)[4], (a)[5]
+#endif
+
+#ifndef FULL_MACSTR
+#define FULL_MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#endif
+#ifndef FULL_MAC2STR
+#define FULL_MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#endif
+
+/** Macros for Data Alignment : size */
+#define ALIGN_SZ(p, a) (((p) + ((a)-1)) & ~((a)-1))
+
+/** Macros for Data Alignment : address */
+#define ALIGN_ADDR(p, a)                                                       \
+	((((t_ptr)(p)) + (((t_ptr)(a)) - 1)) & ~(((t_ptr)(a)) - 1))
+
+/** Return the byte offset of a field in the given structure */
+#define MLAN_FIELD_OFFSET(type, field) ((t_u32)(t_ptr) & (((type *)0)->field))
+/** Return aligned offset */
+#define OFFSET_ALIGN_ADDR(p, a) (t_u32)(ALIGN_ADDR(p, a) - (t_ptr)p)
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM (16)
+#else
+/** Maximum BSS numbers */
+#define MLAN_MAX_BSS_NUM (2)
+#endif
+
+/** NET IP alignment */
+#define MLAN_NET_IP_ALIGN 2
+
+/** US country code */
+#define COUNTRY_CODE_US 0x10
+
+/** DMA alignment */
+/* SDIO3.0 Inrevium Adapter require 32 bit DMA alignment */
+#define DMA_ALIGNMENT 32
+
+/** max size of TxPD */
+#define MAX_TXPD_SIZE 32
+
+/** Minimum data header length */
+#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT + MAX_TXPD_SIZE)
+
+/** rx data header length */
+#define MLAN_RX_HEADER_LEN MLAN_MIN_DATA_HEADER_LEN
+
+/** This is current limit on Maximum Tx AMPDU allowed */
+#define MLAN_MAX_TX_BASTREAM_SUPPORTED 16
+#define MLAN_MAX_TX_BASTREAM_DEFAULT 2
+/** This is current limit on Maximum Rx AMPDU allowed */
+#define MLAN_MAX_RX_BASTREAM_SUPPORTED 16
+
+#ifdef STA_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_STA_AMPDU_DEF_TXWINSIZE 64
+/** Default Win size attached during ADDBA response */
+#define MLAN_STA_AMPDU_DEF_RXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_STA_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+/** Default Win size attached during ADDBA request */
+#define MLAN_UAP_AMPDU_DEF_TXWINSIZE 64
+/** Default Win size attached during ADDBA response */
+#define MLAN_UAP_AMPDU_DEF_RXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_UAP_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif /* UAP_SUPPORT */
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** WFD use the same window size for tx/rx */
+#define MLAN_WFD_AMPDU_DEF_TXRXWINSIZE 64
+/** RX winsize for COEX */
+#define MLAN_WFD_COEX_AMPDU_DEF_RXWINSIZE 16
+#endif
+
+/** Block ack timeout value */
+#define MLAN_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff
+/** Maximum Tx Win size configured for ADDBA request [10 bits] */
+#define MLAN_AMPDU_MAX_TXWINSIZE 0x3ff
+/** Maximum Rx Win size configured for ADDBA request [10 bits] */
+#define MLAN_AMPDU_MAX_RXWINSIZE 0x3ff
+
+/** Rate index for HR/DSSS 0 */
+#define MLAN_RATE_INDEX_HRDSSS0 0
+/** Rate index for HR/DSSS 3 */
+#define MLAN_RATE_INDEX_HRDSSS3 3
+/** Rate index for OFDM 0 */
+#define MLAN_RATE_INDEX_OFDM0 4
+/** Rate index for OFDM 7 */
+#define MLAN_RATE_INDEX_OFDM7 11
+/** Rate index for MCS 0 */
+#define MLAN_RATE_INDEX_MCS0 0
+/** Rate index for MCS 2 */
+#define MLAN_RATE_INDEX_MCS2 2
+/** Rate index for MCS 4 */
+#define MLAN_RATE_INDEX_MCS4 4
+/** Rate index for MCS 7 */
+#define MLAN_RATE_INDEX_MCS7 7
+/** Rate index for MCS 9 */
+#define MLAN_RATE_INDEX_MCS9 9
+/** Rate index for MCS11 */
+#define MLAN_RATE_INDEX_MCS11 11
+/** Rate index for MCS15 */
+#define MLAN_RATE_INDEX_MCS15 15
+/** Rate index for MCS 32 */
+#define MLAN_RATE_INDEX_MCS32 32
+/** Rate index for MCS 127 */
+#define MLAN_RATE_INDEX_MCS127 127
+#define MLAN_RATE_NSS1 1
+#define MLAN_RATE_NSS2 2
+
+/** Rate bitmap for OFDM 0 */
+#define MLAN_RATE_BITMAP_OFDM0 16
+/** Rate bitmap for OFDM 7 */
+#define MLAN_RATE_BITMAP_OFDM7 23
+/** Rate bitmap for MCS 0 */
+#define MLAN_RATE_BITMAP_MCS0 32
+/** Rate bitmap for MCS 127 */
+#define MLAN_RATE_BITMAP_MCS127 159
+#define MLAN_RATE_BITMAP_NSS1_MCS0 160
+#define MLAN_RATE_BITMAP_NSS1_MCS9 169
+#define MLAN_RATE_BITMAP_NSS2_MCS0 176
+#define MLAN_RATE_BITMAP_NSS2_MCS9 185
+
+/** MU beamformer */
+#define DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK (MBIT(19))
+
+/** Size of rx data buffer 3839+256 */
+#define MLAN_RX_DATA_BUF_SIZE 4096
+
+/** Size of command buffer */
+/** because cal_data_size 2.4 k */
+#define MRVDRV_SIZE_OF_CMD_BUFFER (3 * 1024)
+/** Size of rx command buffer */
+#define MLAN_RX_CMD_BUF_SIZE MRVDRV_SIZE_OF_CMD_BUFFER
+/** Upload size */
+#define WLAN_UPLD_SIZE MRVDRV_SIZE_OF_CMD_BUFFER
+
+#if defined(PCIE)
+#define MLAN_SSU_MAX_PKT_SIZE (283 * 4)
+#define MLAN_SSU_HEADER_SIZE 256
+/**
+ * Size of DMA buffer to collect 10ms SSU data:
+ * 2500 spectral packets, plus header
+ */
+#define MLAN_SSU_BUF_SIZE_1MS (MLAN_SSU_MAX_PKT_SIZE * 250)
+#define MLAN_SSU_BUF_SIZE (MLAN_SSU_HEADER_SIZE + MLAN_SSU_BUF_SIZE_1MS * 10)
+#define MLAN_SSU_BUF_SIZE_HOST (MLAN_SSU_BUF_SIZE)
+#endif
+
+/** driver initial the fw reset */
+#define FW_RELOAD_SDIO_INBAND_RESET 1
+/** out band reset trigger reset, no interface re-emulation */
+#define FW_RELOAD_NO_EMULATION 2
+/** out band reset with interface re-emulation */
+#define FW_RELOAD_WITH_EMULATION 3
+#ifdef PCIE
+/** pcie card reset */
+#define FW_RELOAD_PCIE_RESET 4
+#endif
+#define FW_RELOAD_SDIO_HW_RESET   5
+
+#ifdef USB
+#define MLAN_USB_BLOCK_SIZE (512)
+#define MLAN_USB_AGGR_MODE_NUM (0)
+#define MLAN_USB_AGGR_MODE_LEN (1)
+#define MLAN_USB_AGGR_MODE_LEN_V2 (2)
+#define MLAN_USB_TX_AGGR_MAX_LEN (16000)
+#define MLAN_USB_TX_AGGR_MAX_NUM 10
+#define MLAN_USB_TX_AGGR_V2_ALIGN 4
+#define MLAN_USB_TX_AGGR_HEADER 4
+#define MLAN_USB_MAX_PKT_SIZE (MLAN_USB_BLOCK_SIZE * 4)
+
+#define MLAN_USB_RX_ALIGN_SIZE MLAN_USB_BLOCK_SIZE
+#define MLAN_USB_RX_MAX_AGGR_NUM (8)
+#define MLAN_USB_RX_DEAGGR_TIMEOUT_USEC (200)
+
+#define MLAN_USB_TX_AGGR_ALIGN (MLAN_USB_BLOCK_SIZE * 4)
+#define MLAN_USB_TX_MAX_AGGR_NUM (8)
+#define MLAN_USB_TX_MAX_AGGR_SIZE                                              \
+	(MLAN_USB_BLOCK_SIZE * 4 * MLAN_USB_TX_MAX_AGGR_NUM)
+#define MLAN_USB_TX_MIN_AGGR_TIMEOUT (1)
+#define MLAN_USB_TX_MAX_AGGR_TIMEOUT (4)
+#define MLAN_USB_TX_AGGR_TIMEOUT_MSEC MLAN_USB_TX_MIN_AGGR_TIMEOUT
+#define MLAN_USB_TX_AGGR_TIMEOUT_DYN (0xFFFF)
+#endif /*USB*/
+/** MLAN MAC Address Length */
+#define MLAN_MAC_ADDR_LENGTH (6)
+/** MLAN 802.11 MAC Address */
+	typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
+
+/** MLAN Maximum SSID Length */
+#define MLAN_MAX_SSID_LENGTH (32)
+
+/** RTS/FRAG related defines */
+/** Minimum RTS value */
+#define MLAN_RTS_MIN_VALUE (0)
+/** Maximum RTS value */
+#define MLAN_RTS_MAX_VALUE (2347)
+/** Minimum FRAG value */
+#define MLAN_FRAG_MIN_VALUE (256)
+/** Maximum FRAG value */
+#define MLAN_FRAG_MAX_VALUE (2346)
+
+/** Minimum tx retry count */
+#define MLAN_TX_RETRY_MIN (0)
+/** Maximum tx retry count */
+#define MLAN_TX_RETRY_MAX (14)
+
+/** max Wmm AC queues */
+#define MAX_AC_QUEUES 4
+
+#ifdef SDIO
+/** define SDIO block size for data Tx/Rx */
+/* We support up to 480-byte block size due to FW buffer limitation. */
+#define MLAN_SDIO_BLOCK_SIZE 256
+
+/** define SDIO block size for firmware download */
+#define MLAN_SDIO_BLOCK_SIZE_FW_DNLD MLAN_SDIO_BLOCK_SIZE
+
+/** define allocated buffer size */
+#define ALLOC_BUF_SIZE MLAN_RX_DATA_BUF_SIZE
+/** SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT (16)
+/** SDIO MP aggr pkt limit 8 */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_8 (8)
+/** max SDIO MP aggr pkt limit */
+#define SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX (16)
+
+/** SDIO IO Port mask */
+#define MLAN_SDIO_IO_PORT_MASK 0xfffff
+/** SDIO Block/Byte mode mask */
+#define MLAN_SDIO_BYTE_MODE_MASK 0x80000000
+#endif /* SDIO */
+
+/** SD Interface */
+#define INTF_SD MBIT(0)
+#define IS_SD(ct) (ct & (INTF_SD << 8))
+/** PCIE Interface */
+#define INTF_PCIE MBIT(1)
+#define IS_PCIE(ct) (ct & (INTF_PCIE << 8))
+/** USB Interface */
+#define INTF_USB MBIT(2)
+#define IS_USB(ct) (ct & (INTF_USB << 8))
+
+/** 8887 card type */
+#define CARD_TYPE_8887 0x01
+/** 8897 card type */
+#define CARD_TYPE_8897 0x02
+/** 8977 card type */
+#define CARD_TYPE_8977 0x03
+/** 8997 card type */
+#define CARD_TYPE_8997 0x04
+/** 8987 card type */
+#define CARD_TYPE_8987 0x05
+/** 9098 card type */
+#define CARD_TYPE_9098 0x06
+/** 9097 card type */
+#define CARD_TYPE_9097 0x07
+/** 8978 card type */
+#define CARD_TYPE_8978 0x08
+/** 9177 card type */
+#define CARD_TYPE_9177 0x09
+/** 8801 card type */
+#define CARD_TYPE_8801 0x0a
+
+/** 9098 A0 reverion num */
+#define CHIP_9098_REV_A0 1
+#define CHIP_9098_REV_A1 2
+/** 9097 CHIP REV */
+#define CHIP_9097_REV_B0 1
+
+#define INTF_MASK 0xff
+#define CARD_TYPE_MASK 0xff
+
+#ifdef SDIO
+/** SD8887 card type */
+#define CARD_TYPE_SD8887 (CARD_TYPE_8887 | (INTF_SD << 8))
+/** SD8897 card type */
+#define CARD_TYPE_SD8897 (CARD_TYPE_8897 | (INTF_SD << 8))
+/** SD8977 card type */
+#define CARD_TYPE_SD8977 (CARD_TYPE_8977 | (INTF_SD << 8))
+/** SD8978 card type */
+#define CARD_TYPE_SD8978 (CARD_TYPE_8978 | (INTF_SD << 8))
+/** SD8997 card type */
+#define CARD_TYPE_SD8997 (CARD_TYPE_8997 | (INTF_SD << 8))
+/** SD8987 card type */
+#define CARD_TYPE_SD8987 (CARD_TYPE_8987 | (INTF_SD << 8))
+/** SD9097 card type */
+#define CARD_TYPE_SD9097 (CARD_TYPE_9097 | (INTF_SD << 8))
+/** SD9098 card type */
+#define CARD_TYPE_SD9098 (CARD_TYPE_9098 | (INTF_SD << 8))
+/** SD9177 card type */
+#define CARD_TYPE_SD9177 (CARD_TYPE_9177 | (INTF_SD << 8))
+/** SD8801 card type */
+#define CARD_TYPE_SD8801 (CARD_TYPE_8801 | (INTF_SD << 8))
+
+#define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
+#define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
+#define IS_SD8977(ct) (CARD_TYPE_SD8977 == (ct))
+#define IS_SD8978(ct) (CARD_TYPE_SD8978 == (ct))
+#define IS_SD8997(ct) (CARD_TYPE_SD8997 == (ct))
+#define IS_SD8987(ct) (CARD_TYPE_SD8987 == (ct))
+#define IS_SD9097(ct) (CARD_TYPE_SD9097 == (ct))
+#define IS_SD9098(ct) (CARD_TYPE_SD9098 == (ct))
+#define IS_SD9177(ct) (CARD_TYPE_SD9177 == (ct))
+#define IS_SD8801(ct) (CARD_TYPE_SD8801 == (ct))
+
+/** SD8887 Card */
+#define CARD_SD8887 "SD8887"
+/** SD8897 Card */
+#define CARD_SD8897 "SD8897"
+/** SD8977 Card */
+#define CARD_SD8977 "SD8977"
+/** SD8978 Card */
+#define CARD_SD8978 "SD8978"
+/** SD8997 Card */
+#define CARD_SD8997 "SD8997"
+/** SD8987 Card */
+#define CARD_SD8987 "SD8987"
+/** SD9097 Card */
+#define CARD_SD9097 "SD9097"
+/** SDIW620 Card */
+#define CARD_SDIW620 "SDIW620"
+/** SD9098 Card */
+#define CARD_SD9098 "SD9098"
+/** SD9177 Card */
+#define CARD_SD9177 "SD9177"
+/** SD8801 Card */
+#define CARD_SD8801 "SD8801"
+#endif
+
+#ifdef PCIE
+/** PCIE8897 card type */
+#define CARD_TYPE_PCIE8897 (CARD_TYPE_8897 | (INTF_PCIE << 8))
+/** PCIE8997 card type */
+#define CARD_TYPE_PCIE8997 (CARD_TYPE_8997 | (INTF_PCIE << 8))
+/** PCIE9097 card type */
+#define CARD_TYPE_PCIE9097 (CARD_TYPE_9097 | (INTF_PCIE << 8))
+/** PCIE9098 card type */
+#define CARD_TYPE_PCIE9098 (CARD_TYPE_9098 | (INTF_PCIE << 8))
+
+#define IS_PCIE8897(ct) (CARD_TYPE_PCIE8897 == (ct))
+#define IS_PCIE8997(ct) (CARD_TYPE_PCIE8997 == (ct))
+#define IS_PCIE9097(ct) (CARD_TYPE_PCIE9097 == (ct))
+#define IS_PCIE9098(ct) (CARD_TYPE_PCIE9098 == (ct))
+
+/** PCIE8897 Card */
+#define CARD_PCIE8897 "PCIE8897"
+/** PCIE8997 Card */
+#define CARD_PCIE8997 "PCIE8997"
+/** PCIE9097 Card */
+#define CARD_PCIE9097 "PCIE9097"
+/** PCIEIW620 Card */
+#define CARD_PCIEIW620 "PCIEIW620"
+/** PCIE9000S Card */
+#define CARD_PCIE9000S "PCIE9000S"
+/** PCIE9098 Card */
+#define CARD_PCIE9098 "PCIE9098"
+/** PCIEAW690 Card */
+#define CARD_PCIEAW690 "PCIEAW690"
+#endif
+
+#ifdef USB
+/** USB8801 card type */
+#define CARD_TYPE_USB8801   (CARD_TYPE_8801 | (INTF_USB << 8))
+/** USB8897 card type */
+#define CARD_TYPE_USB8897 (CARD_TYPE_8897 | (INTF_USB << 8))
+/** USB8997 card type */
+#define CARD_TYPE_USB8997 (CARD_TYPE_8997 | (INTF_USB << 8))
+/** USB8978 card type */
+#define CARD_TYPE_USB8978 (CARD_TYPE_8978 | (INTF_USB << 8))
+/** USB9098 card type */
+#define CARD_TYPE_USB9098 (CARD_TYPE_9098 | (INTF_USB << 8))
+/** USB9097 card type */
+#define CARD_TYPE_USB9097 (CARD_TYPE_9097 | (INTF_USB << 8))
+
+#define IS_USB8801(ct) (CARD_TYPE_USB8801 == (ct))
+#define IS_USB8897(ct) (CARD_TYPE_USB8897 == (ct))
+#define IS_USB8997(ct) (CARD_TYPE_USB8997 == (ct))
+#define IS_USB8978(ct) (CARD_TYPE_USB8978 == (ct))
+#define IS_USB9098(ct) (CARD_TYPE_USB9098 == (ct))
+#define IS_USB9097(ct) (CARD_TYPE_USB9097 == (ct))
+
+/** USB8801 Card */
+#define CARD_USB8801     "USB8801"
+/** USB8897 Card */
+#define CARD_USB8897 "USB8897"
+/** USB8997 Card */
+#define CARD_USB8997 "USB8997"
+/** USB8978 Card */
+#define CARD_USB8978 "USB8978"
+/** USB9098 Card */
+#define CARD_USB9098 "USB9098"
+/** USB9097 Card */
+#define CARD_USB9097 "USB9097"
+/** USBIW620 Card */
+#define CARD_USBIW620 "USBIW620"
+#endif
+
+#define IS_CARD8801(ct) (CARD_TYPE_8801 == ((ct) & 0xf))
+#define IS_CARD8887(ct) (CARD_TYPE_8887 == ((ct)&0xf))
+#define IS_CARD8897(ct) (CARD_TYPE_8897 == ((ct)&0xf))
+#define IS_CARD8977(ct) (CARD_TYPE_8977 == ((ct)&0xf))
+#define IS_CARD8997(ct) (CARD_TYPE_8997 == ((ct)&0xf))
+#define IS_CARD8987(ct) (CARD_TYPE_8987 == ((ct)&0xf))
+#define IS_CARD9098(ct) (CARD_TYPE_9098 == ((ct)&0xf))
+#define IS_CARD9097(ct) (CARD_TYPE_9097 == ((ct)&0xf))
+#define IS_CARD9177(ct) (CARD_TYPE_9177 == ((ct)&0xf))
+
+typedef struct _card_type_entry {
+	t_u16 card_type;
+	t_u16 func_id;
+	char *name;
+} card_type_entry;
+
+#if defined(SDIO) || defined(PCIE)
+/** Max retry number of IO write */
+#define MAX_WRITE_IOMEM_RETRY 2
+#endif /* SDIO || PCIE */
+
+#ifdef PCIE
+typedef enum {
+	PCIE_INT_MODE_LEGACY = 0,
+	PCIE_INT_MODE_MSI,
+	PCIE_INT_MODE_MSIX,
+	PCIE_INT_MODE_MAX,
+} PCIE_INT_MODE;
+#endif /* PCIE */
+
+/** IN parameter */
+#define IN
+/** OUT parameter */
+#define OUT
+
+/** BIT value */
+#define MBIT(x) (((t_u32)1) << (x))
+
+/** Buffer flag for requeued packet */
+#define MLAN_BUF_FLAG_REQUEUED_PKT MBIT(0)
+/** Buffer flag for transmit buf from moal */
+#define MLAN_BUF_FLAG_MOAL_TX_BUF MBIT(1)
+/** Buffer flag for malloc mlan_buffer */
+#define MLAN_BUF_FLAG_MALLOC_BUF MBIT(2)
+
+/** Buffer flag for bridge packet */
+#define MLAN_BUF_FLAG_BRIDGE_BUF MBIT(3)
+
+#ifdef USB
+/** Buffer flag for deaggregated rx packet */
+#define MLAN_BUF_FLAG_RX_DEAGGR MBIT(5)
+
+/** Buffer flag for sleep confirm resp packet */
+#define MLAN_BUF_FLAG_SLEEPCFM_RESP MBIT(6)
+
+/** Buffer flag for USB TX AGGR */
+#define MLAN_BUF_FLAG_USB_TX_AGGR MBIT(7)
+#endif
+
+/** Buffer flag for TDLS */
+#define MLAN_BUF_FLAG_TDLS MBIT(8)
+
+/** Buffer flag for TCP_ACK */
+#define MLAN_BUF_FLAG_TCP_ACK MBIT(9)
+
+/** Buffer flag for TX_STATUS */
+#define MLAN_BUF_FLAG_TX_STATUS MBIT(10)
+
+/** Buffer flag for NULL data packet */
+#define MLAN_BUF_FLAG_NULL_PKT MBIT(12)
+/** Buffer flag for Diag pkt */
+#define MLAN_BUF_FLAG_DIAG_BUF MBIT(13)
+
+#define MLAN_BUF_FLAG_TX_CTRL MBIT(14)
+
+#ifdef DEBUG_LEVEL1
+/** Debug level bit definition */
+#define MMSG MBIT(0)
+#define MFATAL MBIT(1)
+#define MERROR MBIT(2)
+#define MDATA MBIT(3)
+#define MCMND MBIT(4)
+#define MEVENT MBIT(5)
+#define MINTR MBIT(6)
+#define MIOCTL MBIT(7)
+
+#define MREG_D MBIT(9)
+
+#define MMPA_D MBIT(15)
+#define MDAT_D MBIT(16)
+#define MCMD_D MBIT(17)
+#define MEVT_D MBIT(18)
+#define MFW_D MBIT(19)
+#define MIF_D MBIT(20)
+
+#define MENTRY MBIT(28)
+#define MWARN MBIT(29)
+#define MINFO MBIT(30)
+#define MHEX_DUMP MBIT(31)
+#endif /* DEBUG_LEVEL1 */
+
+/** Memory allocation type: DMA */
+#define MLAN_MEM_DMA MBIT(0)
+
+/** Default memory allocation flag */
+#define MLAN_MEM_DEF 0
+
+/** mlan_status */
+typedef enum _mlan_status {
+	MLAN_STATUS_FAILURE = 0xffffffff,
+	MLAN_STATUS_SUCCESS = 0,
+	MLAN_STATUS_PENDING,
+	MLAN_STATUS_RESOURCE,
+#ifdef USB
+	/* Status pending and no resource */
+	MLAN_STATUS_PRESOURCE,
+#endif
+	MLAN_STATUS_COMPLETE,
+	MLAN_STATUS_FILE_ERR,
+} mlan_status;
+
+/** mlan_error_code */
+typedef enum _mlan_error_code {
+	/** No error */
+	MLAN_ERROR_NO_ERROR = 0,
+	/** Firmware/device errors below (MSB=0) */
+	MLAN_ERROR_FW_NOT_READY = 0x00000001,
+	MLAN_ERROR_FW_BUSY = 0x00000002,
+	MLAN_ERROR_FW_CMDRESP = 0x00000003,
+	MLAN_ERROR_DATA_TX_FAIL = 0x00000004,
+	MLAN_ERROR_DATA_RX_FAIL = 0x00000005,
+	/** Driver errors below (MSB=1) */
+	MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001,
+	MLAN_ERROR_PKT_TIMEOUT = 0x80000002,
+	MLAN_ERROR_PKT_INVALID = 0x80000003,
+	MLAN_ERROR_CMD_INVALID = 0x80000004,
+	MLAN_ERROR_CMD_TIMEOUT = 0x80000005,
+	MLAN_ERROR_CMD_DNLD_FAIL = 0x80000006,
+	MLAN_ERROR_CMD_CANCEL = 0x80000007,
+	MLAN_ERROR_CMD_RESP_FAIL = 0x80000008,
+	MLAN_ERROR_CMD_ASSOC_FAIL = 0x80000009,
+	MLAN_ERROR_CMD_SCAN_FAIL = 0x8000000A,
+	MLAN_ERROR_IOCTL_INVALID = 0x8000000B,
+	MLAN_ERROR_IOCTL_FAIL = 0x8000000C,
+	MLAN_ERROR_EVENT_UNKNOWN = 0x8000000D,
+	MLAN_ERROR_INVALID_PARAMETER = 0x8000000E,
+	MLAN_ERROR_NO_MEM = 0x8000000F,
+	/** More to add */
+} mlan_error_code;
+
+/** mlan_buf_type */
+typedef enum _mlan_buf_type {
+	MLAN_BUF_TYPE_CMD = 1,
+	MLAN_BUF_TYPE_DATA,
+	MLAN_BUF_TYPE_EVENT,
+	MLAN_BUF_TYPE_RAW_DATA,
+#ifdef SDIO
+	MLAN_BUF_TYPE_SPA_DATA,
+#endif
+} mlan_buf_type;
+
+#ifdef USB
+/** mlan_usb_ep */
+typedef enum _mlan_usb_ep {
+	MLAN_USB_EP_CTRL = 0,
+	MLAN_USB_EP_CMD_EVENT = 1,
+	MLAN_USB_EP_DATA = 2,
+	MLAN_USB_EP_DATA_CH2 = 3,
+	MLAN_USB_EP_CMD_EVENT_IF2 = 4,
+	MLAN_USB_EP_DATA_IF2 = 5,
+	MLAN_USB_EP_DATA_CH2_IF2 = 6,
+} mlan_usb_ep;
+
+/** Timeout in milliseconds for usb_bulk_msg function */
+#define MLAN_USB_BULK_MSG_TIMEOUT 100
+#endif /* USB */
+
+/** MLAN BSS type */
+typedef enum _mlan_bss_type {
+	MLAN_BSS_TYPE_STA = 0,
+	MLAN_BSS_TYPE_UAP = 1,
+#ifdef WIFI_DIRECT_SUPPORT
+	MLAN_BSS_TYPE_WIFIDIRECT = 2,
+#endif
+	MLAN_BSS_TYPE_ANY = 0xff,
+} mlan_bss_type;
+
+/** MLAN BSS role */
+typedef enum _mlan_bss_role {
+	MLAN_BSS_ROLE_STA = 0,
+	MLAN_BSS_ROLE_UAP = 1,
+	MLAN_BSS_ROLE_ANY = 0xff,
+} mlan_bss_role;
+
+/** BSS role mask */
+#define BSS_ROLE_MASK (MBIT(0) | MBIT(1))
+
+/** Get BSS role */
+#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_MASK)
+
+/** mlan_data_frame_type */
+typedef enum _mlan_data_frame_type {
+	MLAN_DATA_FRAME_TYPE_ETH_II = 0,
+	MLAN_DATA_FRAME_TYPE_802_11,
+} mlan_data_frame_type;
+
+/** mlan_event_id */
+typedef enum _mlan_event_id {
+	/* Event generated by firmware (MSB=0) */
+	MLAN_EVENT_ID_FW_UNKNOWN = 0x00000001,
+	MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED = 0x00000002,
+	MLAN_EVENT_ID_FW_ADHOC_LINK_LOST = 0x00000003,
+	MLAN_EVENT_ID_FW_DISCONNECTED = 0x00000004,
+	MLAN_EVENT_ID_FW_MIC_ERR_UNI = 0x00000005,
+	MLAN_EVENT_ID_FW_MIC_ERR_MUL = 0x00000006,
+	MLAN_EVENT_ID_FW_BCN_RSSI_LOW = 0x00000007,
+	MLAN_EVENT_ID_FW_BCN_RSSI_HIGH = 0x00000008,
+	MLAN_EVENT_ID_FW_BCN_SNR_LOW = 0x00000009,
+	MLAN_EVENT_ID_FW_BCN_SNR_HIGH = 0x0000000A,
+	MLAN_EVENT_ID_FW_MAX_FAIL = 0x0000000B,
+	MLAN_EVENT_ID_FW_DATA_RSSI_LOW = 0x0000000C,
+	MLAN_EVENT_ID_FW_DATA_RSSI_HIGH = 0x0000000D,
+	MLAN_EVENT_ID_FW_DATA_SNR_LOW = 0x0000000E,
+	MLAN_EVENT_ID_FW_DATA_SNR_HIGH = 0x0000000F,
+	MLAN_EVENT_ID_FW_LINK_QUALITY = 0x00000010,
+	MLAN_EVENT_ID_FW_PORT_RELEASE = 0x00000011,
+	MLAN_EVENT_ID_FW_PRE_BCN_LOST = 0x00000012,
+	MLAN_EVENT_ID_FW_DEBUG_INFO = 0x00000013,
+	MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE = 0x0000001A,
+	MLAN_EVENT_ID_FW_HS_WAKEUP = 0x0000001B,
+	MLAN_EVENT_ID_FW_BG_SCAN = 0x0000001D,
+	MLAN_EVENT_ID_FW_BG_SCAN_STOPPED = 0x0000001E,
+	MLAN_EVENT_ID_FW_WEP_ICV_ERR = 0x00000020,
+	MLAN_EVENT_ID_FW_STOP_TX = 0x00000021,
+	MLAN_EVENT_ID_FW_START_TX = 0x00000022,
+	MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN = 0x00000023,
+	MLAN_EVENT_ID_FW_RADAR_DETECTED = 0x00000024,
+	MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY = 0x00000025,
+	MLAN_EVENT_ID_FW_BW_CHANGED = 0x00000026,
+	MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED = 0x0000002B,
+
+#ifdef UAP_SUPPORT
+	MLAN_EVENT_ID_UAP_FW_BSS_START = 0x0000002C,
+	MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE = 0x0000002D,
+	MLAN_EVENT_ID_UAP_FW_BSS_IDLE = 0x0000002E,
+	MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES = 0x0000002F,
+	MLAN_EVENT_ID_UAP_FW_STA_CONNECT = 0x00000030,
+	MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT = 0x00000031,
+#endif
+
+	MLAN_EVENT_ID_FW_DUMP_INFO = 0x00000033,
+
+	MLAN_EVENT_ID_FW_TX_STATUS = 0x00000034,
+	MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE = 0x00000036,
+#if defined(PCIE)
+	MLAN_EVENT_ID_SSU_DUMP_FILE = 0x00000039,
+#endif /* SSU_SUPPORT */
+	/* Event generated by MLAN driver (MSB=1) */
+	MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001,
+	MLAN_EVENT_ID_DRV_DEFER_HANDLING = 0x80000002,
+	MLAN_EVENT_ID_DRV_HS_ACTIVATED = 0x80000003,
+	MLAN_EVENT_ID_DRV_HS_DEACTIVATED = 0x80000004,
+	MLAN_EVENT_ID_DRV_MGMT_FRAME = 0x80000005,
+	MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM = 0x80000006,
+	MLAN_EVENT_ID_DRV_PASSTHRU = 0x80000007,
+	MLAN_EVENT_ID_DRV_SCAN_REPORT = 0x80000009,
+	MLAN_EVENT_ID_DRV_MEAS_REPORT = 0x8000000A,
+	MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT = 0x8000000B,
+	MLAN_EVENT_ID_DRV_REPORT_STRING = 0x8000000F,
+	MLAN_EVENT_ID_DRV_DBG_DUMP = 0x80000012,
+	MLAN_EVENT_ID_DRV_BGSCAN_RESULT = 0x80000013,
+	MLAN_EVENT_ID_DRV_FLUSH_RX_WORK = 0x80000015,
+	MLAN_EVENT_ID_DRV_DEFER_RX_WORK = 0x80000016,
+	MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ = 0x80000017,
+	MLAN_EVENT_ID_DRV_FT_RESPONSE = 0x80000018,
+	MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK = 0x80000019,
+#ifdef UAP_SUPPORT
+	MLAN_EVENT_ID_DRV_UAP_CHAN_INFO = 0x80000020,
+#endif
+	MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER = 0x80000026,
+	MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER = 0x80000027,
+	MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER = 0x80000028,
+	MLAN_EVENT_ID_DRV_WIFI_STATUS = 0x80000029,
+	MLAN_EVENT_ID_STORE_HOST_CMD_RESP = 0x80000030,
+} mlan_event_id;
+
+/** Data Structures */
+/** mlan_image data structure */
+typedef struct _mlan_fw_image {
+	/** Firmware image buffer pointer */
+	t_u8 *pfw_buf;
+	/** Firmware image length */
+	t_u32 fw_len;
+	/** Firmware reload flag */
+	t_u8 fw_reload;
+} mlan_fw_image, *pmlan_fw_image;
+
+/** MrvlIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlIEtypesHeader {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+} MLAN_PACK_END MrvlIEtypesHeader_t;
+
+/** MrvlExtIEtypesHeader_t */
+typedef MLAN_PACK_START struct _MrvlExtIEtypesHeader {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+	/** ext id */
+	t_u8 ext_id;
+} MLAN_PACK_END MrvlExtIEtypesHeader_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlExtIEtypes_Data_t {
+	/** Header */
+	MrvlExtIEtypesHeader_t header;
+	/** Data */
+	t_u8 data[];
+} MLAN_PACK_END MrvlExtIEtypes_Data_t;
+
+/** MrvlIEtypes_Data_t */
+typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+	/** Data */
+	t_u8 data[];
+} MLAN_PACK_END MrvlIEtypes_Data_t;
+
+#define OID_TYPE_CAL 0x2
+#define OID_TYPE_DPD 0xa
+#define UNKNOW_DPD_LENGTH   0xffffffff
+
+/** Custom data structure */
+typedef struct _mlan_init_param {
+	/** DPD data buffer pointer */
+	t_u8 *pdpd_data_buf;
+	/** DPD data length */
+	t_u32 dpd_data_len;
+	/** region txpowerlimit cfg data buffer pointer */
+	t_u8 *ptxpwr_data_buf;
+	/** region txpowerlimit cfg data length */
+	t_u32 txpwr_data_len;
+	/** Cal data buffer pointer */
+	t_u8 *pcal_data_buf;
+	/** Cal data length */
+	t_u32 cal_data_len;
+	/** Other custom data */
+} mlan_init_param, *pmlan_init_param;
+
+/** channel type */
+enum mlan_channel_type {
+	CHAN_NO_HT,
+	CHAN_HT20,
+	CHAN_HT40MINUS,
+	CHAN_HT40PLUS,
+	CHAN_VHT80
+};
+
+/** channel band */
+enum { BAND_2GHZ = 0,
+	BAND_5GHZ = 1,
+	BAND_4GHZ = 2,
+};
+
+/** channel offset */
+enum { SEC_CHAN_NONE = 0,
+	SEC_CHAN_ABOVE = 1,
+	SEC_CHAN_5MHZ = 2,
+	SEC_CHAN_BELOW = 3
+};
+
+/** channel bandwidth */
+enum { CHAN_BW_20MHZ = 0,
+	CHAN_BW_10MHZ,
+	CHAN_BW_40MHZ,
+	CHAN_BW_80MHZ,
+};
+
+/** scan mode */
+enum { SCAN_MODE_MANUAL = 0,
+	SCAN_MODE_ACS,
+	SCAN_MODE_USER,
+};
+
+/** DFS state */
+typedef enum _dfs_state_t {
+	/** Channel can be used, CAC (Channel Availability Check) must be done
+	   before using it */
+	DFS_USABLE = 0,
+	/** Channel is not available, radar was detected */
+	DFS_UNAVAILABLE = 1,
+	/** Channel is Available, CAC is done and is free of radar */
+	DFS_AVAILABLE = 2,
+} dfs_state_t;
+
+/** max cac time 10 minutes */
+#define MAX_CAC_DWELL_TIME 600000
+/** default cac time 60 seconds */
+#define DEF_CAC_DWELL_TIME 60000
+/** start freq for 5G */
+#define START_FREQ_11A_BAND 5000
+
+typedef enum _dfs_w53_cfg_t {
+	/** DFS W53 Default Fw Value */
+	DFS_W53_DEFAULT_FW = 0,
+	/** DFS W53 New W53 Rules/Standard */
+	DFS_W53_NEW = 1,
+	/** DFS W53 Old W53 Rules/Standard */
+	DFS_W53_OLD = 2
+} dfs_w53_cfg_t;
+
+/** Band_Config_t */
+typedef MLAN_PACK_START struct _Band_Config_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Channel Selection Mode - (00)=manual, (01)=ACS,  (02)=user*/
+	t_u8 scanMode:2;
+	/** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */
+	t_u8 chan2Offset:2;
+	/** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */
+	t_u8 chanWidth:2;
+	/** Band Info - (00)=2.4GHz, (01)=5GHz */
+	t_u8 chanBand:2;
+#else
+	/** Band Info - (00)=2.4GHz, (01)=5GHz */
+	t_u8 chanBand:2;
+	/** Channel Width - (00)=20MHz, (10)=40MHz, (11)=80MHz */
+	t_u8 chanWidth:2;
+	/** Secondary Channel Offset - (00)=None, (01)=Above, (11)=Below */
+	t_u8 chan2Offset:2;
+	/** Channel Selection Mode - (00)=manual, (01)=ACS, (02)=Adoption mode*/
+	t_u8 scanMode:2;
+#endif
+} MLAN_PACK_END Band_Config_t;
+
+/** channel_band_t */
+typedef MLAN_PACK_START struct _chan_band_info {
+	/** Band Configuration */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** 11n flag */
+	t_u8 is_11n_enabled;
+	/** center channel */
+	t_u8 center_chan;
+	/** dfs channel flag */
+	t_u8 is_dfs_chan;
+} MLAN_PACK_END chan_band_info;
+
+/** Channel usability flags */
+#define NXP_CHANNEL_NO_OFDM MBIT(9)
+#define NXP_CHANNEL_NO_CCK MBIT(8)
+#define NXP_CHANNEL_DISABLED MBIT(7)
+/* BIT 5/6 resevered for FW */
+#define NXP_CHANNEL_NOHT160 MBIT(4)
+#define NXP_CHANNEL_NOHT80 MBIT(3)
+#define NXP_CHANNEL_NOHT40 MBIT(2)
+#define NXP_CHANNEL_DFS MBIT(1)
+#define NXP_CHANNEL_PASSIVE MBIT(0)
+
+/** CFP dynamic (non-const) elements */
+typedef struct _cfp_dyn_t {
+	/** extra flags to specify channel usability
+	 *  bit 9 : if set, channel is non-OFDM
+	 *  bit 8 : if set, channel is non-CCK
+	 *  bit 7 : if set, channel is disabled
+	 *  bit  5/6 resevered for FW
+	 *  bit 4 : if set, 160MHz on channel is disabled
+	 *  bit 3 : if set, 80MHz on channel is disabled
+	 *  bit 2 : if set, 40MHz on channel is disabled
+	 *  bit 1 : if set, channel is DFS channel
+	 *  bit 0 : if set, channel is passive
+	 */
+	t_u16 flags;
+	/** TRUE: Channel is blacklisted (do not use) */
+	t_bool blacklist;
+	/** DFS state of the channel
+	 * 0:DFS_USABLE  1:DFS_AVAILABLE  2:DFS_UNAVAILABLE */
+	dfs_state_t dfs_state;
+} cfp_dyn_t;
+
+/** Chan-Freq-TxPower mapping table*/
+typedef struct _chan_freq_power_t {
+	/** Channel Number */
+	t_u16 channel;
+	/** Frequency of this Channel */
+	t_u32 freq;
+	/** Max allowed Tx power level */
+	t_u16 max_tx_power;
+	/** TRUE:radar detect required for BAND A or passive scan for BAND B/G;
+	 * FALSE:radar detect not required for BAND A or active scan for BAND
+	 * B/G*/
+	t_bool passive_scan_or_radar_detect;
+	/** Elements associated to cfp that change at run-time */
+	cfp_dyn_t dynamic;
+} chan_freq_power_t;
+
+/** mlan_event data structure */
+typedef struct _mlan_event {
+	/** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+	/** Event ID */
+	mlan_event_id event_id;
+	/** Event length */
+	t_u32 event_len;
+	/** Event buffer */
+	t_u8 event_buf[];
+} mlan_event, *pmlan_event;
+
+/** mlan_cmdresp_event data structure */
+typedef struct _mlan_cmdresp_event {
+    /** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+    /** Event ID */
+	mlan_event_id event_id;
+    /** Event length */
+	t_u32 event_len;
+    /** resp buffer pointer */
+	t_u8 *resp;
+} mlan_cmdresp_event, *pmlan_cmdresp_event;
+
+/** csi event data structure */
+
+/** mlan_ioctl_req data structure */
+typedef struct _mlan_ioctl_req {
+	/** Pointer to previous mlan_ioctl_req */
+	struct _mlan_ioctl_req *pprev;
+	/** Pointer to next mlan_ioctl_req */
+	struct _mlan_ioctl_req *pnext;
+	/** Status code from firmware/driver */
+	t_u32 status_code;
+	/** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+	/** Request id */
+	t_u32 req_id;
+	/** Action: set or get */
+	t_u32 action;
+	/** Pointer to buffer */
+	t_u8 *pbuf;
+	/** Length of buffer */
+	t_u32 buf_len;
+	/** Length of the data read/written in buffer */
+	t_u32 data_read_written;
+	/** Length of buffer needed */
+	t_u32 buf_len_needed;
+	/** Reserved for MOAL module */
+	t_ptr reserved_1;
+} mlan_ioctl_req, *pmlan_ioctl_req;
+
+/** txpower structure */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Host tx power ctrl:
+	     0x0: use fw setting for TX power
+	     0x1: value specified in bit[6] and bit[5:0] are valid */
+	t_u8 hostctl:1;
+	/** Sign of the power specified in bit[5:0] */
+	t_u8 sign:1;
+	/** Power to be used for transmission(in dBm) */
+	t_u8 abs_val:6;
+#else
+	/** Power to be used for transmission(in dBm) */
+	t_u8 abs_val:6;
+	/** Sign of the power specified in bit[5:0] */
+	t_u8 sign:1;
+	/** Host tx power ctrl:
+	     0x0: use fw setting for TX power
+	     0x1: value specified in bit[6] and bit[5:0] are valid */
+	t_u8 hostctl:1;
+#endif
+} MLAN_PACK_END tx_power_t;
+/* pkt_txctrl */
+typedef MLAN_PACK_START struct _pkt_txctrl {
+	/**Data rate in unit of 0.5Mbps */
+	t_u16 data_rate;
+	/*Channel number to transmit the frame */
+	t_u8 channel;
+	/** Bandwidth to transmit the frame*/
+	t_u8 bw;
+	/** Power to be used for transmission*/
+	union {
+		tx_power_t tp;
+		t_u8 val;
+	} tx_power;
+	/** Retry time of tx transmission*/
+	t_u8 retry_limit;
+} MLAN_PACK_END pkt_txctrl, *ppkt_txctrl;
+
+/** pkt_rxinfo */
+typedef MLAN_PACK_START struct _pkt_rxinfo {
+	/** Data rate of received paccket*/
+	t_u16 data_rate;
+	/** Channel on which packet was received*/
+	t_u8 channel;
+	/** Rx antenna*/
+	t_u8 antenna;
+	/** Rx Rssi*/
+	t_u8 rssi;
+} MLAN_PACK_END pkt_rxinfo, *ppkt_rxinfo;
+
+/** mlan_buffer data structure */
+typedef struct _mlan_buffer {
+	/** Pointer to previous mlan_buffer */
+	struct _mlan_buffer *pprev;
+	/** Pointer to next mlan_buffer */
+	struct _mlan_buffer *pnext;
+	/** Status code from firmware/driver */
+	t_u32 status_code;
+	/** Flags for this buffer */
+	t_u32 flags;
+	/** BSS index number for multiple BSS support */
+	t_u32 bss_index;
+	/** Buffer descriptor, e.g. skb in Linux */
+	t_void *pdesc;
+	/** Pointer to buffer */
+	t_u8 *pbuf;
+#ifdef PCIE
+	/** Physical address of the pbuf pointer */
+	t_u64 buf_pa;
+	t_u32 total_pcie_buf_len;
+#endif
+	/** Offset to data */
+	t_u32 data_offset;
+	/** Data length */
+	t_u32 data_len;
+	/** Buffer type: data, cmd, event etc. */
+	mlan_buf_type buf_type;
+
+	/** Fields below are valid for data packet only */
+	/** QoS priority */
+	t_u32 priority;
+	/** Time stamp when packet is received (seconds) */
+	t_u32 in_ts_sec;
+	/** Time stamp when packet is received (micro seconds) */
+	t_u32 in_ts_usec;
+	/** Time stamp when packet is processed (seconds) */
+	t_u32 out_ts_sec;
+	/** Time stamp when packet is processed (micro seconds) */
+	t_u32 out_ts_usec;
+	/** tx_seq_num */
+	t_u32 tx_seq_num;
+    /** Time stamp when packet is deque from rx_q(seconds) */
+	t_u32 extra_ts_sec;
+	/** Time stamp when packet is dequed from rx_q(micro seconds) */
+	t_u32 extra_ts_usec;
+	/** Fields below are valid for MLAN module only */
+	/** Pointer to parent mlan_buffer */
+	struct _mlan_buffer *pparent;
+	/** Use count for this buffer */
+	t_u32 use_count;
+	union {
+		pkt_txctrl tx_info;
+		pkt_rxinfo rx_info;
+	} u;
+} mlan_buffer, *pmlan_buffer, **ppmlan_buffer;
+
+/** mlan_hw_info data structure */
+typedef struct _mlan_hw_info {
+	t_u32 fw_cap;
+	t_u32 fw_cap_ext;
+} mlan_hw_info, *pmlan_hw_info;
+
+/** mlan_bss_attr data structure */
+typedef struct _mlan_bss_attr {
+	/** BSS type */
+	t_u32 bss_type;
+	/** Data frame type: Ethernet II, 802.11, etc. */
+	t_u32 frame_type;
+	/** The BSS is active (non-0) or not (0). */
+	t_u32 active;
+	/** BSS Priority */
+	t_u32 bss_priority;
+	/** BSS number */
+	t_u32 bss_num;
+	/** The BSS is virtual */
+	t_u32 bss_virtual;
+} mlan_bss_attr, *pmlan_bss_attr;
+
+/** bss tbl data structure */
+typedef struct _mlan_bss_tbl {
+	/** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+} mlan_bss_tbl, *pmlan_bss_tbl;
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/** Type enumeration for the command result */
+typedef MLAN_PACK_START enum _mlan_cmd_result_e {
+	MLAN_CMD_RESULT_SUCCESS = 0,
+	MLAN_CMD_RESULT_FAILURE = 1,
+	MLAN_CMD_RESULT_TIMEOUT = 2,
+	MLAN_CMD_RESULT_INVALID_DATA = 3
+} MLAN_PACK_END mlan_cmd_result_e;
+
+/** Type enumeration of WMM AC_QUEUES */
+typedef MLAN_PACK_START enum _mlan_wmm_ac_e {
+	WMM_AC_BK,
+	WMM_AC_BE,
+	WMM_AC_VI,
+	WMM_AC_VO
+} MLAN_PACK_END mlan_wmm_ac_e;
+
+/** Type enumeration for the action field in the Queue Config command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e {
+	MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2,
+	MLAN_WMM_QUEUE_CONFIG_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_config_action_e;
+
+/** Type enumeration for the action field in the queue stats command */
+typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e {
+	MLAN_WMM_STATS_ACTION_START = 0,
+	MLAN_WMM_STATS_ACTION_STOP = 1,
+	MLAN_WMM_STATS_ACTION_GET_CLR = 2,
+	MLAN_WMM_STATS_ACTION_SET_CFG = 3,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_GET_CFG = 4,	/* Not currently used */
+	MLAN_WMM_STATS_ACTION_MAX
+} MLAN_PACK_END mlan_wmm_queue_stats_action_e;
+
+/**
+ *  @brief IOCTL structure for a Traffic stream status.
+ *
+ */
+typedef MLAN_PACK_START struct {
+	/** TSID: Range: 0->7 */
+	t_u8 tid;
+	/** TSID specified is valid */
+	t_u8 valid;
+	/** AC TSID is active on */
+	t_u8 access_category;
+	/** UP specified for the TSID */
+	t_u8 user_priority;
+	/** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */
+	t_u8 psb;
+	/** Upstream(0), Downlink(1), Bidirectional(3) */
+	t_u8 flow_dir;
+	/** Medium time granted for the TSID */
+	t_u16 medium_time;
+} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t,
+	/** Type definition of mlan_ds_wmm_ts_status for
+	   MLAN_OID_WMM_CFG_TS_STATUS */
+mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status;
+
+/** Max Ie length */
+#define MAX_IE_SIZE 256
+
+/** custom IE */
+typedef MLAN_PACK_START struct _custom_ie {
+	/** IE Index */
+	t_u16 ie_index;
+	/** Mgmt Subtype Mask */
+	t_u16 mgmt_subtype_mask;
+	/** IE Length */
+	t_u16 ie_length;
+	/** IE buffer */
+	t_u8 ie_buffer[MAX_IE_SIZE];
+} MLAN_PACK_END custom_ie;
+
+/** Max IE index to FW */
+#define MAX_MGMT_IE_INDEX_TO_FW 4
+/** Max IE index per BSS */
+#define MAX_MGMT_IE_INDEX 26
+
+/** custom IE info */
+typedef MLAN_PACK_START struct _custom_ie_info {
+	/** size of buffer */
+	t_u16 buf_size;
+	/** no of buffers of buf_size */
+	t_u16 buf_count;
+} MLAN_PACK_END custom_ie_info;
+
+/** TLV buffer : Max Mgmt IE */
+typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** No of tuples */
+	t_u16 count;
+	/** custom IE info tuples */
+	custom_ie_info info[MAX_MGMT_IE_INDEX];
+} MLAN_PACK_END tlvbuf_max_mgmt_ie;
+
+/** TLV buffer : custom IE */
+typedef MLAN_PACK_START struct _tlvbuf_custom_ie {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+	/** IE data */
+	custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW];
+	/** Max mgmt IE TLV */
+	tlvbuf_max_mgmt_ie max_mgmt_ie;
+} MLAN_PACK_END mlan_ds_misc_custom_ie;
+
+/** Max TDLS config data length */
+#define MAX_TDLS_DATA_LEN 1024
+
+/** Action commands for TDLS enable/disable */
+#define WLAN_TDLS_CONFIG 0x00
+/** Action commands for TDLS configuration :Set */
+#define WLAN_TDLS_SET_INFO 0x01
+/** Action commands for TDLS configuration :Discovery Request */
+#define WLAN_TDLS_DISCOVERY_REQ 0x02
+/** Action commands for TDLS configuration :Setup Request */
+#define WLAN_TDLS_SETUP_REQ 0x03
+/** Action commands for TDLS configuration :Tear down Request */
+#define WLAN_TDLS_TEAR_DOWN_REQ 0x04
+/** Action ID for TDLS power mode */
+#define WLAN_TDLS_POWER_MODE 0x05
+/**Action ID for init TDLS Channel Switch*/
+#define WLAN_TDLS_INIT_CHAN_SWITCH 0x06
+/** Action ID for stop TDLS Channel Switch */
+#define WLAN_TDLS_STOP_CHAN_SWITCH 0x07
+/** Action ID for configure CS related parameters */
+#define WLAN_TDLS_CS_PARAMS 0x08
+/** Action ID for Disable CS */
+#define WLAN_TDLS_CS_DISABLE 0x09
+/** Action ID for TDLS link status */
+#define WLAN_TDLS_LINK_STATUS 0x0A
+/** Action ID for Host TDLS config uapsd and CS */
+#define WLAN_HOST_TDLS_CONFIG 0x0D
+/** Action ID for TDLS CS immediate return */
+#define WLAN_TDLS_DEBUG_CS_RET_IM 0xFFF7
+/** Action ID for TDLS Stop RX */
+#define WLAN_TDLS_DEBUG_STOP_RX 0xFFF8
+/** Action ID for TDLS Allow weak security for links establish */
+#define WLAN_TDLS_DEBUG_ALLOW_WEAK_SECURITY 0xFFF9
+/** Action ID for TDLS Ignore key lifetime expiry */
+#define WLAN_TDLS_DEBUG_IGNORE_KEY_EXPIRY 0xFFFA
+/** Action ID for TDLS Higher/Lower mac Test */
+#define WLAN_TDLS_DEBUG_HIGHER_LOWER_MAC 0xFFFB
+/** Action ID for TDLS Prohibited Test */
+#define WLAN_TDLS_DEBUG_SETUP_PROHIBITED 0xFFFC
+/** Action ID for TDLS Existing link Test */
+#define WLAN_TDLS_DEBUG_SETUP_SAME_LINK 0xFFFD
+/** Action ID for TDLS Fail Setup Confirm */
+#define WLAN_TDLS_DEBUG_FAIL_SETUP_CONFIRM 0xFFFE
+/** Action commands for TDLS debug: Wrong BSS Request */
+#define WLAN_TDLS_DEBUG_WRONG_BSS 0xFFFF
+
+/** tdls each link rate information */
+typedef MLAN_PACK_START struct _tdls_link_rate_info {
+	/** Tx Data Rate */
+	t_u8 tx_data_rate;
+	/** Tx Rate HT info*/
+	t_u8 tx_rate_htinfo;
+} MLAN_PACK_END tdls_link_rate_info;
+
+/** tdls each link status */
+typedef MLAN_PACK_START struct _tdls_each_link_status {
+	/** peer mac Address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Link Flags */
+	t_u8 link_flags;
+	/** Traffic Status */
+	t_u8 traffic_status;
+	/** Tx Failure Count */
+	t_u8 tx_fail_count;
+	/** Channel Number */
+	t_u32 active_channel;
+	/** Last Data RSSI in dBm */
+	t_s16 data_rssi_last;
+	/** Last Data NF in dBm */
+	t_s16 data_nf_last;
+	/** AVG DATA RSSI in dBm */
+	t_s16 data_rssi_avg;
+	/** AVG DATA NF in dBm */
+	t_s16 data_nf_avg;
+	union {
+		/** tdls rate info */
+		tdls_link_rate_info rate_info;
+		/** tdls link final rate*/
+		t_u16 final_data_rate;
+	} u;
+	/** Security Method */
+	t_u8 security_method;
+	/** Key Lifetime in milliseconds */
+	t_u32 key_lifetime;
+	/** Key Length */
+	t_u8 key_length;
+	/** actual key */
+	t_u8 key[1];
+} MLAN_PACK_END tdls_each_link_status;
+
+/** TDLS configuration data */
+typedef MLAN_PACK_START struct _tdls_all_config {
+	union {
+		/** TDLS state enable disable */
+		MLAN_PACK_START struct _tdls_config {
+			/** enable or disable */
+			t_u16 enable;
+		} MLAN_PACK_END tdls_config;
+		/** Host tdls config */
+		MLAN_PACK_START struct _host_tdls_cfg {
+			/** support uapsd */
+			t_u8 uapsd_support;
+			/** channel_switch */
+			t_u8 cs_support;
+			/** TLV  length */
+			t_u16 tlv_len;
+			/** tdls info */
+			t_u8 tlv_buffer[];
+		} MLAN_PACK_END host_tdls_cfg;
+		/** TDLS set info */
+		MLAN_PACK_START struct _tdls_set_data {
+			/** (tlv + capInfo) length */
+			t_u16 tlv_length;
+			/** Cap Info */
+			t_u16 cap_info;
+			/** TLV buffer */
+			t_u8 tlv_buffer[];
+		} MLAN_PACK_END tdls_set;
+
+		/** TDLS discovery and others having mac argument */
+		MLAN_PACK_START struct _tdls_discovery_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+		} MLAN_PACK_END tdls_discovery, tdls_stop_chan_switch,
+			tdls_link_status_req;
+
+		/** TDLS discovery Response */
+		MLAN_PACK_START struct _tdls_discovery_resp {
+			/** payload length */
+			t_u16 payload_len;
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** RSSI */
+			t_s8 rssi;
+			/** Cap Info */
+			t_u16 cap_info;
+			/** TLV buffer */
+			t_u8 tlv_buffer[];
+		} MLAN_PACK_END tdls_discovery_resp;
+
+		/** TDLS setup request */
+		MLAN_PACK_START struct _tdls_setup_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** timeout value in milliseconds */
+			t_u32 setup_timeout;
+			/** key lifetime in milliseconds */
+			t_u32 key_lifetime;
+		} MLAN_PACK_END tdls_setup;
+
+		/** TDLS tear down info */
+		MLAN_PACK_START struct _tdls_tear_down_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** reason code */
+			t_u16 reason_code;
+		} MLAN_PACK_END tdls_tear_down, tdls_cmd_resp;
+
+		/** TDLS power mode info */
+		MLAN_PACK_START struct _tdls_power_mode_data {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** Power Mode */
+			t_u16 power_mode;
+		} MLAN_PACK_END tdls_power_mode;
+
+		/** TDLS channel switch info */
+		MLAN_PACK_START struct _tdls_chan_switch {
+			/** peer mac Address */
+			t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+			/** Channel Switch primary channel no */
+			t_u8 primary_channel;
+			/** Channel Switch secondary channel offset */
+			t_u8 secondary_channel_offset;
+			/** Channel Switch Band */
+			t_u8 band;
+			/** Channel Switch time in milliseconds */
+			t_u16 switch_time;
+			/** Channel Switch timeout in milliseconds */
+			t_u16 switch_timeout;
+			/** Channel Regulatory class*/
+			t_u8 regulatory_class;
+			/** peridicity flag*/
+			t_u8 periodicity;
+		} MLAN_PACK_END tdls_chan_switch;
+
+		/** TDLS channel switch paramters */
+		MLAN_PACK_START struct _tdls_cs_params {
+			/** unit time, multiples of 10ms */
+			t_u8 unit_time;
+			/** threshold for other link */
+			t_u8 threshold_otherlink;
+			/** threshold for direct link */
+			t_u8 threshold_directlink;
+		} MLAN_PACK_END tdls_cs_params;
+
+		/** tdls disable channel switch */
+		MLAN_PACK_START struct _tdls_disable_cs {
+			/** Data*/
+			t_u16 data;
+		} MLAN_PACK_END tdls_disable_cs;
+		/** TDLS debug data */
+		MLAN_PACK_START struct _tdls_debug_data {
+			/** debug data */
+			t_u16 debug_data;
+		} MLAN_PACK_END tdls_debug_data;
+
+		/** TDLS link status Response */
+		MLAN_PACK_START struct _tdls_link_status_resp {
+			/** payload length */
+			t_u16 payload_len;
+			/** number of links */
+			t_u8 active_links;
+			/** structure for link status */
+			tdls_each_link_status link_stats[1];
+		} MLAN_PACK_END tdls_link_status_resp;
+
+	} u;
+} MLAN_PACK_END tdls_all_config;
+
+/** TDLS configuration buffer */
+typedef MLAN_PACK_START struct _buf_tdls_config {
+	/** TDLS Action */
+	t_u16 tdls_action;
+	/** TDLS data */
+	t_u8 tdls_data[MAX_TDLS_DATA_LEN];
+} MLAN_PACK_END mlan_ds_misc_tdls_config;
+
+/** Event structure for tear down */
+typedef struct _tdls_tear_down_event {
+	/** Peer mac address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Reason code */
+	t_u16 reason_code;
+} tdls_tear_down_event;
+
+/** channel width */
+typedef enum wifi_channel_width {
+	WIFI_CHAN_WIDTH_20 = 0,
+	WIFI_CHAN_WIDTH_40 = 1,
+	WIFI_CHAN_WIDTH_80 = 2,
+	WIFI_CHAN_WIDTH_160 = 3,
+	WIFI_CHAN_WIDTH_80P80 = 4,
+	WIFI_CHAN_WIDTH_5 = 5,
+	WIFI_CHAN_WIDTH_10 = 6,
+	WIFI_CHAN_WIDTH_INVALID = -1
+} wifi_channel_width_t;
+
+/** channel information */
+typedef struct {
+	/** channel width (20, 40, 80, 80+80, 160) */
+	wifi_channel_width_t width;
+	/** primary 20 MHz channel */
+	int center_freq;
+	/** center frequency (MHz) first segment */
+	int center_freq0;
+	/** center frequency (MHz) second segment */
+	int center_freq1;
+} wifi_channel_info;
+
+/** wifi rate */
+typedef struct {
+	/** 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+	t_u32 preamble:3;
+	/** 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+	t_u32 nss:2;
+	/** 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */
+	t_u32 bw:3;
+	/** OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps
+	 */
+	/** HT/VHT it would be mcs index */
+	t_u32 rateMcsIdx:8;
+	/** reserved */
+	t_u32 reserved:16;
+	/** units of 100 Kbps */
+	t_u32 bitrate;
+} wifi_rate;
+
+/** wifi Preamble type */
+typedef enum {
+	WIFI_PREAMBLE_LEGACY = 0x1,
+	WIFI_PREAMBLE_HT = 0x2,
+	WIFI_PREAMBLE_VHT = 0x4
+} wifi_preamble;
+
+/** timeval */
+typedef struct {
+	/** Time (seconds) */
+	t_u32 time_sec;
+	/** Time (micro seconds) */
+	t_u32 time_usec;
+} wifi_timeval;
+
+#define MAX_NUM_RATE 32
+#define MAX_RADIO 2
+#define MAX_NUM_CHAN 1
+#define VHT_NUM_SUPPORT_MCS 10
+#define MCS_NUM_SUPP 16
+
+#define BUF_MAXLEN 4096
+/** connection state */
+typedef enum {
+	MLAN_DISCONNECTED = 0,
+	MLAN_AUTHENTICATING = 1,
+	MLAN_ASSOCIATING = 2,
+	MLAN_ASSOCIATED = 3,
+	/** if done by firmware/driver */
+	MLAN_EAPOL_STARTED = 4,
+	/** if done by firmware/driver */
+	MLAN_EAPOL_COMPLETED = 5,
+} mlan_connection_state;
+/** roam state */
+typedef enum {
+	MLAN_ROAMING_IDLE = 0,
+	MLAN_ROAMING_ACTIVE = 1,
+} mlan_roam_state;
+/** interface mode */
+typedef enum {
+	MLAN_INTERFACE_STA = 0,
+	MLAN_INTERFACE_SOFTAP = 1,
+	MLAN_INTERFACE_IBSS = 2,
+	MLAN_INTERFACE_P2P_CLIENT = 3,
+	MLAN_INTERFACE_P2P_GO = 4,
+	MLAN_INTERFACE_NAN = 5,
+	MLAN_INTERFACE_MESH = 6,
+} mlan_interface_mode;
+
+/** set for QOS association */
+#define MLAN_CAPABILITY_QOS 0x00000001
+/** set for protected association (802.11 beacon frame control protected bit
+ * set) */
+#define MLAN_CAPABILITY_PROTECTED 0x00000002
+/** set if 802.11 Extended Capabilities element interworking bit is set */
+#define MLAN_CAPABILITY_INTERWORKING 0x00000004
+/** set for HS20 association */
+#define MLAN_CAPABILITY_HS20 0x00000008
+/** set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */
+#define MLAN_CAPABILITY_SSID_UTF8 0x00000010
+/** set is 802.11 Country Element is present */
+#define MLAN_CAPABILITY_COUNTRY 0x00000020
+
+/** link layer status */
+typedef struct {
+	/** interface mode */
+	mlan_interface_mode mode;
+	/** interface mac address (self) */
+	t_u8 mac_addr[6];
+	/** connection state (valid for STA, CLI only) */
+	mlan_connection_state state;
+	/** roaming state */
+	mlan_roam_state roaming;
+	/** WIFI_CAPABILITY_XXX (self) */
+	t_u32 capabilities;
+	/** null terminated SSID */
+	t_u8 ssid[33];
+	/** bssid */
+	t_u8 bssid[6];
+	/** country string advertised by AP */
+	t_u8 ap_country_str[3];
+	/** country string for this association */
+	t_u8 country_str[3];
+} mlan_interface_link_layer_info, *mlan_interface_handle;
+
+/** channel statistics */
+typedef struct {
+	/** channel */
+	wifi_channel_info channel;
+	/** msecs the radio is awake (32 bits number accruing over time) */
+	t_u32 on_time;
+	/** msecs the CCA register is busy (32 bits number accruing over time)
+	 */
+	t_u32 cca_busy_time;
+} wifi_channel_stat;
+
+#define timeval_to_msec(timeval)                                               \
+	(t_u64)((t_u64)(timeval.time_sec) * 1000 +                             \
+		(t_u64)(timeval.time_usec) / 1000)
+#define timeval_to_usec(timeval)                                               \
+	(t_u64)((t_u64)(timeval.time_sec) * 1000 * 1000 +                      \
+		(t_u64)(timeval.time_usec))
+#define is_zero_timeval(timeval)                                               \
+	((timeval.time_sec == 0) && (timeval.time_usec == 0))
+
+/** radio statistics */
+typedef struct {
+	/** wifi radio (if multiple radio supported) */
+	int radio;
+	/** msecs the radio is awake (32 bits number accruing over time) */
+	t_u32 on_time;
+	/** msecs the radio is transmitting (32 bits number accruing over time)
+	 */
+	t_u32 tx_time;
+	/**  TBD: num_tx_levels: number of radio transmit power levels */
+	t_u32 reserved0;
+	/** TBD: tx_time_per_levels: pointer to an array of radio transmit per
+	 * power levels in msecs accured over time */
+	/* t_u32 *reserved1; */
+	/** msecs the radio is in active receive (32 bits number accruing over
+	 * time) */
+	t_u32 rx_time;
+	/** msecs the radio is awake due to all scan (32 bits number accruing
+	 * over time) */
+	t_u32 on_time_scan;
+	/** msecs the radio is awake due to NAN (32 bits number accruing over
+	 * time) */
+	t_u32 on_time_nbd;
+	/** msecs the radio is awake due to G?scan (32 bits number accruing over
+	 * time) */
+	t_u32 on_time_gscan;
+	/** msecs the radio is awake due to roam?scan (32 bits number accruing
+	 * over time) */
+	t_u32 on_time_roam_scan;
+	/** msecs the radio is awake due to PNO scan (32 bits number accruing
+	 * over time) */
+	t_u32 on_time_pno_scan;
+	/** msecs the radio is awake due to HS2.0 scans and GAS exchange (32
+	 * bits number accruing over time) */
+	t_u32 on_time_hs20;
+	/** number of channels */
+	t_u32 num_channels;
+	/** channel statistics */
+	wifi_channel_stat channels[MAX_NUM_CHAN];
+} wifi_radio_stat;
+
+/** per rate statistics */
+typedef struct {
+	/** rate information */
+	wifi_rate rate;
+	/** number of successfully transmitted data pkts (ACK rcvd) */
+	t_u32 tx_mpdu;
+	/** number of received data pkts */
+	t_u32 rx_mpdu;
+	/** number of data packet losses (no ACK) */
+	t_u32 mpdu_lost;
+	/** total number of data pkt retries */
+	t_u32 retries;
+	/** number of short data pkt retries */
+	t_u32 retries_short;
+	/** number of long data pkt retries */
+	t_u32 retries_long;
+} wifi_rate_stat;
+
+/** wifi peer type */
+typedef enum {
+	WIFI_PEER_STA,
+	WIFI_PEER_AP,
+	WIFI_PEER_P2P_GO,
+	WIFI_PEER_P2P_CLIENT,
+	WIFI_PEER_NAN,
+	WIFI_PEER_TDLS,
+	WIFI_PEER_INVALID,
+} wifi_peer_type;
+
+/** per peer statistics */
+typedef struct {
+	/** peer type (AP, TDLS, GO etc.) */
+	wifi_peer_type type;
+	/** mac address */
+	t_u8 peer_mac_address[6];
+	/** peer WIFI_CAPABILITY_XXX */
+	t_u32 capabilities;
+	/** number of rates */
+	t_u32 num_rate;
+	/** per rate statistics, number of entries  = num_rate */
+	wifi_rate_stat rate_stats[];
+} wifi_peer_info;
+
+/** per access category statistics */
+typedef struct {
+	/** access category (VI, VO, BE, BK) */
+	mlan_wmm_ac_e ac;
+	/** number of successfully transmitted unicast data pkts (ACK rcvd) */
+	t_u32 tx_mpdu;
+	/** number of received unicast mpdus */
+	t_u32 rx_mpdu;
+	/** number of succesfully transmitted multicast data packets */
+	/** STA case: implies ACK received from AP for the unicast packet in
+	 * which mcast pkt was sent */
+	t_u32 tx_mcast;
+	/** number of received multicast data packets */
+	t_u32 rx_mcast;
+	/** number of received unicast a-mpdus */
+	t_u32 rx_ampdu;
+	/** number of transmitted unicast a-mpdus */
+	t_u32 tx_ampdu;
+	/** number of data pkt losses (no ACK) */
+	t_u32 mpdu_lost;
+	/** total number of data pkt retries */
+	t_u32 retries;
+	/** number of short data pkt retries */
+	t_u32 retries_short;
+	/** number of long data pkt retries */
+	t_u32 retries_long;
+	/** data pkt min contention time (usecs) */
+	t_u32 contention_time_min;
+	/** data pkt max contention time (usecs) */
+	t_u32 contention_time_max;
+	/** data pkt avg contention time (usecs) */
+	t_u32 contention_time_avg;
+	/** num of data pkts used for contention statistics */
+	t_u32 contention_num_samples;
+} wifi_wmm_ac_stat;
+
+/** interface statistics */
+typedef struct {
+	/** wifi interface */
+	/* wifi_interface_handle iface; */
+	/** current state of the interface */
+	mlan_interface_link_layer_info info;
+	/** access point beacon received count from connected AP */
+	t_u32 beacon_rx;
+	/** Average beacon offset encountered (beacon_TSF - TBTT)
+	 *    the average_tsf_offset field is used so as to calculate the
+	 *    typical beacon contention time on the channel as well may be
+	 *    used to debug beacon synchronization and related power consumption
+	 * issue
+	 */
+	t_u64 average_tsf_offset;
+	/** indicate that this AP typically leaks packets beyond the driver
+	 * guard time */
+	t_u32 leaky_ap_detected;
+	/** average number of frame leaked by AP after frame with PM bit set was
+	 * ACK'ed by AP */
+	t_u32 leaky_ap_avg_num_frames_leaked;
+	/** Guard time currently in force (when implementing IEEE power
+	 * management based on frame control PM bit), How long driver waits
+	 * before shutting down the radio and after receiving an ACK for a data
+	 * frame with PM bit set)
+	 */
+	t_u32 leaky_ap_guard_time;
+	/** access point mgmt frames received count from connected AP (including
+	 * Beacon) */
+	t_u32 mgmt_rx;
+	/** action frames received count */
+	t_u32 mgmt_action_rx;
+	/** action frames transmit count */
+	t_u32 mgmt_action_tx;
+	/** access Point Beacon and Management frames RSSI (averaged) */
+	t_s32 rssi_mgmt;
+	/** access Point Data Frames RSSI (averaged) from connected AP */
+	t_s32 rssi_data;
+	/** access Point ACK RSSI (averaged) from connected AP */
+	t_s32 rssi_ack;
+	/** per ac data packet statistics */
+	wifi_wmm_ac_stat ac[MAX_AC_QUEUES];
+	/** number of peers */
+	t_u32 num_peers;
+	/** per peer statistics */
+	wifi_peer_info peer_info[];
+} wifi_iface_stat;
+
+/** link layer stat configuration params */
+typedef struct {
+	/** threshold to classify the pkts as short or long */
+	t_u32 mpdu_size_threshold;
+	/** wifi statistics bitmap */
+	t_u32 aggressive_statistics_gathering;
+} wifi_link_layer_params;
+
+/** wifi statistics bitmap  */
+#define WIFI_STATS_RADIO 0x00000001 /** all radio statistics */
+#define WIFI_STATS_RADIO_CCA                                                   \
+	0x00000002 /** cca_busy_time (within radio statistics) */
+#define WIFI_STATS_RADIO_CHANNELS                                              \
+	0x00000004 /** all channel statistics (within radio statistics) */
+#define WIFI_STATS_RADIO_SCAN                                                  \
+	0x00000008 /** all scan statistics (within radio statistics) */
+#define WIFI_STATS_IFACE 0x00000010 /** all interface statistics */
+#define WIFI_STATS_IFACE_TXRATE                                                \
+	0x00000020 /** all tx rate statistics (within interface statistics) */
+#define WIFI_STATS_IFACE_AC                                                    \
+	0x00000040 /** all ac statistics (within interface statistics) */
+#define WIFI_STATS_IFACE_CONTENTION                                            \
+	0x00000080 /** all contention (min, max, avg) statistics (within ac    \
+		      statisctics) */
+
+/** station stats */
+typedef struct _sta_stats {
+	t_u64 last_rx_in_msec;
+} sta_stats;
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+/** mlan_callbacks data structure */
+typedef struct _mlan_callbacks {
+	/** moal_get_fw_data */
+	mlan_status (*moal_get_fw_data) (t_void *pmoal,
+					 t_u32 offset, t_u32 len, t_u8 *pbuf);
+	mlan_status (*moal_get_vdll_data) (t_void *pmoal, t_u32 len,
+					   t_u8 *pbuf);
+	/** moal_get_hw_spec_complete */
+	mlan_status (*moal_get_hw_spec_complete) (t_void *pmoal,
+						  mlan_status status,
+						  pmlan_hw_info phw,
+						  pmlan_bss_tbl ptbl);
+	/** moal_init_fw_complete */
+	mlan_status (*moal_init_fw_complete) (t_void *pmoal,
+					      mlan_status status);
+	/** moal_shutdown_fw_complete */
+	mlan_status (*moal_shutdown_fw_complete) (t_void *pmoal,
+						  mlan_status status);
+	/** moal_send_packet_complete */
+	mlan_status (*moal_send_packet_complete) (t_void *pmoal,
+						  pmlan_buffer pmbuf,
+						  mlan_status status);
+	/** moal_recv_complete */
+	mlan_status (*moal_recv_complete) (t_void *pmoal,
+					   pmlan_buffer pmbuf, t_u32 port,
+					   mlan_status status);
+	/** moal_recv_packet */
+	mlan_status (*moal_recv_packet) (t_void *pmoal, pmlan_buffer pmbuf);
+    /** moal_recv_amsdu_packet */
+	mlan_status (*moal_recv_amsdu_packet) (t_void *pmoal,
+					       pmlan_buffer pmbuf);
+	/** moal_recv_event */
+	mlan_status (*moal_recv_event) (t_void *pmoal, pmlan_event pmevent);
+	/** moal_ioctl_complete */
+	mlan_status (*moal_ioctl_complete) (t_void *pmoal,
+					    pmlan_ioctl_req pioctl_req,
+					    mlan_status status);
+
+	/** moal_alloc_mlan_buffer */
+	mlan_status (*moal_alloc_mlan_buffer) (t_void *pmoal,
+					       t_u32 size, ppmlan_buffer pmbuf);
+	/** moal_free_mlan_buffer */
+	mlan_status (*moal_free_mlan_buffer) (t_void *pmoal,
+					      pmlan_buffer pmbuf);
+
+#ifdef USB
+	/** moal_write_data_async */
+	mlan_status (*moal_write_data_async) (t_void *pmoal,
+					      pmlan_buffer pmbuf, t_u32 port);
+#endif				/* USB */
+#if defined(SDIO) || defined(PCIE)
+	/** moal_write_reg */
+	mlan_status (*moal_write_reg) (t_void *pmoal, t_u32 reg, t_u32 data);
+	/** moal_read_reg */
+	mlan_status (*moal_read_reg) (t_void *pmoal, t_u32 reg, t_u32 *data);
+#endif				/* SDIO || PCIE */
+	/** moal_write_data_sync */
+	mlan_status (*moal_write_data_sync) (t_void *pmoal,
+					     pmlan_buffer pmbuf,
+					     t_u32 port, t_u32 timeout);
+	/** moal_read_data_sync */
+	mlan_status (*moal_read_data_sync) (t_void *pmoal,
+					    pmlan_buffer pmbuf,
+					    t_u32 port, t_u32 timeout);
+	/** moal_malloc */
+	mlan_status (*moal_malloc) (t_void *pmoal, t_u32 size,
+				    t_u32 flag, t_u8 **ppbuf);
+	/** moal_mfree */
+	mlan_status (*moal_mfree) (t_void *pmoal, t_u8 *pbuf);
+	/** moal_vmalloc */
+	mlan_status (*moal_vmalloc) (t_void *pmoal, t_u32 size, t_u8 **ppbuf);
+	/** moal_vfree */
+	mlan_status (*moal_vfree) (t_void *pmoal, t_u8 *pbuf);
+#ifdef PCIE
+	/** moal_malloc_consistent */
+	mlan_status (*moal_malloc_consistent) (t_void *pmoal,
+					       t_u32 size, t_u8 **ppbuf,
+					       t_u64 *pbuf_pa);
+	/** moal_mfree_consistent */
+	mlan_status (*moal_mfree_consistent) (t_void *pmoal,
+					      t_u32 size, t_u8 *pbuf,
+					      t_u64 buf_pa);
+	/** moal_map_memory */
+	mlan_status (*moal_map_memory) (t_void *pmoal, t_u8 *pbuf,
+					t_u64 *pbuf_pa, t_u32 size, t_u32 flag);
+	/** moal_unmap_memory */
+	mlan_status (*moal_unmap_memory) (t_void *pmoal, t_u8 *pbuf,
+					  t_u64 buf_pa, t_u32 size, t_u32 flag);
+#endif				/* PCIE */
+	/** moal_memset */
+	t_void *(*moal_memset) (t_void *pmoal, t_void *pmem,
+				t_u8 byte, t_u32 num);
+	/** moal_memcpy */
+	t_void *(*moal_memcpy) (t_void *pmoal, t_void *pdest,
+				const t_void *psrc, t_u32 num);
+	/** moal_memcpy_ext */
+	t_void *(*moal_memcpy_ext) (t_void *pmoal, t_void *pdest,
+				    const t_void *psrc, t_u32 num,
+				    t_u32 dest_size);
+	/** moal_memmove */
+	t_void *(*moal_memmove) (t_void *pmoal, t_void *pdest,
+				 const t_void *psrc, t_u32 num);
+	/** moal_memcmp */
+	t_s32 (*moal_memcmp) (t_void *pmoal, const t_void *pmem1,
+			      const t_void *pmem2, t_u32 num);
+	/** moal_udelay */
+	t_void (*moal_udelay) (t_void *pmoal, t_u32 udelay);
+	/** moal_usleep_range */
+	t_void (*moal_usleep_range) (t_void *pmoal,
+				     t_u32 min_delay, t_u32 max_delay);
+	/** moal_get_boot_ktime */
+	mlan_status (*moal_get_boot_ktime) (t_void *pmoal, t_u64 *pnsec);
+	/** moal_get_system_time */
+	mlan_status (*moal_get_system_time) (t_void *pmoal,
+					     t_u32 *psec, t_u32 *pusec);
+	/** moal_init_timer*/
+	mlan_status (*moal_init_timer) (t_void *pmoal,
+					t_void **pptimer,
+					IN t_void (*callback) (t_void
+							       *pcontext),
+					t_void *pcontext);
+	/** moal_free_timer */
+	mlan_status (*moal_free_timer) (t_void *pmoal, t_void *ptimer);
+	/** moal_start_timer*/
+	mlan_status (*moal_start_timer) (t_void *pmoal,
+					 t_void *ptimer, t_u8 periodic,
+					 t_u32 msec);
+	/** moal_stop_timer*/
+	mlan_status (*moal_stop_timer) (t_void *pmoal, t_void *ptimer);
+	/** moal_init_lock */
+	mlan_status (*moal_init_lock) (t_void *pmoal, t_void **pplock);
+	/** moal_free_lock */
+	mlan_status (*moal_free_lock) (t_void *pmoal, t_void *plock);
+	/** moal_spin_lock */
+	mlan_status (*moal_spin_lock) (t_void *pmoal, t_void *plock);
+	/** moal_spin_unlock */
+	mlan_status (*moal_spin_unlock) (t_void *pmoal, t_void *plock);
+	/** moal_print */
+	t_void (*moal_print) (t_void *pmoal, t_u32 level,
+			      char *pformat, IN ...);
+	/** moal_print_netintf */
+	t_void (*moal_print_netintf) (t_void *pmoal,
+				      t_u32 bss_index, t_u32 level);
+	/** moal_assert */
+	t_void (*moal_assert) (t_void *pmoal, t_u32 cond);
+
+	/** moal_hist_data_add */
+	t_void (*moal_hist_data_add) (t_void *pmoal,
+				      t_u32 bss_index, t_u16 rx_rate,
+				      t_s8 snr, t_s8 nflr, t_u8 antenna);
+	t_void (*moal_updata_peer_signal) (t_void *pmoal,
+					   t_u32 bss_index,
+					   t_u8 *peer_addr, t_s8 snr,
+					   t_s8 nflr);
+	t_u64 (*moal_do_div) (t_u64 num, t_u32 base);
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	mlan_status (*moal_wait_hostcmd_complete) (t_void *pmoal,
+						   t_u32 bss_index);
+	mlan_status (*moal_notify_hostcmd_complete) (t_void *pmoal,
+						     t_u32 bss_index);
+#endif
+	void (*moal_tp_accounting) (t_void *pmoal,
+				    t_void *buf, t_u32 drop_point);
+	void (*moal_tp_accounting_rx_param) (t_void *pmoal,
+					     unsigned int type,
+					     unsigned int rsvd1);
+	void (*moal_amsdu_tp_accounting) (t_void *pmoal, t_s32 delay,
+					  t_s32 copy_delay);
+} mlan_callbacks, *pmlan_callbacks;
+
+/** Parameter unchanged, use MLAN default setting */
+#define ROBUSTCOEX_GPIO_UNCHANGED 0
+/** Parameter enabled, override MLAN default setting */
+#define ROBUSTCOEX_GPIO_CFG 1
+
+#if defined(SDIO)
+/** Interrupt Mode SDIO */
+#define INT_MODE_SDIO 0
+/** Interrupt Mode GPIO */
+#define INT_MODE_GPIO 1
+/** New mode: GPIO-1 as a duplicated signal of interrupt as appear of SDIO_DAT1
+ */
+#define GPIO_INT_NEW_MODE 255
+#endif
+
+/** Parameter unchanged, use MLAN default setting */
+#define MLAN_INIT_PARA_UNCHANGED 0
+/** Parameter enabled, override MLAN default setting */
+#define MLAN_INIT_PARA_ENABLED 1
+/** Parameter disabled, override MLAN default setting */
+#define MLAN_INIT_PARA_DISABLED 2
+
+/** Control bit for stream 2X2 */
+#define FEATURE_CTRL_STREAM_2X2 MBIT(0)
+/** Control bit for DFS support */
+#define FEATURE_CTRL_DFS_SUPPORT MBIT(1)
+#ifdef USB
+/** Control bit for winner check & not wait for FW ready event */
+#define FEATURE_CTRL_USB_NEW_INIT MBIT(2)
+#endif
+/** Default feature control */
+#define FEATURE_CTRL_DEFAULT 0xffffffff
+/** Check if stream 2X2 enabled */
+#define IS_STREAM_2X2(x) ((x)&FEATURE_CTRL_STREAM_2X2)
+/** Check if DFS support enabled */
+#define IS_DFS_SUPPORT(x) ((x)&FEATURE_CTRL_DFS_SUPPORT)
+#ifdef USB
+/** Check if winner check & not wait for FW ready event */
+#define IS_USB_NEW_INIT(x) ((x)&FEATURE_CTRL_USB_NEW_INIT)
+#endif
+
+/*
+#define DRV_MODE_NAN                 MBIT(4)
+#define DRV_MODE_11P                 MBIT(5)
+#define DRV_MODE_MAC80211            MBIT(6)
+#define DRV_MODE_DFS                 MBIT(7)*/
+#define DRV_MODE_MASK (MBIT(4) | MBIT(5) | MBIT(6) | MBIT(7))
+
+/** mlan_device data structure */
+typedef struct _mlan_device {
+	/** MOAL Handle */
+	t_void *pmoal_handle;
+	/** BSS Attributes */
+	mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM];
+	/** Callbacks */
+	mlan_callbacks callbacks;
+#ifdef MFG_CMD_SUPPORT
+	/** MFG mode */
+	t_u32 mfg_mode;
+#endif
+#ifdef PCIE
+	t_u16 ring_size;
+#endif
+#if defined(SDIO)
+	/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+	t_u32 int_mode;
+	/** GPIO interrupt pin number */
+	t_u32 gpio_pin;
+#endif
+#ifdef DEBUG_LEVEL1
+	/** Driver debug bit masks */
+	t_u32 drvdbg;
+#endif
+	/** allocate fixed buffer size for scan beacon buffer*/
+	t_u32 fixed_beacon_buffer;
+	/** SDIO MPA Tx */
+	t_u32 mpa_tx_cfg;
+	/** SDIO MPA Rx */
+	t_u32 mpa_rx_cfg;
+#ifdef SDIO
+	/** SDIO Single port rx aggr */
+	t_u8 sdio_rx_aggr_enable;
+	/* see blk_queue_max_segment_size */
+	t_u32 max_seg_size;
+	/* see blk_queue_max_segments */
+	t_u16 max_segs;
+#endif
+	/** Auto deep sleep */
+	t_u32 auto_ds;
+	/** IEEE PS mode */
+	t_u32 ps_mode;
+	/** Max Tx buffer size */
+	t_u32 max_tx_buf;
+#if defined(STA_SUPPORT)
+	/** 802.11d configuration */
+	t_u32 cfg_11d;
+#endif
+	/** Feature control bitmask */
+	t_u32 feature_control;
+	/** enable/disable rx work */
+	t_u8 rx_work;
+	/** dev cap mask */
+	t_u32 dev_cap_mask;
+	/** oob independent reset */
+	t_u32 indrstcfg;
+	/** dtim interval */
+	t_u16 multi_dtim;
+	/** IEEE ps inactivity timeout value */
+	t_u16 inact_tmo;
+	/** card type */
+	t_u16 card_type;
+	/** card rev */
+	t_u8 card_rev;
+	/** Host sleep wakeup interval */
+	t_u32 hs_wake_interval;
+	/** GPIO to indicate wakeup source */
+	t_u8 indication_gpio;
+	/** Dynamic MIMO-SISO switch for hscfg*/
+	t_u8 hs_mimo_switch;
+#ifdef USB
+	/** Tx CMD endpoint address */
+	t_u8 tx_cmd_ep;
+	/** Rx CMD/EVT endpoint address */
+	t_u8 rx_cmd_ep;
+
+	/** Rx data endpoint address */
+	t_u8 rx_data_ep;
+	/** Tx data endpoint address */
+	t_u8 tx_data_ep;
+#endif
+	/** passive to active scan */
+	t_u8 passive_to_active_scan;
+	/** uap max supported station per chip */
+	t_u8 uap_max_sta;
+	/** drv mode */
+	t_u32 drv_mode;
+	/** dfs w53 cfg */
+	t_u8 dfs53cfg;
+    /** extend enhance scan */
+	t_u8 ext_scan;
+} mlan_device, *pmlan_device;
+
+/** MLAN API function prototype */
+#define MLAN_API
+
+/** Registration */
+MLAN_API mlan_status mlan_register(pmlan_device pmdevice,
+				   t_void **ppmlan_adapter);
+
+/** Un-registration */
+MLAN_API mlan_status mlan_unregister(t_void *padapter);
+
+/** Firmware Downloading */
+MLAN_API mlan_status mlan_dnld_fw(t_void *padapter, pmlan_fw_image pmfw);
+
+/** Custom data pass API */
+MLAN_API mlan_status mlan_set_init_param(t_void *padapter,
+					 pmlan_init_param pparam);
+
+/** Firmware Initialization */
+MLAN_API mlan_status mlan_init_fw(t_void *padapter);
+
+/** Firmware Shutdown */
+MLAN_API mlan_status mlan_shutdown_fw(t_void *padapter);
+
+/** Main Process */
+MLAN_API mlan_status mlan_main_process(t_void *padapter);
+
+/** Rx process */
+mlan_status mlan_rx_process(t_void *padapter, t_u8 *rx_pkts);
+
+/** Packet Transmission */
+MLAN_API mlan_status mlan_send_packet(t_void *padapter, pmlan_buffer pmbuf);
+
+#ifdef USB
+/** mlan_write_data_async_complete */
+MLAN_API mlan_status mlan_write_data_async_complete(t_void *padapter,
+						    pmlan_buffer pmbuf,
+						    t_u32 port,
+						    mlan_status status);
+
+/** Packet Reception */
+MLAN_API mlan_status mlan_recv(t_void *padapter, pmlan_buffer pmbuf,
+			       t_u32 port);
+#endif /* USB */
+
+/** Packet Reception complete callback */
+MLAN_API mlan_status mlan_recv_packet_complete(t_void *padapter,
+					       pmlan_buffer pmbuf,
+					       mlan_status status);
+
+/** handle amsdu deaggregated packet */
+void mlan_process_deaggr_pkt(t_void *padapter, pmlan_buffer pmbuf, t_u8 *drop);
+
+#if defined(SDIO) || defined(PCIE)
+/** interrupt handler */
+MLAN_API mlan_status mlan_interrupt(t_u16 msg_id, t_void *padapter);
+
+#if defined(SYSKT)
+/** GPIO IRQ callback function */
+MLAN_API t_void mlan_hs_callback(t_void *pctx);
+#endif /* SYSKT_MULTI || SYSKT */
+#endif /* SDIO || PCIE */
+
+MLAN_API t_void mlan_pm_wakeup_card(t_void *padapter, t_u8 keep_wakeup);
+
+MLAN_API t_u8 mlan_is_main_process_running(t_void *adapter);
+#ifdef PCIE
+MLAN_API t_void mlan_set_int_mode(t_void *adapter, t_u32 int_mode,
+				  t_u8 func_num);
+#endif
+/** mlan ioctl */
+MLAN_API mlan_status mlan_ioctl(t_void *padapter, pmlan_ioctl_req pioctl_req);
+/** mlan select wmm queue */
+MLAN_API t_u8 mlan_select_wmm_queue(t_void *padapter, t_u8 bss_num, t_u8 tid);
+
+/** mlan mask host interrupt */
+MLAN_API mlan_status mlan_disable_host_int(t_void *padapter);
+/** mlan unmask host interrupt */
+MLAN_API mlan_status mlan_enable_host_int(t_void *padapter);
+
+#endif /* !_MLAN_DECL_H_ */
diff --git a/wlan_sd8987/mlinux/mlan_ieee.h b/wlan_sd8987/mlinux/mlan_ieee.h
new file mode 100755
index 0000000..aec54d5
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan_ieee.h
@@ -0,0 +1,2003 @@
+/** @file mlan_ieee.h
+ *
+ *  @brief This file contains IEEE information element related
+ *  definitions used in MLAN and MOAL module.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    11/03/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_IEEE_H_
+#define _MLAN_IEEE_H_
+
+/** FIX IES size in beacon buffer */
+#define WLAN_802_11_FIXED_IE_SIZE 12
+/** WLAN supported rates */
+#define WLAN_SUPPORTED_RATES 14
+
+/** WLAN supported rates extension */
+#define WLAN_SUPPORTED_RATES_EXT 60
+
+/** Enumeration definition*/
+/** WLAN_802_11_NETWORK_TYPE */
+typedef enum _WLAN_802_11_NETWORK_TYPE {
+	Wlan802_11FH,
+	Wlan802_11DS,
+	/* Defined as upper bound */
+	Wlan802_11NetworkTypeMax
+} WLAN_802_11_NETWORK_TYPE;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Frame control: Type Mgmt frame */
+#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x3000
+/** Frame control: SubType Mgmt frame */
+#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc)&0xF000) >> 12)
+#else
+/** Frame control: Type Mgmt frame */
+#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x000C
+/** Frame control: SubType Mgmt frame */
+#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc)&0x00F0) >> 4)
+#endif
+
+#ifdef PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+/* Reason codes */
+#define IEEE_80211_REASONCODE_UNSPECIFIED 1
+
+typedef enum _IEEEtypes_Ext_ElementId_e {
+	HE_CAPABILITY = 35,
+	HE_OPERATION = 36
+} IEEEtypes_Ext_ElementId_e;
+
+/** IEEE Type definitions  */
+typedef MLAN_PACK_START enum _IEEEtypes_ElementId_e {
+	SSID = 0,
+	SUPPORTED_RATES = 1,
+
+	FH_PARAM_SET = 2,
+	DS_PARAM_SET = 3,
+	CF_PARAM_SET = 4,
+
+	IBSS_PARAM_SET = 6,
+	COUNTRY_INFO = 7,
+	POWER_CONSTRAINT = 32,
+	POWER_CAPABILITY = 33,
+	TPC_REQUEST = 34,
+	TPC_REPORT = 35,
+	CHANNEL_SWITCH_ANN = 37,
+	EXTEND_CHANNEL_SWITCH_ANN = 60,
+	QUIET = 40,
+	IBSS_DFS = 41,
+	SUPPORTED_CHANNELS = 36,
+	REGULATORY_CLASS = 59,
+	HT_CAPABILITY = 45,
+	QOS_INFO = 46,
+	HT_OPERATION = 61,
+	MULTI_BSSID = 71,
+	BSSCO_2040 = 72,
+	OVERLAPBSSSCANPARAM = 74,
+	NONTX_BSSID_CAP = 83,
+	MBSSID_INDEX = 85,
+	EXT_CAPABILITY = 127,
+	LINK_ID = 101,
+	/*IEEE802.11r */
+	MOBILITY_DOMAIN = 54,
+	FAST_BSS_TRANSITION = 55,
+	TIMEOUT_INTERVAL = 56,
+	RIC = 57,
+	QOS_MAPPING = 110,
+	VHT_CAPABILITY = 191,
+	VHT_OPERATION = 192,
+	EXT_BSS_LOAD = 193,
+	BW_CHANNEL_SWITCH = 194,
+	VHT_TX_POWER_ENV = 195,
+	EXT_POWER_CONSTR = 196,
+	AID_INFO = 197,
+	QUIET_CHAN = 198,
+	OPER_MODE_NTF = 199,
+
+	ERP_INFO = 42,
+
+	EXTENDED_SUPPORTED_RATES = 50,
+
+	VENDOR_SPECIFIC_221 = 221,
+	WMM_IE = VENDOR_SPECIFIC_221,
+
+	WPS_IE = VENDOR_SPECIFIC_221,
+	/* WPA */
+	WPA_IE = VENDOR_SPECIFIC_221,
+	/* WPA2 */
+	RSN_IE = 48,
+	VS_IE = VENDOR_SPECIFIC_221,
+	WAPI_IE = 68,
+	FRAGMENT = 242,
+	RSNX_IE = 244,
+	EXTENSION = 255
+} MLAN_PACK_END IEEEtypes_ElementId_e;
+
+/** IEEE IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_Header_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+} MLAN_PACK_END IEEEtypes_Header_t, *pIEEEtypes_Header_t;
+
+/** Vendor specific IE header */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorHeader_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** OUI */
+	t_u8 oui[3];
+	/** OUI type */
+	t_u8 oui_type;
+	/** OUI subtype */
+	t_u8 oui_subtype;
+	/** Version */
+	t_u8 version;
+} MLAN_PACK_END IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t;
+
+/** Vendor specific IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VendorSpecific_t {
+	/** Vendor specific IE header */
+	IEEEtypes_VendorHeader_t vend_hdr;
+	/** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)];
+} MLAN_PACK_END IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t;
+
+/** IEEE IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Generic_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** IE Max - size of previous fields */
+	t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)];
+} MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t;
+
+/**ft capability policy*/
+typedef MLAN_PACK_START struct _IEEEtypes_FtCapPolicy_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:6;
+	/** RIC support */
+	t_u8 ric:1;
+	/** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+#else
+	/** FT over the DS capable */
+	t_u8 ft_over_ds:1;
+	/** RIC support */
+	t_u8 ric:1;
+	/** Reserved */
+	t_u8 reserved:6;
+#endif
+} MLAN_PACK_END IEEEtypes_FtCapPolicy_t;
+
+/** Mobility domain IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MobilityDomain_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Mobility Domain ID */
+	t_u16 mdid;
+	/** FT Capability policy */
+	t_u8 ft_cap;
+} MLAN_PACK_END IEEEtypes_MobilityDomain_t;
+
+/**FT MIC Control*/
+typedef MLAN_PACK_START struct _IEEEtypes_FT_MICControl_t {
+	/** reserved */
+	t_u8 reserved;
+	/** element count */
+	t_u8 element_count;
+} MLAN_PACK_END IEEEtypes_FT_MICControl_t;
+
+/** FTIE MIC LEN */
+#define FTIE_MIC_LEN 16
+
+/**FT IE*/
+typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** mic control */
+	IEEEtypes_FT_MICControl_t mic_control;
+	/** mic */
+	t_u8 mic[FTIE_MIC_LEN];
+	/** ANonce */
+	t_u8 a_nonce[32];
+	/** SNonce */
+	t_u8 s_nonce[32];
+	/** sub element */
+	t_u8 sub_element[1];
+} MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
+
+/*Category for FT*/
+#define FT_CATEGORY 6
+/** FT ACTION request */
+#define FT_ACTION_REQUEST 1
+/** FT ACTION response */
+#define FT_ACTION_RESPONSE 2
+
+/*FT response and FT ack*/
+typedef MLAN_PACK_START struct {
+	/** category */
+	t_u8 category;
+	/** action */
+	t_u8 action;
+	/** sta address */
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	/** target ap address */
+	t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+	/** status code */
+	t_u16 status_code;
+	/** varible */
+	t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Ft_action_response;
+
+/**FT request */
+typedef MLAN_PACK_START struct {
+	/** category */
+	t_u8 category;
+	/** action */
+	t_u8 action;
+	/** sta address */
+	t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH];
+	/** target ap address */
+	t_u8 target_ap_addr[MLAN_MAC_ADDR_LENGTH];
+	/** varible */
+	t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Ft_action_request;
+
+/** auth frame body*/
+typedef MLAN_PACK_START struct {
+	/** auth alg */
+	t_u16 auth_alg;
+	/** auth transaction */
+	t_u16 auth_transaction;
+	/** status code */
+	t_u16 status_code;
+	/** variable */
+	t_u8 variable[];
+} MLAN_PACK_END IEEEtypes_Auth_framebody;
+
+/** associate request frame */
+typedef MLAN_PACK_START struct {
+	t_u16 capab_info;
+	t_u16 listen_interval;
+	/** followed by SSID and Supported rates */
+	t_u8 variablep[];
+} MLAN_PACK_END IEEEtypes_assoc_req;
+
+/*Mgmt frame*/
+typedef MLAN_PACK_START struct {
+	/** frame control */
+	t_u16 frame_control;
+	/** duration */
+	t_u16 duration;
+	/** dest address */
+	t_u8 da[MLAN_MAC_ADDR_LENGTH];
+	/** source address */
+	t_u8 sa[MLAN_MAC_ADDR_LENGTH];
+	/** bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** seq control */
+	t_u16 seq_ctrl;
+	/** address 4 */
+	t_u8 addr4[MLAN_MAC_ADDR_LENGTH];
+	union {
+		IEEEtypes_Auth_framebody auth;
+		IEEEtypes_assoc_req assoc_req;
+		IEEEtypes_Ft_action_response ft_resp;
+		IEEEtypes_Ft_action_request ft_req;
+	} u;
+} MLAN_PACK_END IEEE80211_MGMT;
+
+/** TLV header */
+typedef MLAN_PACK_START struct _TLV_Generic_t {
+	/** Type */
+	t_u16 type;
+	/** Length */
+	t_u16 len;
+} MLAN_PACK_END TLV_Generic_t, *pTLV_Generic_t;
+
+/** Capability information mask */
+#define CAPINFO_MASK (~(MBIT(15) | MBIT(14) | MBIT(11) | MBIT(9)))
+
+/** Capability Bit Map*/
+#ifdef BIG_ENDIAN_SUPPORT
+typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t {
+	t_u8 rsrvd1:2;
+	t_u8 dsss_ofdm:1;
+	t_u8 radio_measurement:1;
+	t_u8 rsvrd2:1;
+	t_u8 short_slot_time:1;
+	t_u8 rsrvd3:1;
+	t_u8 spectrum_mgmt:1;
+	t_u8 chan_agility:1;
+	t_u8 pbcc:1;
+	t_u8 short_preamble:1;
+	t_u8 privacy:1;
+	t_u8 cf_poll_rqst:1;
+	t_u8 cf_pollable:1;
+	t_u8 ibss:1;
+	t_u8 ess:1;
+} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#else
+typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t {
+	/** Capability Bit Map : ESS */
+	t_u8 ess:1;
+	/** Capability Bit Map : IBSS */
+	t_u8 ibss:1;
+	/** Capability Bit Map : CF pollable */
+	t_u8 cf_pollable:1;
+	/** Capability Bit Map : CF poll request */
+	t_u8 cf_poll_rqst:1;
+	/** Capability Bit Map : privacy */
+	t_u8 privacy:1;
+	/** Capability Bit Map : Short preamble */
+	t_u8 short_preamble:1;
+	/** Capability Bit Map : PBCC */
+	t_u8 pbcc:1;
+	/** Capability Bit Map : Channel agility */
+	t_u8 chan_agility:1;
+	/** Capability Bit Map : Spectrum management */
+	t_u8 spectrum_mgmt:1;
+	/** Capability Bit Map : Reserved */
+	t_u8 rsrvd3:1;
+	/** Capability Bit Map : Short slot time */
+	t_u8 short_slot_time:1;
+	/** Capability Bit Map : APSD */
+	t_u8 Apsd:1;
+	/** Capability Bit Map : Reserved */
+	t_u8 rsvrd2:1;
+	/** Capability Bit Map : DSS OFDM */
+	t_u8 dsss_ofdm:1;
+	/** Capability Bit Map : Reserved */
+	t_u8 rsrvd1:2;
+} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t;
+#endif /* BIG_ENDIAN_SUPPORT */
+
+/** IEEEtypes_Ssid_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Ssid_t {
+	/** SSID: Element ID */
+	t_u8 element_id;
+	/** SSID : Length */
+	t_u8 len;
+	/** ssid */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+} MLAN_PACK_END IEEEtypes_Ssid_t, *pIEEEtypes_Ssid_t;
+
+/** IEEEtypes_CfParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_CfParamSet_t {
+	/** CF peremeter : Element ID */
+	t_u8 element_id;
+	/** CF peremeter : Length */
+	t_u8 len;
+	/** CF peremeter : Count */
+	t_u8 cfp_cnt;
+	/** CF peremeter : Period */
+	t_u8 cfp_period;
+	/** CF peremeter : Maximum duration */
+	t_u16 cfp_max_duration;
+	/** CF peremeter : Remaining duration */
+	t_u16 cfp_duration_remaining;
+} MLAN_PACK_END IEEEtypes_CfParamSet_t, *pIEEEtypes_CfParamSet_t;
+
+/** IEEEtypes_IbssParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_IbssParamSet_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** ATIM window value in milliseconds */
+	t_u16 atim_window;
+} MLAN_PACK_END IEEEtypes_IbssParamSet_t, *pIEEEtypes_IbssParamSet_t;
+
+/** IEEEtypes_SsParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_SsParamSet_t {
+	/** SS parameter : CF parameter set */
+	IEEEtypes_CfParamSet_t cf_param_set;
+	/** SS parameter : IBSS parameter set */
+	IEEEtypes_IbssParamSet_t ibss_param_set;
+} MLAN_PACK_END IEEEtypes_SsParamSet_t, *pIEEEtypes_SsParamSet_t;
+
+/** IEEEtypes_FhParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_FhParamSet_t {
+	/** FH parameter : Element ID */
+	t_u8 element_id;
+	/** FH parameter : Length */
+	t_u8 len;
+	/** FH parameter : Dwell time in milliseconds */
+	t_u16 dwell_time;
+	/** FH parameter : Hop set */
+	t_u8 hop_set;
+	/** FH parameter : Hop pattern */
+	t_u8 hop_pattern;
+	/** FH parameter : Hop index */
+	t_u8 hop_index;
+} MLAN_PACK_END IEEEtypes_FhParamSet_t, *pIEEEtypes_FhParamSet_t;
+
+/** IEEEtypes_DsParamSet_t */
+typedef MLAN_PACK_START struct _IEEEtypes_DsParamSet_t {
+	/** DS parameter : Element ID */
+	t_u8 element_id;
+	/** DS parameter : Length */
+	t_u8 len;
+	/** DS parameter : Current channel */
+	t_u8 current_chan;
+} MLAN_PACK_END IEEEtypes_DsParamSet_t, *pIEEEtypes_DsParamSet_t;
+
+/** IEEEtypes_PhyParamSet_t */
+typedef MLAN_PACK_START union _IEEEtypes_PhyParamSet_t {
+	/** FH parameter set */
+	IEEEtypes_FhParamSet_t fh_param_set;
+	/** DS parameter set */
+	IEEEtypes_DsParamSet_t ds_param_set;
+} MLAN_PACK_END IEEEtypes_PhyParamSet_t, *pIEEEtypes_PhyParamSet_t;
+
+/** IEEEtypes_ERPInfo_t */
+typedef MLAN_PACK_START struct _IEEEtypes_ERPInfo_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** ERP flags */
+	t_u8 erp_flags;
+} MLAN_PACK_END IEEEtypes_ERPInfo_t, *pIEEEtypes_ERPInfo_t;
+
+/** IEEEtypes_AId_t */
+typedef t_u16 IEEEtypes_AId_t;
+
+/** IEEEtypes_StatusCode_t */
+typedef t_u16 IEEEtypes_StatusCode_t;
+
+/** Fixed size in assoc_resp */
+#define ASSOC_RESP_FIXED_SIZE 6
+
+/** IEEEtypes_SeqCtl_t */
+typedef MLAN_PACK_START struct _IEEEtypes_SeqCtl_t {
+	/** Fragment Number */
+	t_u16 FragNum:4;
+	/** Sequence Number */
+	t_u16 SeqNum:12;
+} MLAN_PACK_END IEEEtypes_SeqCtl_t;
+
+/** IEEEtypes_MgmtHdr_t */
+typedef MLAN_PACK_START struct _IEEEtypes_MgmtHdr_t {
+	/** FrmCtl*/
+	t_u16 FrmCtl;
+	/** Duration*/
+	t_u16 Duration;
+	/** Destination Addr*/
+	t_u8 DestAddr[6];
+	/** Source Addr*/
+	t_u8 SrcAddr[6];
+	/** BSSID */
+	t_u8 BssId[6];
+	/** IEEEtypes_SeqCtl_t */
+	IEEEtypes_SeqCtl_t SeqCtl;
+} MLAN_PACK_END IEEEtypes_MgmtHdr_t;
+
+/** IEEEtypes_AssocRsp_t */
+typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
+	/** Capability information */
+	IEEEtypes_CapInfo_t capability;
+	/** Association response status code */
+	IEEEtypes_StatusCode_t status_code;
+	/** Association ID */
+	IEEEtypes_AId_t a_id;
+	/** IE data buffer */
+	t_u8 ie_buffer[1];
+} MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
+
+/** 802.11 supported rates */
+typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES];
+
+/** cipher TKIP */
+#define WPA_CIPHER_TKIP 2
+/** cipher AES */
+#define WPA_CIPHER_AES_CCM 4
+/** AKM: 8021x */
+#define RSN_AKM_8021X 1
+/** AKM: PSK */
+#define RSN_AKM_PSK 2
+/** AKM: PSK SHA256 */
+#define RSN_AKM_PSK_SHA256 6
+
+/** AKM: PSK SHA256 */
+#define RSN_AKM_SAE 8
+/** AKM: PSK SHA256 */
+#define RSN_AKM_OWE 18
+
+#if defined(STA_SUPPORT)
+/** Pairwise Cipher Suite length */
+#define PAIRWISE_CIPHER_SUITE_LEN 4
+/** AKM Suite length */
+#define AKM_SUITE_LEN 4
+/** MFPC bit in RSN capability */
+#define MFPC_BIT 7
+/** MFPR bit in RSN capability */
+#define MFPR_BIT 6
+/** PMF ORing mask */
+#define PMF_MASK 0x00c0
+#endif
+
+/** wpa_suite_t */
+typedef MLAN_PACK_START struct _wpa_suite_t {
+	/** OUI */
+	t_u8 oui[3];
+	/** tyep */
+	t_u8 type;
+} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t;
+
+/** wpa_suite_ucast_t */
+typedef MLAN_PACK_START struct {
+	/* count */
+	t_u16 count;
+	/** wpa_suite list */
+	wpa_suite list[1];
+} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+
+/** IEEEtypes_Rsn_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t {
+	/** Rsn : Element ID */
+	t_u8 element_id;
+	/** Rsn : Length */
+	t_u8 len;
+	/** Rsn : version */
+	t_u16 version;
+	/** Rsn : group cipher */
+	wpa_suite_mcast_t group_cipher;
+	/** Rsn : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t;
+
+/** IEEEtypes_Wpa_t */
+typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t {
+	/** Wpa : Element ID */
+	t_u8 element_id;
+	/** Wpa : Length */
+	t_u8 len;
+	/** Wpa : oui */
+	t_u8 oui[4];
+	/** version */
+	t_u16 version;
+	/** Wpa : group cipher */
+	wpa_suite_mcast_t group_cipher;
+	/** Wpa : pairwise cipher */
+	wpa_suite_ucast_t pairwise_cipher;
+} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t;
+
+/** Data structure of WMM QoS information */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aifsn */
+	t_u8 aifsn:4;
+#else
+	/** Aifsn */
+	t_u8 aifsn:4;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t;
+
+/** Data structure of WMM ECW */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t;
+
+/** Data structure of WMM AC parameters  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t {
+	IEEEtypes_WmmAciAifsn_t aci_aifsn; /**< AciAifSn */
+	IEEEtypes_WmmEcw_t ecw;	/**< Ecw */
+	t_u16 tx_op_limit; /**< Tx op limit */
+} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t;
+
+/** Data structure of WMM Info IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t {
+	/**
+	 * WMM Info IE - Vendor Specific Header:
+	 *   element_id  [221/0xdd]
+	 *   Len         [7]
+	 *   Oui         [00:50:f2]
+	 *   OuiType     [2]
+	 *   OuiSubType  [0]
+	 *   Version     [1]
+	 */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+	/** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+
+} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t;
+
+/** Data structure of WMM parameter IE  */
+typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t {
+	/**
+	 * WMM Parameter IE - Vendor Specific Header:
+	 *   element_id  [221/0xdd]
+	 *   Len         [24]
+	 *   Oui         [00:50:f2]
+	 *   OuiType     [2]
+	 *   OuiSubType  [1]
+	 *   Version     [1]
+	 */
+	IEEEtypes_VendorHeader_t vend_hdr;
+
+	/** QoS information */
+	IEEEtypes_WmmQosInfo_t qos_info;
+	/** Reserved */
+	t_u8 reserved;
+
+	/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES];
+} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t;
+
+/** Enumerator for TSPEC direction */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e {
+
+	TSPEC_DIR_UPLINK = 0,
+	TSPEC_DIR_DOWNLINK = 1,
+	/* 2 is a reserved value */
+	TSPEC_DIR_BIDIRECT = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e;
+
+/** Enumerator for TSPEC PSB */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e {
+
+	TSPEC_PSB_LEGACY = 0,
+	TSPEC_PSB_TRIG = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e;
+
+/** Enumerator for TSPEC Ack Policy */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e {
+
+	TSPEC_ACKPOLICY_NORMAL = 0,
+	TSPEC_ACKPOLICY_NOACK = 1,
+	/* 2 is reserved */
+	TSPEC_ACKPOLICY_BLOCKACK = 3,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e;
+
+/** Enumerator for TSPEC Trafffice type */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e {
+
+	TSPEC_TRAFFIC_APERIODIC = 0,
+	TSPEC_TRAFFIC_PERIODIC = 1,
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e;
+
+/** Data structure of WMM TSPEC information */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+	t_u8 Schedule:1;
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	//IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior : 1; /* !Legacy/Trigg*/
+	t_u8 PowerSaveBehavior:1;
+	t_u8 Aggregation:1;	/* ! Reserved */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 AccessPolicy1:1;	/* ! */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 TID:4;		/* ! Unique identifier */
+	//IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType : 1;
+	t_u8 TrafficType:1;
+#else
+	//IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType : 1;
+	t_u8 TrafficType:1;
+	t_u8 TID:4;		/* ! Unique identifier */
+	IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2;
+	t_u8 AccessPolicy1:1;	/* ! */
+	t_u8 AccessPolicy2:1;	/* ! */
+	t_u8 Aggregation:1;	/* ! Reserved */
+	//IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior : 1; /* ! Legacy/Trigg*/
+	t_u8 PowerSaveBehavior:1;
+	t_u8 UserPri:3;		/* ! 802.1d User Priority */
+	IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2;
+	t_u8 Schedule:1;
+	t_u8 Reserved17_23:7;	/* ! Reserved */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t;
+
+/** Data structure of WMM TSPEC Nominal Size */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is
+				   nominal */
+	t_u16 Size:15;		/* ! Nominal size in octets */
+#else
+	t_u16 Size:15;		/* ! Nominal size in octets */
+	t_u16 Fixed:1;		/* ! 1: Fixed size given in Size, 0: Var, size is
+				   nominal */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t;
+
+/** Data structure of WMM TSPEC SBWA */
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u16 Whole:3;		/* ! Whole portion */
+	t_u16 Fractional:13;	/* ! Fractional portion */
+#else
+	t_u16 Fractional:13;	/* ! Fractional portion */
+	t_u16 Whole:3;		/* ! Whole portion */
+#endif
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA;
+
+/** Data structure of WMM TSPEC Body */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo;
+	IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize;
+	t_u16 MaximumMSDUSize;
+	t_u32 MinServiceInterval;
+	t_u32 MaxServiceInterval;
+	t_u32 InactivityInterval;
+	t_u32 SuspensionInterval;
+	t_u32 ServiceStartTime;
+	t_u32 MinimumDataRate;
+	t_u32 MeanDataRate;
+	t_u32 PeakDataRate;
+	t_u32 MaxBurstSize;
+	t_u32 DelayBound;
+	t_u32 MinPHYRate;
+	IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance;
+	t_u16 MediumTime;
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t;
+
+/** Data structure of WMM TSPEC all elements */
+typedef MLAN_PACK_START struct {
+	t_u8 ElementId;
+	t_u8 Len;
+	t_u8 OuiType[4];	/* 00:50:f2:02 */
+	t_u8 OuiSubType;	/* 01 */
+	t_u8 Version;
+
+	IEEEtypes_WMM_TSPEC_Body_t TspecBody;
+
+} MLAN_PACK_END IEEEtypes_WMM_TSPEC_t;
+
+/** WMM Action Category values */
+typedef MLAN_PACK_START enum _IEEEtypes_ActionCategory_e {
+
+	IEEE_MGMT_ACTION_CATEGORY_SPECTRUM_MGMT = 0,
+	IEEE_MGMT_ACTION_CATEGORY_QOS = 1,
+	IEEE_MGMT_ACTION_CATEGORY_DLS = 2,
+	IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK = 3,
+	IEEE_MGMT_ACTION_CATEGORY_PUBLIC = 4,
+	IEEE_MGMT_ACTION_CATEGORY_RADIO_RSRC = 5,
+	IEEE_MGMT_ACTION_CATEGORY_FAST_BSS_TRANS = 6,
+	IEEE_MGMT_ACTION_CATEGORY_HT = 7,
+
+	IEEE_MGMT_ACTION_CATEGORY_WNM = 10,
+	IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM = 11,
+
+	IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC = 17
+} MLAN_PACK_END IEEEtypes_ActionCategory_e;
+
+/** WMM TSPEC operations */
+typedef MLAN_PACK_START enum _IEEEtypes_WMM_Tspec_Action_e {
+
+	TSPEC_ACTION_CODE_ADDTS_REQ = 0,
+	TSPEC_ACTION_CODE_ADDTS_RSP = 1,
+	TSPEC_ACTION_CODE_DELTS = 2,
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_e;
+
+/** WMM TSPEC Category Action Base */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_ActionCategory_e category;
+	IEEEtypes_WMM_Tspec_Action_e action;
+	t_u8 dialogToken;
+
+} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t;
+
+/** WMM TSPEC AddTS request structure */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+	t_u8 statusCode;
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+	/* Place holder for additional elements after the TSPEC */
+	t_u8 subElem[256];
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsReq_t;
+
+/** WMM TSPEC AddTS response structure */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+	t_u8 statusCode;
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+	/* Place holder for additional elements after the TSPEC */
+	t_u8 subElem[256];
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsRsp_t;
+
+/** WMM TSPEC DelTS structure */
+typedef MLAN_PACK_START struct {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+	t_u8 reasonCode;
+	IEEEtypes_WMM_TSPEC_t tspecIE;
+
+} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t;
+
+/** union of WMM TSPEC structures */
+typedef MLAN_PACK_START union {
+	IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct;
+
+	IEEEtypes_Action_WMM_AddTsReq_t addTsReq;
+	IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp;
+	IEEEtypes_Action_WMM_DelTs_t delTs;
+
+} MLAN_PACK_END IEEEtypes_Action_WMMAC_t;
+
+/** union of WMM TSPEC & Action category */
+typedef MLAN_PACK_START union {
+	IEEEtypes_ActionCategory_e category;
+
+	IEEEtypes_Action_WMMAC_t wmmAc;
+
+} MLAN_PACK_END IEEEtypes_ActionFrame_t;
+
+/** Data structure for subband set */
+typedef MLAN_PACK_START struct _IEEEtypes_SubbandSet_t {
+	/** First channel */
+	t_u8 first_chan;
+	/** Number of channels */
+	t_u8 no_of_chan;
+	/** Maximum Tx power in dBm */
+	t_u8 max_tx_pwr;
+} MLAN_PACK_END IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t;
+
+#ifdef STA_SUPPORT
+/** Data structure for Country IE */
+typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoSet_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[1];
+} MLAN_PACK_END IEEEtypes_CountryInfoSet_t, *pIEEEtypes_CountryInfoSet_t;
+
+/** Data structure for Country IE full set */
+typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoFullSet_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** Country code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Set of subbands */
+	IEEEtypes_SubbandSet_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} MLAN_PACK_END IEEEtypes_CountryInfoFullSet_t,
+	*pIEEEtypes_CountryInfoFullSet_t;
+
+#endif /* STA_SUPPORT */
+
+/** Data structure for Link ID */
+typedef MLAN_PACK_START struct _IEEEtypes_LinkIDElement_t {
+	/** Element ID */
+	t_u8 element_id;
+	/** Length */
+	t_u8 len;
+	/** bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** initial sta address */
+	t_u8 init_sta[MLAN_MAC_ADDR_LENGTH];
+	/** respose sta address */
+	t_u8 resp_sta[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END IEEEtypes_LinkIDElement_t, *pIEEEtypes_LinkIDElement_t;
+
+/** HT Capabilities Data */
+typedef struct MLAN_PACK_START _HTCap_t {
+	/** HT Capabilities Info field */
+	t_u16 ht_cap_info;
+	/** A-MPDU Parameters field */
+	t_u8 ampdu_param;
+	/** Supported MCS Set field */
+	t_u8 supported_mcs_set[16];
+	/** HT Extended Capabilities field */
+	t_u16 ht_ext_cap;
+	/** Transmit Beamforming Capabilities field */
+	t_u32 tx_bf_cap;
+	/** Antenna Selection Capability field */
+	t_u8 asel;
+} MLAN_PACK_END HTCap_t, *pHTCap_t;
+
+/** HT Information Data */
+typedef struct MLAN_PACK_START _HTInfo_t {
+	/** Primary channel */
+	t_u8 pri_chan;
+	/** Field 2 */
+	t_u8 field2;
+	/** Field 3 */
+	t_u16 field3;
+	/** Field 4 */
+	t_u16 field4;
+	/** Bitmap indicating MCSs supported by all HT STAs in the BSS */
+	t_u8 basic_mcs_set[16];
+} MLAN_PACK_END HTInfo_t, *pHTInfo_t;
+
+/** 20/40 BSS Coexistence Data */
+typedef struct MLAN_PACK_START _BSSCo2040_t {
+	/** 20/40 BSS Coexistence value */
+	t_u8 bss_co_2040_value;
+} MLAN_PACK_END BSSCo2040_t, *pBSSCo2040_t;
+
+#define MAX_DSCP_EXCEPTION_NUM 21
+/** DSCP Range */
+typedef struct MLAN_PACK_START _DSCP_Exception_t {
+	/* DSCP value 0 to 63 or ff */
+	t_u8 dscp_value;
+	/* user priority 0-7 */
+	t_u8 user_priority;
+} MLAN_PACK_END DSCP_Exception_t, *pDSCP_Exception_t;
+
+/** DSCP Range */
+typedef struct MLAN_PACK_START _DSCP_Range_t {
+	/* DSCP low value */
+	t_u8 dscp_low_value;
+	/* DSCP high value */
+	t_u8 dscp_high_value;
+} MLAN_PACK_END DSCP_Range_t, *pDSCP_Range_t;
+
+/** Overlapping BSS Scan Parameters Data */
+typedef struct MLAN_PACK_START _OverlapBSSScanParam_t {
+	/** OBSS Scan Passive Dwell in milliseconds */
+	t_u16 obss_scan_passive_dwell;
+	/** OBSS Scan Active Dwell in milliseconds */
+	t_u16 obss_scan_active_dwell;
+	/** BSS Channel Width Trigger Scan Interval in seconds */
+	t_u16 bss_chan_width_trigger_scan_int;
+	/** OBSS Scan Passive Total Per Channel */
+	t_u16 obss_scan_passive_total;
+	/** OBSS Scan Active Total Per Channel */
+	t_u16 obss_scan_active_total;
+	/** BSS Width Channel Transition Delay Factor */
+	t_u16 bss_width_chan_trans_delay;
+	/** OBSS Scan Activity Threshold */
+	t_u16 obss_scan_active_threshold;
+} MLAN_PACK_END OBSSScanParam_t, *pOBSSScanParam_t;
+
+/** HT Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_HTCap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** HTCap struct */
+	HTCap_t ht_cap;
+} MLAN_PACK_END IEEEtypes_HTCap_t, *pIEEEtypes_HTCap_t;
+
+/** HT Information IE */
+typedef MLAN_PACK_START struct _IEEEtypes_HTInfo_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** HTInfo struct */
+	HTInfo_t ht_info;
+} MLAN_PACK_END IEEEtypes_HTInfo_t, *pIEEEtypes_HTInfo_t;
+
+/** the AP which send the multi_bssid IE */
+#define MULTI_BSSID_AP 1
+/** the AP which don't send beacon */
+#define MULTI_BSSID_SUB_AP 2
+/** IEEEtypes_NotxBssCap_t */
+typedef MLAN_PACK_START struct _IEEEtypes_NotxBssCap_t {
+	/** Nontransmitted BSSID Capability: Element ID */
+	t_u8 element_id;
+	/** Nontransmitted BSSID Capability : Length */
+	t_u8 len;
+	/** capability */
+	t_u16 cap;
+} MLAN_PACK_END IEEEtypes_NotxBssCap_t, *pIEEEtypes_NotxBssCap_t;
+
+/** Multi BSSID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MultiBSSIDIndex_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** BSSID Index */
+	t_u8 bssid_index;
+	/** DTIM Period (Optional, not Present in ProbeRsp) */
+	t_u8 dtim_period;
+	/** DTIM Count (Optional, not Present in ProbeRsp) */
+	t_u8 dtim_count;
+} MLAN_PACK_END IEEEtypes_MultiBSSIDIndex_t, *pIEEEtypes_MultiBSSIDIndex_t;
+
+/** NonTransmitted BSSID Profile Subelement IE */
+/** SUBID for IEEEtypes_NonTransBSSIDCap_t */
+#define NONTRANS_BSSID_PROFILE_SUBELEM_ID 0
+
+/** NonTransmitted BSSID Capability IE */
+typedef MLAN_PACK_START struct _IEEEtypes_NonTransBSSIDProfile_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 profile_data[];
+} MLAN_PACK_END IEEEtypes_NonTransBSSIDProfile_t,
+	*pIEEEtypes_NonTransBSSIDProfile_t;
+
+/** Multi BSSID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MultiBSSID_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Max BSSID Indicator */
+	t_u8 max_bssid_indicator;
+	/** Optional Subelement data*/
+	t_u8 sub_elem_data[];
+} MLAN_PACK_END IEEEtypes_MultiBSSID_t, *pIEEEtypes_MultiBSSID_t;
+/** 20/40 BSS Coexistence IE */
+typedef MLAN_PACK_START struct _IEEEtypes_2040BSSCo_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** BSSCo2040_t struct */
+	BSSCo2040_t bss_co_2040;
+} MLAN_PACK_END IEEEtypes_2040BSSCo_t, *pIEEEtypes_2040BSSCo_t;
+
+/** Extended Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtCap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** ExtCap_t struct */
+	ExtCap_t ext_cap;
+} MLAN_PACK_END IEEEtypes_ExtCap_t, *pIEEEtypes_ExtCap_t;
+
+/** Overlapping BSS Scan Parameters IE */
+typedef MLAN_PACK_START struct _IEEEtypes_OverlapBSSScanParam_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** OBSSScanParam_t struct */
+	OBSSScanParam_t obss_scan_param;
+} MLAN_PACK_END IEEEtypes_OverlapBSSScanParam_t,
+	*pIEEEtypes_OverlapBSSScanParam_t;
+
+/** VHT MCS rate set field, refer to 802.11ac */
+typedef MLAN_PACK_START struct _VHT_MCS_set {
+	t_u16 rx_mcs_map;
+	t_u16 rx_max_rate;	/* bit 29-31 reserved */
+	t_u16 tx_mcs_map;
+	t_u16 tx_max_rate;	/* bit 61-63 reserved */
+} MLAN_PACK_END VHT_MCS_set_t, *pVHT_MCS_set_t;
+
+/** VHT Capabilities info field, reference 802.11ac D1.4 p89 */
+typedef MLAN_PACK_START struct _VHT_capa {
+#if 0
+#ifdef BIG_ENDIAN_SUPPORT
+	t_u8 mpdu_max_len:2;
+	t_u8 chan_width:2;
+	t_u8 rx_LDPC:1;
+	t_u8 sgi_80:1;
+	t_u8 sgi_160:1;
+	t_u8 tx_STBC:1;
+	t_u8 rx_STBC:3;
+	t_u8 SU_beamformer_capa:1;
+	t_u8 SU_beamformee_capa:1;
+	t_u8 beamformer_ante_num:3;
+	t_u8 sounding_dim_num:3;
+	t_u8 MU_beamformer_capa:1;
+	t_u8 MU_beamformee_capa:1;
+	t_u8 VHT_TXOP_ps:1;
+	t_u8 HTC_VHT_capa:1;
+	t_u8 max_ampdu_len:3;
+	t_u8 link_apapt_capa:2;
+	t_u8 reserved_1:4;
+#else
+	t_u8 reserved_1:4;
+	t_u8 link_apapt_capa:2;
+	t_u8 max_ampdu_len:3;
+	t_u8 HTC_VHT_capa:1;
+	t_u8 VHT_TXOP_ps:1;
+	t_u8 MU_beamformee_capa:1;
+	t_u8 MU_beamformer_capa:1;
+	t_u8 sounding_dim_num:3;
+	t_u8 beamformer_ante_num:3;
+	t_u8 SU_beamformee_capa:1;
+	t_u8 SU_beamformer_capa:1;
+	t_u8 rx_STBC:3;
+	t_u8 tx_STBC:1;
+	t_u8 sgi_160:1;
+	t_u8 sgi_80:1;
+	t_u8 rx_LDPC:1;
+	t_u8 chan_width:2;
+	t_u8 mpdu_max_len:2;
+#endif				/* BIG_ENDIAN_SUPPORT */
+#endif
+	t_u32 vht_cap_info;
+	VHT_MCS_set_t mcs_sets;
+} MLAN_PACK_END VHT_capa_t, *pVHT_capa_t;
+
+/** VHT Capabilities IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTCap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	VHT_capa_t vht_cap;
+} MLAN_PACK_END IEEEtypes_VHTCap_t, *pIEEEtypes_VHTCap_t;
+
+#define VHT_CAP_CHWD_80MHZ 0
+#define VHT_CAP_CHWD_160MHZ 1
+#define VHT_CAP_CHWD_80_80MHZ 2
+
+/** VHT Operations IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTOprat_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 chan_width;
+	t_u8 chan_center_freq_1;
+	t_u8 chan_center_freq_2;
+	/** Basic MCS set map, each 2 bits stands for a Nss */
+	t_u16 basic_MCS_map;
+} MLAN_PACK_END IEEEtypes_VHTOprat_t, *pIEEEtypes_VHTOprat_t;
+
+#define VHT_OPER_CHWD_20_40MHZ 0
+#define VHT_OPER_CHWD_80MHZ 1
+#define VHT_OPER_CHWD_160MHZ 2
+#define VHT_OPER_CHWD_80_80MHZ 3
+
+/** VHT Transmit Power Envelope IE */
+typedef MLAN_PACK_START struct _IEEEtypes_VHTtxpower_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 max_tx_power;
+	t_u8 chan_center_freq;
+	t_u8 chan_width;
+} MLAN_PACK_END IEEEtypes_VHTtxpower_t, *pIEEEtypes_VHTtxpower_t;
+
+/** Extended Power Constraint IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtPwerCons_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** channel width */
+	t_u8 chan_width;
+	/** local power constraint */
+	t_u8 local_power_cons;
+} MLAN_PACK_END IEEEtypes_ExtPwerCons_t, *pIEEEtypes_ExtPwerCons_t;
+
+/** Extended BSS Load IE */
+typedef MLAN_PACK_START struct _IEEEtypes_ExtBSSload_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 MU_MIMO_capa_count;
+	t_u8 stream_underutilization;
+	t_u8 VHT40_util;
+	t_u8 VHT80_util;
+	t_u8 VHT160_util;
+} MLAN_PACK_END IEEEtypes_ExtBSSload_t, *pIEEEtypes_ExtBSSload_t;
+
+/** Quiet Channel IE */
+typedef MLAN_PACK_START struct _IEEEtypes_QuietChan_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 AP_quiet_mode;
+	t_u8 quiet_count;
+	t_u8 quiet_period;
+	t_u16 quiet_dur;
+	t_u16 quiet_offset;
+} MLAN_PACK_END IEEEtypes_QuietChan_t, *pIEEEtypes_QuietChan_t;
+
+/** Wide Bandwidth Channel Switch IE */
+typedef MLAN_PACK_START struct _IEEEtypes_BWSwitch_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 new_chan_width;
+	t_u8 new_chan_center_freq_1;
+	t_u8 new_chan_center_freq_2;
+} MLAN_PACK_END IEEEtypes_BWSwitch_t, *pIEEEtypes_BWSwitch_t;
+
+/** AID IE */
+typedef MLAN_PACK_START struct _IEEEtypes_AID_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** AID number */
+	t_u16 AID;
+} MLAN_PACK_END IEEEtypes_AID_t, *pIEEEtypes_AID_t;
+
+/** Operating Mode Notificaton IE */
+typedef MLAN_PACK_START struct _IEEEtypes_OperModeNtf_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Operating Mode */
+	t_u8 oper_mode;
+} MLAN_PACK_END IEEEtypes_OperModeNtf_t, *pIEEEtypes_OperModeNtf_t;
+
+typedef MLAN_PACK_START struct _IEEEtypes_Extension_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** payload */
+	t_u8 data[];
+} MLAN_PACK_END IEEEtypes_Extension_t, *pIEEEtypes_Extension_t;
+
+typedef MLAN_PACK_START struct _IEEEtypes_HECap_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** he mac capability info */
+	t_u8 he_mac_cap[6];
+	/** he phy capability info */
+	t_u8 he_phy_cap[11];
+	/** he txrx mcs support , size would be 4 or 8 or 12 */
+	t_u8 he_txrx_mcs_support[4];
+	/** PPE Thresholds (optional) */
+} MLAN_PACK_END IEEEtypes_HECap_t, *pIEEEtypes_HECap_t;
+
+/** default channel switch count */
+#define DEF_CHAN_SWITCH_COUNT 5
+
+/*  IEEE Channel Switch Announcement Element (7.3.2.20) */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a chan switch element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 37 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 chan_switch_mode; /**< STA should not transmit any frames if 1 */
+	t_u8 new_channel_num; /**< Channel # that AP/IBSS is moving to */
+	t_u8 chan_switch_count;	/**< # of TBTTs before channel switch */
+
+} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t;
+
+/** data structure for extended channel switch */
+typedef MLAN_PACK_START struct {
+	/** IEEE element ID = 60 */
+	t_u8 element_id;
+	/** Element length after id and len, set to 4 */
+	t_u8 len;
+	/** STA should not transmit any frames if 1 */
+	t_u8 chan_switch_mode;
+	/** Operate class # that AP/IBSS is moving to */
+	t_u8 new_oper_class;
+	/** Channel # that AP/IBSS is moving to */
+	t_u8 new_channel_num;
+	/** of TBTTs before channel switch */
+	t_u8 chan_switch_count;
+} MLAN_PACK_END IEEEtypes_ExtChanSwitchAnn_t;
+
+/** Maximum number of subbands in the IEEEtypes_SupportedChannels_t structure */
+#define WLAN_11H_MAX_SUBBANDS 5
+/** Maximum number of DFS channels configured in IEEEtypes_IBSS_DFS_t */
+#define WLAN_11H_MAX_IBSS_DFS_CHANNELS 25
+
+/**  IEEE Power Constraint element (7.3.2.15) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 32 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 local_constraint; /**< Local power constraint applied to 11d
+				chan info */
+} MLAN_PACK_END IEEEtypes_PowerConstraint_t;
+
+/**  IEEE Power Capability element (7.3.2.16) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 33 */
+	t_u8 len; /**< Element length after id and len */
+	t_s8 min_tx_power_capability; /**< Minimum Transmit power (dBm) */
+	t_s8 max_tx_power_capability; /**< Maximum Transmit power (dBm) */
+} MLAN_PACK_END IEEEtypes_PowerCapability_t;
+
+/**  IEEE TPC Report element (7.3.2.18) */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 35 */
+	t_u8 len; /**< Element length after id and len */
+	t_s8 tx_power; /**< Max power used to transmit the TPC Report frame
+			  (dBm) */
+	t_s8 link_margin; /**< Link margin when TPC Request received (dB) */
+} MLAN_PACK_END IEEEtypes_TPCReport_t;
+
+/*  IEEE Supported Channel sub-band description (7.3.2.19) */
+/**
+ *  Sub-band description used in the supported channels element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 start_chan; /**< Starting channel in the subband */
+	t_u8 num_chans;	/**< Number of channels in the subband */
+
+} MLAN_PACK_END IEEEtypes_SupportChan_Subband_t;
+
+/*  IEEE Supported Channel element (7.3.2.19) */
+/**
+ *  Sent in association requests. Details the sub-bands and number
+ *    of channels supported in each subband
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 36 */
+	t_u8 len; /**< Element length after id and len */
+
+	/** Configured sub-bands information in the element */
+	IEEEtypes_SupportChan_Subband_t subband[WLAN_11H_MAX_SUBBANDS];
+
+} MLAN_PACK_END IEEEtypes_SupportedChannels_t;
+
+/*  IEEE Wide Bandwidth Channel Switch Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise when
+ *    and to which channel it is changing to.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a wide bandwidth chan
+ *    switch element.
+ */
+typedef MLAN_PACK_START struct {
+	/** Generic IE header IEEE Element ID = 194*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 new_channel_width;
+	t_u8 new_channel_center_freq0;
+	t_u8 new_channel_center_freq1;
+} MLAN_PACK_END IEEEtypes_WideBWChanSwitch_t;
+
+/*  IEEE VHT Transmit Power Envelope Element */
+/**
+ *  Provided in beacons and probe responses.  Used to advertise the max
+ *    TX power in sepeate bandwidth and as a sub element of Channel Switch
+ *    Wrapper IE.
+ */
+typedef MLAN_PACK_START struct {
+	/** Generic IE header IEEE Element ID = 195*/
+	IEEEtypes_Header_t ieee_hdr;
+	t_u8 tpc_info; /**< Transmit Power Information>*/
+	t_u8 local_max_tp_20mhz; /**< Local Maximum Transmit Power for 20 MHZ>*/
+	t_u8 local_max_tp_40mhz; /**< Local Maximum Transmit Power for 40 MHZ>*/
+	t_u8 local_max_tp_80mhz; /**< Local Maximum Transmit Power for 80 MHZ>*/
+	t_u8 local_max_tp_160mhz_80_80mhz; /**< Local Maximum Transmit Power for 160/80+80 MHZ>*/
+} MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t;
+
+/*  IEEE Quiet Period Element (7.3.2.23) */
+/**
+ *  Provided in beacons and probe responses.  Indicates times during
+ *    which the STA should not be transmitting data.  Only starting STAs in
+ *    an IBSS and APs are allowed to originate a quiet element.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 40 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 quiet_count; /**< Number of TBTTs until beacon with the quiet
+			     period */
+	t_u8 quiet_period; /**< Regular quiet period, # of TBTTS between periods
+			    */
+	t_u16 quiet_duration; /**< Duration of the quiet period in TUs */
+	t_u16 quiet_offset; /**< Offset in TUs from the TBTT for the quiet
+			       period */
+
+} MLAN_PACK_END IEEEtypes_Quiet_t;
+
+/**
+***  @brief Map octet of the basic measurement report (7.3.2.22.1)
+**/
+typedef MLAN_PACK_START struct {
+#ifdef BIG_ENDIAN_SUPPORT
+	/**< Reserved */
+	t_u8 rsvd5_7:3;
+	/**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+	/**< Radar detected on channel */
+	t_u8 radar:1;
+	/**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+	/**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+	/**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+#else
+	/**< At least one valid MPDU received on channel */
+	t_u8 bss:1;
+	/**< OFDM preamble detected on channel */
+	t_u8 ofdm_preamble:1;
+	/**< Unidentified signal found on channel */
+	t_u8 unidentified_sig:1;
+	/**< Radar detected on channel */
+	t_u8 radar:1;
+	/**< Channel is unmeasured */
+	t_u8 unmeasured:1;
+	/**< Reserved */
+	t_u8 rsvd5_7:3;
+#endif				/* BIG_ENDIAN_SUPPORT */
+
+} MLAN_PACK_END MeasRptBasicMap_t;
+
+/*  IEEE DFS Channel Map field (7.3.2.24) */
+/**
+ *  Used to list supported channels and provide a octet "map" field which
+ *    contains a basic measurement report for that channel in the
+ *    IEEEtypes_IBSS_DFS_t element
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 channel_number; /**< Channel number */
+	MeasRptBasicMap_t rpt_map; /**< Basic measurement report for the channel
+				    */
+
+} MLAN_PACK_END IEEEtypes_ChannelMap_t;
+
+/*  IEEE IBSS DFS Element (7.3.2.24) */
+/**
+ *  IBSS DFS element included in ad hoc beacons and probe responses.
+ *    Provides information regarding the IBSS DFS Owner as well as the
+ *    originating STAs supported channels and basic measurement results.
+ */
+typedef MLAN_PACK_START struct {
+	t_u8 element_id; /**< IEEE Element ID = 41 */
+	t_u8 len; /**< Element length after id and len */
+	t_u8 dfs_owner[MLAN_MAC_ADDR_LENGTH]; /**< DFS Owner STA Address */
+	t_u8 dfs_recovery_interval; /**< DFS Recovery time in TBTTs */
+
+	/** Variable length map field, one Map entry for each supported channel
+	 */
+	IEEEtypes_ChannelMap_t channel_map[WLAN_11H_MAX_IBSS_DFS_CHANNELS];
+
+} MLAN_PACK_END IEEEtypes_IBSS_DFS_t;
+
+/* 802.11h BSS information kept for each BSSID received in scan results */
+/**
+ * IEEE BSS information needed from scan results for later processing in
+ *    join commands
+ */
+typedef struct {
+	t_u8 sensed_11h; /**< Capability bit set or 11h IE found in this BSS */
+
+	IEEEtypes_PowerConstraint_t power_constraint; /**< Power Constraint IE
+						       */
+	IEEEtypes_PowerCapability_t power_capability; /**< Power Capability IE
+						       */
+	IEEEtypes_TPCReport_t tpc_report; /**< TPC Report IE */
+	IEEEtypes_ChanSwitchAnn_t chan_switch_ann; /**< Channel Switch
+						      Announcement IE */
+	IEEEtypes_Quiet_t quiet; /**< Quiet IE */
+	IEEEtypes_IBSS_DFS_t ibss_dfs; /**< IBSS DFS Element IE */
+
+} wlan_11h_bss_info_t;
+
+/** Ethernet packet type for TDLS */
+#define MLAN_ETHER_PKT_TYPE_TDLS_ACTION (0x890D)
+
+/*802.11z  TDLS action frame type and strcuct */
+typedef MLAN_PACK_START struct {
+	/*link indentifier ie =101 */
+	t_u8 element_id;
+	/*len = 18 */
+	t_u8 len;
+	/** bssid */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** init sta mac address */
+	t_u8 init_sta[MLAN_MAC_ADDR_LENGTH];
+	/** resp sta mac address */
+	t_u8 resp_sta[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END IEEEtypes_tdls_linkie;
+
+/** action code for tdls setup request */
+#define TDLS_SETUP_REQUEST 0
+/** action code for tdls setup response */
+#define TDLS_SETUP_RESPONSE 1
+/** action code for tdls setup confirm */
+#define TDLS_SETUP_CONFIRM 2
+/** action code for tdls tear down */
+#define TDLS_TEARDOWN 3
+/** action code for tdls traffic indication */
+#define TDLS_PEER_TRAFFIC_INDICATION 4
+/** action code for tdls channel switch request */
+#define TDLS_CHANNEL_SWITCH_REQUEST 5
+/** action code for tdls channel switch response */
+#define TDLS_CHANNEL_SWITCH_RESPONSE 6
+/** action code for tdls psm request */
+#define TDLS_PEER_PSM_REQUEST 7
+/** action code for tdls psm response */
+#define TDLS_PEER_PSM_RESPONSE 8
+/** action code for tdls traffic response */
+#define TDLS_PEER_TRAFFIC_RESPONSE 9
+/** action code for tdls discovery request */
+#define TDLS_DISCOVERY_REQUEST 10
+/** action code for TDLS discovery response */
+#define TDLS_DISCOVERY_RESPONSE 14
+/** category public */
+#define CATEGORY_PUBLIC 4
+
+/** action code for 20/40 BSS Coexsitence Management frame */
+#define BSS_20_40_COEX 0
+
+#ifdef STA_SUPPORT
+/** Macro for maximum size of scan response buffer */
+#define MAX_SCAN_RSP_BUF (16 * 1024)
+
+/** Maximum number of channels that can be sent in user scan config */
+#define WLAN_USER_SCAN_CHAN_MAX 50
+/** Maximum length of SSID list */
+#define MRVDRV_MAX_SSID_LIST_LENGTH 10
+
+/** Maximum length of BSSID list */
+#define MAX_BSSID_FILTER_LIST 5
+
+/** Scan all the channels in specified band */
+#define BAND_SPECIFIED 0x80
+
+/**
+ *  IOCTL SSID List sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ *  Used to specify SSID specific filters as well as SSID pattern matching
+ *    filters for scan result processing in firmware.
+ */
+typedef MLAN_PACK_START struct _wlan_user_scan_ssid {
+	/** SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1];
+	/** Maximum length of SSID */
+	t_u8 max_len;
+} MLAN_PACK_END wlan_user_scan_ssid;
+
+/**
+ *  @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ *  Multiple instances of this structure are included in the IOCTL command
+ *   to configure a instance of a scan on the specific channel.
+ */
+typedef MLAN_PACK_START struct _wlan_user_scan_chan {
+	/** Channel Number to scan */
+	t_u8 chan_number;
+	/** Radio type: 'B/G' Band = 0, 'A' Band = 1 */
+	t_u8 radio_type;
+	/** Scan type: Active = 1, Passive = 2 */
+	t_u8 scan_type;
+	/** Reserved */
+	t_u8 reserved;
+	/** Scan duration in milliseconds; if 0 default used */
+	t_u32 scan_time;
+} MLAN_PACK_END wlan_user_scan_chan;
+
+/** channel statictics */
+typedef MLAN_PACK_START struct _ChanStatistics_t {
+	/** channle number */
+	t_u8 chan_num;
+	/** band info */
+	Band_Config_t bandcfg;
+	/** flags */
+	t_u8 flags;
+	/** noise */
+	t_s8 noise;
+	/** total network */
+	t_u16 total_networks;
+	/** scan duration */
+	t_u16 cca_scan_duration;
+	/** busy duration */
+	t_u16 cca_busy_duration;
+	/** min rss */
+	t_u8 min_rss;
+	/** max rssi */
+	t_u8 max_rss;
+} MLAN_PACK_END ChanStatistics_t;
+
+/** Enhance ext scan type defination */
+typedef enum _MLAN_EXT_SCAN_TYPE {
+	EXT_SCAN_DEFAULT,
+	EXT_SCAN_ENHANCE,
+	EXT_SCAN_CANCEL,
+} MLAN_EXT_SCAN_TYPE;
+
+/**
+ *  Input structure to configure an immediate scan cmd to firmware
+ *
+ *  Specifies a number of parameters to be used in general for the scan
+ *    as well as a channel list (wlan_user_scan_chan) for each scan period
+ *    desired.
+ */
+typedef MLAN_PACK_START struct {
+	/**
+	 *  Flag set to keep the previous scan table intact
+	 *
+	 *  If set, the scan results will accumulate, replacing any previous
+	 *   matched entries for a BSS with the new scan data
+	 */
+	t_u8 keep_previous_scan;
+	/**
+	 *  BSS mode to be sent in the firmware command
+	 *
+	 *  Field can be used to restrict the types of networks returned in the
+	 *    scan.  Valid settings are:
+	 *
+	 *   - MLAN_SCAN_MODE_BSS  (infrastructure)
+	 *   - MLAN_SCAN_MODE_IBSS (adhoc)
+	 *   - MLAN_SCAN_MODE_ANY  (unrestricted, adhoc and infrastructure)
+	 */
+	t_u8 bss_mode;
+	/**
+	 *  Configure the number of probe requests for active chan scans
+	 */
+	t_u8 num_probes;
+	/**
+	 *  @brief ssid filter flag
+	 */
+	t_u8 ssid_filter;
+	/**
+	 *  @brief BSSID filter sent in the firmware command to limit the
+	 * results
+	 */
+	t_u8 specific_bssid[MLAN_MAC_ADDR_LENGTH];
+	/**
+	 *  SSID filter list used in the to limit the scan results
+	 */
+	wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+	/**
+	 *  Variable number (fixed maximum) of channels to scan up
+	 */
+	wlan_user_scan_chan chan_list[WLAN_USER_SCAN_CHAN_MAX];
+	/** scan channel gap */
+	t_u16 scan_chan_gap;
+	/** scan type: 0 legacy, 1: enhance scan*/
+	t_u8 ext_scan_type;
+	/** flag to filer only probe response */
+	t_u8 proberesp_only;
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Number of BSSIDs to be filtered */
+	t_u8 bssid_num;
+	/** BSSID filter list used in the to limit the scan results */
+	mlan_802_11_mac_addr bssid_list[MAX_BSSID_FILTER_LIST];
+} MLAN_PACK_END wlan_user_scan_cfg;
+
+/** Default scan interval in millisecond*/
+#define DEFAULT_BGSCAN_INTERVAL 30000
+
+/** action get all, except pps/uapsd config */
+#define BG_SCAN_ACT_GET 0x0000
+/** action set all, except pps/uapsd config */
+#define BG_SCAN_ACT_SET 0x0001
+/** action get pps/uapsd config */
+#define BG_SCAN_ACT_GET_PPS_UAPSD 0x0100
+/** action set pps/uapsd config */
+#define BG_SCAN_ACT_SET_PPS_UAPSD 0x0101
+/** action set all */
+#define BG_SCAN_ACT_SET_ALL 0xff01
+/** ssid match */
+#define BG_SCAN_SSID_MATCH 0x0001
+/** ssid match and RSSI exceeded */
+#define BG_SCAN_SSID_RSSI_MATCH 0x0004
+/**wait for all channel scan to complete to report scan result*/
+#define BG_SCAN_WAIT_ALL_CHAN_DONE 0x80000000
+/** Maximum number of channels that can be sent in bg scan config */
+#define WLAN_BG_SCAN_CHAN_MAX 38
+
+/** Enumeration definition */
+/** EES MODE */
+typedef enum {
+	/** EES MODE: LOW */
+	EES_MODE_LOW = 0,
+	/** EES MODE: MID */
+	EES_MODE_MID,
+	/** EES MODE: HIGH */
+	EES_MODE_HIGH,
+	/** EES MODE: OFF */
+	EES_MODE_OFF,
+	/** EES MODE: LOOP */
+	EES_MODE_LOOP = 15,
+} ees_modes;
+
+/** EES Maximum SSID */
+#define EES_MAX_SSIDS 2
+
+/** ees_ssid_config */
+typedef MLAN_PACK_START struct {
+	/** SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1];
+	/** Maximum length of SSID */
+	t_u8 max_len;
+	/** PairCipher */
+	t_u8 pair_cipher;
+	/** GroupCipher */
+	t_u8 group_cipher;
+} MLAN_PACK_END ees_ssid_config;
+
+/**
+ *  Input structure to configure bs scan cmd to firmware
+ */
+typedef MLAN_PACK_START struct {
+	/** action */
+	t_u16 action;
+	/** enable/disable */
+	t_u8 enable;
+	/**  BSS type:
+	 *   MLAN_SCAN_MODE_BSS  (infrastructure)
+	 *   MLAN_SCAN_MODE_IBSS (adhoc)
+	 *   MLAN_SCAN_MODE_ANY  (unrestricted, adhoc and infrastructure)
+	 */
+	t_u8 bss_type;
+	/** number of channel scanned during each scan */
+	t_u8 chan_per_scan;
+	/** interval between consecutive scan */
+	t_u32 scan_interval;
+	/** bit 0: ssid match bit 1: ssid match and SNR exceeded
+	 *  bit 2: ssid match and RSSI exceeded
+	 *  bit 31: wait for all channel scan to complete to report scan result
+	 */
+	t_u32 report_condition;
+	/*  Configure the number of probe requests for active chan scans */
+	t_u8 num_probes;
+	/** RSSI threshold */
+	t_u8 rssi_threshold;
+	/** SNR threshold */
+	t_u8 snr_threshold;
+	/** repeat count */
+	t_u16 repeat_count;
+	/** start later flag */
+	t_u16 start_later;
+	/** SSID filter list used in the to limit the scan results */
+	wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH];
+	/** Variable number (fixed maximum) of channels to scan up */
+	wlan_user_scan_chan chan_list[WLAN_BG_SCAN_CHAN_MAX];
+	/** scan channel gap */
+	t_u16 scan_chan_gap;
+	/** Enable EES configuration */
+	t_u8 config_ees;
+	/** EES scan mode */
+	t_u16 ees_mode;
+	/** EES report condition */
+	t_u16 report_cond;
+	/** EES High Period scan interval */
+	t_u16 high_period;
+	/** EES High Period scan count */
+	t_u16 high_period_count;
+	/** EES Medium Period scan interval */
+	t_u16 mid_period;
+	/** EES Medium Period scan count */
+	t_u16 mid_period_count;
+	/** EES Low Period scan interval */
+	t_u16 low_period;
+	/** EES Low Period scan count */
+	t_u16 low_period_count;
+	/** Number of networks in the list */
+	t_u8 network_count;
+	/** Maximum number of connection count */
+	t_u8 max_conn_count;
+	/** Black List Exp */
+	t_u8 black_list_exp;
+	/** Array of ees config struct */
+	ees_ssid_config ees_ssid_cfg[EES_MAX_SSIDS];
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+} MLAN_PACK_END wlan_bgscan_cfg;
+#endif /* STA_SUPPORT */
+
+#ifdef PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+/** BSSDescriptor_t
+ *    Structure used to store information for beacon/probe response
+ */
+typedef struct _BSSDescriptor_t {
+	/** MAC address */
+	mlan_802_11_mac_addr mac_address;
+
+	/** SSID */
+	mlan_802_11_ssid ssid;
+
+	/** WEP encryption requirement */
+	t_u32 privacy;
+
+	/** Receive signal strength in dBm */
+	t_s32 rssi;
+	/** channel load */
+	t_u8 chan_load;
+	/** Channel */
+	t_u32 channel;
+
+	/** Freq */
+	t_u32 freq;
+
+	/** Beacon period */
+	t_u16 beacon_period;
+
+	/** ATIM window */
+	t_u32 atim_window;
+
+	/** ERP flags */
+	t_u8 erp_flags;
+
+	/** Type of network in use */
+	WLAN_802_11_NETWORK_TYPE network_type_use;
+
+	/** Network infrastructure mode */
+	t_u32 bss_mode;
+
+	/** Network supported rates */
+	WLAN_802_11_RATES supported_rates;
+
+	/** Supported data rates */
+	t_u8 data_rates[WLAN_SUPPORTED_RATES];
+
+	/** Current channel bandwidth
+	 *  0 : 20MHZ
+	 *  1 : 40MHZ
+	 *  2 : 80MHZ
+	 *  3 : 160MHZ
+	 */
+	t_u8 curr_bandwidth;
+
+	/** Network band.
+	 * BAND_B(0x01): 'b' band
+	 * BAND_G(0x02): 'g' band
+	 * BAND_A(0X04): 'a' band
+	 */
+	t_u16 bss_band;
+
+	/** TSF timestamp from the current firmware TSF */
+	t_u64 network_tsf;
+
+	/** TSF value included in the beacon/probe response */
+	t_u8 time_stamp[8];
+
+	/** PHY parameter set */
+	IEEEtypes_PhyParamSet_t phy_param_set;
+
+	/** SS parameter set */
+	IEEEtypes_SsParamSet_t ss_param_set;
+
+	/** Capability information */
+	IEEEtypes_CapInfo_t cap_info;
+
+	/** WMM IE */
+	IEEEtypes_WmmParameter_t wmm_ie;
+
+	/** 802.11h BSS information */
+	wlan_11h_bss_info_t wlan_11h_bss_info;
+
+	/** Indicate disabling 11n when associate with AP */
+	t_u8 disable_11n;
+	/** 802.11n BSS information */
+	/** HT Capabilities IE */
+	IEEEtypes_HTCap_t *pht_cap;
+	/** HT Capabilities Offset */
+	t_u16 ht_cap_offset;
+	/** HT Information IE */
+	IEEEtypes_HTInfo_t *pht_info;
+	/** HT Information Offset */
+	t_u16 ht_info_offset;
+	/** Flag to indicate this is multi_bssid_ap */
+	t_u8 multi_bssid_ap;
+	/** the mac address of multi-bssid AP */
+	mlan_802_11_mac_addr multi_bssid_ap_addr;
+	/** 20/40 BSS Coexistence IE */
+	IEEEtypes_2040BSSCo_t *pbss_co_2040;
+	/** 20/40 BSS Coexistence Offset */
+	t_u16 bss_co_2040_offset;
+	/** Extended Capabilities IE */
+	IEEEtypes_ExtCap_t *pext_cap;
+	/** Extended Capabilities Offset */
+	t_u16 ext_cap_offset;
+	/** Overlapping BSS Scan Parameters IE */
+	IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param;
+	/** Overlapping BSS Scan Parameters Offset */
+	t_u16 overlap_bss_offset;
+
+	/** VHT Capabilities IE */
+	IEEEtypes_VHTCap_t *pvht_cap;
+	/** VHT Capabilities IE offset */
+	t_u16 vht_cap_offset;
+	/** VHT Operations IE */
+	IEEEtypes_VHTOprat_t *pvht_oprat;
+	/** VHT Operations IE offset */
+	t_u16 vht_oprat_offset;
+	/** VHT Transmit Power Envelope IE */
+	IEEEtypes_VHTtxpower_t *pvht_txpower;
+	/** VHT Transmit Power Envelope IE offset */
+	t_u16 vht_txpower_offset;
+	/** Extended Power Constraint IE */
+	IEEEtypes_ExtPwerCons_t *pext_pwer;
+	/** Extended Power Constraint IE offset */
+	t_u16 ext_pwer_offset;
+	/** Extended BSS Load IE  */
+	IEEEtypes_ExtBSSload_t *pext_bssload;
+	/** Extended BSS Load IE offset */
+	t_u16 ext_bssload_offset;
+	/** Quiet Channel IE */
+	IEEEtypes_QuietChan_t *pquiet_chan;
+	/** Quiet Channel IE offset */
+	t_u16 quiet_chan_offset;
+	/** Operating Mode Notification IE */
+	IEEEtypes_OperModeNtf_t *poper_mode;
+	/** Operating Mode Notification IE offset */
+	t_u16 oper_mode_offset;
+	/** HE Capability IE */
+	IEEEtypes_HECap_t *phe_cap;
+	/** HE Capability IE offset */
+	t_u16 he_cap_offset;
+	/** HE operation IE */
+	IEEEtypes_Extension_t *phe_oprat;
+	/** HE operation IE offset */
+	t_u16 he_oprat_offset;
+#ifdef STA_SUPPORT
+	/** Country information set */
+	IEEEtypes_CountryInfoFullSet_t country_info;
+#endif				/* STA_SUPPORT */
+
+	/** WPA IE */
+	IEEEtypes_VendorSpecific_t *pwpa_ie;
+	/** WPA IE offset in the beacon buffer */
+	t_u16 wpa_offset;
+	/** RSN IE */
+	IEEEtypes_Generic_t *prsn_ie;
+	/** RSN IE offset in the beacon buffer */
+	t_u16 rsn_offset;
+	/** RSNX IE */
+	IEEEtypes_Generic_t *prsnx_ie;
+	/** RSNX IE offset in the beacon buffer */
+	t_u16 rsnx_offset;
+#ifdef STA_SUPPORT
+	/** WAPI IE */
+	IEEEtypes_Generic_t *pwapi_ie;
+	/** WAPI IE offset in the beacon buffer */
+	t_u16 wapi_offset;
+#endif
+	/* Hotspot 2.0 OSEN AKM  IE */
+	IEEEtypes_Generic_t *posen_ie;
+	/** osen IE offset in the beacon buffer */
+	t_u16 osen_offset;
+	/* Mobility domain IE */
+	IEEEtypes_MobilityDomain_t *pmd_ie;
+	/** Mobility domain IE offset in the beacon buffer */
+	t_u16 md_offset;
+
+	/** Pointer to the returned scan response */
+	t_u8 *pbeacon_buf;
+	/** Length of the stored scan response */
+	t_u32 beacon_buf_size;
+	/** Max allocated size for updated scan response */
+	t_u32 beacon_buf_size_max;
+    /** scan age in secs */
+	t_u32 age_in_secs;
+} BSSDescriptor_t, *pBSSDescriptor_t;
+
+#endif /* !_MLAN_IEEE_H_ */
diff --git a/wlan_sd8987/mlinux/mlan_ioctl.h b/wlan_sd8987/mlinux/mlan_ioctl.h
new file mode 100755
index 0000000..09c11a1
--- /dev/null
+++ b/wlan_sd8987/mlinux/mlan_ioctl.h
@@ -0,0 +1,5450 @@
+/** @file mlan_ioctl.h
+ *
+ *  @brief This file declares the IOCTL data structures and APIs.
+ *
+ *
+ *  Copyright 2008-2021 NXP
+ *
+ *  This software file (the File) is distributed by NXP
+ *  under the terms of the GNU General Public License Version 2, June 1991
+ *  (the License).  You may use, redistribute and/or modify the File in
+ *  accordance with the terms and conditions of the License, a copy of which
+ *  is available by writing to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ *  this warranty disclaimer.
+ *
+ */
+
+/******************************************************
+Change log:
+    11/07/2008: initial version
+******************************************************/
+
+#ifndef _MLAN_IOCTL_H_
+#define _MLAN_IOCTL_H_
+
+/** Enumeration for IOCTL request ID */
+enum _mlan_ioctl_req_id {
+	/* Scan Group */
+	MLAN_IOCTL_SCAN = 0x00010000,
+	MLAN_OID_SCAN_NORMAL = 0x00010001,
+	MLAN_OID_SCAN_SPECIFIC_SSID = 0x00010002,
+	MLAN_OID_SCAN_USER_CONFIG = 0x00010003,
+	MLAN_OID_SCAN_CONFIG = 0x00010004,
+	MLAN_OID_SCAN_GET_CURRENT_BSS = 0x00010005,
+	MLAN_OID_SCAN_CANCEL = 0x00010006,
+	MLAN_OID_SCAN_TABLE_FLUSH = 0x0001000A,
+	MLAN_OID_SCAN_BGSCAN_CONFIG = 0x0001000B,
+	/* BSS Configuration Group */
+	MLAN_IOCTL_BSS = 0x00020000,
+	MLAN_OID_BSS_START = 0x00020001,
+	MLAN_OID_BSS_STOP = 0x00020002,
+	MLAN_OID_BSS_MODE = 0x00020003,
+	MLAN_OID_BSS_CHANNEL = 0x00020004,
+	MLAN_OID_BSS_CHANNEL_LIST = 0x00020005,
+	MLAN_OID_BSS_MAC_ADDR = 0x00020006,
+	MLAN_OID_BSS_MULTICAST_LIST = 0x00020007,
+	MLAN_OID_BSS_FIND_BSS = 0x00020008,
+	MLAN_OID_IBSS_BCN_INTERVAL = 0x00020009,
+	MLAN_OID_IBSS_ATIM_WINDOW = 0x0002000A,
+	MLAN_OID_IBSS_CHANNEL = 0x0002000B,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_BSS_CONFIG = 0x0002000C,
+	MLAN_OID_UAP_DEAUTH_STA = 0x0002000D,
+	MLAN_OID_UAP_BSS_RESET = 0x0002000E,
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	MLAN_OID_BSS_ROLE = 0x0002000F,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	MLAN_OID_WIFI_DIRECT_MODE = 0x00020010,
+#endif
+#ifdef STA_SUPPORT
+	MLAN_OID_BSS_LISTEN_INTERVAL = 0x00020011,
+#endif
+	MLAN_OID_BSS_REMOVE = 0x00020014,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_CFG_WMM_PARAM = 0x00020015,
+#endif
+	MLAN_OID_BSS_11D_CHECK_CHANNEL = 0x00020016,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_ACS_SCAN = 0x00020017,
+	MLAN_OID_UAP_SCAN_CHANNELS = 0x00020018,
+	MLAN_OID_UAP_CHANNEL = 0x00020019,
+	MLAN_OID_UAP_OPER_CTRL = 0x0002001A,
+#endif
+#ifdef STA_SUPPORT
+	MLAN_OID_BSS_CHAN_INFO = 0x0002001B,
+#endif
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_ADD_STATION = 0x0002001C,
+#endif
+
+	MLAN_OID_BSS_FIND_BSSID = 0x0002001D,
+#ifdef UAP_SUPPORT
+	MLAN_OID_ACTION_CHAN_SWITCH = 0x0002001E,
+#endif
+
+	/* Radio Configuration Group */
+	MLAN_IOCTL_RADIO_CFG = 0x00030000,
+	MLAN_OID_RADIO_CTRL = 0x00030001,
+	MLAN_OID_BAND_CFG = 0x00030002,
+	MLAN_OID_ANT_CFG = 0x00030003,
+	MLAN_OID_REMAIN_CHAN_CFG = 0x00030004,
+	MLAN_OID_MIMO_SWITCH = 0x00030005,
+
+	/* SNMP MIB Group */
+	MLAN_IOCTL_SNMP_MIB = 0x00040000,
+	MLAN_OID_SNMP_MIB_RTS_THRESHOLD = 0x00040001,
+	MLAN_OID_SNMP_MIB_FRAG_THRESHOLD = 0x00040002,
+	MLAN_OID_SNMP_MIB_RETRY_COUNT = 0x00040003,
+	MLAN_OID_SNMP_MIB_DOT11D = 0x00040004,
+#if defined(UAP_SUPPORT)
+	MLAN_OID_SNMP_MIB_DOT11H = 0x00040005,
+#endif
+	MLAN_OID_SNMP_MIB_DTIM_PERIOD = 0x00040006,
+	MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE = 0x00040007,
+	MLAN_OID_SNMP_MIB_CTRL_DEAUTH = 0x00040008,
+
+	/* Status Information Group */
+	MLAN_IOCTL_GET_INFO = 0x00050000,
+	MLAN_OID_GET_STATS = 0x00050001,
+	MLAN_OID_GET_SIGNAL = 0x00050002,
+	MLAN_OID_GET_FW_INFO = 0x00050003,
+	MLAN_OID_GET_VER_EXT = 0x00050004,
+	MLAN_OID_GET_BSS_INFO = 0x00050005,
+	MLAN_OID_GET_DEBUG_INFO = 0x00050006,
+#ifdef UAP_SUPPORT
+	MLAN_OID_UAP_STA_LIST = 0x00050007,
+#endif
+	MLAN_OID_GET_SIGNAL_EXT = 0x00050008,
+	MLAN_OID_LINK_STATS = 0x00050009,
+	MLAN_OID_GET_UAP_STATS_LOG = 0x0005000A,
+	/* Security Configuration Group */
+	MLAN_IOCTL_SEC_CFG = 0x00060000,
+	MLAN_OID_SEC_CFG_AUTH_MODE = 0x00060001,
+	MLAN_OID_SEC_CFG_ENCRYPT_MODE = 0x00060002,
+	MLAN_OID_SEC_CFG_WPA_ENABLED = 0x00060003,
+	MLAN_OID_SEC_CFG_ENCRYPT_KEY = 0x00060004,
+	MLAN_OID_SEC_CFG_PASSPHRASE = 0x00060005,
+	MLAN_OID_SEC_CFG_EWPA_ENABLED = 0x00060006,
+	MLAN_OID_SEC_CFG_ESUPP_MODE = 0x00060007,
+	MLAN_OID_SEC_CFG_WAPI_ENABLED = 0x00060009,
+	MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED = 0x0006000A,
+#ifdef UAP_SUPPORT
+	MLAN_OID_SEC_CFG_REPORT_MIC_ERR = 0x0006000B,
+#endif
+	MLAN_OID_SEC_QUERY_KEY = 0x0006000C,
+
+	/* Rate Group */
+	MLAN_IOCTL_RATE = 0x00070000,
+	MLAN_OID_RATE_CFG = 0x00070001,
+	MLAN_OID_GET_DATA_RATE = 0x00070002,
+	MLAN_OID_SUPPORTED_RATES = 0x00070003,
+
+	/* Power Configuration Group */
+	MLAN_IOCTL_POWER_CFG = 0x00080000,
+	MLAN_OID_POWER_CFG = 0x00080001,
+	MLAN_OID_POWER_CFG_EXT = 0x00080002,
+	MLAN_OID_POWER_LOW_POWER_MODE = 0x00080003,
+
+	/* Power Management Configuration Group */
+	MLAN_IOCTL_PM_CFG = 0x00090000,
+	MLAN_OID_PM_CFG_IEEE_PS = 0x00090001,
+	MLAN_OID_PM_CFG_HS_CFG = 0x00090002,
+	MLAN_OID_PM_CFG_INACTIVITY_TO = 0x00090003,
+	MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004,
+	MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005,
+	MLAN_OID_PM_CFG_PS_CFG = 0x00090006,
+	MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008,
+#ifdef UAP_SUPPORT
+	MLAN_OID_PM_CFG_PS_MODE = 0x00090009,
+#endif /* UAP_SUPPORT */
+	MLAN_OID_PM_INFO = 0x0009000A,
+	MLAN_OID_PM_HS_WAKEUP_REASON = 0x0009000B,
+	MLAN_OID_PM_MGMT_FILTER = 0x0009000C,
+	MLAN_OID_PM_CFG_BCN_TIMEOUT = 0x0009000D,
+
+	/* WMM Configuration Group */
+	MLAN_IOCTL_WMM_CFG = 0x000A0000,
+	MLAN_OID_WMM_CFG_ENABLE = 0x000A0001,
+	MLAN_OID_WMM_CFG_QOS = 0x000A0002,
+	MLAN_OID_WMM_CFG_ADDTS = 0x000A0003,
+	MLAN_OID_WMM_CFG_DELTS = 0x000A0004,
+	MLAN_OID_WMM_CFG_QUEUE_CONFIG = 0x000A0005,
+	MLAN_OID_WMM_CFG_QUEUE_STATS = 0x000A0006,
+	MLAN_OID_WMM_CFG_QUEUE_STATUS = 0x000A0007,
+	MLAN_OID_WMM_CFG_TS_STATUS = 0x000A0008,
+
+	/* WPS Configuration Group */
+	MLAN_IOCTL_WPS_CFG = 0x000B0000,
+	MLAN_OID_WPS_CFG_SESSION = 0x000B0001,
+
+	/* 802.11n Configuration Group */
+	MLAN_IOCTL_11N_CFG = 0x000C0000,
+	MLAN_OID_11N_CFG_TX = 0x000C0001,
+	MLAN_OID_11N_HTCAP_CFG = 0x000C0002,
+	MLAN_OID_11N_CFG_ADDBA_REJECT = 0x000C0003,
+	MLAN_OID_11N_CFG_AGGR_PRIO_TBL = 0x000C0004,
+	MLAN_OID_11N_CFG_ADDBA_PARAM = 0x000C0005,
+	MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE = 0x000C0006,
+	MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL = 0x000C0007,
+	MLAN_OID_11N_CFG_SUPPORTED_MCS_SET = 0x000C0008,
+	MLAN_OID_11N_CFG_TX_BF_CAP = 0x000C0009,
+	MLAN_OID_11N_CFG_TX_BF_CFG = 0x000C000A,
+	MLAN_OID_11N_CFG_STREAM_CFG = 0x000C000B,
+	MLAN_OID_11N_CFG_DELBA = 0x000C000C,
+	MLAN_OID_11N_CFG_REJECT_ADDBA_REQ = 0x000C000D,
+	MLAN_OID_11N_CFG_COEX_RX_WINSIZE = 0x000C000E,
+	MLAN_OID_11N_CFG_TX_AGGR_CTRL = 0x000C000F,
+	MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM = 0x000C0010,
+	MLAN_OID_11N_CFG_MIN_BA_THRESHOLD = 0x000C0011,
+
+	/* 802.11d Configuration Group */
+	MLAN_IOCTL_11D_CFG = 0x000D0000,
+#ifdef STA_SUPPORT
+	MLAN_OID_11D_CFG_ENABLE = 0x000D0001,
+	MLAN_OID_11D_CLR_CHAN_TABLE = 0x000D0002,
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	MLAN_OID_11D_DOMAIN_INFO = 0x000D0003,
+#endif
+	MLAN_OID_11D_DOMAIN_INFO_EXT = 0x000D0004,
+
+	/* Register Memory Access Group */
+	MLAN_IOCTL_REG_MEM = 0x000E0000,
+	MLAN_OID_REG_RW = 0x000E0001,
+	MLAN_OID_EEPROM_RD = 0x000E0002,
+	MLAN_OID_MEM_RW = 0x000E0003,
+
+	/* Multi-Radio Configuration Group */
+	MLAN_IOCTL_MFR_CFG = 0x00100000,
+	/* 802.11h Configuration Group */
+	MLAN_IOCTL_11H_CFG = 0x00110000,
+	MLAN_OID_11H_CHANNEL_CHECK = 0x00110001,
+	MLAN_OID_11H_LOCAL_POWER_CONSTRAINT = 0x00110002,
+	MLAN_OID_11H_DFS_TESTING = 0x00110003,
+	MLAN_OID_11H_CHAN_REPORT_REQUEST = 0x00110004,
+	MLAN_OID_11H_CHAN_SWITCH_COUNT = 0x00110005,
+	MLAN_OID_11H_CHAN_NOP_INFO = 0x00110006,
+	MLAN_OID_11H_DFS_W53_CFG = 0x00110008,
+
+	/* 802.11n Configuration Group RANDYTODO for value assign */
+	MLAN_IOCTL_11AC_CFG = 0x00120000,
+	MLAN_OID_11AC_VHT_CFG = 0x00120001,
+	MLAN_OID_11AC_CFG_SUPPORTED_MCS_SET = 0x00120002,
+	MLAN_OID_11AC_OPERMODE_CFG = 0x00120003,
+
+	/* 802.11ax Configuration Group  */
+	MLAN_IOCTL_11AX_CFG = 0x00170000,
+	MLAN_OID_11AX_HE_CFG = 0x00170001,
+	MLAN_OID_11AX_CMD_CFG = 0x00170002,
+	MLAN_OID_11AX_TWT_CFG = 0x00170003,
+
+	/* Miscellaneous Configuration Group */
+	MLAN_IOCTL_MISC_CFG = 0x00200000,
+	MLAN_OID_MISC_GEN_IE = 0x00200001,
+	MLAN_OID_MISC_REGION = 0x00200002,
+	MLAN_OID_MISC_WARM_RESET = 0x00200003,
+#ifdef SDIO
+	MLAN_OID_MISC_SDIO_MPA_CTRL = 0x00200006,
+#endif
+	MLAN_OID_MISC_HOST_CMD = 0x00200007,
+	MLAN_OID_MISC_SYS_CLOCK = 0x00200009,
+	MLAN_OID_MISC_SOFT_RESET = 0x0020000A,
+	MLAN_OID_MISC_WWS = 0x0020000B,
+	MLAN_OID_MISC_ASSOC_RSP = 0x0020000C,
+	MLAN_OID_MISC_INIT_SHUTDOWN = 0x0020000D,
+	MLAN_OID_MISC_CUSTOM_IE = 0x0020000F,
+	MLAN_OID_MISC_TDLS_CONFIG = 0x00200010,
+	MLAN_OID_MISC_TX_DATAPAUSE = 0x00200012,
+	MLAN_OID_MISC_IP_ADDR = 0x00200013,
+	MLAN_OID_MISC_MAC_CONTROL = 0x00200014,
+	MLAN_OID_MISC_MEF_CFG = 0x00200015,
+	MLAN_OID_MISC_CFP_CODE = 0x00200016,
+	MLAN_OID_MISC_COUNTRY_CODE = 0x00200017,
+	MLAN_OID_MISC_THERMAL = 0x00200018,
+	MLAN_OID_MISC_RX_MGMT_IND = 0x00200019,
+	MLAN_OID_MISC_SUBSCRIBE_EVENT = 0x0020001A,
+#ifdef DEBUG_LEVEL1
+	MLAN_OID_MISC_DRVDBG = 0x0020001B,
+#endif
+	MLAN_OID_MISC_HOTSPOT_CFG = 0x0020001C,
+	MLAN_OID_MISC_OTP_USER_DATA = 0x0020001D,
+#ifdef USB
+	MLAN_OID_MISC_USB_AGGR_CTRL = 0x0020001F,
+#endif
+	MLAN_OID_MISC_TXCONTROL = 0x00200020,
+#ifdef STA_SUPPORT
+	MLAN_OID_MISC_EXT_CAP_CFG = 0x00200021,
+#endif
+#if defined(STA_SUPPORT)
+	MLAN_OID_MISC_PMFCFG = 0x00200022,
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	MLAN_OID_MISC_WIFI_DIRECT_CONFIG = 0x00200025,
+#endif
+	MLAN_OID_MISC_TDLS_OPER = 0x00200026,
+	MLAN_OID_MISC_GET_TDLS_IES = 0x00200027,
+	MLAN_OID_MISC_LOW_PWR_MODE = 0x00200029,
+	MLAN_OID_MISC_MEF_FLT_CFG = 0x0020002A,
+	MLAN_OID_MISC_DFS_REAPTER_MODE = 0x0020002B,
+#ifdef RX_PACKET_COALESCE
+	MLAN_OID_MISC_RX_PACKET_COALESCE = 0x0020002C,
+#endif
+	MLAN_OID_MISC_TDLS_CS_CHANNEL = 0x0020002D,
+	MLAN_OID_MISC_COALESCE_CFG = 0x0020002E,
+	MLAN_OID_MISC_TDLS_IDLE_TIME = 0x0020002F,
+	MLAN_OID_MISC_GET_SENSOR_TEMP = 0x00200030,
+	MLAN_OID_MISC_IPV6_RA_OFFLOAD = 0x00200036,
+	MLAN_OID_MISC_GTK_REKEY_OFFLOAD = 0x00200037,
+	MLAN_OID_MISC_OPER_CLASS = 0x00200038,
+	MLAN_OID_MISC_PMIC_CFG = 0x00200039,
+	MLAN_OID_MISC_IND_RST_CFG = 0x00200040,
+	MLAN_OID_MISC_GET_TSF = 0x00200045,
+	MLAN_OID_MISC_GET_CHAN_REGION_CFG = 0x00200046,
+	MLAN_OID_MISC_CLOUD_KEEP_ALIVE = 0x00200048,
+	MLAN_OID_MISC_OPER_CLASS_CHECK = 0x00200049,
+
+	MLAN_OID_MISC_CWMODE_CTRL = 0x00200051,
+	MLAN_OID_MISC_AGGR_CTRL = 0x00200052,
+	MLAN_OID_MISC_DYN_BW = 0x00200053,
+	MLAN_OID_MISC_FW_DUMP_EVENT = 0x00200054,
+	MLAN_OID_MISC_PER_PKT_CFG = 0x00200055,
+
+	MLAN_OID_MISC_ROBUSTCOEX = 0x00200056,
+	MLAN_OID_MISC_GET_TX_RX_HISTOGRAM = 0x00200057,
+	MLAN_OID_MISC_CFP_INFO = 0x00200060,
+	MLAN_OID_MISC_BOOT_SLEEP = 0x00200061,
+#if defined(PCIE)
+	MLAN_OID_MISC_SSU = 0x00200062,
+#endif
+	MLAN_OID_MISC_DMCS_CONFIG = 0x00200065,
+	MLAN_OID_MISC_RX_ABORT_CFG = 0x00200066,
+	MLAN_OID_MISC_RX_ABORT_CFG_EXT = 0x00200067,
+	MLAN_OID_MISC_TX_AMPDU_PROT_MODE = 0x00200068,
+	MLAN_OID_MISC_RATE_ADAPT_CFG = 0x00200069,
+	MLAN_OID_MISC_CCK_DESENSE_CFG = 0x00200070,
+	MLAN_OID_MISC_GET_CHAN_TRPC_CFG = 0x00200072,
+	MLAN_OID_MISC_BAND_STEERING = 0x00200073,
+	MLAN_OID_MISC_GET_REGIONPWR_CFG = 0x00200074,
+	MLAN_OID_MISC_RF_TEST_GENERIC = 0x00200075,
+	MLAN_OID_MISC_RF_TEST_TX_CONT = 0x00200076,
+	MLAN_OID_MISC_RF_TEST_TX_FRAME = 0x00200077,
+	MLAN_OID_MISC_ARB_CONFIG = 0x00200078,
+	MLAN_OID_MISC_BEACON_STUCK = 0x00200079,
+	MLAN_OID_MISC_CFP_TABLE = 0x0020007A,
+	MLAN_OID_MISC_RANGE_EXT = 0x0020007B,
+	MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG = 0x0020007C,
+	MLAN_OID_MISC_TP_STATE = 0x0020007D,
+	MLAN_OID_MISC_HAL_PHY_CFG = 0x0020007E,
+	MLAN_OID_MISC_RF_TEST_HE_POWER = 0X0020007F,
+#ifdef UAP_SUPPORT
+	MLAN_OID_MISC_WACP_MODE = 0x00200081,
+#endif
+	MLAN_OID_MISC_GPIO_TSF_LATCH = 0x00200082,
+	MLAN_OID_MISC_GET_TSF_INFO = 0x00200083,
+};
+
+/** Sub command size */
+#define MLAN_SUB_COMMAND_SIZE 4
+
+/** Enumeration for the action of IOCTL request */
+enum _mlan_act_ioctl {
+	MLAN_ACT_SET = 1,
+	MLAN_ACT_GET,
+	MLAN_ACT_CANCEL,
+	MLAN_ACT_CLEAR,
+	MLAN_ACT_RESET,
+	MLAN_ACT_DEFAULT
+};
+
+/** Enumeration for generic enable/disable */
+enum _mlan_act_generic { MLAN_ACT_DISABLE = 0, MLAN_ACT_ENABLE = 1 };
+
+/** Enumeration for scan mode */
+enum _mlan_scan_mode {
+	MLAN_SCAN_MODE_UNCHANGED = 0,
+	MLAN_SCAN_MODE_BSS,
+	MLAN_SCAN_MODE_IBSS,
+	MLAN_SCAN_MODE_ANY
+};
+
+/** Enumeration for scan type */
+enum _mlan_scan_type {
+	MLAN_SCAN_TYPE_UNCHANGED = 0,
+	MLAN_SCAN_TYPE_ACTIVE,
+	MLAN_SCAN_TYPE_PASSIVE,
+	MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE
+};
+
+/** Enumeration for passive to active scan */
+enum _mlan_pass_to_act_scan {
+	MLAN_PASS_TO_ACT_SCAN_UNCHANGED = 0,
+	MLAN_PASS_TO_ACT_SCAN_EN,
+	MLAN_PASS_TO_ACT_SCAN_DIS
+};
+
+/** Max number of supported rates */
+#define MLAN_SUPPORTED_RATES 32
+
+/** Mrvl Proprietary Tlv base */
+#define PROPRIETARY_TLV_BASE_ID 0x100
+
+/** RSSI scan */
+#define SCAN_RSSI(RSSI) (0x100 - ((t_u8)(RSSI)))
+
+/** Max passive scan time for each channel in milliseconds */
+#define MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME 2000
+
+/** Max active scan time for each channel in milliseconds  */
+#define MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME 500
+/** Max gap time between 2 scan in milliseconds  */
+#define MRVDRV_MAX_SCAN_CHAN_GAP_TIME 500
+
+/** Maximum number of probes to send on each channel */
+#define MAX_PROBES 5
+
+/** Default number of probes to send on each channel */
+#define DEFAULT_PROBES 4
+
+/**
+ *  @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS
+ *
+ *  Fixed field information returned for the scan response in the IOCTL
+ *    response.
+ */
+typedef struct _wlan_get_scan_table_fixed {
+	/** BSSID of this network */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Channel this beacon/probe response was detected */
+	t_u8 channel;
+	/** RSSI for the received packet */
+	t_u8 rssi;
+	/** channel load */
+	t_u8 chan_load;
+	/** TSF value in microseconds from the firmware at packet reception */
+	t_u64 network_tsf;
+} wlan_get_scan_table_fixed;
+
+/** mlan_802_11_ssid data structure */
+typedef struct _mlan_802_11_ssid {
+	/** SSID Length */
+	t_u32 ssid_len;
+	/** SSID information field */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+} mlan_802_11_ssid, *pmlan_802_11_ssid;
+
+typedef MLAN_PACK_START struct _tx_status_event {
+	/** packet type */
+	t_u8 packet_type;
+	/** tx_token_id */
+	t_u8 tx_token_id;
+	/** 0--success, 1--fail, 2--watchdogtimeout */
+	t_u8 status;
+} MLAN_PACK_END tx_status_event;
+
+/**
+ *  Sructure to retrieve the scan table
+ */
+typedef struct {
+	/**
+	 *  - Zero based scan entry to start retrieval in command request
+	 *  - Number of scans entries returned in command response
+	 */
+	t_u32 scan_number;
+	/**
+	 * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
+	 * structures. Each struct is padded to the nearest 32 bit boundary.
+	 */
+	t_u8 scan_table_entry_buf[1];
+} wlan_ioctl_get_scan_table_info;
+
+/**
+ *  Structure passed in the wlan_ioctl_get_scan_table_info for each
+ *    BSS returned in the WLAN_GET_SCAN_RESP IOCTL
+ */
+typedef struct _wlan_ioctl_get_scan_table_entry {
+	/**
+	 *  Fixed field length included in the response.
+	 *
+	 *  Length value is included so future fixed fields can be added to the
+	 *   response without breaking backwards compatibility.  Use the length
+	 *   to find the offset for the bssInfoLength field, not a sizeof()
+	 * calc.
+	 */
+	t_u32 fixed_field_length;
+
+	/**
+	 *  Length of the BSS Information (probe resp or beacon) that
+	 *    follows after the fixed_field_length
+	 */
+	t_u32 bss_info_length;
+
+	/**
+	 *  Always present, fixed length data fields for the BSS
+	 */
+	wlan_get_scan_table_fixed fixed_fields;
+
+	/*
+	 * Probe response or beacon scanned for the BSS.
+	 *
+	 * Field layout:
+	 *  - TSF              8 octets
+	 *  - Beacon Interval  2 octets
+	 *  - Capability Info  2 octets
+	 *
+	 *  - IEEE Infomation Elements; variable number & length per 802.11 spec
+	 */
+	/* t_u8  bss_info_buffer[]; */
+} wlan_ioctl_get_scan_table_entry;
+
+/** Type definition of mlan_scan_time_params */
+typedef struct _mlan_scan_time_params {
+	/** Scan channel time for specific scan in milliseconds */
+	t_u32 specific_scan_time;
+	/** Scan channel time for active scan in milliseconds */
+	t_u32 active_scan_time;
+	/** Scan channel time for passive scan in milliseconds */
+	t_u32 passive_scan_time;
+} mlan_scan_time_params, *pmlan_scan_time_params;
+
+/** Type definition of mlan_user_scan */
+typedef struct _mlan_user_scan {
+	/** Length of scan_cfg_buf */
+	t_u32 scan_cfg_len;
+	/** Buffer of scan config */
+	t_u8 scan_cfg_buf[1];
+} mlan_user_scan, *pmlan_user_scan;
+
+/** Type definition of mlan_scan_req */
+typedef struct _mlan_scan_req {
+	/** BSS mode for scanning */
+	t_u32 scan_mode;
+	/** Scan type */
+	t_u32 scan_type;
+	/** SSID */
+	mlan_802_11_ssid scan_ssid;
+	/** Scan time parameters */
+	mlan_scan_time_params scan_time;
+	/** Scan config parameters in user scan */
+	mlan_user_scan user_scan;
+} mlan_scan_req, *pmlan_scan_req;
+
+/** Type defnition of mlan_scan_resp */
+typedef struct _mlan_scan_resp {
+	/** Number of scan result */
+	t_u32 num_in_scan_table;
+	/** Scan table */
+	t_u8 *pscan_table;
+	/* Age in seconds */
+	t_u32 age_in_secs;
+	/** channel statstics */
+	t_u8 *pchan_stats;
+	/** Number of records in the chan_stats */
+	t_u32 num_in_chan_stats;
+} mlan_scan_resp, *pmlan_scan_resp;
+
+#define EXT_SCAN_TYPE_ENH 2
+/** Type definition of mlan_scan_cfg */
+typedef struct _mlan_scan_cfg {
+	/** Scan type */
+	t_u32 scan_type;
+	/** BSS mode for scanning */
+	t_u32 scan_mode;
+	/** Scan probe */
+	t_u32 scan_probe;
+	/** Scan time parameters */
+	mlan_scan_time_params scan_time;
+	/** First passive scan then active scan */
+	t_u8 passive_to_active_scan;
+	/** Ext_scan:  0 disable, 1: enable, 2: enhance scan*/
+	t_u32 ext_scan;
+	/** scan channel gap */
+	t_u32 scan_chan_gap;
+} mlan_scan_cfg, *pmlan_scan_cfg;
+
+/** Type defnition of mlan_ds_scan for MLAN_IOCTL_SCAN */
+typedef struct _mlan_ds_scan {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Scan request/response */
+	union {
+		/** Scan request */
+		mlan_scan_req scan_req;
+		/** Scan response */
+		mlan_scan_resp scan_resp;
+		/** Scan config parameters in user scan */
+		mlan_user_scan user_scan;
+		/** Scan config parameters */
+		mlan_scan_cfg scan_cfg;
+	} param;
+} mlan_ds_scan, *pmlan_ds_scan;
+
+/*-----------------------------------------------------------------*/
+/** BSS Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for BSS mode */
+enum _mlan_bss_mode {
+	MLAN_BSS_MODE_INFRA = 1,
+	MLAN_BSS_MODE_IBSS,
+	MLAN_BSS_MODE_AUTO
+};
+
+/** Maximum key length */
+#define MLAN_MAX_KEY_LENGTH 32
+
+/** Maximum atim window in milliseconds */
+#define MLAN_MAX_ATIM_WINDOW 50
+
+/** Minimum beacon interval */
+#define MLAN_MIN_BEACON_INTERVAL 20
+/** Maximum beacon interval */
+#define MLAN_MAX_BEACON_INTERVAL 1000
+/** Default beacon interval */
+#define MLAN_BEACON_INTERVAL 100
+
+/** Receive all packets */
+#define MLAN_PROMISC_MODE 1
+/** Receive multicast packets in multicast list */
+#define MLAN_MULTICAST_MODE 2
+/** Receive all multicast packets */
+#define MLAN_ALL_MULTI_MODE 4
+
+/** Maximum size of multicast list */
+#define MLAN_MAX_MULTICAST_LIST_SIZE 32
+
+/** mlan_multicast_list data structure for MLAN_OID_BSS_MULTICAST_LIST */
+typedef struct _mlan_multicast_list {
+	/** Multicast mode */
+	t_u32 mode;
+	/** Number of multicast addresses in the list */
+	t_u32 num_multicast_addr;
+	/** Multicast address list */
+	mlan_802_11_mac_addr mac_list[MLAN_MAX_MULTICAST_LIST_SIZE];
+} mlan_multicast_list, *pmlan_multicast_list;
+
+/** Max channel */
+#define MLAN_MAX_CHANNEL 165
+/** Maximum number of channels in table */
+#define MLAN_MAX_CHANNEL_NUM 128
+
+/** Channel/frequence for MLAN_OID_BSS_CHANNEL */
+typedef struct _chan_freq {
+	/** Channel Number */
+	t_u32 channel;
+	/** Frequency of this Channel */
+	t_u32 freq;
+} chan_freq;
+
+/** mlan_chan_list data structure for MLAN_OID_BSS_CHANNEL_LIST */
+typedef struct _mlan_chan_list {
+	/** Number of channel */
+	t_u32 num_of_chan;
+	/** Channel-Frequency table */
+	chan_freq cf[MLAN_MAX_CHANNEL_NUM];
+} mlan_chan_list;
+
+/* This channel is disabled.*/
+#define CHAN_FLAGS_DISABLED MBIT(0)
+/* do not initiate radiation, this includes sending probe requests or beaconing
+ */
+#define CHAN_FLAGS_NO_IR MBIT(1)
+/* Radar detection is required on this channel */
+#define CHAN_FLAGS_RADAR MBIT(3)
+/* extension channel above this channel is not permitted */
+#define CHAN_FLAGS_NO_HT40PLUS MBIT(4)
+/* extension channel below this channel is not permitted */
+#define CHAN_FLAGS_NO_HT40MINUS MBIT(5)
+/* OFDM is not allowed on this channel */
+#define CHAN_FLAGS_NO_OFDM MBIT(6)
+/** 80Mhz can not used on this channel */
+#define CHAN_FLAGS_NO_80MHZ MBIT(7)
+/** 180Mhz can not used on this channel */
+#define CHAN_FLAGS_NO_160MHZ MBIT(8)
+/* Only indoor use is permitted on this channel */
+#define CHAN_FLAGS_INDOOR_ONLY MBIT(9)
+/* IR operation is allowed on this channel if it's
+ * connected concurrently to a BSS on the same channel on
+ * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz
+ * band), and IEEE80211_CHAN_RADAR is not set */
+#define CHAN_FLAGS_IR_CONCURRENT MBIT(10)
+/* 20 MHz operation is not allowed on this channel */
+#define CHAN_FLAGS_20MHZ MBIT(11)
+/* 10 MHz operation is not allowed on this channel */
+#define CHAN_FLAGS_NO_10MHZ MBIT(12)
+/** This channel's flag is valid */
+#define CHAN_FLAGS_MAX MBIT(31)
+
+/** Maximum response buffer length */
+#define ASSOC_RSP_BUF_SIZE 500
+
+/** Type definition of mlan_ds_misc_assoc_rsp for MLAN_OID_MISC_ASSOC_RSP */
+typedef struct _mlan_ds_misc_assoc_rsp {
+	/** Associate response buffer */
+	t_u8 assoc_resp_buf[ASSOC_RSP_BUF_SIZE];
+	/** Response buffer length */
+	t_u32 assoc_resp_len;
+} mlan_ds_misc_assoc_rsp, *pmlan_ds_misc_assoc_rsp;
+
+/** mlan_ssid_bssid  data structure for
+ *  MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS
+ */
+typedef struct _mlan_ssid_bssid {
+	/** SSID */
+	mlan_802_11_ssid ssid;
+	/** BSSID */
+	mlan_802_11_mac_addr bssid;
+	/** index in BSSID list, start from 1 */
+	t_u32 idx;
+	/** Receive signal strength in dBm */
+	t_s32 rssi;
+	/* previous bssid */
+	mlan_802_11_mac_addr prev_bssid;
+	/**channel*/
+	t_u16 channel;
+	/**mobility domain value*/
+	t_u16 ft_md;
+	/**ft capability*/
+	t_u8 ft_cap;
+	/**band*/
+	t_u16 bss_band;
+	/** channel flag */
+	t_u32 channel_flags;
+	/** host mlme flag*/
+	t_u8 host_mlme;
+	/** assoicate resp frame/ie from firmware */
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+} mlan_ssid_bssid, *pmlan_ssid_bssid;
+
+/** Data structure of WMM ECW */
+typedef struct _wmm_ecw_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+#else
+	/** Minimum Ecw */
+	t_u8 ecw_min:4;
+	/** Maximum Ecw */
+	t_u8 ecw_max:4;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} wmm_ecw_t, *pwmm_ecw_t;
+
+/** Data structure of WMM Aci/Aifsn */
+typedef struct _wmm_aci_aifsn_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** Reserved */
+	t_u8 reserved:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aifsn */
+	t_u8 aifsn:4;
+#else
+	/** Aifsn */
+	t_u8 aifsn:4;
+	/** Acm */
+	t_u8 acm:1;
+	/** Aci */
+	t_u8 aci:2;
+	/** Reserved */
+	t_u8 reserved:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} wmm_aci_aifsn_t, *pwmm_aci_aifsn_t;
+
+/** Data structure of WMM AC parameters  */
+typedef struct _wmm_ac_parameters_t {
+	wmm_aci_aifsn_t aci_aifsn; /**< AciAifSn */
+	wmm_ecw_t ecw; /**< Ecw */
+	t_u16 tx_op_limit; /**< Tx op limit */
+} wmm_ac_parameters_t, *pwmm_ac_parameters_t;
+
+/** mlan_deauth_param */
+typedef struct _mlan_deauth_param {
+	/** STA mac addr */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** deauth reason */
+	t_u16 reason_code;
+} mlan_deauth_param;
+
+#ifdef UAP_SUPPORT
+/** UAP FLAG: Host based */
+#define UAP_FLAG_HOST_BASED MBIT(0)
+/** UAP FLAG: Host mlme */
+#define UAP_FLAG_HOST_MLME MBIT(1)
+
+/** Maximum packet forward control value */
+#define MAX_PKT_FWD_CTRL 15
+/** Maximum BEACON period */
+#define MAX_BEACON_PERIOD 4000
+/** Minimum BEACON period */
+#define MIN_BEACON_PERIOD 50
+/** Maximum DTIM period */
+#define MAX_DTIM_PERIOD 100
+/** Minimum DTIM period */
+#define MIN_DTIM_PERIOD 1
+/** Maximum TX Power Limit */
+#define MAX_TX_POWER 20
+/** Minimum TX Power Limit */
+#define MIN_TX_POWER 0
+/** MAX station count */
+#define MAX_STA_COUNT 64
+/** Maximum RTS threshold */
+#define MAX_RTS_THRESHOLD 2347
+/** Maximum fragmentation threshold */
+#define MAX_FRAG_THRESHOLD 2346
+/** Minimum fragmentation threshold */
+#define MIN_FRAG_THRESHOLD 256
+/** data rate 54 M */
+#define DATA_RATE_54M 108
+/** Maximum value of bcast_ssid_ctl */
+#define MAX_BCAST_SSID_CTL 2
+/** antenna A */
+#define ANTENNA_MODE_A 0
+/** antenna B */
+#define ANTENNA_MODE_B 1
+/** transmit antenna */
+#define TX_ANTENNA 1
+/** receive antenna */
+#define RX_ANTENNA 0
+/** Maximum stage out time */
+#define MAX_STAGE_OUT_TIME 864000
+/** Minimum stage out time */
+#define MIN_STAGE_OUT_TIME 50
+/** Maximum Retry Limit */
+#define MAX_RETRY_LIMIT 14
+
+/** Maximum group key timer in seconds */
+#define MAX_GRP_TIMER 86400
+
+/** Maximum value of 4 byte configuration */
+#define MAX_VALID_DWORD 0x7FFFFFFF	/*  (1 << 31) - 1 */
+
+/** default UAP BAND 2.4G */
+#define DEFAULT_UAP_BAND 0
+/** default UAP channel 6 */
+#define DEFAULT_UAP_CHANNEL 6
+
+/** Maximum data rates */
+#define MAX_DATA_RATES 14
+
+/** auto data rate */
+#define DATA_RATE_AUTO 0
+
+/**filter mode: disable */
+#define MAC_FILTER_MODE_DISABLE 0
+/**filter mode: block mac address */
+#define MAC_FILTER_MODE_ALLOW_MAC 1
+/**filter mode: block mac address */
+#define MAC_FILTER_MODE_BLOCK_MAC 2
+/** Maximum mac filter num */
+#define MAX_MAC_FILTER_NUM 64
+
+/* Bitmap for protocol to use */
+/** No security */
+#define PROTOCOL_NO_SECURITY 0x01
+/** Static WEP */
+#define PROTOCOL_STATIC_WEP 0x02
+/** WPA */
+#define PROTOCOL_WPA 0x08
+/** WPA2 */
+#define PROTOCOL_WPA2 0x20
+/** WP2 Mixed */
+#define PROTOCOL_WPA2_MIXED 0x28
+/** EAP */
+#define PROTOCOL_EAP 0x40
+/** WAPI */
+#define PROTOCOL_WAPI 0x80
+/** WPA3 SAE */
+#define PROTOCOL_WPA3_SAE 0x100
+
+/** Key_mgmt_psk */
+#define KEY_MGMT_NONE 0x04
+/** Key_mgmt_none */
+#define KEY_MGMT_PSK 0x02
+/** Key_mgmt_eap  */
+#define KEY_MGMT_EAP 0x01
+/** Key_mgmt_psk_sha256 */
+#define KEY_MGMT_PSK_SHA256 0x100
+/** Key_mgmt_sae */
+#define KEY_MGMT_SAE 0x400
+/** Key_mgmt_owe */
+#define KEY_MGMT_OWE 0x200
+
+/** TKIP */
+#define CIPHER_TKIP 0x04
+/** AES CCMP */
+#define CIPHER_AES_CCMP 0x08
+
+/** Valid cipher bitmap */
+#define VALID_CIPHER_BITMAP 0x0c
+
+/** Packet forwarding to be done by FW or host */
+#define PKT_FWD_FW_BIT 0x01
+/** Intra-BSS broadcast packet forwarding allow bit */
+#define PKT_FWD_INTRA_BCAST 0x02
+/** Intra-BSS unicast packet forwarding allow bit */
+#define PKT_FWD_INTRA_UCAST 0x04
+/** Inter-BSS unicast packet forwarding allow bit */
+#define PKT_FWD_INTER_UCAST 0x08
+/** Intra-BSS unicast packet */
+#define PKT_INTRA_UCAST 0x01
+/** Inter-BSS unicast packet */
+#define PKT_INTER_UCAST 0x02
+/** Enable Host PKT forwarding */
+#define PKT_FWD_ENABLE_BIT 0x01
+
+/** Channel List Entry */
+typedef struct _channel_list {
+	/** Channel Number */
+	t_u8 chan_number;
+	/** Band Config */
+	Band_Config_t bandcfg;
+} scan_chan_list;
+
+/** mac_filter data structure */
+typedef struct _mac_filter {
+	/** mac filter mode */
+	t_u16 filter_mode;
+	/** mac adress count */
+	t_u16 mac_count;
+	/** mac address list */
+	mlan_802_11_mac_addr mac_list[MAX_MAC_FILTER_NUM];
+} mac_filter;
+
+/** wpa parameter */
+typedef struct _wpa_param {
+	/** Pairwise cipher WPA */
+	t_u8 pairwise_cipher_wpa;
+	/** Pairwise cipher WPA2 */
+	t_u8 pairwise_cipher_wpa2;
+	/** group cipher */
+	t_u8 group_cipher;
+	/** RSN replay protection */
+	t_u8 rsn_protection;
+	/** passphrase length */
+	t_u32 length;
+	/** passphrase */
+	t_u8 passphrase[64];
+	/**group key rekey time in seconds */
+	t_u32 gk_rekey_time;
+} wpa_param;
+
+/** wep key */
+typedef struct _wep_key {
+	/** key index 0-3 */
+	t_u8 key_index;
+	/** is default */
+	t_u8 is_default;
+	/** length */
+	t_u16 length;
+	/** key data */
+	t_u8 key[26];
+} wep_key;
+
+/** wep param */
+typedef struct _wep_param {
+	/** key 0 */
+	wep_key key0;
+	/** key 1 */
+	wep_key key1;
+	/** key 2 */
+	wep_key key2;
+	/** key 3 */
+	wep_key key3;
+} wep_param;
+
+/** Data structure of WMM QoS information */
+typedef struct _wmm_qos_info_t {
+#ifdef BIG_ENDIAN_SUPPORT
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+#else
+	/** Parameter set count */
+	t_u8 para_set_count:4;
+	/** Reserved */
+	t_u8 reserved:3;
+	/** QoS UAPSD */
+	t_u8 qos_uapsd:1;
+#endif				/* BIG_ENDIAN_SUPPORT */
+} wmm_qos_info_t, *pwmm_qos_info_t;
+
+/** Data structure of WMM parameter IE  */
+typedef struct _wmm_parameter_t {
+	/** OuiType:  00:50:f2:02 */
+	t_u8 ouitype[4];
+	/** Oui subtype: 01 */
+	t_u8 ouisubtype;
+	/** version: 01 */
+	t_u8 version;
+	/** QoS information */
+	t_u8 qos_info;
+	/** Reserved */
+	t_u8 reserved;
+	/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */
+	wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+} wmm_parameter_t, *pwmm_parameter_t;
+
+/** MAX BG channel */
+#define MAX_BG_CHANNEL 14
+/** mlan_bss_param
+ * Note: For each entry you must enter an invalid value
+ * in the MOAL function woal_set_sys_config_invalid_data().
+ * Otherwise for a valid data an unwanted TLV will be
+ * added to that command.
+ */
+typedef struct _mlan_uap_bss_param {
+	/** AP mac addr */
+	mlan_802_11_mac_addr mac_addr;
+	/** SSID */
+	mlan_802_11_ssid ssid;
+	/** Broadcast ssid control */
+	t_u8 bcast_ssid_ctl;
+	/** Radio control: on/off */
+	t_u8 radio_ctl;
+	/** dtim period */
+	t_u8 dtim_period;
+	/** beacon period */
+	t_u16 beacon_period;
+	/** rates */
+	t_u8 rates[MAX_DATA_RATES];
+	/** Tx data rate */
+	t_u16 tx_data_rate;
+	/** Tx beacon rate */
+	t_u16 tx_beacon_rate;
+	/** multicast/broadcast data rate */
+	t_u16 mcbc_data_rate;
+	/** Tx power level in dBm */
+	t_u8 tx_power_level;
+	/** Tx antenna */
+	t_u8 tx_antenna;
+	/** Rx antenna */
+	t_u8 rx_antenna;
+	/** packet forward control */
+	t_u8 pkt_forward_ctl;
+	/** max station count */
+	t_u16 max_sta_count;
+	/** mac filter */
+	mac_filter filter;
+	/** station ageout timer in unit of 100ms  */
+	t_u32 sta_ageout_timer;
+	/** PS station ageout timer in unit of 100ms  */
+	t_u32 ps_sta_ageout_timer;
+	/** RTS threshold */
+	t_u16 rts_threshold;
+	/** fragmentation threshold */
+	t_u16 frag_threshold;
+	/**  retry_limit */
+	t_u16 retry_limit;
+	/**  pairwise update timeout in milliseconds */
+	t_u32 pairwise_update_timeout;
+	/** pairwise handshake retries */
+	t_u32 pwk_retries;
+	/**  groupwise update timeout in milliseconds */
+	t_u32 groupwise_update_timeout;
+	/** groupwise handshake retries */
+	t_u32 gwk_retries;
+	/** preamble type */
+	t_u8 preamble_type;
+	/** band cfg */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** auth mode */
+	t_u16 auth_mode;
+	/** encryption protocol */
+	t_u16 protocol;
+	/** key managment type */
+	t_u16 key_mgmt;
+	/** wep param */
+	wep_param wep_cfg;
+	/** wpa param */
+	wpa_param wpa_cfg;
+	/** Mgmt IE passthru mask */
+	t_u32 mgmt_ie_passthru_mask;
+	/*
+	 * 11n HT Cap  HTCap_t  ht_cap
+	 */
+	/** HT Capabilities Info field */
+	t_u16 ht_cap_info;
+	/** A-MPDU Parameters field */
+	t_u8 ampdu_param;
+	/** Supported MCS Set field */
+	t_u8 supported_mcs_set[16];
+	/** HT Extended Capabilities field */
+	t_u16 ht_ext_cap;
+	/** Transmit Beamforming Capabilities field */
+	t_u32 tx_bf_cap;
+	/** Antenna Selection Capability field */
+	t_u8 asel;
+	/** Enable 2040 Coex */
+	t_u8 enable_2040coex;
+	/** key management operation */
+	t_u16 key_mgmt_operation;
+	/** BSS status */
+	t_u16 bss_status;
+#ifdef WIFI_DIRECT_SUPPORT
+	/* pre shared key */
+	t_u8 psk[MLAN_MAX_KEY_LENGTH];
+#endif				/* WIFI_DIRECT_SUPPORT */
+	/** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+	/** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+	/** Wmm parameters */
+	wmm_parameter_t wmm_para;
+
+	/** uap host based config */
+	t_u32 uap_host_based_config;
+} mlan_uap_bss_param, *pmlan_uap_bss_param;
+
+/** mlan_uap_scan_channels */
+typedef struct _mlan_uap_scan_channels {
+	/** flag for remove nop channel*/
+	t_u8 remove_nop_channel;
+	/** num of removed channel */
+	t_u8 num_remvoed_channel;
+	/** Number of channels in scan_channel_list */
+	t_u32 num_of_chan;
+	/** scan channel list in ACS mode */
+	scan_chan_list chan_list[MLAN_MAX_CHANNEL];
+} mlan_uap_scan_channels;
+
+/** mlan_chan_switch_param */
+typedef struct _mlan_action_chan_switch {
+	/** mode*/
+	t_u8 mode;
+	/** switch mode*/
+	t_u8 chan_switch_mode;
+	/** oper class*/
+	t_u8 new_oper_class;
+    /** new channel */
+	t_u8 new_channel_num;
+    /** chan_switch_count */
+	t_u8 chan_switch_count;
+} mlan_action_chan_switch;
+
+/** mlan_uap_oper_ctrl */
+typedef struct _mlan_uap_oper_ctrl {
+	/** control value
+	 *  0: do nothing,
+	 *  2: uap stops and restarts automaticaly
+	 */
+	t_u16 ctrl_value;
+	/** channel opt
+	 *  1: uap restart on default 2.4G/channel 6
+	 *  2: uap restart on the band/channel configured by driver previously
+	 *  3: uap restart on the band/channel specified by band_cfg and channel
+	 */
+	t_u16 chan_opt;
+	/** band cfg   0
+	 *  0: 20Mhz  2: 40 Mhz  3: 80Mhz
+	 */
+	t_u8 band_cfg;
+	/** channel */
+	t_u8 channel;
+} mlan_uap_oper_ctrl;
+
+/** mlan_uap_acs_scan */
+typedef struct _mlan_uap_acs_scan {
+	/** band */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 chan;
+} mlan_uap_acs_scan;
+
+/** station is authorized (802.1X) */
+#define STA_FLAG_AUTHORIZED MBIT(1)
+/** Station is capable of receiving frames with short barker preamble */
+#define STA_FLAG_SHORT_PREAMBLE MBIT(2)
+/** station is WME/QoS capable */
+#define STA_FLAG_WME MBIT(3)
+/** station uses management frame protection */
+#define STA_FLAG_MFP MBIT(4)
+/** station is authenticated */
+#define STA_FLAG_AUTHENTICATED MBIT(5)
+/** station is a TDLS peer */
+#define STA_FLAG_TDLS_PEER MBIT(6)
+/** station is associated */
+#define STA_FLAG_ASSOCIATED MBIT(7)
+/** mlan_ds_sta_info */
+typedef struct _mlan_ds_sta_info {
+	/** aid */
+	t_u16 aid;
+	/** peer_mac */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Listen Interval */
+	int listen_interval;
+	/** Capability Info */
+	t_u16 cap_info;
+	/** station flag */
+	t_u32 sta_flags;
+	/** tlv len */
+	t_u16 tlv_len;
+	/** tlv start */
+	t_u8 tlv[];
+} mlan_ds_sta_info;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** mode: disable wifi direct */
+#define WIFI_DIRECT_MODE_DISABLE 0
+/** mode: listen */
+#define WIFI_DIRECT_MODE_LISTEN 1
+/** mode: GO */
+#define WIFI_DIRECT_MODE_GO 2
+/** mode: client */
+#define WIFI_DIRECT_MODE_CLIENT 3
+/** mode: find */
+#define WIFI_DIRECT_MODE_FIND 4
+/** mode: stop find */
+#define WIFI_DIRECT_MODE_STOP_FIND 5
+#endif
+
+/** Type definition of mlan_ds_bss for MLAN_IOCTL_BSS */
+typedef struct _mlan_ds_bss {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** BSS parameter */
+	union {
+		/** SSID-BSSID for MLAN_OID_BSS_START */
+		mlan_ssid_bssid ssid_bssid;
+		/** BSSID for MLAN_OID_BSS_STOP */
+		mlan_802_11_mac_addr bssid;
+		/** BSS mode for MLAN_OID_BSS_MODE */
+		t_u32 bss_mode;
+		/** BSS channel/frequency for MLAN_OID_BSS_CHANNEL */
+		chan_freq bss_chan;
+		/** BSS channel list for MLAN_OID_BSS_CHANNEL_LIST */
+		mlan_chan_list chanlist;
+		/** MAC address for MLAN_OID_BSS_MAC_ADDR */
+		mlan_802_11_mac_addr mac_addr;
+		/** Multicast list for MLAN_OID_BSS_MULTICAST_LIST */
+		mlan_multicast_list multicast_list;
+		/** Beacon interval for MLAN_OID_IBSS_BCN_INTERVAL */
+		t_u32 bcn_interval;
+		/** ATIM window for MLAN_OID_IBSS_ATIM_WINDOW */
+		t_u32 atim_window;
+		/** deauth param for MLAN_OID_BSS_STOP & MLAN_OID_UAP_DEAUTH_STA
+		 */
+		mlan_deauth_param deauth_param;
+#ifdef UAP_SUPPORT
+		/** host based flag for MLAN_OID_BSS_START */
+		t_u8 host_based;
+		/** BSS param for AP mode for MLAN_OID_UAP_BSS_CONFIG */
+		mlan_uap_bss_param bss_config;
+		/** AP Wmm parameters for MLAN_OID_UAP_CFG_WMM_PARAM */
+		wmm_parameter_t ap_wmm_para;
+		/** ap scan channels for MLAN_OID_UAP_SCAN_CHANNELS*/
+		mlan_uap_scan_channels ap_scan_channels;
+	/** channel switch for MLAN_OID_UAP_CHAN_SWITCH */
+		mlan_action_chan_switch chanswitch;
+		/** ap channel for MLAN_OID_UAP_CHANNEL*/
+		chan_band_info ap_channel;
+		/** ap operation control for MLAN_OID_UAP_OPER_CTRL*/
+		mlan_uap_oper_ctrl ap_oper_ctrl;
+		/** AP acs scan 	    MLAN_OID_UAP_ACS_SCAN */
+		mlan_uap_acs_scan ap_acs_scan;
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		/** BSS role for MLAN_OID_BSS_ROLE */
+		t_u8 bss_role;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		/** wifi direct mode for MLAN_OID_WIFI_DIRECT_MODE */
+		t_u16 wfd_mode;
+#endif
+#ifdef STA_SUPPORT
+		/** Listen interval for MLAN_OID_BSS_LISTEN_INTERVAL */
+		t_u16 listen_interval;
+		/** STA channel info for MLAN_OID_BSS_CHAN_INFO */
+		chan_band_info sta_channel;
+#endif
+#ifdef UAP_SUPPORT
+		/** STA info for MLAN_OID_UAP_ADD_STATION */
+		mlan_ds_sta_info sta_info;
+#endif
+	} param;
+} mlan_ds_bss, *pmlan_ds_bss;
+
+/* OTP Region info */
+typedef MLAN_PACK_START struct _otp_region_info {
+	t_u8 country_code[2];
+	t_u8 region_code;
+	t_u8 environment;
+	t_u8 force_reg:1;
+	t_u8 reserved:7;
+	t_u8 dfs_region;
+} MLAN_PACK_END otp_region_info_t;
+
+/** Type definition of mlan_ds_custom_reg_domain */
+typedef struct _mlan_ds_custom_reg_domain {
+	otp_region_info_t region;
+	/** num of 2g channels in custom_reg_domain */
+	t_u8 num_bg_chan;
+	/** num of 5g channels in custom_reg_domain */
+	t_u8 num_a_chan;
+	/** cfp table */
+	chan_freq_power_t cfp_tbl[];
+} mlan_ds_custom_reg_domain;
+/*-----------------------------------------------------------------*/
+/** Radio Control Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for band */
+enum _mlan_band_def {
+	BAND_B = 1,
+	BAND_G = 2,
+	BAND_A = 4,
+	BAND_GN = 8,
+	BAND_AN = 16,
+	BAND_GAC = 32,
+	BAND_AAC = 64,
+	BAND_GAX = 256,
+	BAND_AAX = 512,
+
+};
+
+/** Channel bandwidth */
+#define CHANNEL_BW_20MHZ 0
+#define CHANNEL_BW_40MHZ_ABOVE 1
+#define CHANNEL_BW_40MHZ_BELOW 3
+/** secondary channel is 80Mhz bandwidth for 11ac */
+#define CHANNEL_BW_80MHZ 4
+#define CHANNEL_BW_160MHZ 5
+
+/** RF antenna selection */
+#define RF_ANTENNA_MASK(n) ((1 << (n)) - 1)
+/** RF antenna auto select */
+#define RF_ANTENNA_AUTO 0xFFFF
+
+/** Type definition of mlan_ds_band_cfg for MLAN_OID_BAND_CFG */
+typedef struct _mlan_ds_band_cfg {
+	/** Infra band */
+	t_u32 config_bands;
+	/** Ad-hoc start band */
+	t_u32 adhoc_start_band;
+	/** Ad-hoc start channel */
+	t_u32 adhoc_channel;
+	/** fw supported band */
+	t_u32 fw_bands;
+} mlan_ds_band_cfg;
+
+/** Type definition of mlan_ds_ant_cfg for MLAN_OID_ANT_CFG */
+typedef struct _mlan_ds_ant_cfg {
+	/** Tx antenna mode */
+	t_u32 tx_antenna;
+	/** Rx antenna mode */
+	t_u32 rx_antenna;
+} mlan_ds_ant_cfg, *pmlan_ds_ant_cfg;
+/** Type definition of mlan_ds_mimo_switch for MLAN_OID_MIMO_SWITCH */
+typedef struct _mlan_ds_mimo_switch {
+	/** Tx antenna mode */
+	t_u8 txpath_antmode;
+	/** Rx antenna mode */
+	t_u8 rxpath_antmode;
+} mlan_ds_mimo_switch, *pmlan_ds_mimo_switch;
+/** Type definition of mlan_ds_ant_cfg_1x1 for MLAN_OID_ANT_CFG */
+typedef struct _mlan_ds_ant_cfg_1x1 {
+	/** Antenna mode */
+	t_u32 antenna;
+	/** Evaluate time */
+	t_u16 evaluate_time;
+	/** Current antenna */
+	t_u16 current_antenna;
+} mlan_ds_ant_cfg_1x1, *pmlan_ds_ant_cfg_1x1;
+
+/** Type definition of mlan_ds_remain_chan for MLAN_OID_REMAIN_CHAN_CFG */
+typedef struct _mlan_ds_remain_chan {
+	/** remove flag */
+	t_u16 remove;
+	/** status */
+	t_u8 status;
+	/** Band cfg */
+	Band_Config_t bandcfg;
+	/** channel */
+	t_u8 channel;
+	/** remain time: Unit ms*/
+	t_u32 remain_period;
+} mlan_ds_remain_chan, *pmlan_ds_remain_chan;
+
+/** Type definition of mlan_ds_radio_cfg for MLAN_IOCTL_RADIO_CFG */
+typedef struct _mlan_ds_radio_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Radio control parameter */
+	union {
+		/** Radio on/off for MLAN_OID_RADIO_CTRL */
+		t_u32 radio_on_off;
+		/** Band info for MLAN_OID_BAND_CFG */
+		mlan_ds_band_cfg band_cfg;
+		/** Antenna info for MLAN_OID_ANT_CFG */
+		mlan_ds_ant_cfg ant_cfg;
+		/** Antenna mode for MLAN_OID_MIMO_SWITCH */
+		mlan_ds_mimo_switch mimo_switch_cfg;
+		/** Antenna info for MLAN_OID_ANT_CFG */
+		mlan_ds_ant_cfg_1x1 ant_cfg_1x1;
+		/** remain on channel for MLAN_OID_REMAIN_CHAN_CFG */
+		mlan_ds_remain_chan remain_chan;
+	} param;
+} mlan_ds_radio_cfg, *pmlan_ds_radio_cfg;
+
+enum COALESCE_OPERATION {
+	RECV_FILTER_MATCH_TYPE_EQ = 0x80,
+	RECV_FILTER_MATCH_TYPE_NE,
+};
+
+enum COALESCE_PACKET_TYPE {
+	PACKET_TYPE_UNICAST = 1,
+	PACKET_TYPE_MULTICAST = 2,
+	PACKET_TYPE_BROADCAST = 3
+};
+
+#define COALESCE_MAX_RULES 8
+#define COALESCE_MAX_BYTESEQ 4	/* non-adjustable */
+#define COALESCE_MAX_FILTERS 4
+#define MAX_COALESCING_DELAY 100	/* in msecs */
+#define MAX_PATTERN_LEN 20
+#define MAX_OFFSET_LEN 100
+
+struct filt_field_param {
+	t_u8 operation;
+	t_u8 operand_len;
+	t_u16 offset;
+	t_u8 operand_byte_stream[COALESCE_MAX_BYTESEQ];
+};
+
+struct coalesce_rule {
+	t_u16 max_coalescing_delay;
+	t_u8 num_of_fields;
+	t_u8 pkt_type;
+	struct filt_field_param params[COALESCE_MAX_FILTERS];
+};
+
+typedef struct _mlan_ds_coalesce_cfg {
+	t_u16 num_of_rules;
+	struct coalesce_rule rule[COALESCE_MAX_RULES];
+} mlan_ds_coalesce_cfg;
+
+/*-----------------------------------------------------------------*/
+/** SNMP MIB Group */
+/*-----------------------------------------------------------------*/
+/** Type definition of mlan_ds_snmp_mib for MLAN_IOCTL_SNMP_MIB */
+typedef struct _mlan_ds_snmp_mib {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** SNMP MIB parameter */
+	union {
+		/** RTS threshold for MLAN_OID_SNMP_MIB_RTS_THRESHOLD */
+		t_u32 rts_threshold;
+		/** Fragment threshold for MLAN_OID_SNMP_MIB_FRAG_THRESHOLD */
+		t_u32 frag_threshold;
+		/** Retry count for MLAN_OID_SNMP_MIB_RETRY_COUNT */
+		t_u32 retry_count;
+		/** OID value for MLAN_OID_SNMP_MIB_DOT11D/H */
+		t_u32 oid_value;
+		/** DTIM period for MLAN_OID_SNMP_MIB_DTIM_PERIOD */
+		t_u32 dtim_period;
+		/** Singal_ext Enable for MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE */
+		t_u8 signalext_enable;
+		/** Control deauth when uap switch channel */
+		t_u8 deauthctrl;
+	} param;
+} mlan_ds_snmp_mib, *pmlan_ds_snmp_mib;
+
+/*-----------------------------------------------------------------*/
+/** Status Information Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for ad-hoc status */
+enum _mlan_adhoc_status {
+	ADHOC_IDLE,
+	ADHOC_STARTED,
+	ADHOC_JOINED,
+	ADHOC_COALESCED,
+	ADHOC_STARTING
+};
+
+typedef struct _mlan_ds_get_stats_org {
+	/** Statistics counter */
+	/** Multicast transmitted frame count */
+	t_u32 mcast_tx_frame;
+	/** Failure count */
+	t_u32 failed;
+	/** Retry count */
+	t_u32 retry;
+	/** Multi entry count */
+	t_u32 multi_retry;
+	/** Duplicate frame count */
+	t_u32 frame_dup;
+	/** RTS success count */
+	t_u32 rts_success;
+	/** RTS failure count */
+	t_u32 rts_failure;
+	/** Ack failure count */
+	t_u32 ack_failure;
+	/** Rx fragmentation count */
+	t_u32 rx_frag;
+	/** Multicast Tx frame count */
+	t_u32 mcast_rx_frame;
+	/** FCS error count */
+	t_u32 fcs_error;
+	/** Tx frame count */
+	t_u32 tx_frame;
+	/** WEP ICV error count */
+	t_u32 wep_icv_error[4];
+	/** beacon recv count */
+	t_u32 bcn_rcv_cnt;
+	/** beacon miss count */
+	t_u32 bcn_miss_cnt;
+	/** received amsdu count*/
+	t_u32 amsdu_rx_cnt;
+	/** received msdu count in amsdu*/
+	t_u32 msdu_in_rx_amsdu_cnt;
+	/** tx amsdu count*/
+	t_u32 amsdu_tx_cnt;
+	/** tx msdu count in amsdu*/
+	t_u32 msdu_in_tx_amsdu_cnt;
+} mlan_ds_get_stats_org;
+
+/** Type definition of mlan_ds_get_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_get_stats {
+	/** Statistics counter */
+	/** Multicast transmitted frame count */
+	t_u32 mcast_tx_frame;
+	/** Failure count */
+	t_u32 failed;
+	/** Retry count */
+	t_u32 retry;
+	/** Multi entry count */
+	t_u32 multi_retry;
+	/** Duplicate frame count */
+	t_u32 frame_dup;
+	/** RTS success count */
+	t_u32 rts_success;
+	/** RTS failure count */
+	t_u32 rts_failure;
+	/** Ack failure count */
+	t_u32 ack_failure;
+	/** Rx fragmentation count */
+	t_u32 rx_frag;
+	/** Multicast Tx frame count */
+	t_u32 mcast_rx_frame;
+	/** FCS error count */
+	t_u32 fcs_error;
+	/** Tx frame count */
+	t_u32 tx_frame;
+	/** WEP ICV error count */
+	t_u32 wep_icv_error[4];
+	/** beacon recv count */
+	t_u32 bcn_rcv_cnt;
+	/** beacon miss count */
+	t_u32 bcn_miss_cnt;
+	/** received amsdu count*/
+	t_u32 amsdu_rx_cnt;
+	/** received msdu count in amsdu*/
+	t_u32 msdu_in_rx_amsdu_cnt;
+	/** tx amsdu count*/
+	t_u32 amsdu_tx_cnt;
+	/** tx msdu count in amsdu*/
+	t_u32 msdu_in_tx_amsdu_cnt;
+
+	/** Tx frag count */
+	t_u32 tx_frag_cnt;
+	/** Qos Tx frag count */
+	t_u32 qos_tx_frag_cnt[8];
+	/** Qos failed count */
+	t_u32 qos_failed_cnt[8];
+	/** Qos retry count */
+	t_u32 qos_retry_cnt[8];
+	/** Qos multi retry count */
+	t_u32 qos_multi_retry_cnt[8];
+	/** Qos frame dup count */
+	t_u32 qos_frm_dup_cnt[8];
+	/** Qos rts success count */
+	t_u32 qos_rts_suc_cnt[8];
+	/** Qos rts failure count */
+	t_u32 qos_rts_failure_cnt[8];
+	/** Qos ack failure count */
+	t_u32 qos_ack_failure_cnt[8];
+	/** Qos Rx frag count */
+	t_u32 qos_rx_frag_cnt[8];
+	/** Qos Tx frame count */
+	t_u32 qos_tx_frm_cnt[8];
+	/** Qos discarded frame count */
+	t_u32 qos_discarded_frm_cnt[8];
+	/** Qos mpdus Rx count */
+	t_u32 qos_mpdus_rx_cnt[8];
+	/** Qos retry rx count */
+	t_u32 qos_retries_rx_cnt[8];
+	/** CMAC ICV errors count */
+	t_u32 cmacicv_errors;
+	/** CMAC replays count */
+	t_u32 cmac_replays;
+	/** mgmt CCMP replays count */
+	t_u32 mgmt_ccmp_replays;
+	/** TKIP ICV errors count */
+	t_u32 tkipicv_errors;
+	/** TKIP replays count */
+	t_u32 tkip_replays;
+	/** CCMP decrypt errors count */
+	t_u32 ccmp_decrypt_errors;
+	/** CCMP replays count */
+	t_u32 ccmp_replays;
+	/** Tx amsdu count */
+	t_u32 tx_amsdu_cnt;
+	/** failed amsdu count */
+	t_u32 failed_amsdu_cnt;
+	/** retry amsdu count */
+	t_u32 retry_amsdu_cnt;
+	/** multi-retry amsdu count */
+	t_u32 multi_retry_amsdu_cnt;
+	/** Tx octets in amsdu count */
+	t_u64 tx_octets_in_amsdu_cnt;
+	/** amsdu ack failure count */
+	t_u32 amsdu_ack_failure_cnt;
+	/** Rx amsdu count */
+	t_u32 rx_amsdu_cnt;
+	/** Rx octets in amsdu count */
+	t_u64 rx_octets_in_amsdu_cnt;
+	/** Tx ampdu count */
+	t_u32 tx_ampdu_cnt;
+	/** tx mpdus in ampdu count */
+	t_u32 tx_mpdus_in_ampdu_cnt;
+	/** tx octets in ampdu count */
+	t_u64 tx_octets_in_ampdu_cnt;
+	/** ampdu Rx count */
+	t_u32 ampdu_rx_cnt;
+	/** mpdu in Rx ampdu count */
+	t_u32 mpdu_in_rx_ampdu_cnt;
+	/** Rx octets ampdu count */
+	t_u64 rx_octets_in_ampdu_cnt;
+	/** ampdu delimiter CRC error count */
+	t_u32 ampdu_delimiter_crc_error_cnt;
+    /** Rx Stuck Related Info*/
+    /** Rx Stuck Issue count */
+	t_u32 rx_stuck_issue_cnt[2];
+    /** Rx Stuck Recovery count */
+	t_u32 rx_stuck_recovery_cnt;
+    /** Rx Stuck TSF */
+	t_u64 rx_stuck_tsf[2];
+    /** Tx Watchdog Recovery Related Info */
+    /** Tx Watchdog Recovery count */
+	t_u32 tx_watchdog_recovery_cnt;
+    /** Tx Watchdog TSF */
+	t_u64 tx_watchdog_tsf[2];
+    /** Channel Switch Related Info */
+    /** Channel Switch Announcement Sent */
+	t_u32 channel_switch_ann_sent;
+    /** Channel Switch State */
+	t_u32 channel_switch_state;
+    /** Register Class */
+	t_u32 reg_class;
+    /** Channel Number */
+	t_u32 channel_number;
+    /** Channel Switch Mode */
+	t_u32 channel_switch_mode;
+    /** Reset Rx Mac Count */
+	t_u32 rx_reset_mac_recovery_cnt;
+    /** ISR2 Not Done Count*/
+	t_u32 rx_Isr2_NotDone_Cnt;
+    /** GDMA Abort Count */
+	t_u32 gdma_abort_cnt;
+    /** Rx Reset MAC Count */
+	t_u32 g_reset_rx_mac_cnt;
+	//Ownership error counters
+	/*Error Ownership error count */
+	t_u32 dwCtlErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwBcnErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwMgtErrCnt;
+	/*Control Ownership error count */
+	t_u32 dwDatErrCnt;
+	/*BIGTK MME good count */
+	t_u32 bigtk_mmeGoodCnt;
+	/*BIGTK Replay error count */
+	t_u32 bigtk_replayErrCnt;
+	/*BIGTK MIC error count */
+	t_u32 bigtk_micErrCnt;
+	/*BIGTK MME not included count */
+	t_u32 bigtk_mmeNotFoundCnt;
+} mlan_ds_get_stats, *pmlan_ds_get_stats;
+
+/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */
+typedef struct _mlan_ds_uap_stats {
+	/** tkip mic failures */
+	t_u32 tkip_mic_failures;
+	/** ccmp decrypt errors */
+	t_u32 ccmp_decrypt_errors;
+	/** wep undecryptable count */
+	t_u32 wep_undecryptable_count;
+	/** wep icv error count */
+	t_u32 wep_icv_error_count;
+	/** decrypt failure count */
+	t_u32 decrypt_failure_count;
+	/** dot11 multicast tx count */
+	t_u32 mcast_tx_count;
+	/** dot11 failed count */
+	t_u32 failed_count;
+	/** dot11 retry count */
+	t_u32 retry_count;
+	/** dot11 multi retry count */
+	t_u32 multi_retry_count;
+	/** dot11 frame duplicate count */
+	t_u32 frame_dup_count;
+	/** dot11 rts success count */
+	t_u32 rts_success_count;
+	/** dot11 rts failure count */
+	t_u32 rts_failure_count;
+	/** dot11 ack failure count */
+	t_u32 ack_failure_count;
+	/** dot11 rx ragment count */
+	t_u32 rx_fragment_count;
+	/** dot11 mcast rx frame count */
+	t_u32 mcast_rx_frame_count;
+	/** dot11 fcs error count */
+	t_u32 fcs_error_count;
+	/** dot11 tx frame count */
+	t_u32 tx_frame_count;
+	/** dot11 rsna tkip cm invoked */
+	t_u32 rsna_tkip_cm_invoked;
+	/** dot11 rsna 4way handshake failures */
+	t_u32 rsna_4way_hshk_failures;
+} mlan_ds_uap_stats, *pmlan_ds_uap_stats;
+
+/** Mask of last beacon RSSI */
+#define BCN_RSSI_LAST_MASK 0x00000001
+/** Mask of average beacon RSSI */
+#define BCN_RSSI_AVG_MASK 0x00000002
+/** Mask of last data RSSI */
+#define DATA_RSSI_LAST_MASK 0x00000004
+/** Mask of average data RSSI */
+#define DATA_RSSI_AVG_MASK 0x00000008
+/** Mask of last beacon SNR */
+#define BCN_SNR_LAST_MASK 0x00000010
+/** Mask of average beacon SNR */
+#define BCN_SNR_AVG_MASK 0x00000020
+/** Mask of last data SNR */
+#define DATA_SNR_LAST_MASK 0x00000040
+/** Mask of average data SNR */
+#define DATA_SNR_AVG_MASK 0x00000080
+/** Mask of last beacon NF */
+#define BCN_NF_LAST_MASK 0x00000100
+/** Mask of average beacon NF */
+#define BCN_NF_AVG_MASK 0x00000200
+/** Mask of last data NF */
+#define DATA_NF_LAST_MASK 0x00000400
+/** Mask of average data NF */
+#define DATA_NF_AVG_MASK 0x00000800
+/** Mask of all RSSI_INFO */
+#define ALL_RSSI_INFO_MASK 0x00000fff
+#define MAX_PATH_NUM 3
+/** path A */
+#define PATH_A 0x01
+/** path B */
+#define PATH_B 0x02
+/** path AB */
+#define PATH_AB 0x03
+/** ALL the path */
+#define PATH_ALL 0
+/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */
+typedef struct _mlan_ds_get_signal {
+	/** Selector of get operation */
+	/*
+	 * Bit0:  Last Beacon RSSI,  Bit1:  Average Beacon RSSI,
+	 * Bit2:  Last Data RSSI,    Bit3:  Average Data RSSI,
+	 * Bit4:  Last Beacon SNR,   Bit5:  Average Beacon SNR,
+	 * Bit6:  Last Data SNR,     Bit7:  Average Data SNR,
+	 * Bit8:  Last Beacon NF,    Bit9:  Average Beacon NF,
+	 * Bit10: Last Data NF,      Bit11: Average Data NF
+	 *
+	 * Bit0: PATH A
+	 * Bit1: PATH B
+	 */
+	t_u16 selector;
+
+	/** RSSI */
+	/** RSSI of last beacon */
+	t_s16 bcn_rssi_last;
+	/** RSSI of beacon average */
+	t_s16 bcn_rssi_avg;
+	/** RSSI of last data packet */
+	t_s16 data_rssi_last;
+	/** RSSI of data packet average */
+	t_s16 data_rssi_avg;
+
+	/** SNR */
+	/** SNR of last beacon */
+	t_s16 bcn_snr_last;
+	/** SNR of beacon average */
+	t_s16 bcn_snr_avg;
+	/** SNR of last data packet */
+	t_s16 data_snr_last;
+	/** SNR of data packet average */
+	t_s16 data_snr_avg;
+
+	/** NF */
+	/** NF of last beacon */
+	t_s16 bcn_nf_last;
+	/** NF of beacon average */
+	t_s16 bcn_nf_avg;
+	/** NF of last data packet */
+	t_s16 data_nf_last;
+	/** NF of data packet average */
+	t_s16 data_nf_avg;
+} mlan_ds_get_signal, *pmlan_ds_get_signal;
+
+/** bit for 2.4 G antenna diversity */
+#define ANT_DIVERSITY_2G MBIT(3)
+/** bit for 5 G antenna diversity */
+#define ANT_DIVERSITY_5G MBIT(7)
+
+/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */
+typedef struct _mlan_fw_info {
+	/** Firmware version */
+	t_u32 fw_ver;
+	/** Firmware Hotfix version */
+	t_u8 hotfix_version;
+	/** MAC address */
+	mlan_802_11_mac_addr mac_addr;
+	/** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+	/** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+	/** user's MCS setting */
+	t_u8 usr_dev_mcs_support;
+	/** 802.11ac device capabilities */
+	t_u32 hw_dot_11ac_dev_cap;
+	/** 802.11ac device Capabilities for 2.4GHz */
+	t_u32 usr_dot_11ac_dev_cap_bg;
+	/** 802.11ac device Capabilities for 5GHz */
+	t_u32 usr_dot_11ac_dev_cap_a;
+	/** length of hw he capability */
+	t_u8 hw_hecap_len;
+	/** 802.11ax HE capability */
+	t_u8 hw_he_cap[54];
+	/** length of hw 2.4G he capability */
+	t_u8 hw_2g_hecap_len;
+	/** 802.11ax 2.4G HE capability */
+	t_u8 hw_2g_he_cap[54];
+	/** 802.11ac device support for MIMO abstraction of MCSs */
+	t_u32 hw_dot_11ac_mcs_support;
+	/** User conf 802.11ac device support for MIMO abstraction of MCSs */
+	t_u32 usr_dot_11ac_mcs_support;
+	/** fw supported band */
+	t_u16 fw_bands;
+	/** region code */
+	t_u16 region_code;
+	/** force_reg */
+	t_u8 force_reg;
+	/** ECSA support */
+	t_u8 ecsa_enable;
+	/** Get log support */
+	t_u8 getlog_enable;
+	/** FW support for embedded supplicant */
+	t_u8 fw_supplicant_support;
+	/** ant info */
+	t_u8 antinfo;
+	/** max AP associated sta count supported by fw */
+	t_u8 max_ap_assoc_sta;
+	/** Bandwidth not support 80Mhz */
+	t_u8 prohibit_80mhz;
+	/** FW support beacon protection */
+	t_u8 fw_beacon_prot;
+} mlan_fw_info, *pmlan_fw_info;
+
+/** Version string buffer length */
+#define MLAN_MAX_VER_STR_LEN 128
+
+/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */
+typedef struct _mlan_ver_ext {
+	/** Selected version string */
+	t_u32 version_str_sel;
+	/** Version string */
+	char version_str[MLAN_MAX_VER_STR_LEN];
+} mlan_ver_ext, *pmlan_ver_ext;
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+	/** Extended Capabilities value */
+	t_u8 rsvdBit87:1;	/* bit 87 */
+	t_u8 rsvdBit86:1;	/* bit 86 */
+	t_u8 rsvdBit85:1;	/* bit 85 */
+	t_u8 beacon_prot:1;	/* bit 84 */
+	t_u8 rsvdBit83:1;	/* bit 83 */
+	t_u8 rsvdBit82:1;	/* bit 82 */
+	t_u8 rsvdBit81:1;	/* bit 81 */
+	t_u8 rsvdBit80:1;	/* bit 80 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 TWTResp:1;		/* bit 78 */
+	t_u8 TWTReq:1;		/* bit 77 */
+	t_u8 rsvdBit76:1;	/* bit 76 */
+	t_u8 rsvdBit75:1;	/* bit 75 */
+	t_u8 rsvdBit74:1;	/* bit 74 */
+	t_u8 rsvdBit73:1;	/* bit 73 */
+	t_u8 FILS:1;		/* bit 72 */
+	t_u8 FTMI:1;		/* bit 71 */
+	t_u8 FTMR:1;		/* bit 70 */
+	t_u8 CAQ:1;		/* bit 69 */
+	t_u8 rsvdBit68:1;	/* bit 68 */
+	t_u8 NCC:1;		/* bit 67 */
+	t_u8 rsvdBit66:1;	/* bit 66 */
+	t_u8 chanSchedMgnt:1;	/* bit 65 */
+	t_u8 MaxAMSDU1:1;	/* bit 64 */
+	t_u8 MaxAMSDU0:1;	/* bit 63 */
+	t_u8 OperModeNtf:1;	/* bit 62 */
+	t_u8 TDLSWildBandwidth:1;	/* bit 61 */
+	t_u8 rsvdBit60:1;	/* bit 60 */
+	t_u8 rsvdBit59:1;	/* bit 59 */
+	t_u8 rsvdBit58:1;	/* bit 58 */
+	t_u8 rsvdBit57:1;	/* bit 57 */
+	t_u8 rsvdBit56:1;	/* bit 56 */
+	t_u8 rsvdBit55:1;	/* bit 55 */
+	t_u8 rsvdBit54:1;	/* bit 54 */
+	t_u8 rsvdBit53:1;	/* bit 53 */
+	t_u8 rsvdBit52:1;	/* bit 52 */
+	t_u8 rsvdBit51:1;	/* bit 51 */
+	t_u8 rsvdBit50:1;	/* bit 50 */
+	t_u8 rsvdBit49:1;	/* bit 49 */
+	t_u8 rsvdBit48:1;	/* bit 48 */
+	t_u8 rsvdBit47:1;	/* bit 47 */
+	t_u8 rsvdBit46:1;	/* bit 46 */
+	t_u8 rsvdBit45:1;	/* bit 45 */
+	t_u8 rsvdBit44:1;	/* bit 44 */
+	t_u8 rsvdBit43:1;	/* bit 43 */
+	t_u8 rsvdBit42:1;	/* bit 42 */
+	t_u8 rsvdBit41:1;	/* bit 41 */
+	t_u8 rsvdBit40:1;	/* bit 40 */
+	t_u8 TDLSChlSwitchProhib:1;	/* bit 39 */
+	t_u8 TDLSProhibited:1;	/* bit 38 */
+	t_u8 TDLSSupport:1;	/* bit 37 */
+	t_u8 MSGCF_Capa:1;	/* bit 36 */
+	t_u8 Reserved35:1;	/* bit 35 */
+	t_u8 SSPN_Interface:1;	/* bit 34 */
+	t_u8 EBR:1;		/* bit 33 */
+	t_u8 Qos_Map:1;		/* bit 32 */
+	t_u8 Interworking:1;	/* bit 31 */
+	t_u8 TDLSChannelSwitching:1;	/* bit 30 */
+	t_u8 TDLSPeerPSMSupport:1;	/* bit 29 */
+	t_u8 TDLSPeerUAPSDSupport:1;	/* bit 28 */
+	t_u8 UTC:1;		/* bit 27 */
+	t_u8 DMS:1;		/* bit 26 */
+	t_u8 SSID_List:1;	/* bit 25 */
+	t_u8 ChannelUsage:1;	/* bit 24 */
+	t_u8 TimingMeasurement:1;	/* bit 23 */
+	t_u8 MultipleBSSID:1;	/* bit 22 */
+	t_u8 AC_StationCount:1;	/* bit 21 */
+	t_u8 QoSTrafficCap:1;	/* bit 20 */
+	t_u8 BSS_Transition:1;	/* bit 19 */
+	t_u8 TIM_Broadcast:1;	/* bit 18 */
+	t_u8 WNM_Sleep:1;	/* bit 17 */
+	t_u8 TFS:1;		/* bit 16 */
+	t_u8 GeospatialLocation:1;	/* bit 15 */
+	t_u8 CivicLocation:1;	/* bit 14 */
+	t_u8 CollocatedIntf:1;	/* bit 13 */
+	t_u8 ProxyARPService:1;	/* bit 12 */
+	t_u8 FMS:1;		/* bit 11 */
+	t_u8 LocationTracking:1;	/* bit 10 */
+	t_u8 MulticastDiagnostics:1;	/* bit 9  */
+	t_u8 Diagnostics:1;	/* bit 8  */
+	t_u8 Event:1;		/* bit 7  */
+	t_u8 SPSMP_Support:1;	/* bit 6 */
+	t_u8 Reserved5:1;	/* bit 5 */
+	t_u8 PSMP_Capable:1;	/* bit 4 */
+	t_u8 RejectUnadmFrame:1;	/* bit 3 */
+	t_u8 ExtChanSwitching:1;	/* bit 2 */
+	t_u8 Reserved1:1;	/* bit 1 */
+	t_u8 BSS_CoexistSupport:1;	/* bit 0 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#else
+/** Extended Capabilities Data */
+typedef struct MLAN_PACK_START _ExtCap_t {
+	/** Extended Capabilities value */
+	t_u8 BSS_CoexistSupport:1;	/* bit 0 */
+	t_u8 Reserved1:1;	/* bit 1 */
+	t_u8 ExtChanSwitching:1;	/* bit 2 */
+	t_u8 RejectUnadmFrame:1;	/* bit 3 */
+	t_u8 PSMP_Capable:1;	/* bit 4 */
+	t_u8 Reserved5:1;	/* bit 5 */
+	t_u8 SPSMP_Support:1;	/* bit 6 */
+	t_u8 Event:1;		/* bit 7  */
+	t_u8 Diagnostics:1;	/* bit 8  */
+	t_u8 MulticastDiagnostics:1;	/* bit 9  */
+	t_u8 LocationTracking:1;	/* bit 10 */
+	t_u8 FMS:1;		/* bit 11 */
+	t_u8 ProxyARPService:1;	/* bit 12 */
+	t_u8 CollocatedIntf:1;	/* bit 13 */
+	t_u8 CivicLocation:1;	/* bit 14 */
+	t_u8 GeospatialLocation:1;	/* bit 15 */
+	t_u8 TFS:1;		/* bit 16 */
+	t_u8 WNM_Sleep:1;	/* bit 17 */
+	t_u8 TIM_Broadcast:1;	/* bit 18 */
+	t_u8 BSS_Transition:1;	/* bit 19 */
+	t_u8 QoSTrafficCap:1;	/* bit 20 */
+	t_u8 AC_StationCount:1;	/* bit 21 */
+	t_u8 MultipleBSSID:1;	/* bit 22 */
+	t_u8 TimingMeasurement:1;	/* bit 23 */
+	t_u8 ChannelUsage:1;	/* bit 24 */
+	t_u8 SSID_List:1;	/* bit 25 */
+	t_u8 DMS:1;		/* bit 26 */
+	t_u8 UTC:1;		/* bit 27 */
+	t_u8 TDLSPeerUAPSDSupport:1;	/* bit 28 */
+	t_u8 TDLSPeerPSMSupport:1;	/* bit 29 */
+	t_u8 TDLSChannelSwitching:1;	/* bit 30 */
+	t_u8 Interworking:1;	/* bit 31 */
+	t_u8 Qos_Map:1;		/* bit 32 */
+	t_u8 EBR:1;		/* bit 33 */
+	t_u8 SSPN_Interface:1;	/* bit 34 */
+	t_u8 Reserved35:1;	/* bit 35 */
+	t_u8 MSGCF_Capa:1;	/* bit 36 */
+	t_u8 TDLSSupport:1;	/* bit 37 */
+	t_u8 TDLSProhibited:1;	/* bit 38 */
+	t_u8 TDLSChlSwitchProhib:1;	/* bit 39 */
+	t_u8 rsvdBit40:1;	/* bit 40 */
+	t_u8 rsvdBit41:1;	/* bit 41 */
+	t_u8 rsvdBit42:1;	/* bit 42 */
+	t_u8 rsvdBit43:1;	/* bit 43 */
+	t_u8 rsvdBit44:1;	/* bit 44 */
+	t_u8 rsvdBit45:1;	/* bit 45 */
+	t_u8 rsvdBit46:1;	/* bit 46 */
+	t_u8 rsvdBit47:1;	/* bit 47 */
+	t_u8 rsvdBit48:1;	/* bit 48 */
+	t_u8 rsvdBit49:1;	/* bit 49 */
+	t_u8 rsvdBit50:1;	/* bit 50 */
+	t_u8 rsvdBit51:1;	/* bit 51 */
+	t_u8 rsvdBit52:1;	/* bit 52 */
+	t_u8 rsvdBit53:1;	/* bit 53 */
+	t_u8 rsvdBit54:1;	/* bit 54 */
+	t_u8 rsvdBit55:1;	/* bit 55 */
+	t_u8 rsvdBit56:1;	/* bit 56 */
+	t_u8 rsvdBit57:1;	/* bit 57 */
+	t_u8 rsvdBit58:1;	/* bit 58 */
+	t_u8 rsvdBit59:1;	/* bit 59 */
+	t_u8 rsvdBit60:1;	/* bit 60 */
+	t_u8 TDLSWildBandwidth:1;	/* bit 61 */
+	t_u8 OperModeNtf:1;	/* bit 62 */
+	t_u8 MaxAMSDU0:1;	/* bit 63 */
+	t_u8 MaxAMSDU1:1;	/* bit 64 */
+	t_u8 chanSchedMgnt:1;	/* bit 65 */
+	t_u8 rsvdBit66:1;	/* bit 66 */
+	t_u8 NCC:1;		/* bit 67 */
+	t_u8 rsvdBit68:1;	/* bit 68 */
+	t_u8 CAQ:1;		/* bit 69 */
+	t_u8 FTMR:1;		/* bit 70 */
+	t_u8 FTMI:1;		/* bit 71 */
+	t_u8 FILS:1;		/* bit 72 */
+	t_u8 rsvdBit73:1;	/* bit 73 */
+	t_u8 rsvdBit74:1;	/* bit 74 */
+	t_u8 rsvdBit75:1;	/* bit 75 */
+	t_u8 rsvdBit76:1;	/* bit 76 */
+	t_u8 TWTReq:1;		/* bit 77 */
+	t_u8 TWTResp:1;		/* bit 78 */
+	t_u8 rsvdBit79:1;	/* bit 79 */
+	t_u8 rsvdBit80:1;	/* bit 80 */
+	t_u8 rsvdBit81:1;	/* bit 81 */
+	t_u8 rsvdBit82:1;	/* bit 82 */
+	t_u8 rsvdBit83:1;	/* bit 83 */
+	t_u8 beacon_prot:1;	/* bit 84 */
+	t_u8 rsvdBit85:1;	/* bit 85 */
+	t_u8 rsvdBit86:1;	/* bit 86 */
+	t_u8 rsvdBit87:1;	/* bit 87 */
+} MLAN_PACK_END ExtCap_t, *pExtCap_t;
+#endif
+
+/** ExtCap : TDLS prohibited */
+#define IS_EXTCAP_TDLS_PROHIBITED(ext_cap) (ext_cap.TDLSProhibited)
+/** ExtCap : TDLS channel switch prohibited */
+#define IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ext_cap) (ext_cap.TDLSChlSwitchProhib)
+
+/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */
+typedef struct _mlan_bss_info {
+	/** BSS mode */
+	t_u32 bss_mode;
+	/** SSID */
+	mlan_802_11_ssid ssid;
+	/** Table index */
+	t_u32 scan_table_idx;
+	/** Channel */
+	t_u32 bss_chan;
+	/** Band */
+	t_u8 bss_band;
+	/** Region code */
+	t_u32 region_code;
+	/** Connection status */
+	t_u32 media_connected;
+	/** Radio on */
+	t_u32 radio_on;
+	/** Max power level in dBm */
+	t_s32 max_power_level;
+	/** Min power level in dBm */
+	t_s32 min_power_level;
+	/** Adhoc state */
+	t_u32 adhoc_state;
+	/** NF of last beacon */
+	t_s32 bcn_nf_last;
+	/** wep status */
+	t_u32 wep_status;
+	/** scan block status */
+	t_u8 scan_block;
+	/** Host Sleep configured flag */
+	t_u32 is_hs_configured;
+	/** Deep Sleep flag */
+	t_u32 is_deep_sleep;
+	/** BSSID */
+	mlan_802_11_mac_addr bssid;
+#ifdef STA_SUPPORT
+	/** Capability Info */
+	t_u16 capability_info;
+	/** Beacon Interval */
+	t_u16 beacon_interval;
+	/** Listen Interval */
+	t_u16 listen_interval;
+	/** Association Id  */
+	t_u16 assoc_id;
+	/** AP/Peer supported rates */
+	t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES];
+	/** extend capability for AP */
+	ExtCap_t ext_cap;
+#endif				/* STA_SUPPORT */
+	/** Mobility Domain ID */
+	t_u16 mdid;
+	/** FT Capability policy */
+	t_u8 ft_cap;
+	/** 11h active */
+	t_bool is_11h_active;
+	/** dfs check channel */
+	t_u8 dfs_check_channel;
+} mlan_bss_info, *pmlan_bss_info;
+
+/** MAXIMUM number of TID */
+#define MAX_NUM_TID 8
+
+/** Max RX Win size */
+#define MAX_RX_WINSIZE 64
+
+/** rx_reorder_tbl */
+typedef struct {
+	/** TID */
+	t_u16 tid;
+	/** TA */
+	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
+	/** Start window */
+	t_u32 start_win;
+	/** Window size */
+	t_u32 win_size;
+	/** amsdu flag */
+	t_u8 amsdu;
+	/** buffer status */
+	t_u32 buffer[MAX_RX_WINSIZE];
+} rx_reorder_tbl;
+
+/** tx_ba_stream_tbl */
+typedef struct {
+	/** TID */
+	t_u16 tid;
+	/** RA */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	/** amsdu flag */
+	t_u8 amsdu;
+} tx_ba_stream_tbl;
+
+/** Debug command number */
+#define DBG_CMD_NUM 10
+
+#ifdef SDIO
+/** sdio mp debug number */
+#define SDIO_MP_DBG_NUM 10
+#endif
+
+/** Maximum size of IEEE Information Elements */
+#define IEEE_MAX_IE_SIZE 256
+
+/** support up to 8 TDLS peer */
+#define MLAN_MAX_TDLS_PEER_SUPPORTED 8
+/** TDLS peer info */
+typedef struct _tdls_peer_info {
+	/** station mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** SNR */
+	t_s8 snr;
+	/** Noise Floor */
+	t_s8 nf;
+	/** Extended Capabilities IE */
+	t_u8 ext_cap[IEEE_MAX_IE_SIZE];
+	/** HT Capabilities IE */
+	t_u8 ht_cap[IEEE_MAX_IE_SIZE];
+	/** VHT Capabilities IE */
+	t_u8 vht_cap[IEEE_MAX_IE_SIZE];
+} tdls_peer_info;
+
+/** max ralist num */
+#define MLAN_MAX_RALIST_NUM 8
+/** ralist info */
+typedef struct _ralist_info {
+	/** RA list buffer */
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	/** total packets in RA list */
+	t_u16 total_pkts;
+	/** tid num */
+	t_u8 tid;
+	/** tx_pause flag */
+	t_u8 tx_pause;
+} ralist_info, *pralist_info;
+
+/** mlan_debug_info data structure for MLAN_OID_GET_DEBUG_INFO */
+typedef struct _mlan_debug_info {
+	/* WMM AC_BK count */
+	t_u32 wmm_ac_bk;
+	/* WMM AC_BE count */
+	t_u32 wmm_ac_be;
+	/* WMM AC_VI count */
+	t_u32 wmm_ac_vi;
+	/* WMM AC_VO count */
+	t_u32 wmm_ac_vo;
+	/** Corresponds to max_tx_buf_size member of mlan_adapter*/
+	t_u32 max_tx_buf_size;
+	/** Corresponds to tx_buf_size member of mlan_adapter*/
+	t_u32 tx_buf_size;
+	/** Corresponds to curr_tx_buf_size member of mlan_adapter*/
+	t_u32 curr_tx_buf_size;
+	/** Tx table num */
+	t_u32 tx_tbl_num;
+	/** Tx ba stream table */
+	tx_ba_stream_tbl tx_tbl[MLAN_MAX_TX_BASTREAM_SUPPORTED];
+	/** Rx table num */
+	t_u32 rx_tbl_num;
+	/** Rx reorder table*/
+	rx_reorder_tbl rx_tbl[MLAN_MAX_RX_BASTREAM_SUPPORTED];
+	/** TDLS peer number */
+	t_u32 tdls_peer_num;
+	/** TDLS peer list*/
+	tdls_peer_info tdls_peer_list[MLAN_MAX_TDLS_PEER_SUPPORTED];
+	/** ralist num */
+	t_u32 ralist_num;
+	/** ralist info */
+	ralist_info ralist[MLAN_MAX_RALIST_NUM];
+	/** Corresponds to ps_mode member of mlan_adapter */
+	t_u16 ps_mode;
+	/** Corresponds to ps_state member of mlan_adapter */
+	t_u32 ps_state;
+#ifdef STA_SUPPORT
+	/** Corresponds to is_deep_sleep member of mlan_adapter */
+	t_u8 is_deep_sleep;
+#endif /** STA_SUPPORT */
+	/** Corresponds to pm_wakeup_card_req member of mlan_adapter */
+	t_u8 pm_wakeup_card_req;
+	/** Corresponds to pm_wakeup_fw_try member of mlan_adapter */
+	t_u32 pm_wakeup_fw_try;
+	/** time stamp when host try to wake up firmware */
+	t_u32 pm_wakeup_in_secs;
+	/** wake up timeout happened */
+	t_u32 pm_wakeup_timeout;
+	/** Corresponds to is_hs_configured member of mlan_adapter */
+	t_u8 is_hs_configured;
+	/** Corresponds to hs_activated member of mlan_adapter */
+	t_u8 hs_activated;
+	/** Corresponds to pps_uapsd_mode member of mlan_adapter */
+	t_u16 pps_uapsd_mode;
+	/** Corresponds to sleep_period.period member of mlan_adapter */
+	t_u16 sleep_pd;
+	/** Corresponds to wmm_qosinfo member of mlan_private */
+	t_u8 qos_cfg;
+	/** Corresponds to tx_lock_flag member of mlan_adapter */
+	t_u8 tx_lock_flag;
+	/** Corresponds to port_open member of mlan_private */
+	t_u8 port_open;
+	/** bypass pkt count */
+	t_u32 bypass_pkt_count;
+	/** Corresponds to scan_processing member of mlan_adapter */
+	t_u32 scan_processing;
+	/** Corresponds to mlan_processing member of mlan_adapter */
+	t_u32 mlan_processing;
+	/** Corresponds to main_lock_flag member of mlan_adapter */
+	t_u32 main_lock_flag;
+	/** Corresponds to main_process_cnt member of mlan_adapter */
+	t_u32 main_process_cnt;
+	/** Corresponds to delay_task_flag member of mlan_adapter */
+	t_u32 delay_task_flag;
+	/** mlan_rx_processing */
+	t_u32 mlan_rx_processing;
+	/** rx pkts queued */
+	t_u32 rx_pkts_queued;
+	/** Number of host to card command failures */
+	t_u32 num_cmd_host_to_card_failure;
+	/** Number of host to card sleep confirm failures */
+	t_u32 num_cmd_sleep_cfm_host_to_card_failure;
+	/** Number of host to card Tx failures */
+	t_u32 num_tx_host_to_card_failure;
+	/** Number of allocate buffer failure */
+	t_u32 num_alloc_buffer_failure;
+	/** Number of pkt dropped */
+	t_u32 num_pkt_dropped;
+#ifdef SDIO
+	/** Number of card to host command/event failures */
+	t_u32 num_cmdevt_card_to_host_failure;
+	/** Number of card to host Rx failures */
+	t_u32 num_rx_card_to_host_failure;
+	/** Number of interrupt read failures */
+	t_u32 num_int_read_failure;
+	/** Last interrupt status */
+	t_u32 last_int_status;
+	/** number of interrupt receive */
+	t_u32 num_of_irq;
+	/** flag for sdio rx aggr */
+	t_u8 sdio_rx_aggr;
+	/** FW update port number */
+	t_u32 mp_update[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX * 2];
+	/** Invalid port update count */
+	t_u32 mp_invalid_update;
+	/** Number of packets tx aggr */
+	t_u32 mpa_tx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** no more packets count*/
+	t_u32 mpa_sent_last_pkt;
+	/** no write_ports count */
+	t_u32 mpa_sent_no_ports;
+	/** last recv wr_bitmap */
+	t_u32 last_recv_wr_bitmap;
+    /** last recv rd_bitmap */
+	t_u32 last_recv_rd_bitmap;
+    /** mp_data_port_mask */
+	t_u32 mp_data_port_mask;
+	/** last mp_wr_bitmap */
+	t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM];
+	/** last ports for cmd53 write data */
+	t_u32 last_mp_wr_ports[SDIO_MP_DBG_NUM];
+	/** last len for cmd53 write data */
+	t_u32 last_mp_wr_len[SDIO_MP_DBG_NUM];
+	/** last curr_wr_port */
+	t_u8 last_curr_wr_port[SDIO_MP_DBG_NUM];
+	/** length info for cmd53 write data */
+	t_u16 last_mp_wr_info[SDIO_MP_DBG_NUM * SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** last mp_index */
+	t_u8 last_mp_index;
+	/** buffer for mp debug */
+	t_u8 *mpa_buf;
+	/** length info for mp buf size */
+	t_u32 mpa_buf_size;
+	/** Number of packets rx aggr */
+	t_u32 mpa_rx_count[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	/** mp aggr_pkt limit */
+	t_u8 mp_aggr_pkt_limit;
+#endif
+	/** Number of deauthentication events */
+	t_u32 num_event_deauth;
+	/** Number of disassosiation events */
+	t_u32 num_event_disassoc;
+	/** Number of link lost events */
+	t_u32 num_event_link_lost;
+	/** Number of deauthentication commands */
+	t_u32 num_cmd_deauth;
+	/** Number of association comamnd successes */
+	t_u32 num_cmd_assoc_success;
+	/** Number of association command failures */
+	t_u32 num_cmd_assoc_failure;
+	/** Number of consecutive association failures */
+	t_u32 num_cons_assoc_failure;
+
+	/** Number of command timeouts */
+	t_u32 num_cmd_timeout;
+	/** Timeout command ID */
+	t_u16 timeout_cmd_id;
+	/** Timeout command action */
+	t_u16 timeout_cmd_act;
+	/** List of last command IDs */
+	t_u16 last_cmd_id[DBG_CMD_NUM];
+	/** List of last command actions */
+	t_u16 last_cmd_act[DBG_CMD_NUM];
+	/** Last command index */
+	t_u16 last_cmd_index;
+	/** List of last command response IDs */
+	t_u16 last_cmd_resp_id[DBG_CMD_NUM];
+	/** Last command response index */
+	t_u16 last_cmd_resp_index;
+	/** List of last events */
+	t_u16 last_event[DBG_CMD_NUM];
+	/** Last event index */
+	t_u16 last_event_index;
+	/** Number of no free command node */
+	t_u16 num_no_cmd_node;
+	/** pending command id */
+	t_u16 pending_cmd;
+	/** time stamp for dnld last cmd */
+	t_u32 dnld_cmd_in_secs;
+	/** Corresponds to data_sent member of mlan_adapter */
+	t_u8 data_sent;
+	/** Corresponds to data_sent_cnt member of mlan_adapter */
+	t_u32 data_sent_cnt;
+	/** Corresponds to cmd_sent member of mlan_adapter */
+	t_u8 cmd_sent;
+	/** SDIO multiple port read bitmap */
+	t_u32 mp_rd_bitmap;
+	/** SDIO multiple port write bitmap */
+	t_u32 mp_wr_bitmap;
+	/** Current available port for read */
+	t_u8 curr_rd_port;
+	/** Current available port for write */
+	t_u8 curr_wr_port;
+#ifdef PCIE
+	/** PCIE txbd read pointer */
+	t_u32 txbd_rdptr;
+	/** PCIE txbd write pointer */
+	t_u32 txbd_wrptr;
+	/** PCIE rxbd read pointer */
+	t_u32 rxbd_rdptr;
+	/** PCIE rxbd write pointer */
+	t_u32 rxbd_wrptr;
+	/** PCIE eventbd read pointer */
+	t_u32 eventbd_rdptr;
+	/** PCIE eventbd write pointer */
+	t_u32 eventbd_wrptr;
+	/** txrx_bd_size */
+	t_u16 txrx_bd_size;
+	/** txbd ring vbase */
+	t_u8 *txbd_ring_vbase;
+	/** txbd ring size */
+	t_u32 txbd_ring_size;
+	/** rxbd ring vbase */
+	t_u8 *rxbd_ring_vbase;
+	/** rxbd ring size */
+	t_u32 rxbd_ring_size;
+	/** evtbd ring vbase */
+	t_u8 *evtbd_ring_vbase;
+	/** evtbd ring size */
+	t_u32 evtbd_ring_size;
+#endif
+	/** Corresponds to cmdresp_received member of mlan_adapter */
+	t_u8 cmd_resp_received;
+	/** Corresponds to event_received member of mlan_adapter */
+	t_u8 event_received;
+	/**  pendig tx pkts */
+	t_u32 tx_pkts_queued;
+#ifdef UAP_SUPPORT
+	/**  pending bridge pkts */
+	t_u16 num_bridge_pkts;
+	/**  dropped pkts */
+	t_u32 num_drop_pkts;
+#endif
+	/** FW hang report */
+	t_u8 fw_hang_report;
+	/** mlan_adapter pointer */
+	t_void *mlan_adapter;
+	/** mlan_adapter_size */
+	t_u32 mlan_adapter_size;
+	/** mlan_priv vector */
+	t_void *mlan_priv[MLAN_MAX_BSS_NUM];
+	/** mlan_priv_size */
+	t_u32 mlan_priv_size[MLAN_MAX_BSS_NUM];
+	/** mlan_priv_num */
+	t_u8 mlan_priv_num;
+} mlan_debug_info, *pmlan_debug_info;
+
+#ifdef UAP_SUPPORT
+/** Maximum number of clients supported by AP */
+#define MAX_NUM_CLIENTS MAX_STA_COUNT
+
+/** station info */
+typedef struct _sta_info_data {
+	/** STA MAC address */
+	t_u8 mac_address[MLAN_MAC_ADDR_LENGTH];
+	/** Power mgmt status */
+	t_u8 power_mgmt_status;
+	/** RSSI */
+	t_s8 rssi;
+	/** station bandmode */
+	t_u16 bandmode;
+	/** station stats */
+	sta_stats stats;
+	/** ie length */
+	t_u16 ie_len;
+} sta_info_data;
+
+/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */
+typedef struct _mlan_ds_sta_list {
+	/** station count */
+	t_u16 sta_count;
+	/** station list */
+	sta_info_data info[MAX_NUM_CLIENTS];
+	/* ie_buf will be append at the end */
+} mlan_ds_sta_list, *pmlan_ds_sta_list;
+#endif
+
+/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */
+typedef struct _mlan_ds_get_info {
+	/** Sub-command */
+	t_u32 sub_command;
+
+	/** Status information parameter */
+	union {
+		/** Signal information for MLAN_OID_GET_SIGNAL */
+		mlan_ds_get_signal signal;
+		/** Signal path id for MLAN_OID_GET_SIGNAL_EXT */
+		t_u16 path_id;
+		/** Signal information for MLAN_OID_GET_SIGNAL_EXT */
+		mlan_ds_get_signal signal_ext[MAX_PATH_NUM];
+		/** Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_get_stats stats;
+		/** Statistics information for MLAN_OID_LINK_STATS*/
+		t_u8 link_statistic[1];
+		/** Firmware information for MLAN_OID_GET_FW_INFO */
+		mlan_fw_info fw_info;
+		/** Extended version information for MLAN_OID_GET_VER_EXT */
+		mlan_ver_ext ver_ext;
+		/** BSS information for MLAN_OID_GET_BSS_INFO */
+		mlan_bss_info bss_info;
+		/** Debug information for MLAN_OID_GET_DEBUG_INFO */
+		t_u8 debug_info[1];
+#ifdef UAP_SUPPORT
+		/** UAP Statistics information for MLAN_OID_GET_STATS */
+		mlan_ds_uap_stats ustats;
+		/** UAP station list for MLAN_OID_UAP_STA_LIST */
+		mlan_ds_sta_list sta_list;
+#endif
+	} param;
+} mlan_ds_get_info, *pmlan_ds_get_info;
+
+/*-----------------------------------------------------------------*/
+/** Security Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for authentication mode */
+enum _mlan_auth_mode {
+	MLAN_AUTH_MODE_OPEN = 0x00,
+	MLAN_AUTH_MODE_SHARED = 0x01,
+	MLAN_AUTH_MODE_FT = 0x02,
+	MLAN_AUTH_MODE_SAE = 0x03,
+	MLAN_AUTH_MODE_NETWORKEAP = 0x80,
+	MLAN_AUTH_MODE_AUTO = 0xFF,
+};
+
+/**Enumeration for AssocAgent authentication mode, sync from FW.*/
+typedef enum {
+	AssocAgentAuth_Open,
+	AssocAgentAuth_Shared,
+	AssocAgentAuth_FastBss,
+	AssocAgentAuth_FastBss_Skip,
+	AssocAgentAuth_Network_EAP,
+	AssocAgentAuth_Wpa3Sae = 6,
+	AssocAgentAuth_Auto,
+} AssocAgentAuthType_e;
+
+/** Enumeration for encryption mode */
+enum _mlan_encryption_mode {
+	MLAN_ENCRYPTION_MODE_NONE = 0,
+	MLAN_ENCRYPTION_MODE_WEP40 = 1,
+	MLAN_ENCRYPTION_MODE_TKIP = 2,
+	MLAN_ENCRYPTION_MODE_CCMP = 3,
+	MLAN_ENCRYPTION_MODE_WEP104 = 4,
+	MLAN_ENCRYPTION_MODE_GCMP = 5,
+	MLAN_ENCRYPTION_MODE_GCMP_256 = 6,
+	MLAN_ENCRYPTION_MODE_CCMP_256 = 7,
+};
+
+/** Enumeration for PSK */
+enum _mlan_psk_type {
+	MLAN_PSK_PASSPHRASE = 1,
+	MLAN_PSK_PMK,
+	MLAN_PSK_CLEAR,
+	MLAN_PSK_QUERY,
+	MLAN_PSK_SAE_PASSWORD,
+};
+
+/** The bit to indicate the key is for unicast */
+#define MLAN_KEY_INDEX_UNICAST 0x40000000
+/** The key index to indicate default key */
+#define MLAN_KEY_INDEX_DEFAULT 0x000000ff
+/** Maximum key length */
+/* #define MLAN_MAX_KEY_LENGTH        32 */
+/** Minimum passphrase length */
+#define MLAN_MIN_PASSPHRASE_LENGTH 8
+/** Maximum passphrase length */
+#define MLAN_MAX_PASSPHRASE_LENGTH 63
+/** Minimum sae_password length */
+#define MLAN_MIN_SAE_PASSWORD_LENGTH 8
+/** Maximum sae_password length */
+#define MLAN_MAX_SAE_PASSWORD_LENGTH 255
+/** PMK length */
+#define MLAN_PMK_HEXSTR_LENGTH 64
+/* A few details needed for WEP (Wireless Equivalent Privacy) */
+/** 104 bits */
+#define MAX_WEP_KEY_SIZE 13
+/** 40 bits RC4 - WEP */
+#define MIN_WEP_KEY_SIZE 5
+/** packet number size */
+#define PN_SIZE 16
+/** max seq size of wpa/wpa2 key */
+#define SEQ_MAX_SIZE 8
+
+/** key flag for tx_seq */
+#define KEY_FLAG_TX_SEQ_VALID 0x00000001
+/** key flag for rx_seq */
+#define KEY_FLAG_RX_SEQ_VALID 0x00000002
+/** key flag for group key */
+#define KEY_FLAG_GROUP_KEY 0x00000004
+/** key flag for tx */
+#define KEY_FLAG_SET_TX_KEY 0x00000008
+/** key flag for mcast IGTK */
+#define KEY_FLAG_AES_MCAST_IGTK 0x00000010
+/** key flag for remove key */
+#define KEY_FLAG_REMOVE_KEY 0x80000000
+/** key flag for GCMP */
+#define KEY_FLAG_GCMP 0x00000020
+/** key flag for GCMP_256 */
+#define KEY_FLAG_GCMP_256 0x00000040
+/** key flag for ccmp 256 */
+#define KEY_FLAG_CCMP_256 0x00000080
+/** key flag for GMAC_128 */
+#define KEY_FLAG_GMAC_128 0x00000100
+/** key flag for GMAC_256 */
+#define KEY_FLAG_GMAC_256 0x00000200
+
+/** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+typedef struct _mlan_ds_encrypt_key {
+	/** Key disabled, all other fields will be
+	 *  ignore when this flag set to MTRUE
+	 */
+	t_u32 key_disable;
+	/** key removed flag, when this flag is set
+	 *  to MTRUE, only key_index will be check
+	 */
+	t_u32 key_remove;
+	/** Key index, used as current tx key index
+	 *  when is_current_wep_key is set to MTRUE
+	 */
+	t_u32 key_index;
+	/** Current Tx key flag */
+	t_u32 is_current_wep_key;
+	/** Key length */
+	t_u32 key_len;
+	/** Key */
+	t_u8 key_material[MLAN_MAX_KEY_LENGTH];
+	/** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** wapi key flag */
+	t_u32 is_wapi_key;
+	/** Initial packet number */
+	t_u8 pn[PN_SIZE];
+	/** key flags */
+	t_u32 key_flags;
+} mlan_ds_encrypt_key, *pmlan_ds_encrypt_key;
+
+/** Type definition of mlan_passphrase_t */
+typedef struct _mlan_passphrase_t {
+	/** Length of passphrase */
+	t_u32 passphrase_len;
+	/** Passphrase */
+	t_u8 passphrase[MLAN_MAX_PASSPHRASE_LENGTH];
+} mlan_passphrase_t;
+
+/** Type definition of mlan_sae_password_t */
+typedef struct _mlan_sae_password_t {
+	/** Length of SAE Password */
+	t_u32 sae_password_len;
+	/** SAE Password */
+	t_u8 sae_password[MLAN_MAX_SAE_PASSWORD_LENGTH];
+} mlan_sae_password_t;
+
+/** Type defnition of mlan_pmk_t */
+typedef struct _mlan_pmk_t {
+	/** PMK */
+	t_u8 pmk[MLAN_MAX_KEY_LENGTH];
+} mlan_pmk_t;
+
+/** Embedded supplicant RSN type: No RSN */
+#define RSN_TYPE_NO_RSN MBIT(0)
+/** Embedded supplicant RSN type: WPA */
+#define RSN_TYPE_WPA MBIT(3)
+/** Embedded supplicant RSN type: WPA-NONE */
+#define RSN_TYPE_WPANONE MBIT(4)
+/** Embedded supplicant RSN type: WPA2 */
+#define RSN_TYPE_WPA2 MBIT(5)
+/** Embedded supplicant RSN type: RFU */
+#define RSN_TYPE_VALID_BITS                                                    \
+	(RSN_TYPE_NO_RSN | RSN_TYPE_WPA | RSN_TYPE_WPANONE | RSN_TYPE_WPA2)
+
+/** Embedded supplicant cipher type: TKIP */
+#define EMBED_CIPHER_TKIP MBIT(2)
+/** Embedded supplicant cipher type: AES */
+#define EMBED_CIPHER_AES MBIT(3)
+/** Embedded supplicant cipher type: RFU */
+#define EMBED_CIPHER_VALID_BITS (EMBED_CIPHER_TKIP | EMBED_CIPHER_AES)
+
+/** Type definition of mlan_ds_passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */
+typedef struct _mlan_ds_passphrase {
+	/** SSID may be used */
+	mlan_802_11_ssid ssid;
+	/** BSSID may be used */
+	mlan_802_11_mac_addr bssid;
+	/** Flag for passphrase or pmk used */
+	t_u16 psk_type;
+	/** Passphrase or PMK */
+	union {
+		/** Passphrase */
+		mlan_passphrase_t passphrase;
+		/** SAE Password */
+		mlan_sae_password_t sae_password;
+		/** PMK */
+		mlan_pmk_t pmk;
+	} psk;
+} mlan_ds_passphrase, *pmlan_ds_passphrase;
+
+/** Type definition of mlan_ds_esupp_mode for MLAN_OID_SEC_CFG_ESUPP_MODE */
+typedef struct _mlan_ds_ewpa_mode {
+	/** RSN mode */
+	t_u32 rsn_mode;
+	/** Active pairwise cipher */
+	t_u32 act_paircipher;
+	/** Active pairwise cipher */
+	t_u32 act_groupcipher;
+} mlan_ds_esupp_mode, *pmlan_ds_esupp_mode;
+
+/** Type definition of mlan_ds_sec_cfg for MLAN_IOCTL_SEC_CFG */
+typedef struct _mlan_ds_sec_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Security configuration parameter */
+	union {
+		/** Authentication mode for MLAN_OID_SEC_CFG_AUTH_MODE */
+		t_u32 auth_mode;
+		/** Encryption mode for MLAN_OID_SEC_CFG_ENCRYPT_MODE */
+		t_u32 encrypt_mode;
+		/** WPA enabled flag for MLAN_OID_SEC_CFG_WPA_ENABLED */
+		t_u32 wpa_enabled;
+		/** WAPI enabled flag for MLAN_OID_SEC_CFG_WAPI_ENABLED */
+		t_u32 wapi_enabled;
+		/** Port Control enabled flag for MLAN_OID_SEC_CFG_PORT_CTRL */
+		t_u32 port_ctrl_enabled;
+		/** Encryption key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */
+		mlan_ds_encrypt_key encrypt_key;
+		/** Passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */
+		mlan_ds_passphrase passphrase;
+		/** Embedded supplicant WPA enabled flag for
+		 *  MLAN_OID_SEC_CFG_EWPA_ENABLED
+		 */
+		t_u32 ewpa_enabled;
+		/** Embedded supplicant mode for MLAN_OID_SEC_CFG_ESUPP_MODE */
+		mlan_ds_esupp_mode esupp_mode;
+#ifdef UAP_SUPPORT
+		t_u8 sta_mac[MLAN_MAC_ADDR_LENGTH];
+#endif
+	} param;
+} mlan_ds_sec_cfg, *pmlan_ds_sec_cfg;
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+#define BIT_TLV_TYPE_CRYPTO_KEY (1 << 0)
+#define BIT_TLV_TYPE_CRYPTO_KEY_IV (1 << 1)
+#define BIT_TLV_TYPE_CRYPTO_KEY_PREFIX (1 << 2)
+#define BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK (1 << 3)
+
+/** Type definition of mlan_ds_sup_cfg */
+typedef struct _mlan_ds_sup_cfg {
+	/** Sub-command */
+	t_u8 sub_command;
+	/** output length */
+	t_u16 output_len;
+	/** number of data blks */
+	t_u16 data_blks_nr;
+	/** sub action code */
+	t_u8 sub_action_code;
+	/** skip bytes */
+	t_u16 skip_bytes;
+	/** iteration */
+	t_u32 iteration;
+	/** count */
+	t_u32 count;
+	/** pointer to output */
+	t_u8 *output;
+	/** key length  */
+	t_u16 key_len;
+	/** pointer to key */
+	t_u8 *key;
+	/** key iv length  */
+	t_u16 key_iv_len;
+	/** pointer to key iv */
+	t_u8 *key_iv;
+	/** key prefix length */
+	t_u16 key_prefix_len;
+	/** pointer to key prefix */
+	t_u8 *key_prefix;
+	/** pointer to data blk length array */
+	t_u32 *key_data_blk_len;
+	/** pointer to key data blk pointer array */
+	t_u8 **key_data_blk;
+	/** callback */
+	t_u8 call_back;
+} mlan_ds_sup_cfg, *pmlan_ds_sup_cfg;
+#endif
+
+/*-----------------------------------------------------------------*/
+/** Rate Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for rate type */
+enum _mlan_rate_type { MLAN_RATE_INDEX, MLAN_RATE_VALUE, MLAN_RATE_BITMAP };
+
+/** Enumeration for rate format */
+enum _mlan_rate_format {
+	MLAN_RATE_FORMAT_LG = 0,
+	MLAN_RATE_FORMAT_HT,
+	MLAN_RATE_FORMAT_VHT,
+	MLAN_RATE_FORMAT_HE,
+	MLAN_RATE_FORMAT_AUTO = 0xFF,
+};
+
+/** Max bitmap rates size */
+#define MAX_BITMAP_RATES_SIZE 26
+
+/** Type definition of mlan_rate_cfg_t for MLAN_OID_RATE_CFG */
+typedef struct _mlan_rate_cfg_t {
+	/** Fixed rate: 0, auto rate: 1 */
+	t_u32 is_rate_auto;
+	/** Rate type. 0: index; 1: value; 2: bitmap */
+	t_u32 rate_type;
+	/** Rate/MCS index or rate value if fixed rate */
+	t_u32 rate;
+	/** Rate Bitmap */
+	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+	/** NSS */
+	t_u32 nss;
+	/* LG rate: 0, HT rate: 1, VHT rate: 2 */
+	t_u32 rate_format;
+	/** Rate Setting */
+	t_u16 rate_setting;
+} mlan_rate_cfg_t;
+
+/** HT channel bandwidth */
+typedef enum _mlan_ht_bw {
+	MLAN_HT_BW20,
+	MLAN_HT_BW40,
+	/** VHT channel bandwidth */
+	MLAN_VHT_BW80,
+	MLAN_VHT_BW160,
+} mlan_ht_bw;
+
+/** HT guard interval */
+typedef enum _mlan_ht_gi {
+	MLAN_HT_LGI,
+	MLAN_HT_SGI,
+} mlan_ht_gi;
+
+typedef enum _mlan_vht_stbc {
+	MLAN_VHT_STBC,
+	MLAN_VHT_NO_STBC,
+} mlan_vht_stbc;
+
+typedef enum _mlan_vht_ldpc {
+	MLAN_VHT_LDPC,
+	MLAN_VHT_NO_LDPC,
+} mlan_vht_ldpc;
+
+/** Band and BSS mode */
+typedef struct _mlan_band_data_rate {
+	/** Band configuration */
+	t_u8 config_bands;
+	/** BSS mode (Infra or IBSS) */
+	t_u8 bss_mode;
+} mlan_band_data_rate;
+
+/** Type definition of mlan_data_rate for MLAN_OID_GET_DATA_RATE */
+typedef struct _mlan_data_rate {
+	/** Tx data rate */
+	t_u32 tx_data_rate;
+	/** Rx data rate */
+	t_u32 rx_data_rate;
+
+	/** Tx channel bandwidth */
+	t_u32 tx_ht_bw;
+	/** Tx guard interval */
+	t_u32 tx_ht_gi;
+	/** Rx channel bandwidth */
+	t_u32 rx_ht_bw;
+	/** Rx guard interval */
+	t_u32 rx_ht_gi;
+	/** MCS index */
+	t_u32 tx_mcs_index;
+	t_u32 rx_mcs_index;
+	/** NSS */
+	t_u32 tx_nss;
+	t_u32 rx_nss;
+	/* LG rate: 0, HT rate: 1, VHT rate: 2 */
+	t_u32 tx_rate_format;
+	t_u32 rx_rate_format;
+} mlan_data_rate;
+
+/** Type definition of mlan_ds_rate for MLAN_IOCTL_RATE */
+typedef struct _mlan_ds_rate {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Rate configuration parameter */
+	union {
+		/** Rate configuration for MLAN_OID_RATE_CFG */
+		mlan_rate_cfg_t rate_cfg;
+		/** Data rate for MLAN_OID_GET_DATA_RATE */
+		mlan_data_rate data_rate;
+		/** Supported rates for MLAN_OID_SUPPORTED_RATES */
+		t_u8 rates[MLAN_SUPPORTED_RATES];
+		/** Band/BSS mode for getting supported rates */
+		mlan_band_data_rate rate_band_cfg;
+	} param;
+} mlan_ds_rate, *pmlan_ds_rate;
+
+/*-----------------------------------------------------------------*/
+/** Power Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** Type definition of mlan_power_cfg_t for MLAN_OID_POWER_CFG */
+typedef struct _mlan_power_cfg_t {
+	/** Is power auto */
+	t_u32 is_power_auto;
+	/** Power level in dBm */
+	t_s32 power_level;
+} mlan_power_cfg_t;
+
+/** max power table size */
+#define MAX_POWER_TABLE_SIZE 128
+#define TX_PWR_CFG_AUTO_CTRL_OFF 0xFF
+#define MAX_POWER_GROUP 64
+/** Type definition of mlan_power group info */
+typedef struct mlan_power_group {
+	/** rate format (LG: 0, HT: 1, VHT: 2, no auto ctrl: 0xFF) */
+	t_u32 rate_format;
+	/** bandwidth (LG: 20 MHz, HT: 20/40 MHz, VHT: 80/160/80+80 MHz) */
+	t_u8 bandwidth;
+	/** NSS */
+	t_u32 nss;
+	/** LG: first rate index, HT/VHT: first MCS */
+	t_u8 first_rate_ind;
+	/** LG: last rate index, HT/VHT: last MCS */
+	t_u8 last_rate_ind;
+	/** minmum tx power (dBm) */
+	t_s8 power_min;
+	/** maximum tx power (dBm) */
+	t_s8 power_max;
+	/** tx power step (dB) */
+	t_s8 power_step;
+} mlan_power_group;
+
+/** Type definition of mlan_power_cfg_ext for MLAN_OID_POWER_CFG_EXT */
+typedef struct _mlan_power_cfg_ext {
+	/** number of power_groups */
+	t_u32 num_pwr_grp;
+	/** array of power groups */
+	mlan_power_group power_group[MAX_POWER_GROUP];
+} mlan_power_cfg_ext;
+
+/** Type definition of mlan_ds_power_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_power_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Power configuration parameter */
+	union {
+		/** Power configuration for MLAN_OID_POWER_CFG */
+		mlan_power_cfg_t power_cfg;
+		/** Extended power configuration for MLAN_OID_POWER_CFG_EXT */
+		mlan_power_cfg_ext power_ext;
+		/** Low power mode for MLAN_OID_POWER_LOW_POWER_MODE */
+		t_u16 lpm;
+	} param;
+} mlan_ds_power_cfg, *pmlan_ds_power_cfg;
+
+/** Type definition of mlan_ds_band_steer_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_band_steer_cfg {
+	/** Set/Get */
+	t_u8 action;
+	/** enable/disable band steering*/
+	t_u8 state;
+	/** Probe Response will be blocked to 2G channel for first
+	 * block_2g_prb_req probe requests*/
+	t_u8 block_2g_prb_req;
+	/** When band steering is enabled, limit the btm request sent to STA at
+	 * <max_btm_req_allowed>*/
+	t_u8 max_btm_req_allowed;
+} mlan_ds_band_steer_cfg, *pmlan_ds_band_steer_cfg;
+
+/** Type definition of mlan_ds_beacon_stuck_param_cfg for MLAN_IOCTL_POWER_CFG */
+typedef struct _mlan_ds_beacon_stuck_param_cfg {
+    /** subcmd */
+	t_u32 subcmd;
+    /** Set/Get */
+	t_u8 action;
+    /** No of beacon interval after which firmware will check if beacon Tx is going fine */
+	t_u8 beacon_stuck_detect_count;
+    /** Upon performing MAC reset, no of beacon interval after which firmware will check if recovery was successful */
+	t_u8 recovery_confirm_count;
+} mlan_ds_beacon_stuck_param_cfg, *pmlan_ds_beacon_stuck_param_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Power Management Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Host sleep config conditions : Cancel */
+#define HOST_SLEEP_CFG_CANCEL 0xffffffff
+
+/** Host sleep config condition: broadcast data */
+#define HOST_SLEEP_COND_BROADCAST_DATA MBIT(0)
+/** Host sleep config condition: unicast data */
+#define HOST_SLEEP_COND_UNICAST_DATA MBIT(1)
+/** Host sleep config condition: mac event */
+#define HOST_SLEEP_COND_MAC_EVENT MBIT(2)
+/** Host sleep config condition: multicast data */
+#define HOST_SLEEP_COND_MULTICAST_DATA MBIT(3)
+/** Host sleep config condition: IPV6 packet */
+#define HOST_SLEEP_COND_IPV6_PACKET MBIT(31)
+
+/** Host sleep config conditions: Default */
+#define HOST_SLEEP_DEF_COND                                                    \
+	(HOST_SLEEP_COND_BROADCAST_DATA | HOST_SLEEP_COND_UNICAST_DATA |       \
+	 HOST_SLEEP_COND_MAC_EVENT)
+
+/** Host sleep config GPIO : Default */
+#define HOST_SLEEP_DEF_GPIO 0xff
+/** Host sleep config gap : Default */
+#define HOST_SLEEP_DEF_GAP 200
+/** Host sleep config min wake holdoff */
+#define HOST_SLEEP_DEF_WAKE_HOLDOFF 0;
+/** Host sleep config inactivity timeout */
+#define HOST_SLEEP_DEF_INACTIVITY_TIMEOUT 10;
+
+/** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */
+typedef struct _mlan_ds_hs_cfg {
+	/** MTRUE to invoke the HostCmd, MFALSE otherwise */
+	t_u32 is_invoke_hostcmd;
+	/** Host sleep config condition */
+	/** Bit0: broadcast data
+	 *  Bit1: unicast data
+	 *  Bit2: mac event
+	 *  Bit3: multicast data
+	 */
+	t_u32 conditions;
+	/** GPIO pin or 0xff for interface */
+	t_u32 gpio;
+	/** Gap in milliseconds or or 0xff for special
+	 *  setting when GPIO is used to wakeup host
+	 */
+	t_u32 gap;
+	/** Host sleep wake interval */
+	t_u32 hs_wake_interval;
+	/** Parameter type for indication gpio*/
+	t_u8 param_type_ind;
+	/** GPIO pin for indication wakeup source */
+	t_u32 ind_gpio;
+	/** Level on ind_gpio pin for indication normal wakeup source */
+	t_u32 level;
+	/** Parameter type for extend hscfg*/
+	t_u8 param_type_ext;
+	/** Events that will be forced ignore*/
+	t_u32 event_force_ignore;
+	/** Events that will use extend gap to inform host*/
+	t_u32 event_use_ext_gap;
+	/** Ext gap*/
+	t_u8 ext_gap;
+	/** GPIO wave level for extend hscfg*/
+	t_u8 gpio_wave;
+} mlan_ds_hs_cfg, *pmlan_ds_hs_cfg;
+
+#define MAX_MGMT_FRAME_FILTER 2
+typedef struct _mlan_mgmt_frame_wakeup {
+	/** action - bitmap
+	 ** On matching rx'd pkt and filter during NON_HOSTSLEEP mode:
+	 **   Action[1]=0  Discard
+	 **   Action[1]=1  Allow
+	 ** Note that default action on non-match is "Allow".
+	 **
+	 ** On matching rx'd pkt and filter during HOSTSLEEP mode:
+	 **   Action[1:0]=00  Discard and Not Wake host
+	 **   Action[1:0]=01  Discard and Wake host
+	 **   Action[1:0]=10  Invalid
+	 ** Note that default action on non-match is "Discard and Not Wake
+	 *host".
+	 **/
+	t_u32 action;
+	/** Frame type(p2p, tdls...)
+	 ** type=0: invalid
+	 ** type=1: p2p
+	 ** type=others: reserved
+	 **/
+	t_u32 type;
+	/** Frame mask according to each type
+	 ** When type=1 for p2p, frame-mask have following define:
+	 **    Bit      Frame
+	 **     0       GO Negotiation Request
+	 **     1       GO Negotiation Response
+	 **     2       GO Negotiation Confirmation
+	 **     3       P2P Invitation Request
+	 **     4       P2P Invitation Response
+	 **     5       Device Discoverability Request
+	 **     6       Device Discoverability Response
+	 **     7       Provision Discovery Request
+	 **     8       Provision Discovery Response
+	 **     9       Notice of Absence
+	 **     10      P2P Presence Request
+	 **     11      P2P Presence Response
+	 **     12      GO Discoverability Request
+	 **     13-31   Reserved
+	 **
+	 ** When type=others, frame-mask is reserved.
+	 **/
+	t_u32 frame_mask;
+} mlan_mgmt_frame_wakeup, *pmlan_mgmt_frame_wakeup;
+
+/** Enable deep sleep mode */
+#define DEEP_SLEEP_ON 1
+/** Disable deep sleep mode */
+#define DEEP_SLEEP_OFF 0
+
+/** Default idle time in milliseconds for auto deep sleep */
+#define DEEP_SLEEP_IDLE_TIME 100
+
+typedef struct _mlan_ds_auto_ds {
+	/** auto ds mode, 0 - disable, 1 - enable */
+	t_u16 auto_ds;
+	/** auto ds idle time in milliseconds */
+	t_u16 idletime;
+} mlan_ds_auto_ds;
+
+/** Type definition of mlan_ds_inactivity_to
+ *  for MLAN_OID_PM_CFG_INACTIVITY_TO
+ */
+typedef struct _mlan_ds_inactivity_to {
+	/** Timeout unit in microsecond, 0 means 1000us (1ms) */
+	t_u32 timeout_unit;
+	/** Inactivity timeout for unicast data */
+	t_u32 unicast_timeout;
+	/** Inactivity timeout for multicast data */
+	t_u32 mcast_timeout;
+	/** Timeout for additional Rx traffic after Null PM1 packet exchange */
+	t_u32 ps_entry_timeout;
+} mlan_ds_inactivity_to, *pmlan_ds_inactivity_to;
+
+/** Minimum sleep period in milliseconds */
+#define MIN_SLEEP_PERIOD 10
+/** Maximum sleep period in milliseconds */
+#define MAX_SLEEP_PERIOD 60
+/** Special setting for UPSD certification tests */
+#define SLEEP_PERIOD_RESERVED_FF 0xFF
+
+/** PS null interval disable */
+#define PS_NULL_DISABLE (-1)
+
+/** Local listen interval disable */
+#define MRVDRV_LISTEN_INTERVAL_DISABLE (-1)
+/** Minimum listen interval */
+#define MRVDRV_MIN_LISTEN_INTERVAL 0
+
+/** Minimum multiple DTIM */
+#define MRVDRV_MIN_MULTIPLE_DTIM 0
+/** Maximum multiple DTIM */
+#define MRVDRV_MAX_MULTIPLE_DTIM 5
+/** Ignore multiple DTIM */
+#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
+/** Match listen interval to closest DTIM */
+#define MRVDRV_MATCH_CLOSEST_DTIM 0xfffd
+
+/** Minimum beacon miss timeout in milliseconds */
+#define MIN_BCN_MISS_TO 0
+/** Maximum beacon miss timeout in milliseconds */
+#define MAX_BCN_MISS_TO 50
+/** Disable beacon miss timeout */
+#define DISABLE_BCN_MISS_TO 65535
+
+/** Minimum delay to PS in milliseconds */
+#define MIN_DELAY_TO_PS 0
+/** Maximum delay to PS in milliseconds */
+#define MAX_DELAY_TO_PS 65535
+/** Delay to PS unchanged */
+#define DELAY_TO_PS_UNCHANGED (-1)
+/** Default delay to PS in milliseconds */
+#define DELAY_TO_PS_DEFAULT 1000
+
+/** PS mode: Unchanged */
+#define PS_MODE_UNCHANGED 0
+/** PS mode: Auto */
+#define PS_MODE_AUTO 1
+/** PS mode: Poll */
+#define PS_MODE_POLL 2
+/** PS mode: Null */
+#define PS_MODE_NULL 3
+
+/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
+typedef struct _mlan_ds_ps_cfg {
+	/** PS null interval in seconds */
+	t_u32 ps_null_interval;
+	/** Multiple DTIM interval */
+	t_u32 multiple_dtim_interval;
+	/** Listen interval */
+	t_u32 listen_interval;
+	/** Beacon miss timeout in milliseconds */
+	t_u32 bcn_miss_timeout;
+	/** Delay to PS in milliseconds */
+	t_s32 delay_to_ps;
+	/** PS mode */
+	t_u32 ps_mode;
+} mlan_ds_ps_cfg, *pmlan_ds_ps_cfg;
+
+/** Type definition of mlan_ds_sleep_params for MLAN_OID_PM_CFG_SLEEP_PARAMS */
+typedef struct _mlan_ds_sleep_params {
+	/** Error */
+	t_u32 error;
+	/** Offset in microseconds */
+	t_u32 offset;
+	/** Stable time in microseconds */
+	t_u32 stable_time;
+	/** Calibration control */
+	t_u32 cal_control;
+	/** External sleep clock */
+	t_u32 ext_sleep_clk;
+	/** Reserved */
+	t_u32 reserved;
+} mlan_ds_sleep_params, *pmlan_ds_sleep_params;
+
+/** sleep_param */
+typedef struct _ps_sleep_param {
+	/** control bitmap */
+	t_u32 ctrl_bitmap;
+	/** minimum sleep period (micro second) */
+	t_u32 min_sleep;
+	/** maximum sleep period (micro second) */
+	t_u32 max_sleep;
+} ps_sleep_param;
+
+/** inactivity sleep_param */
+typedef struct _inact_sleep_param {
+	/** inactivity timeout (micro second) */
+	t_u32 inactivity_to;
+	/** miniumu awake period (micro second) */
+	t_u32 min_awake;
+	/** maximum awake period (micro second) */
+	t_u32 max_awake;
+} inact_sleep_param;
+
+/** flag for ps mode */
+#define PS_FLAG_PS_MODE 1
+/** flag for sleep param */
+#define PS_FLAG_SLEEP_PARAM 2
+/** flag for inactivity sleep param */
+#define PS_FLAG_INACT_SLEEP_PARAM 4
+
+/** Enable Robust Coex mode */
+#define ROBUSTCOEX_GPIOCFG_ENABLE 1
+/** Disable Robust Coex mode */
+#define ROBUSTCOEX_GPIOCFG_DISABLE 0
+
+/** Disable power mode */
+#define PS_MODE_DISABLE 0
+/** Enable periodic dtim ps */
+#define PS_MODE_PERIODIC_DTIM 1
+/** Enable inactivity ps */
+#define PS_MODE_INACTIVITY 2
+/** FW wake up method interface */
+#define FW_WAKEUP_METHOD_INTERFACE 1
+/** FW wake up method gpio */
+#define FW_WAKEUP_METHOD_GPIO 2
+/** mlan_ds_ps_mgmt */
+typedef struct _mlan_ds_ps_mgmt {
+	/** flags for valid field */
+	t_u16 flags;
+	/** power mode */
+	t_u16 ps_mode;
+	/** sleep param */
+	ps_sleep_param sleep_param;
+	/** inactivity sleep param */
+	inact_sleep_param inact_param;
+} mlan_ds_ps_mgmt;
+
+/** mlan_ds_ps_info */
+typedef struct _mlan_ds_ps_info {
+	/** suspend allowed flag */
+	t_u32 is_suspend_allowed;
+} mlan_ds_ps_info;
+
+/** Type definition of mlan_ds_wakeup_reason for MLAN_OID_PM_HS_WAKEUP_REASON */
+typedef struct _mlan_ds_hs_wakeup_reason {
+	t_u16 hs_wakeup_reason;
+} mlan_ds_hs_wakeup_reason;
+
+/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
+typedef struct _mlan_ds_bcn_timeout {
+	/** Beacon miss timeout period window */
+	t_u16 bcn_miss_tmo_window;
+	/** Beacon miss timeout period */
+	t_u16 bcn_miss_tmo_period;
+	/** Beacon reacquire timeout period window */
+	t_u16 bcn_rq_tmo_window;
+	/** Beacon reacquire timeout period */
+	t_u16 bcn_rq_tmo_period;
+} mlan_ds_bcn_timeout, *pmlan_ds_bcn_timeout;
+
+/** Type definition of mlan_ds_pm_cfg for MLAN_IOCTL_PM_CFG */
+typedef struct _mlan_ds_pm_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Power management parameter */
+	union {
+		/** Power saving mode for MLAN_OID_PM_CFG_IEEE_PS */
+		t_u32 ps_mode;
+		/** Host Sleep configuration for MLAN_OID_PM_CFG_HS_CFG */
+		mlan_ds_hs_cfg hs_cfg;
+		/** Deep sleep mode for MLAN_OID_PM_CFG_DEEP_SLEEP */
+		mlan_ds_auto_ds auto_deep_sleep;
+		/** Inactivity timeout for MLAN_OID_PM_CFG_INACTIVITY_TO */
+		mlan_ds_inactivity_to inactivity_to;
+		/** Sleep period for MLAN_OID_PM_CFG_SLEEP_PD */
+		t_u32 sleep_period;
+		/** PS configuration parameters for MLAN_OID_PM_CFG_PS_CFG */
+		mlan_ds_ps_cfg ps_cfg;
+		/** PS configuration parameters for MLAN_OID_PM_CFG_SLEEP_PARAMS
+		 */
+		mlan_ds_sleep_params sleep_params;
+		/** PS configuration parameters for MLAN_OID_PM_CFG_PS_MODE */
+		mlan_ds_ps_mgmt ps_mgmt;
+		/** power info for MLAN_OID_PM_INFO */
+		mlan_ds_ps_info ps_info;
+		/** hs wakeup reason for MLAN_OID_PM_HS_WAKEUP_REASON */
+		mlan_ds_hs_wakeup_reason wakeup_reason;
+		/** config manamgement frame for hs wakeup */
+		mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER];
+		/** Beacon timout parameters for MLAN_OID_PM_CFG_BCN_TIMEOUT */
+		mlan_ds_bcn_timeout bcn_timeout;
+	} param;
+} mlan_ds_pm_cfg, *pmlan_ds_pm_cfg;
+
+#ifdef RX_PACKET_COALESCE
+typedef struct {
+	mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+
+	t_u32 pkt_threshold; /** Packet threshold */
+	t_u16 delay; /** Timeout value in milliseconds */
+} wlan_ioctl_rx_pkt_coalesce_config_t;
+#endif
+
+/*-----------------------------------------------------------------*/
+/** WMM Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** WMM TSpec size */
+#define MLAN_WMM_TSPEC_SIZE 63
+/** WMM Add TS extra IE bytes */
+#define MLAN_WMM_ADDTS_EXTRA_IE_BYTES 256
+/** WMM statistics for packets hist bins */
+#define MLAN_WMM_STATS_PKTS_HIST_BINS 7
+/** Maximum number of AC QOS queues available */
+#define MLAN_WMM_MAX_AC_QUEUES 4
+
+/**
+ *  @brief IOCTL structure to send an ADDTS request and retrieve the response.
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    instigate an ADDTS management frame with an appropriate TSPEC IE as well
+ *    as any additional IEs appended in the ADDTS Action frame.
+ *
+ *  @sa woal_wmm_addts_req_ioctl
+ */
+typedef struct {
+	mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+
+	t_u32 timeout_ms; /**< Timeout value in milliseconds */
+	t_u8 ieee_status_code; /**< IEEE status code */
+
+	t_u32 ie_data_len; /**< Length of ie block in ie_data */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE /**< TSPEC to send in the ADDTS */
+		     + MLAN_WMM_ADDTS_EXTRA_IE_BYTES]; /**< Extra IE buf*/
+} wlan_ioctl_wmm_addts_req_t;
+
+/**
+ *  @brief IOCTL structure to send a DELTS request.
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    instigate an DELTS management frame with an appropriate TSPEC IE.
+ *
+ *  @sa woal_wmm_delts_req_ioctl
+ */
+typedef struct {
+	mlan_cmd_result_e cmd_result; /**< Firmware execution result */
+	t_u8 ieee_reason_code; /**< IEEE reason code sent, unused for WMM */
+	t_u32 ie_data_len; /**< Length of ie block in ie_data */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE]; /**< TSPEC to send in the DELTS */
+} wlan_ioctl_wmm_delts_req_t;
+
+/**
+ *  @brief IOCTL structure to configure a specific AC Queue's parameters
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    get, set, or default the WMM AC queue parameters.
+ *
+ *  - msdu_lifetime_expiry is ignored if set to 0 on a set command
+ *
+ *  @sa woal_wmm_queue_config_ioctl
+ */
+typedef struct {
+	mlan_wmm_queue_config_action_e action; /**< Set, Get, or Default */
+	mlan_wmm_ac_e access_category; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */
+	t_u16 msdu_lifetime_expiry; /**< lifetime expiry in TUs */
+	t_u8 supported_rates[10]; /**< Not supported yet */
+} wlan_ioctl_wmm_queue_config_t;
+
+/**
+ *  @brief IOCTL structure to start, stop, and get statistics for a WMM AC
+ *
+ *  IOCTL structure from the application layer relayed to firmware to
+ *    start or stop statistical collection for a given AC.  Also used to
+ *    retrieve and clear the collected stats on a given AC.
+ *
+ *  @sa woal_wmm_queue_stats_ioctl
+ */
+typedef struct {
+	/** Action of Queue Config : Start, Stop, or Get */
+	mlan_wmm_queue_stats_action_e action;
+	/** User Priority */
+	t_u8 user_priority;
+	/** Number of successful packets transmitted */
+	t_u16 pkt_count;
+	/** Packets lost; not included in pkt_count */
+	t_u16 pkt_loss;
+	/** Average Queue delay in microseconds */
+	t_u32 avg_queue_delay;
+	/** Average Transmission delay in microseconds */
+	t_u32 avg_tx_delay;
+	/** Calculated used time in units of 32 microseconds */
+	t_u16 used_time;
+	/** Calculated policed time in units of 32 microseconds */
+	t_u16 policed_time;
+	/** Queue Delay Histogram; number of packets per queue delay range
+	 *
+	 *  [0] -  0ms <= delay < 5ms
+	 *  [1] -  5ms <= delay < 10ms
+	 *  [2] - 10ms <= delay < 20ms
+	 *  [3] - 20ms <= delay < 30ms
+	 *  [4] - 30ms <= delay < 40ms
+	 *  [5] - 40ms <= delay < 50ms
+	 *  [6] - 50ms <= delay < msduLifetime (TUs)
+	 */
+	t_u16 delay_histogram[MLAN_WMM_STATS_PKTS_HIST_BINS];
+} wlan_ioctl_wmm_queue_stats_t,
+	/** Type definition of mlan_ds_wmm_queue_stats
+	 *  for MLAN_OID_WMM_CFG_QUEUE_STATS
+	 */
+mlan_ds_wmm_queue_stats, *pmlan_ds_wmm_queue_stats;
+
+/**
+ *  @brief IOCTL sub structure for a specific WMM AC Status
+ */
+typedef struct {
+	/** WMM Acm */
+	t_u8 wmm_acm;
+	/** Flow required flag */
+	t_u8 flow_required;
+	/** Flow created flag */
+	t_u8 flow_created;
+	/** Disabled flag */
+	t_u8 disabled;
+} wlan_ioctl_wmm_queue_status_ac_t;
+
+/**
+ *  @brief IOCTL structure to retrieve the WMM AC Queue status
+ *
+ *  IOCTL structure from the application layer to retrieve:
+ *     - ACM bit setting for the AC
+ *     - Firmware status (flow required, flow created, flow disabled)
+ *
+ *  @sa woal_wmm_queue_status_ioctl
+ */
+typedef struct {
+	/** WMM AC queue status */
+	wlan_ioctl_wmm_queue_status_ac_t ac_status[MLAN_WMM_MAX_AC_QUEUES];
+} wlan_ioctl_wmm_queue_status_t,
+	/** Type definition of mlan_ds_wmm_queue_status
+	 *  for MLAN_OID_WMM_CFG_QUEUE_STATUS
+	 */
+mlan_ds_wmm_queue_status, *pmlan_ds_wmm_queue_status;
+
+/** Type definition of mlan_ds_wmm_addts for MLAN_OID_WMM_CFG_ADDTS */
+typedef struct _mlan_ds_wmm_addts {
+	/** Result of ADDTS request */
+	mlan_cmd_result_e result;
+	/** Timeout value in milliseconds */
+	t_u32 timeout;
+	/** IEEE status code */
+	t_u32 status_code;
+	/** Dialog token */
+	t_u8 dialog_tok;
+	/** TSPEC data length */
+	t_u32 ie_data_len;
+	/** TSPEC to send in the ADDTS + buffering for any extra IEs */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE + MLAN_WMM_ADDTS_EXTRA_IE_BYTES];
+} mlan_ds_wmm_addts, *pmlan_ds_wmm_addts;
+
+/** Type definition of mlan_ds_wmm_delts for MLAN_OID_WMM_CFG_DELTS */
+typedef struct _mlan_ds_wmm_delts {
+	/** Result of DELTS request */
+	mlan_cmd_result_e result;
+	/** IEEE status code */
+	t_u32 status_code;
+	/** TSPEC data length */
+	t_u8 ie_data_len;
+	/** TSPEC to send in the DELTS */
+	t_u8 ie_data[MLAN_WMM_TSPEC_SIZE];
+} mlan_ds_wmm_delts, *pmlan_ds_wmm_delts;
+
+/** Type definition of mlan_ds_wmm_queue_config
+ *  for MLAN_OID_WMM_CFG_QUEUE_CONFIG
+ */
+typedef struct _mlan_ds_wmm_queue_config {
+	/** Action of Queue Config : Set, Get, or Default */
+	mlan_wmm_queue_config_action_e action;
+	/** WMM Access Category: WMM_AC_BK(0) to WMM_AC_VO(3) */
+	mlan_wmm_ac_e access_category;
+	/** Lifetime expiry in TUs */
+	t_u16 msdu_lifetime_expiry;
+	/** Reserve for future use */
+	t_u8 reserved[10];
+} mlan_ds_wmm_queue_config, *pmlan_ds_wmm_queue_config;
+
+/** Type definition of mlan_ds_wmm_cfg for MLAN_IOCTL_WMM_CFG */
+typedef struct _mlan_ds_wmm_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** WMM configuration parameter */
+	union {
+		/** WMM enable for MLAN_OID_WMM_CFG_ENABLE */
+		t_u32 wmm_enable;
+		/** QoS configuration for MLAN_OID_WMM_CFG_QOS */
+		t_u8 qos_cfg;
+		/** WMM add TS for MLAN_OID_WMM_CFG_ADDTS */
+		mlan_ds_wmm_addts addts;
+		/** WMM delete TS for MLAN_OID_WMM_CFG_DELTS */
+		mlan_ds_wmm_delts delts;
+		/** WMM queue configuration for MLAN_OID_WMM_CFG_QUEUE_CONFIG */
+		mlan_ds_wmm_queue_config q_cfg;
+		/** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
+		 * WMM_AC_VO */
+		wmm_ac_parameters_t ac_params[MAX_AC_QUEUES];
+		/** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATS */
+		mlan_ds_wmm_queue_stats q_stats;
+		/** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATUS */
+		mlan_ds_wmm_queue_status q_status;
+		/** WMM TS status for MLAN_OID_WMM_CFG_TS_STATUS */
+		mlan_ds_wmm_ts_status ts_status;
+	} param;
+} mlan_ds_wmm_cfg, *pmlan_ds_wmm_cfg;
+
+/*-----------------------------------------------------------------*/
+/** WPS Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for WPS session */
+enum _mlan_wps_status {
+	MLAN_WPS_CFG_SESSION_START = 1,
+	MLAN_WPS_CFG_SESSION_END = 0
+};
+
+/** Type definition of mlan_ds_wps_cfg for MLAN_IOCTL_WPS_CFG */
+typedef struct _mlan_ds_wps_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** WPS configuration parameter */
+	union {
+		/** WPS session for MLAN_OID_WPS_CFG_SESSION */
+		t_u32 wps_session;
+	} param;
+} mlan_ds_wps_cfg, *pmlan_ds_wps_cfg;
+
+/*-----------------------------------------------------------------*/
+/** 802.11n Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Maximum MCS */
+#define NUM_MCS_FIELD 16
+
+/** Supported stream modes */
+#define HT_STREAM_MODE_1X1 0x11
+#define HT_STREAM_MODE_2X2 0x22
+
+/* Both 2.4G and 5G band selected */
+#define BAND_SELECT_BOTH 0
+/* Band 2.4G selected */
+#define BAND_SELECT_BG 1
+/* Band 5G selected */
+#define BAND_SELECT_A 2
+
+/** Type definition of mlan_ds_11n_htcap_cfg for MLAN_OID_11N_HTCAP_CFG */
+typedef struct _mlan_ds_11n_htcap_cfg {
+	/** HT Capability information */
+	t_u32 htcap;
+	/** Band selection */
+	t_u32 misc_cfg;
+	/** Hardware HT cap information required */
+	t_u32 hw_cap_req;
+} mlan_ds_11n_htcap_cfg, *pmlan_ds_11n_htcap_cfg;
+
+/** Type definition of mlan_ds_11n_addba_param
+ * for MLAN_OID_11N_CFG_ADDBA_PARAM
+ */
+typedef struct _mlan_ds_11n_addba_param {
+	/** Timeout */
+	t_u32 timeout;
+	/** Buffer size for ADDBA request */
+	t_u32 txwinsize;
+	/** Buffer size for ADDBA response */
+	t_u32 rxwinsize;
+	/** amsdu for ADDBA request */
+	t_u8 txamsdu;
+	/** amsdu for ADDBA response */
+	t_u8 rxamsdu;
+} mlan_ds_11n_addba_param, *pmlan_ds_11n_addba_param;
+
+/** Type definition of mlan_ds_11n_tx_cfg for MLAN_OID_11N_CFG_TX */
+typedef struct _mlan_ds_11n_tx_cfg {
+	/** HTTxCap */
+	t_u16 httxcap;
+	/** HTTxInfo */
+	t_u16 httxinfo;
+	/** Band selection */
+	t_u32 misc_cfg;
+} mlan_ds_11n_tx_cfg, *pmlan_ds_11n_tx_cfg;
+
+/** BF Global Configuration */
+#define BF_GLOBAL_CONFIGURATION 0x00
+/** Performs NDP sounding for PEER specified */
+#define TRIGGER_SOUNDING_FOR_PEER 0x01
+/** TX BF interval for channel sounding */
+#define SET_GET_BF_PERIODICITY 0x02
+/** Tell FW not to perform any sounding for peer */
+#define TX_BF_FOR_PEER_ENBL 0x03
+/** TX BF SNR threshold for peer */
+#define SET_SNR_THR_PEER 0x04
+/** TX Sounding*/
+#define TX_SOUNDING_CFG 0x05
+
+/* Maximum number of peer MAC and status/SNR tuples */
+#define MAX_PEER_MAC_TUPLES 10
+
+/** Any new subcommand structure should be declare here */
+
+/** bf global cfg args */
+typedef struct _mlan_bf_global_cfg_args {
+	/** Global enable/disable bf */
+	t_u8 bf_enbl;
+	/** Global enable/disable sounding */
+	t_u8 sounding_enbl;
+	/** FB Type */
+	t_u8 fb_type;
+	/** SNR Threshold */
+	t_u8 snr_threshold;
+	/** Sounding interval in milliseconds */
+	t_u16 sounding_interval;
+	/** BF mode */
+	t_u8 bf_mode;
+	/** Reserved */
+	t_u8 reserved;
+} mlan_bf_global_cfg_args;
+
+/** trigger sounding args */
+typedef struct _mlan_trigger_sound_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Status */
+	t_u8 status;
+} mlan_trigger_sound_args;
+
+/** bf periodicity args */
+typedef struct _mlan_bf_periodicity_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Current Tx BF Interval in milliseconds */
+	t_u16 interval;
+	/** Status */
+	t_u8 status;
+} mlan_bf_periodicity_args;
+
+/** tx bf peer args */
+typedef struct _mlan_tx_bf_peer_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Reserved */
+	t_u16 reserved;
+	/** Enable/Disable Beamforming */
+	t_u8 bf_enbl;
+	/** Enable/Disable sounding */
+	t_u8 sounding_enbl;
+	/** FB Type */
+	t_u8 fb_type;
+} mlan_tx_bf_peer_args;
+
+/** SNR threshold args */
+typedef struct _mlan_snr_thr_args {
+	/** Peer MAC address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** SNR for peer */
+	t_u8 snr;
+} mlan_snr_thr_args;
+
+/** Type definition of mlan_ds_11n_tx_bf_cfg for MLAN_OID_11N_CFG_TX_BF_CFG */
+typedef struct _mlan_ds_11n_tx_bf_cfg {
+	/** BF Action */
+	t_u16 bf_action;
+	/** Action */
+	t_u16 action;
+	/** Number of peers */
+	t_u32 no_of_peers;
+	union {
+		mlan_bf_global_cfg_args bf_global_cfg;
+		mlan_trigger_sound_args bf_sound[MAX_PEER_MAC_TUPLES];
+		mlan_bf_periodicity_args bf_periodicity[MAX_PEER_MAC_TUPLES];
+		mlan_tx_bf_peer_args tx_bf_peer[MAX_PEER_MAC_TUPLES];
+		mlan_snr_thr_args bf_snr[MAX_PEER_MAC_TUPLES];
+	} body;
+} mlan_ds_11n_tx_bf_cfg, *pmlan_ds_11n_tx_bf_cfg;
+
+/** Type definition of mlan_ds_11n_amsdu_aggr_ctrl for
+ * MLAN_OID_11N_AMSDU_AGGR_CTRL*/
+typedef struct _mlan_ds_11n_amsdu_aggr_ctrl {
+	/** Enable/Disable */
+	t_u16 enable;
+	/** Current AMSDU size valid */
+	t_u16 curr_buf_size;
+} mlan_ds_11n_amsdu_aggr_ctrl, *pmlan_ds_11n_amsdu_aggr_ctrl;
+
+/** Type definition of mlan_ds_11n_aggr_prio_tbl
+ *  for MLAN_OID_11N_CFG_AGGR_PRIO_TBL
+ */
+typedef struct _mlan_ds_11n_aggr_prio_tbl {
+	/** ampdu priority table */
+	t_u8 ampdu[MAX_NUM_TID];
+	/** amsdu priority table */
+	t_u8 amsdu[MAX_NUM_TID];
+} mlan_ds_11n_aggr_prio_tbl, *pmlan_ds_11n_aggr_prio_tbl;
+
+/** DelBA All TIDs */
+#define DELBA_ALL_TIDS 0xff
+/** DelBA Tx */
+#define DELBA_TX MBIT(0)
+/** DelBA Rx */
+#define DELBA_RX MBIT(1)
+
+/** Type definition of mlan_ds_11n_delba for MLAN_OID_11N_CFG_DELBA */
+typedef struct _mlan_ds_11n_delba {
+	/** TID */
+	t_u8 tid;
+	/** Peer MAC address */
+	t_u8 peer_mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** Direction (Tx: bit 0, Rx: bit 1) */
+	t_u8 direction;
+} mlan_ds_11n_delba, *pmlan_ds_11n_delba;
+
+/** Type definition of mlan_ds_delba for MLAN_OID_11N_CFG_REJECT_ADDBA_REQ */
+typedef struct _mlan_ds_reject_addba_req {
+	/** Bit0    : host sleep activated
+	 *  Bit1    : auto reconnect enabled
+	 *  Others  : reserved
+	 */
+	t_u32 conditions;
+} mlan_ds_reject_addba_req, *pmlan_ds_reject_addba_req;
+
+/** Type definition of mlan_ds_ibss_ampdu_param */
+typedef struct _mlan_ds_ibss_ampdu_param {
+	/** ampdu priority table */
+	t_u8 ampdu[MAX_NUM_TID];
+	/** rx amdpdu setting */
+	t_u8 addba_reject[MAX_NUM_TID];
+} mlan_ds_ibss_ampdu_param, *pmlan_ds_ibss_ampdu_param;
+
+/** Type definition of mlan_ds_11n_cfg for MLAN_IOCTL_11N_CFG */
+typedef struct _mlan_ds_11n_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11n configuration parameter */
+	union {
+		/** Tx param for 11n for MLAN_OID_11N_CFG_TX */
+		mlan_ds_11n_tx_cfg tx_cfg;
+		/** Aggr priority table for MLAN_OID_11N_CFG_AGGR_PRIO_TBL */
+		mlan_ds_11n_aggr_prio_tbl aggr_prio_tbl;
+		/** Add BA param for MLAN_OID_11N_CFG_ADDBA_PARAM */
+		mlan_ds_11n_addba_param addba_param;
+		/** Add BA Reject paramters for MLAN_OID_11N_CFG_ADDBA_REJECT */
+		t_u8 addba_reject[MAX_NUM_TID];
+		/** Tx buf size for MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE */
+		t_u32 tx_buf_size;
+		/** HT cap info configuration for MLAN_OID_11N_HTCAP_CFG */
+		mlan_ds_11n_htcap_cfg htcap_cfg;
+		/** Tx param for 11n for MLAN_OID_11N_AMSDU_AGGR_CTRL */
+		mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
+		/** Supported MCS Set field */
+		t_u8 supported_mcs_set[NUM_MCS_FIELD];
+		/** Transmit Beamforming Capabilities field */
+		t_u32 tx_bf_cap;
+		/** Transmit Beamforming configuration */
+		mlan_ds_11n_tx_bf_cfg tx_bf;
+		/** HT stream configuration */
+		t_u32 stream_cfg;
+		/** DelBA for MLAN_OID_11N_CFG_DELBA */
+		mlan_ds_11n_delba del_ba;
+		/** Reject Addba Req for MLAN_OID_11N_CFG_REJECT_ADDBA_REQ */
+		mlan_ds_reject_addba_req reject_addba_req;
+		/** Control coex RX window size configuration */
+		t_u32 coex_rx_winsize;
+		/** Control TX AMPDU configuration */
+		t_u32 txaggrctrl;
+		/** aggrprirotity table for MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM */
+		mlan_ds_ibss_ampdu_param ibss_ampdu;
+		/** Minimum BA Threshold for MLAN_OID_11N_CFG_MIN_BA_THRESHOLD
+		 */
+		t_u8 min_ba_threshold;
+	} param;
+} mlan_ds_11n_cfg, *pmlan_ds_11n_cfg;
+
+#define NUM_MCS_SUPP 20
+#define VHT_MCS_SET_LEN 8
+
+/** Type definition of mlan_ds_11ac_vhtcap_cfg for MLAN_OID_11AC_VHTCAP_CFG */
+typedef struct _mlan_ds_11ac_vhtcap_cfg {
+	/** HT Capability information */
+	t_u32 vhtcap;
+	/** Band selection */
+	t_u32 misc_cfg;
+	/** Hardware HT cap information required */
+	t_u32 hw_cap_req;
+} mlan_ds_11ac_vhtcap_cfg, *pmlan_ds_11ac_vhtcap_cfg;
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG_TX */
+typedef struct _mlan_ds_11ac_tx_cfg {
+	/** Band selection */
+	t_u8 band_cfg;
+	/** misc configuration */
+	t_u8 misc_cfg;
+	/** HTTxCap */
+	t_u16 vhttxcap;
+	/** HTTxInfo */
+	t_u16 vhttxinfo;
+} mlan_ds_11ac_tx_cfg, *pmlan_ds_11ac_tx_cfg;
+
+/** Tx */
+#define MLAN_RADIO_TX MBIT(0)
+/** Rx */
+#define MLAN_RADIO_RX MBIT(1)
+/** Tx & Rx */
+#define MLAN_RADIO_TXRX (MLAN_RADIO_TX | MLAN_RADIO_RX)
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG */
+typedef struct _mlan_ds_11ac_vht_cfg {
+	/** Band selection (1: 2.4G, 2: 5 G, 3: both 2.4G and 5G) */
+	t_u32 band;
+	/** TxRx (1: Tx, 2: Rx, 3: both Tx and Rx) */
+	t_u32 txrx;
+	/** BW CFG (0: 11N CFG, 1: vhtcap) */
+	t_u32 bwcfg;
+	/** VHT capabilities. */
+	t_u32 vht_cap_info;
+	/** VHT Tx mcs */
+	t_u32 vht_tx_mcs;
+	/** VHT Rx mcs */
+	t_u32 vht_rx_mcs;
+	/** VHT rx max rate */
+	t_u16 vht_rx_max_rate;
+	/** VHT max tx rate */
+	t_u16 vht_tx_max_rate;
+	/** Skip usr 11ac mcs cfg */
+	t_bool skip_usr_11ac_mcs_cfg;
+} mlan_ds_11ac_vht_cfg, *pmlan_ds_11ac_vht_cfg;
+
+/** Type definition of mlan_ds_11ac_tx_cfg for MLAN_OID_11AC_CFG */
+typedef struct _mlan_ds_11ac_opermode_cfg {
+	/** channel width: 1-20MHz, 2-40MHz, 3-80MHz, 4-160MHz or 80+80MHz */
+	t_u8 bw;
+	/** Rx NSS */
+	t_u8 nss;
+} mlan_ds_11ac_opermode_cfg, *pmlan_ds_11ac_opermode_cfg;
+
+/** Type definition of mlan_ds_11ac_cfg for MLAN_IOCTL_11AC_CFG */
+typedef struct _mlan_ds_11ac_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11n configuration parameter */
+	union {
+		/** VHT configuration for MLAN_OID_11AC_VHT_CFG */
+		mlan_ds_11ac_vht_cfg vht_cfg;
+		/** Supported MCS Set field */
+		t_u8 supported_mcs_set[NUM_MCS_SUPP];
+		/** Oper mode configuration for MLAN_OID_11AC_OPERMODE_CFG */
+		mlan_ds_11ac_opermode_cfg opermode_cfg;
+	} param;
+} mlan_ds_11ac_cfg, *pmlan_ds_11ac_cfg;
+
+/** Type definition of mlan_ds_11ax_he_capa for MLAN_OID_11AX_HE_CFG */
+typedef MLAN_PACK_START struct _mlan_ds_11ax_he_capa {
+	/** tlv id of he capability */
+	t_u16 id;
+	/** length of the payload */
+	t_u16 len;
+	/** extension id */
+	t_u8 ext_id;
+	/** he mac capability info */
+	t_u8 he_mac_cap[6];
+	/** he phy capability info */
+	t_u8 he_phy_cap[11];
+	/** he txrx mcs support for 80MHz */
+	t_u8 he_txrx_mcs_support[4];
+	/** val for txrx mcs 160Mhz or 80+80, and PPE thresholds */
+	t_u8 val[28];
+} MLAN_PACK_END mlan_ds_11ax_he_capa, *pmlan_ds_11ax_he_capa;
+
+/** Type definition of mlan_ds_11ax_he_cfg for MLAN_OID_11AX_HE_CFG */
+typedef struct _mlan_ds_11ax_he_cfg {
+	/** band, BIT0:2.4G, BIT1:5G*/
+	t_u8 band;
+	/** mlan_ds_11ax_he_capa */
+	mlan_ds_11ax_he_capa he_cap;
+} mlan_ds_11ax_he_cfg, *pmlan_ds_11ax_he_cfg;
+/** Type definition of mlan_ds_11as_cfg for MLAN_IOCTL_11AX_CFG */
+typedef struct _mlan_ds_11ax_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11n configuration parameter */
+	union {
+		/** HE configuration for MLAN_OID_11AX_HE_CFG */
+		mlan_ds_11ax_he_cfg he_cfg;
+	} param;
+} mlan_ds_11ax_cfg, *pmlan_ds_11ax_cfg;
+
+#define MLAN_11AXCMD_CFG_ID_SR_OBSS_PD_OFFSET 1
+#define MLAN_11AXCMD_CFG_ID_SR_ENABLE 2
+#define MLAN_11AXCMD_CFG_ID_BEAM_CHANGE 3
+#define MLAN_11AXCMD_CFG_ID_HTC_ENABLE 4
+#define MLAN_11AXCMD_CFG_ID_TXOP_RTS 5
+#define MLAN_11AXCMD_CFG_ID_TX_OMI 6
+#define MLAN_11AXCMD_CFG_ID_OBSSNBRU_TOLTIME 7
+
+#define MLAN_11AXCMD_SR_SUBID 0x102
+#define MLAN_11AXCMD_BEAM_SUBID 0x103
+#define MLAN_11AXCMD_HTC_SUBID 0x104
+#define MLAN_11AXCMD_TXOMI_SUBID 0x105
+#define MLAN_11AXCMD_OBSS_TOLTIME_SUBID 0x106
+#define MLAN_11AXCMD_TXOPRTS_SUBID 0x108
+
+#define MLAN_11AX_TWT_SETUP_SUBID 0x114
+#define MLAN_11AX_TWT_TEARDOWN_SUBID 0x115
+
+#define MRVL_DOT11AX_ENABLE_SR_TLV_ID (PROPRIETARY_TLV_BASE_ID + 322)
+#define MRVL_DOT11AX_OBSS_PD_OFFSET_TLV_ID (PROPRIETARY_TLV_BASE_ID + 323)
+
+/** Type definition of mlan_11axcmdcfg_obss_pd_offset for MLAN_OID_11AX_CMD_CFG
+ */
+typedef struct MLAN_PACK_START _mlan_11axcmdcfg_obss_pd_offset {
+	/** <NON_SRG_OffSET, SRG_OFFSET> */
+	t_u8 offset[2];
+} MLAN_PACK_END mlan_11axcmdcfg_obss_pd_offset;
+
+/** Type definition of mlan_11axcmdcfg_sr_control for MLAN_OID_11AX_CMD_CFG */
+typedef struct MLAN_PACK_START _mlan_11axcmdcfg_sr_control {
+	/** 1 enable, 0 disable */
+	t_u8 control;
+} MLAN_PACK_END mlan_11axcmdcfg_sr_control;
+
+/** Type definition of mlan_ds_11ax_sr_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_11ax_sr_cmd {
+	/** type*/
+	t_u16 type;
+	/** length of TLV */
+	t_u16 len;
+	/** value */
+	union {
+		mlan_11axcmdcfg_obss_pd_offset obss_pd_offset;
+		mlan_11axcmdcfg_sr_control sr_control;
+	} param;
+} MLAN_PACK_END mlan_ds_11ax_sr_cmd, *pmlan_ds_11ax_sr_cmd;
+
+/** Type definition of mlan_ds_11ax_beam_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_beam_cmd {
+	/** command value: 1 is disable, 0 is enable*/
+	t_u8 value;
+} mlan_ds_11ax_beam_cmd, *pmlan_ds_11ax_beam_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_htc_cmd {
+	/** command value: 1 is enable, 0 is disable*/
+	t_u8 value;
+} mlan_ds_11ax_htc_cmd, *pmlan_ds_11ax_htc_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_txop_cmd {
+	/** Two byte rts threshold value of which only 10 bits, bit 0 to bit 9
+	 * are valid */
+	t_u16 rts_thres;
+} mlan_ds_11ax_txop_cmd, *pmlan_ds_11ax_txop_cmd;
+
+/** Type definition of mlan_ds_11ax_htc_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_txomi_cmd {
+	/* 11ax spec 9.2.4.6a.2 OM Control 12 bits. Bit 0 to bit 11 */
+	t_u16 omi;
+} mlan_ds_11ax_txomi_cmd, *pmlan_ds_11ax_txomi_cmd;
+
+/** Type definition of mlan_ds_11ax_toltime_cmd for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_toltime_cmd {
+	/* OBSS Narrow Bandwidth RU Tolerance Time */
+	t_u32 tol_time;
+} mlan_ds_11ax_toltime_cmd, *pmlan_ds_11ax_toltime_cmd;
+
+/** Type definition of mlan_ds_11ax_cmd_cfg for MLAN_OID_11AX_CMD_CFG */
+typedef struct _mlan_ds_11ax_cmd_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Sub-id */
+	t_u32 sub_id;
+	/** 802.11n configuration parameter */
+	union {
+		/** SR configuration for MLAN_11AXCMD_SR_SUBID */
+		mlan_ds_11ax_sr_cmd sr_cfg;
+		/** Beam configuration for MLAN_11AXCMD_BEAM_SUBID */
+		mlan_ds_11ax_beam_cmd beam_cfg;
+		/** HTC configuration for MLAN_11AXCMD_HTC_SUBID */
+		mlan_ds_11ax_htc_cmd htc_cfg;
+		/** txop RTS configuration for MLAN_11AXCMD_TXOPRTS_SUBID */
+		mlan_ds_11ax_txop_cmd txop_cfg;
+		/** tx omi configuration for MLAN_11AXCMD_TXOMI_SUBID */
+		mlan_ds_11ax_txomi_cmd txomi_cfg;
+		/** OBSS tolerance time configuration for
+		 * MLAN_11AXCMD_TOLTIME_SUBID */
+		mlan_ds_11ax_toltime_cmd toltime_cfg;
+	} param;
+} mlan_ds_11ax_cmd_cfg, *pmlan_ds_11ax_cmd_cfg;
+
+/** Type definition of mlan_ds_twt_setup for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twt_setup {
+	/** Implicit, 0: TWT session is explicit, 1: Session is implicit */
+	t_u8 implicit;
+	/** Announced, 0: Unannounced, 1: Announced TWT */
+	t_u8 announced;
+	/** Trigger Enabled, 0: Non-Trigger enabled, 1: Trigger enabled TWT */
+	t_u8 trigger_enabled;
+	/** TWT Information Disabled, 0: TWT info enabled, 1: TWT info disabled
+	 */
+	t_u8 twt_info_disabled;
+	/** Negotiation Type, 0: Future Individual TWT SP start time, 1: Next
+	 * Wake TBTT time */
+	t_u8 negotiation_type;
+	/** TWT Wakeup Duration, time after which the TWT requesting STA can
+	 * transition to doze state */
+	t_u8 twt_wakeup_duration;
+	/** Flow Identifier. Range: [0-7]*/
+	t_u8 flow_identifier;
+	/** Hard Constraint, 0: FW can tweak the TWT setup parameters if it is
+	 *rejected by AP.
+	 ** 1: Firmware should not tweak any parameters. */
+	t_u8 hard_constraint;
+	/** TWT Exponent, Range: [0-63] */
+	t_u8 twt_exponent;
+	/** TWT Mantissa Range: [0-sizeof(UINT16)] */
+	t_u16 twt_mantissa;
+    /** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
+	t_u8 twt_request;
+} MLAN_PACK_END mlan_ds_twt_setup, *pmlan_ds_twt_setup;
+
+/** Type definition of mlan_ds_twt_teardown for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twt_teardown {
+	/** TWT Flow Identifier. Range: [0-7] */
+	t_u8 flow_identifier;
+	/** Negotiation Type. 0: Future Individual TWT SP start time, 1: Next
+	 * Wake TBTT time */
+	t_u8 negotiation_type;
+	/** Tear down all TWT. 1: To teardown all TWT, 0 otherwise */
+	t_u8 teardown_all_twt;
+} MLAN_PACK_END mlan_ds_twt_teardown, *pmlan_ds_twt_teardown;
+
+/** Type definition of mlan_ds_twtcfg for MLAN_OID_11AX_TWT_CFG */
+typedef struct MLAN_PACK_START _mlan_ds_twtcfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Sub-id */
+	t_u32 sub_id;
+	/** TWT Setup/Teardown configuration parameter */
+	union {
+		/** TWT Setup config for Sub ID: MLAN_11AX_TWT_SETUP_SUBID */
+		mlan_ds_twt_setup twt_setup;
+		/** TWT Teardown config for Sub ID: MLAN_11AX_TWT_TEARDOWN_SUBID
+		 */
+		mlan_ds_twt_teardown twt_teardown;
+	} param;
+} MLAN_PACK_END mlan_ds_twtcfg, *pmlan_ds_twtcfg;
+
+/** Country code length */
+#define COUNTRY_CODE_LEN 3
+
+/*-----------------------------------------------------------------*/
+/** 802.11d Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Maximum subbands for 11d */
+#define MRVDRV_MAX_SUBBAND_802_11D 83
+
+/** Data structure for subband set */
+typedef struct _mlan_ds_subband_set_t {
+	/** First channel */
+	t_u8 first_chan;
+	/** Number of channels */
+	t_u8 no_of_chan;
+	/** Maximum Tx power in dBm */
+	t_u8 max_tx_pwr;
+} mlan_ds_subband_set_t;
+
+/** Domain regulatory information */
+typedef struct _mlan_ds_11d_domain_info {
+	/** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	/** Band that channels in sub_band belong to */
+	t_u8 band;
+	/** No. of subband in below */
+	t_u8 no_of_sub_band;
+	/** Subband data to send/last sent */
+	mlan_ds_subband_set_t sub_band[MRVDRV_MAX_SUBBAND_802_11D];
+} mlan_ds_11d_domain_info;
+
+/** Type definition of mlan_ds_11d_cfg for MLAN_IOCTL_11D_CFG */
+typedef struct _mlan_ds_11d_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** 802.11d configuration parameter */
+	union {
+#ifdef STA_SUPPORT
+		/** Enable for MLAN_OID_11D_CFG_ENABLE */
+		t_u32 enable_11d;
+#endif				/* STA_SUPPORT */
+		/** Domain info for MLAN_OID_11D_DOMAIN_INFO_EXT */
+		mlan_ds_11d_domain_info domain_info;
+#ifdef UAP_SUPPORT
+		/** tlv data for MLAN_OID_11D_DOMAIN_INFO */
+		t_u8 domain_tlv[MAX_IE_SIZE];
+#endif				/* UAP_SUPPORT */
+	} param;
+} mlan_ds_11d_cfg, *pmlan_ds_11d_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Register Memory Access Group */
+/*-----------------------------------------------------------------*/
+/** Enumeration for CSU target device type */
+enum _mlan_csu_target_type {
+	MLAN_CSU_TARGET_CAU = 1,
+	MLAN_CSU_TARGET_PSU,
+};
+
+/** Enumeration for register type */
+enum _mlan_reg_type {
+	MLAN_REG_MAC = 1,
+	MLAN_REG_BBP,
+	MLAN_REG_RF,
+	MLAN_REG_CAU = 5,
+	MLAN_REG_PSU = 6,
+	MLAN_REG_BCA = 7,
+#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || defined(PCIE9097) || defined(USB9097) || defined(SD9097)
+	MLAN_REG_MAC2 = 0x81,
+	MLAN_REG_BBP2 = 0x82,
+	MLAN_REG_RF2 = 0x83,
+	MLAN_REG_BCA2 = 0x87
+#endif
+};
+
+/** Type definition of mlan_ds_reg_rw for MLAN_OID_REG_RW */
+typedef struct _mlan_ds_reg_rw {
+	/** Register type */
+	t_u32 type;
+	/** Offset */
+	t_u32 offset;
+	/** Value */
+	t_u32 value;
+} mlan_ds_reg_rw;
+
+/** Maximum EEPROM data */
+#define MAX_EEPROM_DATA 256
+
+/** Type definition of mlan_ds_read_eeprom for MLAN_OID_EEPROM_RD */
+typedef struct _mlan_ds_read_eeprom {
+	/** Multiples of 4 */
+	t_u16 offset;
+	/** Number of bytes */
+	t_u16 byte_count;
+	/** Value */
+	t_u8 value[MAX_EEPROM_DATA];
+} mlan_ds_read_eeprom;
+
+/** Type definition of mlan_ds_mem_rw for MLAN_OID_MEM_RW */
+typedef struct _mlan_ds_mem_rw {
+	/** Address */
+	t_u32 addr;
+	/** Value */
+	t_u32 value;
+} mlan_ds_mem_rw;
+
+/** Type definition of mlan_ds_reg_mem for MLAN_IOCTL_REG_MEM */
+typedef struct _mlan_ds_reg_mem {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Register memory access parameter */
+	union {
+		/** Register access for MLAN_OID_REG_RW */
+		mlan_ds_reg_rw reg_rw;
+		/** EEPROM access for MLAN_OID_EEPROM_RD */
+		mlan_ds_read_eeprom rd_eeprom;
+		/** Memory access for MLAN_OID_MEM_RW */
+		mlan_ds_mem_rw mem_rw;
+	} param;
+} mlan_ds_reg_mem, *pmlan_ds_reg_mem;
+
+/*-----------------------------------------------------------------*/
+/** Multi-Radio Configuration Group */
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+/** 802.11h Configuration Group */
+/*-----------------------------------------------------------------*/
+/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_DFS_TESTING */
+typedef struct _mlan_ds_11h_dfs_testing {
+	/** User-configured CAC period in milliseconds, 0 to use default */
+	t_u32 usr_cac_period_msec;
+	/** User-configured NOP period in seconds, 0 to use default */
+	t_u16 usr_nop_period_sec;
+	/** User-configured skip channel change, 0 to disable */
+	t_u8 usr_no_chan_change;
+	/** User-configured fixed channel to change to, 0 to use random channel
+	 */
+	t_u8 usr_fixed_new_chan;
+	/** User-configured cac restart */
+	t_u8 usr_cac_restart;
+} mlan_ds_11h_dfs_testing, *pmlan_ds_11h_dfs_testing;
+
+/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_CHAN_NOP_INFO */
+typedef struct _mlan_ds_11h_chan_nop_info {
+	/** current channel */
+	t_u8 curr_chan;
+	/** channel_width */
+	t_u8 chan_width;
+	/** flag for chan under nop */
+	t_bool chan_under_nop;
+	/** chan_ban_info for new channel */
+	chan_band_info new_chan;
+} mlan_ds_11h_chan_nop_info, *pmlan_ds_11h_chan_nop_info;
+
+typedef struct _mlan_ds_11h_chan_rep_req {
+	t_u16 startFreq;
+	Band_Config_t bandcfg;
+	t_u8 chanNum;
+	t_u32 millisec_dwell_time; /**< Channel dwell time in milliseconds */
+	t_u8 host_based;
+} mlan_ds_11h_chan_rep_req;
+
+typedef struct _mlan_ds_11h_dfs_w53_cfg {
+	/** dfs w53 cfg */
+	t_u8 dfs53cfg;
+} mlan_ds_11h_dfs_w53_cfg;
+
+/** Type definition of mlan_ds_11h_cfg for MLAN_IOCTL_11H_CFG */
+typedef struct _mlan_ds_11h_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	union {
+		/** Local power constraint for
+		 * MLAN_OID_11H_LOCAL_POWER_CONSTRAINT */
+		t_s8 usr_local_power_constraint;
+		/** User-configuation for MLAN_OID_11H_DFS_TESTING */
+		mlan_ds_11h_dfs_testing dfs_testing;
+		/** channel NOP information for MLAN_OID_11H_CHAN_NOP_INFO */
+		mlan_ds_11h_chan_nop_info ch_nop_info;
+		/** channel report req for MLAN_OID_11H_CHAN_REPORT_REQUEST */
+		mlan_ds_11h_chan_rep_req chan_rpt_req;
+		/** channel switch count for MLAN_OID_11H_CHAN_SWITCH_COUNT*/
+		t_s8 cs_count;
+		mlan_ds_11h_dfs_w53_cfg dfs_w53_cfg;
+	} param;
+} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg;
+
+/*-----------------------------------------------------------------*/
+/** Miscellaneous Configuration Group */
+/*-----------------------------------------------------------------*/
+
+/** CMD buffer size */
+#define MLAN_SIZE_OF_CMD_BUFFER (3 * 1024)
+
+/** LDO Internal */
+#define LDO_INTERNAL 0
+/** LDO External */
+#define LDO_EXTERNAL 1
+
+/** Enumeration for IE type */
+enum _mlan_ie_type {
+	MLAN_IE_TYPE_GEN_IE = 0,
+#ifdef STA_SUPPORT
+	MLAN_IE_TYPE_ARP_FILTER,
+#endif /* STA_SUPPORT */
+};
+
+/** Type definition of mlan_ds_misc_gen_ie for MLAN_OID_MISC_GEN_IE */
+typedef struct _mlan_ds_misc_gen_ie {
+	/** IE type */
+	t_u32 type;
+	/** IE length */
+	t_u32 len;
+	/** IE buffer */
+	t_u8 ie_data[MAX_IE_SIZE];
+} mlan_ds_misc_gen_ie;
+
+#ifdef SDIO
+/** Type definition of mlan_ds_misc_sdio_mpa_ctrl
+ *  for MLAN_OID_MISC_SDIO_MPA_CTRL
+ */
+typedef struct _mlan_ds_misc_sdio_mpa_ctrl {
+	/** SDIO MP-A TX enable/disable */
+	t_u16 tx_enable;
+	/** SDIO MP-A RX enable/disable */
+	t_u16 rx_enable;
+	/** SDIO MP-A TX buf size */
+	t_u16 tx_buf_size;
+	/** SDIO MP-A RX buf size */
+	t_u16 rx_buf_size;
+	/** SDIO MP-A TX Max Ports */
+	t_u16 tx_max_ports;
+	/** SDIO MP-A RX Max Ports */
+	t_u16 rx_max_ports;
+} mlan_ds_misc_sdio_mpa_ctrl;
+#endif
+
+/** Type definition of mlan_ds_misc_cmd for MLAN_OID_MISC_HOST_CMD */
+typedef struct _mlan_ds_misc_cmd {
+	/** Command length */
+	t_u32 len;
+	/** Command buffer */
+	t_u8 cmd[MRVDRV_SIZE_OF_CMD_BUFFER];
+} mlan_ds_misc_cmd;
+
+/** Maximum number of system clocks */
+#define MLAN_MAX_CLK_NUM 16
+
+/** Clock type : Configurable */
+#define MLAN_CLK_CONFIGURABLE 0
+/** Clock type : Supported */
+#define MLAN_CLK_SUPPORTED 1
+
+/** Type definition of mlan_ds_misc_sys_clock for MLAN_OID_MISC_SYS_CLOCK */
+typedef struct _mlan_ds_misc_sys_clock {
+	/** Current system clock */
+	t_u16 cur_sys_clk;
+	/** Clock type */
+	t_u16 sys_clk_type;
+	/** Number of clocks */
+	t_u16 sys_clk_num;
+	/** System clocks */
+	t_u16 sys_clk[MLAN_MAX_CLK_NUM];
+} mlan_ds_misc_sys_clock;
+
+/** Enumeration for function init/shutdown */
+enum _mlan_func_cmd {
+	MLAN_FUNC_INIT = 1,
+	MLAN_FUNC_SHUTDOWN,
+};
+
+/** Type definition of mlan_ds_misc_tx_datapause
+ * for MLAN_OID_MISC_TX_DATAPAUSE
+ */
+typedef struct _mlan_ds_misc_tx_datapause {
+	/** Tx data pause flag */
+	t_u16 tx_pause;
+	/** Max number of Tx buffers for all PS clients */
+	t_u16 tx_buf_cnt;
+} mlan_ds_misc_tx_datapause;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg
+ * for MLAN_OID_MISC_RX_ABORT_CFG
+ */
+typedef struct _mlan_ds_misc_rx_abort_cfg {
+	/** enable/disable rx abort */
+	t_u8 enable;
+	/** Rx weak RSSI pkt threshold */
+	t_s8 rssi_threshold;
+} mlan_ds_misc_rx_abort_cfg;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg_ext
+ * for MLAN_OID_MISC_RX_ABORT_CFG_EXT
+ */
+typedef struct _mlan_ds_misc_rx_abort_cfg_ext {
+	/** enable/disable dynamic rx abort */
+	t_u8 enable;
+	/** rssi margin */
+	t_s8 rssi_margin;
+	/** specify ceil rssi threshold */
+	t_s8 ceil_rssi_threshold;
+} mlan_ds_misc_rx_abort_cfg_ext;
+
+/** Type definition of mlan_ds_misc_rx_abort_cfg_ext
+ * for MLAN_OID_MISC_TX_AMDPU_PROT_MODE
+ */
+typedef struct _mlan_ds_misc_tx_ampdu_prot_mode {
+	/** set prot mode */
+	t_u16 mode;
+} mlan_ds_misc_tx_ampdu_prot_mode;
+
+/** Type definition of mlan_ds_misc_dot11mc_unassoc_ftm_cfg
+ * for MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG
+ */
+typedef struct _mlan_ds_misc_dot11mc_unassoc_ftm_cfg {
+	/** set the state */
+	t_u16 state;
+} mlan_ds_misc_dot11mc_unassoc_ftm_cfg;
+
+#define RATEADAPT_ALGO_LEGACY 0
+#define RATEADAPT_ALGO_SR 1
+
+/** Type definition of mlan_ds_misc_rate_adapt_cfg
+ * for MLAN_OID_MISC_RATE_ADAPT_CFG
+ */
+typedef struct _mlan_ds_misc_rate_adapt_cfg {
+	/** SR Rateadapt */
+	t_u8 sr_rateadapt;
+	/** set low threshold */
+	t_u8 ra_low_thresh;
+	/** set high threshold */
+	t_u8 ra_high_thresh;
+	/** set interval */
+	t_u16 ra_interval;
+} mlan_ds_misc_rate_adapt_cfg;
+
+/** Type definition of mlan_ds_misc_cck_desense_cfg
+ * for MLAN_OID_MISC_CCK_DESENSE_CFG
+ */
+typedef struct _mlan_ds_misc_cck_desense_cfg {
+	/** cck desense mode: 0:disable 1:normal 2:dynamic */
+	t_u16 mode;
+	/** specify rssi margin */
+	t_s8 margin;
+	/** specify ceil rssi threshold */
+	t_s8 ceil_thresh;
+	/** cck desense "on" interval count */
+	t_u8 num_on_intervals;
+	/** cck desense "off" interval count */
+	t_u8 num_off_intervals;
+} mlan_ds_misc_cck_desense_cfg;
+
+/** IP address length */
+#define IPADDR_LEN (16)
+/** Max number of ip */
+#define MAX_IPADDR (4)
+/** IP address type - NONE*/
+#define IPADDR_TYPE_NONE (0)
+/** IP address type - IPv4*/
+#define IPADDR_TYPE_IPV4 (1)
+/** IP operation remove */
+#define MLAN_IPADDR_OP_IP_REMOVE (0)
+/** IP operation ARP filter */
+#define MLAN_IPADDR_OP_ARP_FILTER MBIT(0)
+/** IP operation ARP response */
+#define MLAN_IPADDR_OP_AUTO_ARP_RESP MBIT(1)
+
+/** Type definition of mlan_ds_misc_ipaddr_cfg for MLAN_OID_MISC_IP_ADDR */
+typedef struct _mlan_ds_misc_ipaddr_cfg {
+	/** Operation code */
+	t_u32 op_code;
+	/** IP address type */
+	t_u32 ip_addr_type;
+	/** Number of IP */
+	t_u32 ip_addr_num;
+	/** IP address */
+	t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN];
+} mlan_ds_misc_ipaddr_cfg;
+
+/** Type definnition of mlan_ds_misc_ipv6_ra_offload for
+ * MLAN_OID_MISC_IPV6_RA_OFFLOAD*/
+typedef struct _mlan_ds_misc_ipv6_ra_offload {
+	/** 0: disable; 1: enable*/
+	t_u8 enable;
+	t_u8 ipv6_addr[16];
+} mlan_ds_misc_ipv6_ra_offload;
+
+/* MEF configuration disable */
+#define MEF_CFG_DISABLE 0
+/* MEF configuration Rx filter enable */
+#define MEF_CFG_RX_FILTER_ENABLE 1
+/* MEF configuration auto ARP response */
+#define MEF_CFG_AUTO_ARP_RESP 2
+/* MEF configuration host command */
+#define MEF_CFG_HOSTCMD 0xFFFF
+
+/** Type definition of mlan_ds_misc_mef_cfg for MLAN_OID_MISC_MEF_CFG */
+typedef struct _mlan_ds_misc_mef_cfg {
+	/** Sub-ID for operation */
+	t_u32 sub_id;
+	/** Parameter according to sub-ID */
+	union {
+		/** MEF command buffer for MEF_CFG_HOSTCMD */
+		mlan_ds_misc_cmd cmd_buf;
+	} param;
+} mlan_ds_misc_mef_cfg;
+
+/** Type definition of mlan_ds_misc_cfp_code for MLAN_OID_MISC_CFP_CODE */
+typedef struct _mlan_ds_misc_cfp_code {
+	/** CFP table code for 2.4GHz */
+	t_u32 cfp_code_bg;
+	/** CFP table code for 5GHz */
+	t_u32 cfp_code_a;
+} mlan_ds_misc_cfp_code;
+
+/** Type definition of mlan_ds_misc_arb_cfg
+ * for MLAN_OID_MISC_ARB_CFG
+ */
+typedef struct _mlan_ds_misc_arb_cfg {
+	/** arb mode 0-4 */
+	t_u32 arb_mode;
+} mlan_ds_misc_arb_cfg;
+
+/** Type definition of mlan_ds_misc_tp_state
+ *  for MLAN_OID_MISC_TP_STATE
+ */
+typedef struct _mlan_ds_misc_tp_state {
+	/** TP account mode 0-disable 1-enable */
+	t_u32 on;
+	/** Packet drop point */
+	t_u32 drop_point;
+} mlan_ds_misc_tp_state;
+
+/** Type definition of mlan_ds_misc_country_code
+ *  for MLAN_OID_MISC_COUNTRY_CODE
+ */
+typedef struct _mlan_ds_misc_country_code {
+	/** Country Code */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+} mlan_ds_misc_country_code;
+
+/** action for set */
+#define SUBSCRIBE_EVT_ACT_BITWISE_SET 0x0002
+/** action for clear */
+#define SUBSCRIBE_EVT_ACT_BITWISE_CLR 0x0003
+/** BITMAP for subscribe event rssi low */
+#define SUBSCRIBE_EVT_RSSI_LOW MBIT(0)
+/** BITMAP for subscribe event snr low */
+#define SUBSCRIBE_EVT_SNR_LOW MBIT(1)
+/** BITMAP for subscribe event max fail */
+#define SUBSCRIBE_EVT_MAX_FAIL MBIT(2)
+/** BITMAP for subscribe event beacon missed */
+#define SUBSCRIBE_EVT_BEACON_MISSED MBIT(3)
+/** BITMAP for subscribe event rssi high */
+#define SUBSCRIBE_EVT_RSSI_HIGH MBIT(4)
+/** BITMAP for subscribe event snr high */
+#define SUBSCRIBE_EVT_SNR_HIGH MBIT(5)
+/** BITMAP for subscribe event data rssi low */
+#define SUBSCRIBE_EVT_DATA_RSSI_LOW MBIT(6)
+/** BITMAP for subscribe event data snr low */
+#define SUBSCRIBE_EVT_DATA_SNR_LOW MBIT(7)
+/** BITMAP for subscribe event data rssi high */
+#define SUBSCRIBE_EVT_DATA_RSSI_HIGH MBIT(8)
+/** BITMAP for subscribe event data snr high */
+#define SUBSCRIBE_EVT_DATA_SNR_HIGH MBIT(9)
+/** BITMAP for subscribe event link quality */
+#define SUBSCRIBE_EVT_LINK_QUALITY MBIT(10)
+/** BITMAP for subscribe event pre_beacon_lost */
+#define SUBSCRIBE_EVT_PRE_BEACON_LOST MBIT(11)
+/** default PRE_BEACON_MISS_COUNT */
+#define DEFAULT_PRE_BEACON_MISS 30
+
+/** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */
+typedef struct _mlan_ds_subscribe_evt {
+	/** evt action */
+	t_u16 evt_action;
+	/** bitmap for subscribe event */
+	t_u16 evt_bitmap;
+	/** Absolute value of RSSI threshold value (dBm) */
+	t_u8 low_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 * N -- report only happend > N consecutive times
+	 */
+	t_u8 low_rssi_freq;
+	/** SNR threshold value (dB) */
+	t_u8 low_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 low_snr_freq;
+	/** Failure count threshold */
+	t_u8 failure_count;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 failure_count_freq;
+	/** num of missed beacons */
+	t_u8 beacon_miss;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 beacon_miss_freq;
+	/** Absolute value of RSSI threshold value (dBm) */
+	t_u8 high_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 high_rssi_freq;
+	/** SNR threshold value (dB) */
+	t_u8 high_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 high_snr_freq;
+	/** Absolute value of data RSSI threshold value (dBm) */
+	t_u8 data_low_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_low_rssi_freq;
+	/** Absolute value of data SNR threshold value (dBm) */
+	t_u8 data_low_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_low_snr_freq;
+	/** Absolute value of data RSSI threshold value (dBm) */
+	t_u8 data_high_rssi;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_high_rssi_freq;
+	/** Absolute value of data SNR threshold value (dBm) */
+	t_u8 data_high_snr;
+	/** 0--report once, 1--report everytime happen,
+	 *  N -- report only happend > N consecutive times
+	 */
+	t_u8 data_high_snr_freq;
+	/* Link SNR threshold (dB) */
+	t_u16 link_snr;
+	/* Link SNR frequency */
+	t_u16 link_snr_freq;
+	/* Second minimum rate value as per the rate table below */
+	t_u16 link_rate;
+	/* Second minimum rate frequency */
+	t_u16 link_rate_freq;
+	/* Tx latency value (us) */
+	t_u16 link_tx_latency;
+	/* Tx latency frequency */
+	t_u16 link_tx_lantency_freq;
+	/* Number of pre missed beacons */
+	t_u8 pre_beacon_miss;
+} mlan_ds_subscribe_evt;
+
+/** Max OTP user data length */
+#define MAX_OTP_USER_DATA_LEN 252
+
+/** Type definition of mlan_ds_misc_otp_user_data
+ * for MLAN_OID_MISC_OTP_USER_DATA
+ */
+typedef struct _mlan_ds_misc_otp_user_data {
+	/** Reserved */
+	t_u16 reserved;
+	/** OTP user data length */
+	t_u16 user_data_length;
+	/** User data buffer */
+	t_u8 user_data[MAX_OTP_USER_DATA_LEN];
+} mlan_ds_misc_otp_user_data;
+
+typedef struct _aggr_ctrl_cfg {
+	/** Enable */
+	t_u16 enable;
+	/** Aggregation alignment */
+	t_u16 aggr_align;
+	/** Aggregation max size */
+	t_u16 aggr_max_size;
+	/** Aggregation max packet number */
+	t_u16 aggr_max_num;
+	/** Aggrgation timeout, in microseconds */
+	t_u16 aggr_tmo;
+} aggr_ctrl_cfg;
+
+/** Type definition of mlan_ds_misc_aggr_ctrl
+ *  for MLAN_OID_MISC_AGGR_CTRL
+ */
+typedef struct _mlan_ds_misc_aggr_ctrl {
+	/** Tx aggregation control */
+	aggr_ctrl_cfg tx;
+} mlan_ds_misc_aggr_ctrl;
+
+#ifdef USB
+typedef struct _usb_aggr_ctrl_cfg {
+	/** Enable */
+	t_u16 enable;
+	/** Aggregation mode */
+	t_u16 aggr_mode;
+	/** Aggregation alignment */
+	t_u16 aggr_align;
+	/** Aggregation max packet/size */
+	t_u16 aggr_max;
+	/** Aggrgation timeout, in microseconds */
+	t_u16 aggr_tmo;
+} usb_aggr_ctrl_cfg;
+
+/** Type definition of mlan_ds_misc_usb_aggr_ctrl
+ *  for MLAN_OID_MISC_USB_AGGR_CTRL
+ */
+typedef struct _mlan_ds_misc_usb_aggr_ctrl {
+	/** Tx aggregation control */
+	usb_aggr_ctrl_cfg tx_aggr_ctrl;
+	/** Rx deaggregation control */
+	usb_aggr_ctrl_cfg rx_deaggr_ctrl;
+} mlan_ds_misc_usb_aggr_ctrl;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** flag for NOA */
+#define WIFI_DIRECT_NOA 1
+/** flag for OPP_PS */
+#define WIFI_DIRECT_OPP_PS 2
+/** Type definition of mlan_ds_wifi_direct_config
+ *  for MLAN_OID_MISC_WIFI_DIRECT_CONFIG
+ */
+typedef struct _mlan_ds_wifi_direct_config {
+	/** flags for NOA/OPP_PS */
+	t_u8 flags;
+	/** NoA enable/disable */
+	t_u8 noa_enable;
+	/** index */
+	t_u16 index;
+	/** NoA count */
+	t_u8 noa_count;
+	/** NoA duration */
+	t_u32 noa_duration;
+	/** NoA interval */
+	t_u32 noa_interval;
+	/** opp ps enable/disable */
+	t_u8 opp_ps_enable;
+	/** CT window value */
+	t_u8 ct_window;
+} mlan_ds_wifi_direct_config;
+#endif
+
+/** Type definition of mlan_ds_gpio_tsf_latch */
+typedef struct _mlan_ds_gpio_tsf_latch {
+    /**clock sync Mode */
+	t_u8 clock_sync_mode;
+    /**clock sync Role */
+	t_u8 clock_sync_Role;
+    /**clock sync GPIO Pin Number */
+	t_u8 clock_sync_gpio_pin_number;
+    /**clock sync GPIO Level or Toggle */
+	t_u8 clock_sync_gpio_level_toggle;
+    /**clock sync GPIO Pulse Width */
+	t_u16 clock_sync_gpio_pulse_width;
+} mlan_ds_gpio_tsf_latch;
+
+/** Type definition of mlan_ds_tsf_info */
+typedef struct _mlan_ds_tsf_info {
+	/**get tsf info format */
+	t_u16 tsf_format;
+	/**tsf info */
+	t_u16 tsf_info;
+	/**tsf */
+	t_u64 tsf;
+	/**Positive or negative offset in microsecond from Beacon TSF to GPIO toggle TSF  */
+	t_s32 tsf_offset;
+} mlan_ds_tsf_info;
+
+#if defined(STA_SUPPORT)
+typedef struct _mlan_ds_misc_pmfcfg {
+	/** Management Frame Protection Capable */
+	t_u8 mfpc;
+	/** Management Frame Protection Required */
+	t_u8 mfpr;
+} mlan_ds_misc_pmfcfg;
+#endif
+
+#define MAX_SSID_NUM 16
+#define MAX_AP_LIST 8
+
+/**Action ID for TDLS disable link*/
+#define WLAN_TDLS_DISABLE_LINK 0x00
+/**Action ID for TDLS enable link*/
+#define WLAN_TDLS_ENABLE_LINK 0x01
+/**Action ID for TDLS create link*/
+#define WLAN_TDLS_CREATE_LINK 0x02
+/**Action ID for TDLS config link*/
+#define WLAN_TDLS_CONFIG_LINK 0x03
+/*reason code*/
+#define MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
+/** TDLS operation buffer */
+typedef struct _mlan_ds_misc_tdls_oper {
+	/** TDLS Action */
+	t_u16 tdls_action;
+	/** TDLS peer address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** peer capability */
+	t_u16 capability;
+	/** peer qos info */
+	t_u8 qos_info;
+	/** peer extend capability */
+	t_u8 *ext_capab;
+	/** extend capability len */
+	t_u8 ext_capab_len;
+	/** support rates */
+	t_u8 *supported_rates;
+	/** supported rates len */
+	t_u8 supported_rates_len;
+	/** peer ht_cap */
+	t_u8 *ht_capa;
+	/** peer vht capability */
+	t_u8 *vht_cap;
+} mlan_ds_misc_tdls_oper;
+
+/** flag for TDLS extcap */
+#define TDLS_IE_FLAGS_EXTCAP 0x0001
+/** flag for TDLS HTCAP */
+#define TDLS_IE_FLAGS_HTCAP 0x0002
+/** flag for TDLS HTINFO */
+#define TDLS_IE_FLAGS_HTINFO 0x0004
+/** flag for TDLS VHTCAP */
+#define TDLS_IE_FLAGS_VHTCAP 0x0008
+/** flag for TDLS VHTOPRAT */
+#define TDLS_IE_FLAGS_VHTOPRAT 0x0010
+/** flag for TDLS AID inof */
+#define TDLS_IE_FLAGS_AID 0x0020
+/** flag for TDLS Supported channels and regulatory class IE*/
+#define TDLS_IE_FLAGS_SUPP_CS_IE 0x0040
+/** flag for TDLS Qos info */
+#define TDLS_IE_FLAGS_QOS_INFO 0x0080
+/** flag for TDLS SETUP */
+#define TDLS_IE_FLAGS_SETUP 0x0100
+
+/** TDLS ie buffer */
+typedef struct _mlan_ds_misc_tdls_ies {
+	/** TDLS peer address */
+	t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH];
+	/** flags for request IEs */
+	t_u16 flags;
+	/** Qos info */
+	t_u8 QosInfo;
+	/** Extended Capabilities IE */
+	t_u8 ext_cap[IEEE_MAX_IE_SIZE];
+	/** HT Capabilities IE */
+	t_u8 ht_cap[IEEE_MAX_IE_SIZE];
+	/** HT Information IE */
+	t_u8 ht_info[IEEE_MAX_IE_SIZE];
+	/** VHT Capabilities IE */
+	t_u8 vht_cap[IEEE_MAX_IE_SIZE];
+	/** VHT Operations IE */
+	t_u8 vht_oprat[IEEE_MAX_IE_SIZE];
+	/** aid Info */
+	t_u8 aid_info[IEEE_MAX_IE_SIZE];
+	/** supported channels */
+	t_u8 supp_chan[IEEE_MAX_IE_SIZE];
+	/** supported regulatory class */
+	t_u8 regulatory_class[IEEE_MAX_IE_SIZE];
+} mlan_ds_misc_tdls_ies;
+
+#ifdef RX_PACKET_COALESCE
+typedef struct _mlan_ds_misc_rx_packet_coalesce {
+	/** packet threshold */
+	t_u32 packet_threshold;
+	/** timeout value */
+	t_u16 delay;
+} mlan_ds_misc_rx_packet_coalesce;
+#endif
+
+typedef struct _mlan_ds_misc_dfs_repeater {
+	/** Set or Get */
+	t_u16 action;
+	/** 1 on or 0 off */
+	t_u16 mode;
+} mlan_ds_misc_dfs_repeater;
+
+#define WOWLAN_MAX_PATTERN_LEN 20
+#define WOWLAN_MAX_OFFSET_LEN 50
+#define MAX_NUM_FILTERS 10
+#define MEF_MODE_HOST_SLEEP (1 << 0)
+#define MEF_MODE_NON_HOST_SLEEP (1 << 1)
+#define MEF_ACTION_WAKE (1 << 0)
+#define MEF_ACTION_ALLOW (1 << 1)
+#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3
+#define MEF_AUTO_ARP 0x10
+#define MEF_AUTO_PING 0x20
+#define MEF_NS_RESP 0x40
+#define MEF_MAGIC_PKT 0x80
+#define CRITERIA_BROADCAST BIT(0)
+#define CRITERIA_UNICAST BIT(1)
+#define CRITERIA_MULTICAST BIT(3)
+
+#define MAX_NUM_ENTRIES 8
+#define MAX_NUM_BYTE_SEQ 6
+#define MAX_NUM_MASK_SEQ 6
+
+#define OPERAND_DNUM 1
+#define OPERAND_BYTE_SEQ 2
+
+#define MAX_OPERAND 0x40
+#define TYPE_BYTE_EQ (MAX_OPERAND + 1)
+#define TYPE_DNUM_EQ (MAX_OPERAND + 2)
+#define TYPE_BIT_EQ (MAX_OPERAND + 3)
+
+#define RPN_TYPE_AND (MAX_OPERAND + 4)
+#define RPN_TYPE_OR (MAX_OPERAND + 5)
+
+#define ICMP_OF_IP_PROTOCOL 0x01
+#define TCP_OF_IP_PROTOCOL 0x06
+#define UDP_OF_IP_PROTOCOL 0x11
+
+#define IPV4_PKT_OFFSET 20
+#define IP_PROTOCOL_OFFSET 31
+#define PORT_PROTOCOL_OFFSET 44
+
+#define FILLING_TYPE MBIT(0)
+#define FILLING_PATTERN MBIT(1)
+#define FILLING_OFFSET MBIT(2)
+#define FILLING_NUM_BYTES MBIT(3)
+#define FILLING_REPEAT MBIT(4)
+#define FILLING_BYTE_SEQ MBIT(5)
+#define FILLING_MASK_SEQ MBIT(6)
+
+/** Type definition of filter_item
+ *  Support three match methods:
+ *  <1>Byte comparison type=0x41
+ *  <2>Decimal comparison type=0x42
+ *  <3>Bit comparison type=0x43
+ */
+typedef struct _mef_filter_t {
+	/** flag*/
+	t_u32 fill_flag;
+	/** BYTE 0X41; Decimal 0X42; Bit 0x43*/
+	t_u16 type;
+	/** value*/
+	t_u32 pattern;
+	/** offset*/
+	t_u16 offset;
+	/** number of bytes*/
+	t_u16 num_bytes;
+	/** repeat*/
+	t_u16 repeat;
+	/** byte number*/
+	t_u8 num_byte_seq;
+	/** array*/
+	t_u8 byte_seq[MAX_NUM_BYTE_SEQ];
+	/** mask numbers*/
+	t_u8 num_mask_seq;
+	/** array*/
+	t_u8 mask_seq[MAX_NUM_MASK_SEQ];
+} mef_filter_t;
+
+typedef struct _mef_entry_t {
+	/** mode: bit0--hostsleep mode; bit1--non hostsleep mode */
+	t_u8 mode;
+	/** action: 0--discard and not wake host;
+		    1--discard and wake host;
+		    3--allow and wake host;*/
+	t_u8 action;
+	/** filter number */
+	t_u8 filter_num;
+	/** filter array*/
+	mef_filter_t filter_item[MAX_NUM_FILTERS];
+	/** rpn array*/
+	t_u8 rpn[MAX_NUM_FILTERS];
+} mef_entry_t;
+
+/** Type definition of mlan_ds_nvflt_mef_entry
+ *for MLAN_OID_MISC_MEF_FLT_CFG
+ */
+typedef struct _mlan_ds_misc_mef_flt_cfg {
+	/** Type of action*/
+	int mef_act_type;
+	/** Operation code*/
+	t_u32 op_code;
+	/** NV Filter Criteria*/
+	t_u32 criteria;
+	/** NV MEF entry*/
+	mef_entry_t mef_entry;
+} mlan_ds_misc_mef_flt_cfg;
+
+/** Enumeration for action type*/
+enum _mlan_act_mef_act_type {
+	MEF_ACT_ADD = 1,
+	MEF_ACT_ENABLE,
+	MEF_ACT_DISABLE,
+	MEF_ACT_CANCEL,
+	MEF_ACT_AUTOARP,
+	MEF_ACT_WOWLAN,
+	MEF_ACT_IPV6_NS,
+};
+
+typedef struct _mlan_ds_sensor_temp {
+	t_u32 temperature;
+} mlan_ds_sensor_temp;
+
+#define MLAN_KCK_LEN 16
+#define MLAN_KEK_LEN 16
+#define MLAN_REPLAY_CTR_LEN 8
+/** mlan_ds_misc_gtk_rekey_data */
+typedef struct _mlan_ds_misc_gtk_rekey_data {
+	/** key encryption key */
+	t_u8 kek[MLAN_KEK_LEN];
+	/** key confirmation key */
+	t_u8 kck[MLAN_KCK_LEN];
+	/** replay counter */
+	t_u8 replay_ctr[MLAN_REPLAY_CTR_LEN];
+} mlan_ds_misc_gtk_rekey_data;
+typedef struct _mlan_ds_bw_chan_oper {
+	/* bandwidth 20:20M 40:40M 80:80M */
+	t_u8 bandwidth;
+	/* channel number */
+	t_u8 channel;
+	/* Non-global operating class */
+	t_u8 oper_class;
+} mlan_ds_bw_chan_oper;
+
+typedef struct _mlan_ds_ind_rst_cfg {
+	/** Set or Get */
+	t_u16 action;
+	/** oob mode enable/ disable */
+	t_u8 ir_mode;
+	/** gpio pin */
+	t_u8 gpio_pin;
+} mlan_ds_ind_rst_cfg;
+
+#define MKEEP_ALIVE_IP_PKT_MAX 256
+typedef struct _mlan_ds_misc_keep_alive {
+	t_u8 mkeep_alive_id;
+	t_u8 enable;
+	/** enable/disable tcp reset*/
+	t_u8 reset;
+	/**True means saved in driver, false means not saved or download*/
+	t_u8 cached;
+	t_u32 send_interval;
+	t_u16 retry_interval;
+	t_u16 retry_count;
+	t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
+	t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
+	t_u16 pkt_len;
+	t_u8 packet[MKEEP_ALIVE_IP_PKT_MAX];
+	/** Ethernet type */
+	t_u16 ether_type;
+} mlan_ds_misc_keep_alive, *pmlan_ds_misc_keep_alive;
+
+/** TX and RX histogram statistic parameters*/
+typedef MLAN_PACK_START struct _mlan_ds_misc_tx_rx_histogram {
+	/** Enable or disable get tx/rx histogram statistic */
+	t_u8 enable;
+	/** Choose to get TX, RX or both histogram statistic */
+	t_u16 action;
+	/** Size of Tx/Rx info */
+	t_u16 size;
+	/** Store Tx/Rx info */
+	t_u8 value[1];
+} MLAN_PACK_END mlan_ds_misc_tx_rx_histogram;
+
+typedef MLAN_PACK_START struct _mlan_ds_cw_mode_ctrl {
+	/** Mode of Operation 0: Disable 1: Tx Continuous Packet 2: Tx
+	 * Continuous Wave */
+	t_u8 mode;
+	/*channel */
+	t_u8 channel;
+	/* channel info */
+	t_u8 chanInfo;
+	/** Tx Power level in dBm */
+	t_u16 txPower;
+	/** Packet Length */
+	t_u16 pktLength;
+	/** bit rate Info */
+	t_u32 rateInfo;
+} MLAN_PACK_END mlan_ds_cw_mode_ctrl;
+
+#define RX_PKT_INFO MBIT(1)
+/** Struct for per-packet configuration */
+typedef struct _mlan_per_pkt_cfg {
+	/** Type ID*/
+	t_u16 type;
+	/** Length of payload*/
+	t_u16 len;
+	/**  Tx/Rx per-packet control */
+	t_u8 tx_rx_control;
+	/** Number of ethernet types in ether_type array */
+	t_u8 proto_type_num;
+	/** Array of ether_type for per-packet control */
+	t_u16 ether_type[];
+} mlan_per_pkt_cfg;
+
+/** Type definition of mlan_ds_misc_robustcoex_params for MLAN_IOCTL_MISC_CFG */
+typedef struct _mlan_ds_misc_robustcoex_params {
+	t_u16 method;
+	/** enable/disable robustcoex gpio cfg */
+	t_u8 enable;
+	/** Number of GPIO */
+	t_u8 gpio_num;
+	/** Polarity of GPIO */
+	t_u8 gpio_polarity;
+} mlan_ds_misc_robustcoex_params;
+
+#if defined(PCIE)
+typedef struct _mlan_ds_ssu_params {
+	t_u32 nskip;
+	t_u32 nsel;
+	t_u32 adcdownsample;
+	t_u32 mask_adc_pkt;
+	t_u32 out_16bits;
+	t_u32 spec_pwr_enable;
+	t_u32 rate_deduction;
+	t_u32 n_pkt_avg;
+} mlan_ds_ssu_params;
+#endif
+
+typedef MLAN_PACK_START struct _mlan_ds_hal_phy_cfg_params {
+	/** 11b pwr spectral density mask enable/disable */
+	t_u8 dot11b_psd_mask_cfg;
+	/** reserved fields for future hal/phy cfg use */
+	t_u8 reserved[7];
+} MLAN_PACK_END mlan_ds_hal_phy_cfg_params;
+
+#define MAX_NUM_MAC 2
+/** Type definition of mlan_ds_misc_mapping_policy */
+typedef struct _mlan_ds_misc_mapping_policy {
+	/** Enable/disable dynamic mapping */
+	t_u16 subcmd;
+	/** Mapping policy */
+	t_u8 mapping_policy;
+} mlan_ds_misc_mapping_policy, *pmlan_ds_misc_mapping_policy;
+
+typedef struct _dmcsChanStatus_t {
+	/** Channel number */
+	t_u8 channel;
+	/** Number of ap on this channel */
+	t_u8 ap_count;
+	/** Number of sta on this channel */
+	t_u8 sta_count;
+} dmcsChanStatus_t, *pdmcsChanStatus_t;
+
+typedef struct _dmcsStatus_t {
+	/** Radio ID */
+	t_u8 radio_id;
+	/** Running mode
+	** 0 - Idle
+	** 1 - DBC
+	** 2 - DRCS
+	*/
+	t_u8 running_mode;
+	/** Current channel status */
+	dmcsChanStatus_t chan_status[2];
+} dmcsStatus_t, *pdmcsStatus_t;
+
+/** Type definition of mlan_ds_misc_dmcs_status */
+typedef struct _mlan_ds_misc_dmcs_status {
+	t_u8 mapping_policy;
+	dmcsStatus_t radio_status[MAX_NUM_MAC];
+} mlan_ds_misc_dmcs_status, *pmlan_ds_misc_dmcs_status;
+
+/** Type definition of mlan_ds_misc_chan_trpc_cfg for
+ * MLAN_OID_MISC_GET_CHAN_TRPC_CFG */
+typedef struct _mlan_ds_misc_chan_trpc_cfg {
+	/** sub_band */
+	t_u16 sub_band;
+	/** length */
+	t_u16 length;
+	/** buf */
+	t_u8 trpc_buf[2048];
+} mlan_ds_misc_chan_trpc_cfg;
+
+#define MFG_CMD_SET_TEST_MODE   1
+#define MFG_CMD_UNSET_TEST_MODE 0
+#define MFG_CMD_TX_ANT          0x1004
+#define MFG_CMD_RX_ANT          0x1005
+#define MFG_CMD_TX_CONT         0x1009
+#define MFG_CMD_RF_CHAN         0x100A
+#define MFG_CMD_CLR_RX_ERR      0x1010
+#define MFG_CMD_TX_FRAME        0x1021
+#define MFG_CMD_RFPWR           0x1033
+#define MFG_CMD_RF_BAND_AG      0x1034
+#define MFG_CMD_RF_CHANNELBW    0x1044
+#define MFG_CMD_RADIO_MODE_CFG  0x1211
+#define MFG_CMD_CONFIG_MAC_HE_TB_TX 0x110A
+/** MFG CMD generic cfg */
+struct MLAN_PACK_START mfg_cmd_generic_cfg {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** value 1 */
+	t_u32 data1;
+	/** value 2 */
+	t_u32 data2;
+	/** value 3 */
+	t_u32 data3;
+} MLAN_PACK_END;
+
+/** MFG CMD Tx Frame 2 */
+struct MLAN_PACK_START mfg_cmd_tx_frame2 {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** enable */
+	t_u32 enable;
+	/** data_rate */
+	t_u32 data_rate;
+	/** frame pattern */
+	t_u32 frame_pattern;
+	/** frame length */
+	t_u32 frame_length;
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** Adjust burst sifs */
+	t_u16 adjust_burst_sifs;
+	/** Burst sifs in us*/
+	t_u32 burst_sifs_in_us;
+	/** short preamble */
+	t_u32 short_preamble;
+	/** active sub channel */
+	t_u32 act_sub_ch;
+	/** short GI */
+	t_u32 short_gi;
+	/** Adv coding */
+	t_u32 adv_coding;
+	/** Tx beamforming */
+	t_u32 tx_bf;
+	/** HT Greenfield Mode*/
+	t_u32 gf_mode;
+	/** STBC */
+	t_u32 stbc;
+	/** power id */
+	t_u32 rsvd[2];
+    /** NumPkt */
+	t_u32 NumPkt;
+    /** MaxPE */
+	t_u32 MaxPE;
+    /** BeamChange */
+	t_u32 BeamChange;
+    /** Dcm */
+	t_u32 Dcm;
+    /** Doppler */
+	t_u32 Doppler;
+    /** MidP */
+	t_u32 MidP;
+    /** QNum */
+	t_u32 QNum;
+
+} MLAN_PACK_END;
+
+/* MFG CMD Tx Continuous */
+struct MLAN_PACK_START mfg_cmd_tx_cont {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** enable Tx*/
+	t_u32 enable_tx;
+	/** Continuous Wave mode */
+	t_u32 cw_mode;
+	/** payload pattern */
+	t_u32 payload_pattern;
+	/** CS Mode */
+	t_u32 cs_mode;
+	/** active sub channel */
+	t_u32 act_sub_ch;
+	/** Tx rate */
+	t_u32 tx_rate;
+	/** power id */
+	t_u32 rsvd;
+} MLAN_PACK_END;
+
+struct MLAN_PACK_START mfg_Cmd_HE_TBTx_t {
+    /** MFG command code */
+	t_u32 mfg_cmd;
+    /** Action */
+	t_u16 action;
+    /** Device ID */
+	t_u16 device_id;
+    /** MFG Error code */
+	t_u32 error;
+    /** Enable Tx */
+	t_u16 enable;
+    /** Q num */
+	t_u16 qnum;
+    /** AID */
+	t_u16 aid;
+    /** AXQ Mu Timer */
+	t_u16 axq_mu_timer;
+    /** Tx Power */
+	t_u16 tx_power;
+} MLAN_PACK_END;
+
+typedef struct _mlan_ds_misc_chnrgpwr_cfg {
+	/** length */
+	t_u16 length;
+	/** chnrgpwr buf */
+	t_u8 chnrgpwr_buf[2048];
+} mlan_ds_misc_chnrgpwr_cfg;
+
+/** dfs chan list for MLAN_OID_MISC_CFP_TABLE */
+typedef struct _mlan_ds_misc_cfp_tbl {
+	/** band */
+	t_u8 band;
+	/** num chan */
+	t_u8 num_chan;
+	/** cfp table */
+	chan_freq_power_t cfp_tbl[];
+} mlan_ds_misc_cfp_tbl;
+
+/** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */
+typedef struct _mlan_ds_misc_cfg {
+	/** Sub-command */
+	t_u32 sub_command;
+	/** Miscellaneous configuration parameter */
+	union {
+		/** Generic IE for MLAN_OID_MISC_GEN_IE */
+		mlan_ds_misc_gen_ie gen_ie;
+		/** Region code for MLAN_OID_MISC_REGION */
+		t_u32 region_code;
+#ifdef SDIO
+		/** SDIO MP-A Ctrl command for MLAN_OID_MISC_SDIO_MPA_CTRL */
+		mlan_ds_misc_sdio_mpa_ctrl mpa_ctrl;
+#endif
+		/** Hostcmd for MLAN_OID_MISC_HOST_CMD */
+		mlan_ds_misc_cmd hostcmd;
+		/** System clock for MLAN_OID_MISC_SYS_CLOCK */
+		mlan_ds_misc_sys_clock sys_clock;
+		/** WWS set/get for MLAN_OID_MISC_WWS */
+		t_u32 wws_cfg;
+		/** Get associate response for MLAN_OID_MISC_ASSOC_RSP */
+		mlan_ds_misc_assoc_rsp assoc_resp;
+		/** Function init/shutdown for MLAN_OID_MISC_INIT_SHUTDOWN */
+		t_u32 func_init_shutdown;
+		/** Custom IE for MLAN_OID_MISC_CUSTOM_IE */
+		mlan_ds_misc_custom_ie cust_ie;
+		t_u16 tdls_idle_time;
+		/** Config dynamic bandwidth*/
+		t_u16 dyn_bw;
+		/** TDLS configuration for MLAN_OID_MISC_TDLS_CONFIG */
+		mlan_ds_misc_tdls_config tdls_config;
+		/** TDLS operation for MLAN_OID_MISC_TDLS_OPER */
+		mlan_ds_misc_tdls_oper tdls_oper;
+		/** TDLS ies for  MLAN_OID_MISC_GET_TDLS_IES */
+		mlan_ds_misc_tdls_ies tdls_ies;
+		/**tdls cs off channel*/
+		t_u8 tdls_cs_channel;
+		/** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */
+		mlan_ds_misc_tx_datapause tx_datapause;
+		/** IP address configuration */
+		mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+		/** IPv6 Router Advertisement offload configuration */
+		mlan_ds_misc_ipv6_ra_offload ipv6_ra_offload;
+		/** MAC control for MLAN_OID_MISC_MAC_CONTROL */
+		t_u32 mac_ctrl;
+		/** MEF configuration for MLAN_OID_MISC_MEF_CFG */
+		mlan_ds_misc_mef_cfg mef_cfg;
+		/** CFP code for MLAN_OID_MISC_CFP_CODE */
+		mlan_ds_misc_cfp_code cfp_code;
+		/** Country code for MLAN_OID_MISC_COUNTRY_CODE */
+		mlan_ds_misc_country_code country_code;
+		/** Thermal reading for MLAN_OID_MISC_THERMAL */
+		t_u32 thermal;
+		/** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */
+		t_u32 mgmt_subtype_mask;
+		/** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */
+		mlan_ds_subscribe_evt subscribe_event;
+#ifdef DEBUG_LEVEL1
+		/** Driver debug bit masks */
+		t_u32 drvdbg;
+#endif
+		/** Hotspot config param set */
+		t_u32 hotspot_cfg;
+#ifdef STA_SUPPORT
+		ExtCap_t ext_cap;
+#endif
+		mlan_ds_misc_otp_user_data otp_user_data;
+#ifdef USB
+		/** USB aggregation parameters for MLAN_OID_MISC_USB_AGGR_CTRL
+		 */
+		mlan_ds_misc_usb_aggr_ctrl usb_aggr_params;
+#endif
+		mlan_ds_misc_aggr_ctrl aggr_params;
+		/** Tx control */
+		t_u32 tx_control;
+#if defined(STA_SUPPORT)
+		mlan_ds_misc_pmfcfg pmfcfg;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		mlan_ds_wifi_direct_config p2p_config;
+#endif
+		mlan_ds_gpio_tsf_latch gpio_tsf_latch_config;
+		mlan_ds_tsf_info tsf_info;
+		mlan_ds_coalesce_cfg coalesce_cfg;
+		t_u8 low_pwr_mode;
+		/** MEF-FLT-CONFIG for MLAN_OID_MISC_NV_FLT_CFG */
+		mlan_ds_misc_mef_flt_cfg mef_flt_cfg;
+		mlan_ds_misc_dfs_repeater dfs_repeater;
+#ifdef RX_PACKET_COALESCE
+		mlan_ds_misc_rx_packet_coalesce rx_coalesce;
+#endif
+		/** FW reload flag */
+		t_u8 fw_reload;
+		mlan_ds_sensor_temp sensor_temp;
+		/** GTK rekey data */
+		mlan_ds_misc_gtk_rekey_data gtk_rekey;
+		mlan_ds_bw_chan_oper bw_chan_oper;
+		mlan_ds_ind_rst_cfg ind_rst_cfg;
+		t_u64 misc_tsf;
+		mlan_ds_custom_reg_domain custom_reg_domain;
+		mlan_ds_misc_keep_alive keep_alive;
+		mlan_ds_misc_tx_rx_histogram tx_rx_histogram;
+		mlan_ds_cw_mode_ctrl cwmode;
+		/**  Tx/Rx per-packet control */
+		t_u8 txrx_pkt_ctrl;
+		mlan_ds_misc_robustcoex_params robustcoexparams;
+#if defined(PCIE)
+		mlan_ds_ssu_params ssu_params;
+#endif
+		/** boot sleep enable or disable */
+		t_u16 boot_sleep;
+		/** Mapping Policy */
+		mlan_ds_misc_mapping_policy dmcs_policy;
+		mlan_ds_misc_dmcs_status dmcs_status;
+		mlan_ds_misc_rx_abort_cfg rx_abort_cfg;
+		mlan_ds_misc_rx_abort_cfg_ext rx_abort_cfg_ext;
+		mlan_ds_misc_tx_ampdu_prot_mode tx_ampdu_prot_mode;
+		mlan_ds_misc_rate_adapt_cfg rate_adapt_cfg;
+		mlan_ds_misc_cck_desense_cfg cck_desense_cfg;
+		mlan_ds_misc_chan_trpc_cfg trpc_cfg;
+		mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+
+		mlan_ds_band_steer_cfg band_steer_cfg;
+		mlan_ds_beacon_stuck_param_cfg beacon_stuck_cfg;
+		struct mfg_cmd_generic_cfg mfg_generic_cfg;
+		struct mfg_cmd_tx_cont mfg_tx_cont;
+		struct mfg_cmd_tx_frame2 mfg_tx_frame2;
+		struct mfg_Cmd_HE_TBTx_t mfg_he_power;
+		mlan_ds_misc_arb_cfg arb_cfg;
+		mlan_ds_misc_cfp_tbl cfp;
+		t_u8 range_ext_mode;
+		mlan_ds_misc_dot11mc_unassoc_ftm_cfg dot11mc_unassoc_ftm_cfg;
+		mlan_ds_misc_tp_state tp_state;
+		mlan_ds_hal_phy_cfg_params hal_phy_cfg_params;
+#ifdef UAP_SUPPORT
+		t_u8 wacp_mode;
+#endif
+	} param;
+} mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
+
+/** Hotspot status enable */
+#define HOTSPOT_ENABLED MBIT(0)
+/** Hotspot status disable */
+#define HOTSPOT_DISABLED MFALSE
+/** Keep Hotspot2.0 compatible in mwu and wpa_supplicant */
+#define HOTSPOT_BY_SUPPLICANT MBIT(1)
+
+/** Reason codes */
+#define MLAN_REASON_UNSPECIFIED 1
+#define MLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define MLAN_REASON_DEAUTH_LEAVING 3
+#define MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define MLAN_REASON_DISASSOC_AP_BUSY 5
+#define MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA 6
+#define MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA 7
+#define MLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+#endif /* !_MLAN_IOCTL_H_ */
diff --git a/wlan_sd8987/mlinux/moal_cfg80211.c b/wlan_sd8987/mlinux/moal_cfg80211.c
new file mode 100755
index 0000000..580956c
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfg80211.c
@@ -0,0 +1,5100 @@
+/** @file moal_cfg80211.c
+ *
+ * @brief This file contains the functions for CFG80211.
+ *
+ *
+ * Copyright 2011-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include "moal_cfg80211.h"
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+#endif
+
+/********************************************************
+ *				Local Variables
+ ********************************************************/
+/** Supported rates to be advertised to the cfg80211 */
+static struct ieee80211_rate cfg80211_rates[] = {
+	{
+	 .bitrate = 10,
+	 .hw_value = 2,
+	 },
+	{
+	 .bitrate = 20,
+	 .hw_value = 4,
+	 },
+	{
+	 .bitrate = 55,
+	 .hw_value = 11,
+	 },
+	{
+	 .bitrate = 110,
+	 .hw_value = 22,
+	 },
+	{
+	 .bitrate = 60,
+	 .hw_value = 12,
+	 },
+	{
+	 .bitrate = 90,
+	 .hw_value = 18,
+	 },
+	{
+	 .bitrate = 120,
+	 .hw_value = 24,
+	 },
+	{
+	 .bitrate = 180,
+	 .hw_value = 36,
+	 },
+	{
+	 .bitrate = 240,
+	 .hw_value = 48,
+	 },
+	{
+	 .bitrate = 360,
+	 .hw_value = 72,
+	 },
+	{
+	 .bitrate = 480,
+	 .hw_value = 96,
+	 },
+	{
+	 .bitrate = 540,
+	 .hw_value = 108,
+	 },
+};
+
+/** Channel definitions for 2 GHz to be advertised to cfg80211 */
+static struct ieee80211_channel cfg80211_channels_2ghz[] = {
+	{.center_freq = 2412,.hw_value = 1,.max_power = 20},
+	{.center_freq = 2417,.hw_value = 2,.max_power = 20},
+	{.center_freq = 2422,.hw_value = 3,.max_power = 20},
+	{.center_freq = 2427,.hw_value = 4,.max_power = 20},
+	{.center_freq = 2432,.hw_value = 5,.max_power = 20},
+	{.center_freq = 2437,.hw_value = 6,.max_power = 20},
+	{.center_freq = 2442,.hw_value = 7,.max_power = 20},
+	{.center_freq = 2447,.hw_value = 8,.max_power = 20},
+	{.center_freq = 2452,.hw_value = 9,.max_power = 20},
+	{.center_freq = 2457,.hw_value = 10,.max_power = 20},
+	{.center_freq = 2462,.hw_value = 11,.max_power = 20},
+	{.center_freq = 2467,.hw_value = 12,.max_power = 20},
+	{.center_freq = 2472,.hw_value = 13,.max_power = 20},
+	{.center_freq = 2484,.hw_value = 14,.max_power = 20},
+};
+
+/** Channel definitions for 5 GHz to be advertised to cfg80211 */
+static struct ieee80211_channel cfg80211_channels_5ghz[] = {
+	{.center_freq = 5180,.hw_value = 36,.max_power = 20},
+	{.center_freq = 5200,.hw_value = 40,.max_power = 20},
+	{.center_freq = 5220,.hw_value = 44,.max_power = 20},
+	{.center_freq = 5240,.hw_value = 48,.max_power = 20},
+	{.center_freq = 5260,.hw_value = 52,.max_power = 20},
+	{.center_freq = 5280,.hw_value = 56,.max_power = 20},
+	{.center_freq = 5300,.hw_value = 60,.max_power = 20},
+	{.center_freq = 5320,.hw_value = 64,.max_power = 20},
+	{.center_freq = 5500,.hw_value = 100,.max_power = 20},
+	{.center_freq = 5520,.hw_value = 104,.max_power = 20},
+	{.center_freq = 5540,.hw_value = 108,.max_power = 20},
+	{.center_freq = 5560,.hw_value = 112,.max_power = 20},
+	{.center_freq = 5580,.hw_value = 116,.max_power = 20},
+	{.center_freq = 5600,.hw_value = 120,.max_power = 20},
+	{.center_freq = 5620,.hw_value = 124,.max_power = 20},
+	{.center_freq = 5640,.hw_value = 128,.max_power = 20},
+	{.center_freq = 5660,.hw_value = 132,.max_power = 20},
+	{.center_freq = 5680,.hw_value = 136,.max_power = 20},
+	{.center_freq = 5700,.hw_value = 140,.max_power = 20},
+	{.center_freq = 5720,.hw_value = 144,.max_power = 20},
+	{.center_freq = 5745,.hw_value = 149,.max_power = 20},
+	{.center_freq = 5765,.hw_value = 153,.max_power = 20},
+	{.center_freq = 5785,.hw_value = 157,.max_power = 20},
+	{.center_freq = 5805,.hw_value = 161,.max_power = 20},
+	{.center_freq = 5825,.hw_value = 165,.max_power = 20},
+};
+
+struct ieee80211_supported_band cfg80211_band_2ghz = {
+	.channels = cfg80211_channels_2ghz,
+	.band = IEEE80211_BAND_2GHZ,
+	.n_channels = ARRAY_SIZE(cfg80211_channels_2ghz),
+	.bitrates = cfg80211_rates,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates),
+};
+
+struct ieee80211_supported_band cfg80211_band_5ghz = {
+	.channels = cfg80211_channels_5ghz,
+	.band = IEEE80211_BAND_5GHZ,
+	.n_channels = ARRAY_SIZE(cfg80211_channels_5ghz),
+	.bitrates = cfg80211_rates + 4,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates) - 4,
+};
+
+/** Channel definitions for 5 GHz to be advertised to cfg80211 */
+static struct ieee80211_channel mac1_cfg80211_channels_5ghz[] = {
+	{.center_freq = 5180,.hw_value = 36,.max_power = 20},
+	{.center_freq = 5200,.hw_value = 40,.max_power = 20},
+	{.center_freq = 5220,.hw_value = 44,.max_power = 20},
+	{.center_freq = 5240,.hw_value = 48,.max_power = 20},
+	{.center_freq = 5260,.hw_value = 52,.max_power = 20},
+	{.center_freq = 5280,.hw_value = 56,.max_power = 20},
+	{.center_freq = 5300,.hw_value = 60,.max_power = 20},
+	{.center_freq = 5320,.hw_value = 64,.max_power = 20},
+	{.center_freq = 5500,.hw_value = 100,.max_power = 20},
+	{.center_freq = 5520,.hw_value = 104,.max_power = 20},
+	{.center_freq = 5540,.hw_value = 108,.max_power = 20},
+	{.center_freq = 5560,.hw_value = 112,.max_power = 20},
+	{.center_freq = 5580,.hw_value = 116,.max_power = 20},
+	{.center_freq = 5600,.hw_value = 120,.max_power = 20},
+	{.center_freq = 5620,.hw_value = 124,.max_power = 20},
+	{.center_freq = 5640,.hw_value = 128,.max_power = 20},
+	{.center_freq = 5660,.hw_value = 132,.max_power = 20},
+	{.center_freq = 5680,.hw_value = 136,.max_power = 20},
+	{.center_freq = 5700,.hw_value = 140,.max_power = 20},
+	{.center_freq = 5720,.hw_value = 144,.max_power = 20},
+	{.center_freq = 5745,.hw_value = 149,.max_power = 20},
+	{.center_freq = 5765,.hw_value = 153,.max_power = 20},
+	{.center_freq = 5785,.hw_value = 157,.max_power = 20},
+	{.center_freq = 5805,.hw_value = 161,.max_power = 20},
+	{.center_freq = 5825,.hw_value = 165,.max_power = 20},
+};
+
+struct ieee80211_supported_band mac1_cfg80211_band_2ghz = {
+	.channels = cfg80211_channels_2ghz,
+	.band = IEEE80211_BAND_2GHZ,
+	.n_channels = ARRAY_SIZE(cfg80211_channels_2ghz),
+	.bitrates = cfg80211_rates,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates),
+};
+
+struct ieee80211_supported_band mac1_cfg80211_band_5ghz = {
+	.channels = mac1_cfg80211_channels_5ghz,
+	.band = IEEE80211_BAND_5GHZ,
+	.n_channels = ARRAY_SIZE(mac1_cfg80211_channels_5ghz),
+	.bitrates = cfg80211_rates + 4,
+	.n_bitrates = ARRAY_SIZE(cfg80211_rates) - 4,
+};
+
+#if KERNEL_VERSION(2, 6, 29) < LINUX_VERSION_CODE
+#ifdef UAP_SUPPORT
+/** Network device handlers for uAP */
+extern const struct net_device_ops woal_uap_netdev_ops;
+#endif
+#ifdef STA_SUPPORT
+/** Network device handlers for STA */
+extern const struct net_device_ops woal_netdev_ops;
+#endif
+#endif
+/********************************************************
+ *				Local Functions
+ ********************************************************/
+
+/********************************************************
+ *				Global Functions
+ ********************************************************/
+
+/**
+ * @brief Get the private structure from wiphy
+ *
+ * @param wiphy     A pointer to wiphy structure
+ *
+ * @return          Pointer to moal_private
+ */
+void *
+woal_get_wiphy_priv(struct wiphy *wiphy)
+{
+	return (void *)(*(unsigned long *)wiphy_priv(wiphy));
+}
+
+/**
+ * @brief Get the private structure from net device
+ *
+ * @param dev       A pointer to net_device structure
+ *
+ * @return          Pointer to moal_private
+ */
+void *
+woal_get_netdev_priv(struct net_device *dev)
+{
+	return (void *)netdev_priv(dev);
+}
+
+/**
+ *  @brief Get current frequency of active interface
+ *
+ *  @param priv        A pointer to moal_private
+ *
+ *  @return              channel frequency
+ */
+int
+woal_get_active_intf_freq(moal_private *priv)
+{
+	moal_handle *handle = priv->phandle;
+	int i;
+
+	if (priv->media_connected == MTRUE
+#ifdef UAP_SUPPORT
+	    || priv->bss_started == MTRUE
+#endif
+		)
+		return ieee80211_channel_to_frequency(priv->channel
+#if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
+						      ,
+						      (priv->channel <=
+						       14 ? IEEE80211_BAND_2GHZ
+						       : IEEE80211_BAND_5GHZ)
+#endif
+			);
+
+	for (i = 0; i < handle->priv_num; i++) {
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
+			if (handle->priv[i]->media_connected == MTRUE)
+				return ieee80211_channel_to_frequency(handle->
+								      priv[i]->
+								      channel
+#if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
+								      ,
+								      (handle->
+								       priv[i]->
+								       channel
+								       <=
+								       14 ?
+								       IEEE80211_BAND_2GHZ
+								       :
+								       IEEE80211_BAND_5GHZ)
+#endif
+					);
+		}
+#endif
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+			if (handle->priv[i]->bss_started == MTRUE)
+				return ieee80211_channel_to_frequency(handle->
+								      priv[i]->
+								      channel
+#if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
+								      ,
+								      (handle->
+								       priv[i]->
+								       channel
+								       <=
+								       14 ?
+								       IEEE80211_BAND_2GHZ
+								       :
+								       IEEE80211_BAND_5GHZ)
+#endif
+					);
+		}
+#endif
+	}
+	return 0;
+}
+
+/**
+ *  @brief Convert driver band configuration to IEEE band type
+ *
+ *  @param band     Driver band configuration
+ *
+ *  @return         IEEE band type
+ */
+t_u8
+woal_band_cfg_to_ieee_band(t_u32 band)
+{
+	t_u8 ret_radio_type;
+
+	ENTER();
+
+	switch (band) {
+	case BAND_A:
+	case BAND_AN:
+	case BAND_A | BAND_AN:
+		ret_radio_type = IEEE80211_BAND_5GHZ;
+		break;
+	case BAND_B:
+	case BAND_G:
+	case BAND_B | BAND_G:
+	case BAND_GN:
+	case BAND_B | BAND_GN:
+		/* Fall Through */
+	default:
+		ret_radio_type = IEEE80211_BAND_2GHZ;
+		break;
+	}
+
+	LEAVE();
+	return ret_radio_type;
+}
+
+/**
+ *  @brief Set/Enable encryption key
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param is_enable_wep    Enable WEP default key
+ *  @param cipher           Cipher suite selector
+ *  @param key              A pointer to key
+ *  @param key_len          Key length
+ *  @param seq              A pointer to sequence
+ *  @param seq_len          Sequence length
+ *  @param key_index        Key index
+ *  @param addr             Mac for which key is to be set
+ *  @param disable          Key disabled or not
+ *  @param wait_option      wait option
+ *
+ *  @return                 MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_cfg80211_set_key(moal_private *priv, t_u8 is_enable_wep,
+		      t_u32 cipher, const t_u8 *key, int key_len,
+		      const t_u8 *seq, int seq_len, t_u8 key_index,
+		      const t_u8 *addr, int disable, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	ENTER();
+
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		if (is_enable_wep) {
+			PRINTM(MIOCTL, "Enable UAP default key=%d\n",
+			       key_index);
+			priv->uap_wep_key[key_index].is_default = MTRUE;
+			goto done;
+		}
+		if (key && key_len &&
+		    ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
+		     (cipher == WLAN_CIPHER_SUITE_WEP104))) {
+			priv->uap_wep_key[key_index].length = key_len;
+			moal_memcpy_ext(priv->phandle,
+					priv->uap_wep_key[key_index].key, key,
+					key_len,
+					sizeof(priv->uap_wep_key[key_index].
+					       key));
+			priv->cipher = cipher;
+			priv->uap_wep_key[key_index].key_index = key_index;
+			priv->uap_wep_key[key_index].is_default = MFALSE;
+			PRINTM(MIOCTL, "Set UAP WEP key: key_index=%d len=%d\n",
+			       key_index, key_len);
+			goto done;
+		}
+	}
+#endif
+#endif
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	if (is_enable_wep) {
+		sec->param.encrypt_key.key_index = key_index;
+		sec->param.encrypt_key.is_current_wep_key = MTRUE;
+	} else if (!disable) {
+		if (cipher != WLAN_CIPHER_SUITE_WEP40 &&
+		    cipher != WLAN_CIPHER_SUITE_WEP104 &&
+		    cipher != WLAN_CIPHER_SUITE_TKIP &&
+		    cipher != WLAN_CIPHER_SUITE_SMS4 &&
+		    cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+		    cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
+#endif
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+		    cipher != WLAN_CIPHER_SUITE_GCMP &&
+#endif
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+		    cipher != WLAN_CIPHER_SUITE_BIP_GMAC_128 &&
+		    cipher != WLAN_CIPHER_SUITE_BIP_GMAC_256 &&
+		    cipher != WLAN_CIPHER_SUITE_GCMP_256 &&
+#endif
+		    cipher != WLAN_CIPHER_SUITE_CCMP) {
+			PRINTM(MERROR, "Invalid cipher suite specified\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		sec->param.encrypt_key.key_index = key_index;
+		if (key && key_len) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.key_material,
+					key, key_len, MLAN_MAX_KEY_LENGTH);
+			sec->param.encrypt_key.key_len = key_len;
+		}
+		/* Set WAPI key */
+		if (cipher == WLAN_CIPHER_SUITE_SMS4) {
+			sec->param.encrypt_key.is_wapi_key = MTRUE;
+			if (seq_len) {
+				moal_memcpy_ext(priv->phandle,
+						sec->param.encrypt_key.pn, seq,
+						PN_SIZE, PN_SIZE);
+				DBG_HEXDUMP(MCMD_D, "WAPI PN",
+					    sec->param.encrypt_key.pn, seq_len);
+			}
+		}
+		if (addr) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.mac_addr, addr,
+					ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
+			if (memcmp(sec->param.encrypt_key.mac_addr,
+				   bcast_addr, ETH_ALEN) == 0)
+				sec->param.encrypt_key.key_flags =
+					KEY_FLAG_GROUP_KEY;
+			else
+				sec->param.encrypt_key.key_flags =
+					KEY_FLAG_SET_TX_KEY;
+		} else {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.mac_addr,
+					bcast_addr, ETH_ALEN,
+					MLAN_MAC_ADDR_LENGTH);
+			sec->param.encrypt_key.key_flags =
+				KEY_FLAG_GROUP_KEY | KEY_FLAG_SET_TX_KEY;
+		}
+		if (seq && seq_len) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.pn, seq, seq_len,
+					PN_SIZE);
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_RX_SEQ_VALID;
+		}
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+		if (cipher == WLAN_CIPHER_SUITE_GCMP)
+			sec->param.encrypt_key.key_flags |= KEY_FLAG_GCMP;
+#endif
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+		else if (cipher == WLAN_CIPHER_SUITE_GCMP_256)
+			sec->param.encrypt_key.key_flags |= KEY_FLAG_GCMP_256;
+#endif
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+		if (cipher == WLAN_CIPHER_SUITE_CCMP_256)
+			sec->param.encrypt_key.key_flags |= KEY_FLAG_CCMP_256;
+#endif
+
+		if (cipher == WLAN_CIPHER_SUITE_AES_CMAC
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+		    || cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128
+		    || cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256
+#endif
+			) {
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_AES_MCAST_IGTK;
+
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+			if (cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128)
+				sec->param.encrypt_key.key_flags |=
+					KEY_FLAG_GMAC_128;
+			else if (cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
+				sec->param.encrypt_key.key_flags |=
+					KEY_FLAG_GMAC_256;
+#endif
+		}
+	} else {
+		if (key_index == KEY_INDEX_CLEAR_ALL)
+			sec->param.encrypt_key.key_disable = MTRUE;
+		else {
+			sec->param.encrypt_key.key_remove = MTRUE;
+			sec->param.encrypt_key.key_index = key_index;
+		}
+		sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY;
+		if (addr)
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.mac_addr, addr,
+					ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
+	}
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Enable the WEP key to driver
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param key       A pointer to key data
+ * @param key_len   Length of the key data
+ * @param index     Key index
+ * @param wait_option wait_option
+ *
+ * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_cfg80211_set_wep_keys(moal_private *priv, const t_u8 *key,
+			   int key_len, t_u8 index, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 cipher = 0;
+
+	ENTER();
+
+	if (key_len) {
+		if (key_len == 5)
+			cipher = WLAN_CIPHER_SUITE_WEP40;
+		else
+			cipher = WLAN_CIPHER_SUITE_WEP104;
+		ret = woal_cfg80211_set_key(priv, 0, cipher, key, key_len, NULL,
+					    0, index, NULL, 0, wait_option);
+	} else {
+		/* No key provided so it is enable key. We
+		 * want to just set the transmit key index
+		 */
+		woal_cfg80211_set_key(priv, 1, cipher, key, key_len, NULL, 0,
+				      index, NULL, 0, wait_option);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief clear all mgmt ies
+ *
+ * @param priv              A pointer to moal private structure
+ * @param wait_option       wait_option
+ * @return                  N/A
+ */
+void
+woal_clear_all_mgmt_ies(moal_private *priv, t_u8 wait_option)
+{
+	t_u16 mask = 0;
+	/* clear BEACON WPS/P2P IE */
+	if (priv->beacon_wps_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+		PRINTM(MCMND, "Clear BEACON WPS ie\n");
+		woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0,
+					    NULL, 0, MGMT_MASK_BEACON_WPS_P2P,
+					    wait_option);
+		priv->beacon_wps_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	}
+	if (priv->assocresp_qos_map_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+		PRINTM(MCMND, "Clear associate response QOS map ie\n");
+		woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0,
+					    NULL, 0,
+					    MGMT_MASK_ASSOC_RESP_QOS_MAP,
+					    wait_option);
+		priv->assocresp_qos_map_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	}
+	/* clear mgmt frame ies */
+	if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+		mask |= MGMT_MASK_PROBE_REQ;
+	if (priv->beacon_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+		mask |= MGMT_MASK_BEACON;
+	if (priv->proberesp_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+		mask |= MGMT_MASK_PROBE_RESP;
+	if (priv->assocresp_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+		mask |= MGMT_MASK_ASSOC_RESP;
+	if (priv->proberesp_p2p_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+		mask |= MGMT_MASK_PROBE_RESP;
+	if (priv->beacon_vendor_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+		mask |= MGMT_MASK_BEACON;
+	if (mask) {
+		PRINTM(MCMND, "Clear IES: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+		       priv->beacon_index, priv->probereq_index,
+		       priv->proberesp_index, priv->assocresp_index,
+		       priv->proberesp_p2p_index, priv->beacon_vendor_index);
+		woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0,
+					    NULL, 0, mask, wait_option);
+	}
+	priv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->beacon_vendor_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+}
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/**
+ * @brief set bss role
+ *
+ * @param priv              A pointer to moal private structure
+ * @param action            Action: set or get
+ * @param role              A pointer to bss role
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_bss_role_cfg(moal_private *priv, t_u16 action, t_u8 *bss_role)
+{
+	int ret = 0;
+
+	ENTER();
+
+	if (action == MLAN_ACT_SET) {
+		/* Reset interface */
+		woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE);
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_role_cfg(priv, action, MOAL_IOCTL_WAIT, bss_role)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_SET) {
+		/* set back the mac address */
+		woal_request_set_mac_address(priv, MOAL_IOCTL_WAIT);
+		/* clear the mgmt ies */
+		woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
+		/* Initialize private structures */
+		woal_init_priv(priv, MOAL_IOCTL_WAIT);
+
+		/* Enable interfaces */
+		netif_device_attach(priv->netdev);
+		woal_start_queue(priv->netdev);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+/**
+ *  @brief This function display P2P public action frame type
+ *
+ *  @param  buf      A buffer to a management frame
+ *  @param  len      buffer len
+ *  @param chan      the channel
+ *  @param flag      Tx/Rx flag. Tx:flag = 1;Rx:flag = 0;
+ *
+ *  @return          N/A
+ */
+void
+woal_cfg80211_display_p2p_actframe(const t_u8 *buf, int len,
+				   struct ieee80211_channel *chan,
+				   const t_u8 flag)
+{
+	const t_u8 p2p_oui[] = { 0x50, 0x6f, 0x9a, 0x09 };
+	t_u8 subtype;
+
+	ENTER();
+
+	if (!buf || len < (P2P_ACT_FRAME_OUI_SUBTYPE_OFFSET + 1)) {
+		LEAVE();
+		return;
+	}
+
+	if (((struct ieee80211_mgmt *)buf)->u.action.category ==
+	    P2P_ACT_FRAME_CATEGORY &&
+	    !memcmp(buf + P2P_ACT_FRAME_OUI_OFFSET, p2p_oui, sizeof(p2p_oui))) {
+		subtype = *(buf + P2P_ACT_FRAME_OUI_SUBTYPE_OFFSET);
+		switch (subtype) {
+		case P2P_GO_NEG_REQ:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Group Owner Negotiation Req Frame, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_GO_NEG_RSP:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Group Owner Negotiation Rsp Frame, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_GO_NEG_CONF:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Group Owner Negotiation Confirm Frame, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_INVITE_REQ:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Invitation Request, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_INVITE_RSP:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Invitation Response, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_DEVDIS_REQ:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Device Discoverability Request, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_DEVDIS_RSP:
+			PRINTM(MIOCTL,
+			       "wlan: %s P2P Device Discoverability Response, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_PROVDIS_REQ:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Provision Discovery Request, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		case P2P_PROVDIS_RSP:
+			PRINTM(MMSG,
+			       "wlan: %s P2P Provision Discovery Response, channel=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0);
+			break;
+		default:
+			PRINTM(MMSG,
+			       "wlan: %s Unknown P2P Action Frame, channel=%d, subtype=%d\n",
+			       (flag) ? "TX" : "RX",
+			       (chan) ? chan->hw_value : 0, subtype);
+			break;
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ * @brief initialize p2p client for wpa_supplicant
+ *
+ * @param priv			A pointer to moal private structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_init_p2p_client(moal_private *priv)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u16 wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
+	t_u8 bss_role;
+
+	ENTER();
+
+	/* bss type check */
+	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+		PRINTM(MERROR, "Unexpected bss type when init p2p client\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* get the bss role */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_GET, &bss_role)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (bss_role != MLAN_BSS_ROLE_STA) {
+		bss_role = MLAN_BSS_ROLE_STA;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* first, init wifi direct to listen mode */
+	wifi_direct_mode = WIFI_DIRECT_MODE_LISTEN;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* second, init wifi direct client  */
+	wifi_direct_mode = WIFI_DIRECT_MODE_CLIENT;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief initialize p2p GO for wpa_supplicant
+ *
+ * @param priv			A pointer to moal private structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_init_p2p_go(moal_private *priv)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u16 wifi_direct_mode;
+	t_u8 bss_role;
+	mlan_ds_wifi_direct_config p2p_config;
+	mlan_ds_ps_mgmt ps_mgmt;
+
+	ENTER();
+
+	/* bss type check */
+	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+		PRINTM(MERROR, "Unexpected bss type when init p2p GO\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* first, init wifi direct to listen mode */
+	wifi_direct_mode = WIFI_DIRECT_MODE_LISTEN;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* second, init wifi direct to GO mode  */
+	wifi_direct_mode = WIFI_DIRECT_MODE_GO;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* get the bss role, and set it to uAP */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_GET, &bss_role)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (bss_role != MLAN_BSS_ROLE_UAP) {
+		bss_role = MLAN_BSS_ROLE_UAP;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+/* NoA:-- Interval = 100TUs and Duration= 50TUs, count=255*/
+#define DEF_NOA_COUNT 255
+	if (priv->phandle->noa_duration && priv->phandle->card_info->go_noa) {
+		memset(&p2p_config, 0, sizeof(p2p_config));
+		p2p_config.noa_enable = MTRUE;
+		p2p_config.index = 0;
+		p2p_config.noa_count = DEF_NOA_COUNT;
+		p2p_config.noa_duration = priv->phandle->noa_duration;
+		p2p_config.noa_interval = priv->phandle->noa_interval;
+		p2p_config.flags = WIFI_DIRECT_NOA;
+		woal_p2p_config(priv, MLAN_ACT_SET, &p2p_config);
+		memset(&ps_mgmt, 0, sizeof(ps_mgmt));
+		ps_mgmt.flags = PS_FLAG_PS_MODE;
+		ps_mgmt.ps_mode = PS_MODE_INACTIVITY;
+		woal_set_get_uap_power_mode(priv, MLAN_ACT_SET, &ps_mgmt);
+		PRINTM(MMSG, "Enable NOA: duration=%d, interval=%d\n",
+		       priv->phandle->noa_duration,
+		       priv->phandle->noa_interval);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief reset bss role and wifi direct mode for wpa_supplicant
+ *
+ * @param priv			A pointer to moal private structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_deinit_p2p(moal_private *priv)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u16 wifi_direct_mode;
+	t_u8 bss_role;
+	t_u8 channel_status;
+	moal_private *remain_priv = NULL;
+	mlan_ds_ps_mgmt ps_mgmt;
+
+	ENTER();
+
+	/* bss type check */
+	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+		PRINTM(MERROR, "Unexpected bss type when deinit p2p\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/* unregister mgmt frame from FW */
+	if (priv->mgmt_subtype_mask) {
+		priv->mgmt_subtype_mask = 0;
+		if (woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET,
+					 &priv->mgmt_subtype_mask,
+					 MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR,
+			       "deinit_p2p: fail to unregister mgmt frame\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	/* cancel previous remain on channel */
+	if (priv->phandle->remain_on_channel) {
+		remain_priv =
+			priv->phandle->priv[priv->phandle->remain_bss_index];
+		if (!remain_priv) {
+			PRINTM(MERROR,
+			       "deinit_p2p: wrong remain_bss_index=%d\n",
+			       priv->phandle->remain_bss_index);
+			ret = -EFAULT;
+			goto done;
+		}
+		if (woal_cfg80211_remain_on_channel_cfg
+		    (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL,
+		     0, 0)) {
+			PRINTM(MERROR,
+			       "deinit_p2p: Fail to cancel remain on channel\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (priv->phandle->cookie) {
+			cfg80211_remain_on_channel_expired(
+#if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
+								  remain_priv->
+								  netdev,
+#else
+								  remain_priv->
+								  wdev,
+#endif
+								  priv->
+								  phandle->
+								  cookie,
+								  &priv->
+								  phandle->chan,
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+								  priv->
+								  phandle->
+								  channel_type,
+#endif
+								  GFP_ATOMIC);
+			priv->phandle->cookie = 0;
+		}
+		priv->phandle->remain_on_channel = MFALSE;
+	}
+
+	/* get the bss role */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_GET, &bss_role)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* reset bss role */
+	if (bss_role != MLAN_BSS_ROLE_STA) {
+		memset(&ps_mgmt, 0, sizeof(ps_mgmt));
+		ps_mgmt.flags = PS_FLAG_PS_MODE;
+		ps_mgmt.ps_mode = PS_MODE_DISABLE;
+		woal_set_get_uap_power_mode(priv, MLAN_ACT_SET, &ps_mgmt);
+		bss_role = MLAN_BSS_ROLE_STA;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+
+/**
+ * @brief Request the driver to change the interface type
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param dev           A pointer to net_device structure
+ * @param type          Virtual interface types
+ * @param flags         Flags
+ * @param params        A pointer to vif_params structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_change_virtual_intf(struct wiphy *wiphy,
+				  struct net_device *dev,
+				  enum nl80211_iftype type,
+#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE
+				  u32 *flags,
+#endif
+				  struct vif_params *params)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	t_u8 bss_role;
+#endif
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (priv->wdev->iftype == type) {
+		PRINTM(MINFO, "Already set to required type\n");
+		goto done;
+	}
+#ifdef UAP_SUPPORT
+	if ((priv->bss_type == MLAN_BSS_TYPE_UAP) && (priv->bss_index > 0)) {
+		priv->wdev->iftype = type;
+		PRINTM(MMSG, "%s: Skip change virtual intf on uap: type=%d\n",
+		       dev->name, type);
+		goto done;
+	}
+#endif
+
+	PRINTM(MIOCTL, "%s: change virturl intf=%d\n", dev->name, type);
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	/** cancel previous remain on channel to avoid firmware hang */
+	if (priv->phandle->remain_on_channel) {
+		t_u8 channel_status;
+		moal_private *remain_priv = NULL;
+
+		remain_priv =
+			priv->phandle->priv[priv->phandle->remain_bss_index];
+		if (!remain_priv) {
+			PRINTM(MERROR,
+			       "change_virtual_intf:wrong remain_bss_index=%d\n",
+			       priv->phandle->remain_bss_index);
+			ret = -EFAULT;
+			goto done;
+		}
+		if (woal_cfg80211_remain_on_channel_cfg
+		    (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL,
+		     0, 0)) {
+			PRINTM(MERROR,
+			       "change_virtual_intf: Fail to cancel remain on channel\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (priv->phandle->cookie) {
+			cfg80211_remain_on_channel_expired(
+#if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
+								  remain_priv->
+								  netdev,
+#else
+								  remain_priv->
+								  wdev,
+#endif
+								  priv->
+								  phandle->
+								  cookie,
+								  &priv->
+								  phandle->chan,
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+								  priv->
+								  phandle->
+								  channel_type,
+#endif
+								  GFP_ATOMIC);
+			priv->phandle->cookie = 0;
+		}
+		priv->phandle->remain_on_channel = MFALSE;
+	}
+#endif
+#endif
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MODE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	switch (type) {
+	case NL80211_IFTYPE_STATION:
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    (priv->wdev->iftype == NL80211_IFTYPE_AP ||
+		     priv->wdev->iftype == NL80211_IFTYPE_P2P_GO ||
+		     priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
+			if (priv->phandle->is_go_timer_set) {
+				woal_cancel_timer(&priv->phandle->go_timer);
+				priv->phandle->is_go_timer_set = MFALSE;
+			}
+			/* if we support wifi direct && priv->bss_type ==
+			 * wifi_direct, and currently the interface type is AP
+			 * or GO or client, that means wpa_supplicant deinit()
+			 * wifi direct interface, so we should deinit bss_role
+			 * and wifi direct mode, for other bss_type, we should
+			 * not update bss_role and wifi direct mode
+			 */
+
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_cfg80211_deinit_p2p(priv)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			woal_cfg80211_del_beacon(wiphy, dev);
+			bss_role = MLAN_BSS_ROLE_STA;
+			woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET,
+						   &bss_role);
+			PRINTM(MIOCTL, "set bss role for STA\n");
+		}
+#endif
+		bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
+		priv->wdev->iftype = NL80211_IFTYPE_STATION;
+		PRINTM(MINFO, "Setting interface type to managed\n");
+		break;
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	case NL80211_IFTYPE_P2P_CLIENT:
+		if (priv->phandle->is_go_timer_set) {
+			woal_cancel_timer(&priv->phandle->go_timer);
+			priv->phandle->is_go_timer_set = MFALSE;
+		}
+
+		if (MLAN_STATUS_SUCCESS != woal_cfg80211_init_p2p_client(priv)) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
+		priv->wdev->iftype = NL80211_IFTYPE_P2P_CLIENT;
+		PRINTM(MINFO, "Setting interface type to P2P client\n");
+
+		break;
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+	case NL80211_IFTYPE_AP:
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+		/* Fall Through */
+	case NL80211_IFTYPE_P2P_GO:
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_cfg80211_init_p2p_go(priv)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			priv->phandle->is_go_timer_set = MTRUE;
+			woal_mod_timer(&priv->phandle->go_timer,
+				       MOAL_TIMER_10S);
+		}
+		if (type == NL80211_IFTYPE_P2P_GO)
+			priv->wdev->iftype = NL80211_IFTYPE_P2P_GO;
+#endif
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		if (priv->bss_type == MLAN_BSS_TYPE_STA) {
+#ifdef STA_CFG80211
+			/** cancel pending scan */
+			woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+			if (priv->probereq_index !=
+			    MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+				woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL,
+							    0, NULL, 0, NULL, 0,
+							    MGMT_MASK_PROBE_REQ,
+							    MOAL_IOCTL_WAIT);
+			bss_role = MLAN_BSS_ROLE_UAP;
+			woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET,
+						   &bss_role);
+			PRINTM(MIOCTL, "set bss role for AP\n");
+		}
+#endif
+		if (type == NL80211_IFTYPE_AP)
+			priv->wdev->iftype = NL80211_IFTYPE_AP;
+		PRINTM(MINFO, "Setting interface type to P2P GO\n");
+
+		/* there is no need for P2P GO to set bss_mode */
+		goto done;
+
+		break;
+
+	case NL80211_IFTYPE_UNSPECIFIED:
+		bss->param.bss_mode = MLAN_BSS_MODE_AUTO;
+		priv->wdev->iftype = NL80211_IFTYPE_STATION;
+		PRINTM(MINFO, "Setting interface type to auto\n");
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret)
+		goto done;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to change the value of fragment
+ * threshold or rts threshold or retry limit
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param changed       Change flags
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	pmlan_uap_bss_param sys_cfg = NULL;
+#endif
+#endif
+	int frag_thr = wiphy->frag_threshold;
+	int rts_thr = wiphy->rts_threshold;
+	int retry = wiphy->retry_long;
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+	if (rts_thr == (int)MLAN_FRAG_RTS_DISABLED)
+		rts_thr = MLAN_RTS_MAX_VALUE;
+	if (frag_thr == (int)MLAN_FRAG_RTS_DISABLED)
+		frag_thr = MLAN_FRAG_MAX_VALUE;
+
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+		if (!sys_cfg) {
+			PRINTM(MERROR,
+			       "Fail to alloc memory for mlan_uap_bss_param\n");
+			LEAVE();
+			return -EFAULT;
+		}
+		/* Initialize the invalid values so that the correct
+		 * values below are downloaded to firmware
+		 */
+		woal_set_sys_config_invalid_data(sys_cfg);
+		sys_cfg->frag_threshold = frag_thr;
+		sys_cfg->rts_threshold = rts_thr;
+		sys_cfg->retry_limit = retry;
+
+		if ((changed & WIPHY_PARAM_RTS_THRESHOLD) ||
+		    (changed & WIPHY_PARAM_FRAG_THRESHOLD) ||
+		    (changed &
+		     (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT))) {
+			if (woal_set_get_sys_config(priv, MLAN_ACT_SET,
+						    MOAL_IOCTL_WAIT, sys_cfg)) {
+				kfree(sys_cfg);
+				goto fail;
+			}
+		}
+		kfree(sys_cfg);
+	}
+#endif
+#endif
+
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+			if (woal_set_get_rts(priv, MLAN_ACT_SET,
+					     MOAL_IOCTL_WAIT, &rts_thr))
+				goto fail;
+		}
+		if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
+			if (woal_set_get_frag(priv, MLAN_ACT_SET,
+					      MOAL_IOCTL_WAIT, &frag_thr))
+				goto fail;
+		}
+		if (changed &
+		    (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT))
+			if (woal_set_get_retry(priv, MLAN_ACT_SET,
+					       MOAL_IOCTL_WAIT, &retry))
+				goto fail;
+	}
+#endif
+#endif
+	LEAVE();
+	return 0;
+
+fail:
+	PRINTM(MERROR, "Failed to change wiphy params %x\n", changed);
+	LEAVE();
+	return -EFAULT;
+}
+
+#if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
+/**
+ * @brief Request the driver to add a key
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param netdev        A pointer to net_device structure
+ * @param key_index     Key index
+ * @param pairwise      Flag to indicate pairwise or group (for kernel > 2.6.36)
+ * @param mac_addr      MAC address (NULL for group key)
+ * @param params        A pointer to key_params structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+#else
+/**
+ * @brief Request the driver to add a key
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param netdev        A pointer to net_device structure
+ * @param key_index     Key index
+ * @param mac_addr      MAC address (NULL for group key)
+ * @param params        A pointer to key_params structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+#endif
+int
+woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
+		      t_u8 key_index,
+#if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
+		      bool pairwise,
+#endif
+		      const t_u8 *mac_addr, struct key_params *params)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+
+	ENTER();
+	if (priv->ft_pre_connect) {
+		PRINTM(MINFO, "Skip set keys during ft connecting\n");
+		return -EFAULT;
+	}
+
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+	if (woal_cfg80211_set_key(priv, 0, params->cipher, params->key,
+				  params->key_len, params->seq, params->seq_len,
+				  key_index, mac_addr, 0, MOAL_IOCTL_WAIT)) {
+		PRINTM(MERROR, "Error adding the crypto keys\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	PRINTM(MINFO, "Crypto keys added\n");
+
+	LEAVE();
+	return 0;
+}
+
+#if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
+/**
+ * @brief Request the driver to delete a key
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param netdev        A pointer to net_device structure
+ * @param key_index     Key index
+ * @param pairwise      Flag to indicate pairwise or group (for kernel > 2.6.36)
+ * @param mac_addr      MAC address (NULL for group key)
+ *
+ * @return              0 -- success, otherwise fail
+ */
+#else
+/**
+ * @brief Request the driver to delete a key
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param netdev        A pointer to net_device structure
+ * @param key_index     Key index
+ * @param mac_addr      MAC address (NULL for group key)
+ *
+ * @return              0 -- success, otherwise fail
+ */
+#endif
+int
+woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
+		      t_u8 key_index,
+#if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
+		      bool pairwise,
+#endif
+		      const t_u8 *mac_addr)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+
+	ENTER();
+	if (priv->phandle->driver_status) {
+		PRINTM(MERROR, "Block %s in abnormal driver state\n", __func__);
+		LEAVE();
+		return -EFAULT;
+	}
+	/* del_key will be trigger from cfg80211_rx_mlme_mgmt funtion
+	 * where we receive deauth/disassoicate packet in rx_work
+	 * use MOAL_NO_WAIT to avoid dead lock
+	 */
+	if (MLAN_STATUS_FAILURE ==
+	    woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0, key_index,
+				  mac_addr, 1, MOAL_NO_WAIT)) {
+		PRINTM(MERROR, "Error deleting the crypto keys\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	PRINTM(MINFO, "Crypto keys deleted\n");
+	LEAVE();
+	return 0;
+}
+
+#if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE
+/**
+ * @brief Request to enable WEP key to driver
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param netdev        A pointer to net_device structure
+ * @param key_index     Key index
+ * @param ucast         Unicast flag (for kernel > 2.6.37)
+ * @param mcast         Multicast flag (for kernel > 2.6.37)
+ *
+ * @return              0 -- success, otherwise fail
+ */
+#else
+/**
+ * @brief Request to enable WEP key to driver
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param netdev        A pointer to net_device structure
+ * @param key_index     Key index
+ *
+ * @return              0 -- success, otherwise fail
+ */
+#endif
+int
+woal_cfg80211_set_default_key(struct wiphy *wiphy,
+			      struct net_device *netdev, t_u8 key_index
+#if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE
+			      , bool ucast, bool mcast
+#endif
+	)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(netdev);
+	mlan_bss_info bss_info;
+
+	ENTER();
+	memset(&bss_info, 0, sizeof(mlan_bss_info));
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		if (!bss_info.wep_status) {
+			LEAVE();
+			return ret;
+		}
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_set_wep_keys(priv, NULL, 0, key_index,
+				       MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+}
+
+#if KERNEL_VERSION(2, 6, 30) <= CFG80211_VERSION_CODE
+int
+woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
+				   struct net_device *netdev, t_u8 key_index)
+{
+	PRINTM(MINFO, "set default mgmt key, key index=%d\n", key_index);
+
+	return 0;
+}
+#endif
+
+#if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE
+int
+woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
+				     struct net_device *netdev, t_u8 key_index)
+{
+	PRINTM(MINFO, "set default beacon key, key index=%d\n", key_index);
+
+	return 0;
+}
+#endif
+
+#if KERNEL_VERSION(3, 1, 0) <= CFG80211_VERSION_CODE
+/**
+ *  @brief  Set GTK rekey data to driver
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param gtk_rekey     A pointer to mlan_ds_misc_gtk_rekey_data structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *
+ *  @return             0 --success, otherwise fail
+ */
+mlan_status
+woal_set_rekey_data(moal_private *priv,
+		    mlan_ds_misc_gtk_rekey_data * gtk_rekey,
+		    t_u8 action, t_u8 wait_option)
+{
+	mlan_ioctl_req *req;
+	mlan_ds_misc_cfg *misc_cfg;
+	int ret = 0;
+	mlan_status status;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+
+	if (req == NULL) {
+		ret = -ENOMEM;
+	} else {
+		misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+		misc_cfg->sub_command = MLAN_OID_MISC_GTK_REKEY_OFFLOAD;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+
+		req->action = action;
+		if (action == MLAN_ACT_SET)
+			moal_memcpy_ext(priv->phandle,
+					&misc_cfg->param.gtk_rekey, gtk_rekey,
+					sizeof(mlan_ds_misc_gtk_rekey_data),
+					sizeof(mlan_ds_misc_gtk_rekey_data));
+
+		status = woal_request_ioctl(priv, req, wait_option);
+		if (status != MLAN_STATUS_SUCCESS)
+			ret = -EFAULT;
+		if (status != MLAN_STATUS_PENDING)
+			kfree(req);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Give the data necessary for GTK rekeying to the driver
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param dev           A pointer to net_device structure
+ * @param data        A pointer to cfg80211_gtk_rekey_data structure
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
+			     struct cfg80211_gtk_rekey_data *data)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ds_misc_gtk_rekey_data rekey;
+	mlan_fw_info fw_info;
+
+	ENTER();
+
+	if (priv->phandle->params.gtk_rekey_offload ==
+	    GTK_REKEY_OFFLOAD_DISABLE) {
+		PRINTM(MMSG,
+		       "%s return: gtk_rekey_offload is DISABLE\n", __func__);
+		LEAVE();
+		return ret;
+	}
+
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (!fw_info.fw_supplicant_support) {
+		LEAVE();
+		return -1;
+	}
+
+	moal_memcpy_ext(priv->phandle, rekey.kek, data->kek, MLAN_KEK_LEN,
+			MLAN_KEK_LEN);
+	moal_memcpy_ext(priv->phandle, rekey.kck, data->kck, MLAN_KCK_LEN,
+			MLAN_KCK_LEN);
+	moal_memcpy_ext(priv->phandle, rekey.replay_ctr, data->replay_ctr,
+			MLAN_REPLAY_CTR_LEN, MLAN_REPLAY_CTR_LEN);
+
+	moal_memcpy_ext(priv->phandle, &priv->gtk_rekey_data, &rekey,
+			sizeof(mlan_ds_misc_gtk_rekey_data),
+			sizeof(mlan_ds_misc_gtk_rekey_data));
+	if (priv->phandle->params.gtk_rekey_offload ==
+	    GTK_REKEY_OFFLOAD_SUSPEND) {
+		priv->gtk_data_ready = MTRUE;
+		LEAVE();
+		return ret;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_rekey_data(priv, &rekey, MLAN_ACT_SET, MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef STA_SUPPORT
+/* Opportunistic Key Caching APIs functions support
+ *
+ * this function get pmksa entry list in private structure
+ * @param priv         A pointer to moal_private structure
+ * @param bssid        A pointer to bssid
+ * @return             pointer to target entry or NULL
+ */
+struct pmksa_entry *
+woal_get_pmksa_entry(moal_private *priv, const u8 *bssid)
+{
+	struct pmksa_entry *entry = NULL;
+	unsigned long flags;
+
+	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
+		PRINTM(MERROR, "Invalid interface structure\n");
+		return NULL;
+	}
+
+	spin_lock_irqsave(&priv->pmksa_list_lock, flags);
+	list_for_each_entry(entry, &priv->pmksa_cache_list, link) {
+		if (!memcmp(entry->bssid, bssid, ETH_ALEN)) {
+			spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
+			return entry;
+		}
+	}
+	spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
+
+	return NULL;
+}
+
+/**
+ * This function flush pmksa entry list in private structure
+ * @param priv         A pointer to moal_private structure
+ * @return             success of failure
+ */
+int
+woal_flush_pmksa_list(moal_private *priv)
+{
+	struct pmksa_entry *entry, *tmp;
+	unsigned long flags;
+
+	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
+		PRINTM(MERROR, "Invalid interface structure\n");
+		return -1;
+	}
+
+	spin_lock_irqsave(&priv->pmksa_list_lock, flags);
+	list_for_each_entry_safe(entry, tmp, &priv->pmksa_cache_list, link) {
+		list_del(&entry->link);
+		kfree(entry);
+	}
+	INIT_LIST_HEAD(&priv->pmksa_cache_list);
+	spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
+
+	return 0;
+}
+
+/**
+ *  This function add new pmksa entry to list
+ *  @param wiphy        A pointer to struct wiphy
+ *  @param dev          A pointer to net_device structure
+ *  @param pmksa        A pointer to cfg80211_pmksa structure
+ *  @return             success of failure
+ */
+int
+woal_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_pmksa *pmksa)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct pmksa_entry *entry = NULL;
+	unsigned long flags;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
+		PRINTM(MERROR, "Invalid interface structure\n");
+		ret = -1;
+		goto done;
+	}
+
+	PRINTM(MIOCTL, "Set pmksa entry: bssid=" MACSTR "\n",
+	       MAC2STR(pmksa->bssid));
+	entry = woal_get_pmksa_entry(priv, pmksa->bssid);
+	if (!entry) {
+		entry = kzalloc(sizeof(struct pmksa_entry), GFP_ATOMIC);
+		if (!entry) {
+			PRINTM(MERROR, "Fail to allocate pmksa entry\n");
+			goto done;
+		}
+		INIT_LIST_HEAD(&entry->link);
+		moal_memcpy_ext(priv->phandle, entry->bssid, pmksa->bssid,
+				ETH_ALEN, ETH_ALEN);
+		moal_memcpy_ext(priv->phandle, entry->pmkid, pmksa->pmkid,
+				PMKID_LEN, PMKID_LEN);
+		spin_lock_irqsave(&priv->pmksa_list_lock, flags);
+		list_add_tail(&entry->link, &priv->pmksa_cache_list);
+		spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
+	} else {
+		/** pmkid is differnt from previous value? */
+		memset(entry->pmkid, 0, PMKID_LEN);
+		moal_memcpy_ext(priv->phandle, entry->pmkid, pmksa->pmkid,
+				PMKID_LEN, PMKID_LEN);
+	}
+
+	/** Check if current roaming is going and received target pmkid */
+	if (priv->wait_target_ap_pmkid) {
+		struct cfg80211_connect_params *param = &priv->sme_current;
+
+		if (param && !memcmp(pmksa->bssid, param->bssid, ETH_ALEN)) {
+			PRINTM(MIOCTL,
+			       "Current roaming target bssid=" MACSTR "\n",
+			       MAC2STR(param->bssid));
+			priv->target_ap_pmksa = entry;
+			priv->wait_target_ap_pmkid = MFALSE;
+			wake_up_interruptible(&priv->okc_wait_q);
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  This function delete pmksa entry
+ *  @param wiphy        A pointer to struct wiphy
+ *  @param dev          A pointer to net_device structure
+ *  @param pmksa        A pointer to cfg80211_pmksa structure
+ *  @return             success of failure
+ */
+int
+woal_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_pmksa *pmksa)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct pmksa_entry *entry, *tmp;
+	unsigned long flags;
+
+	ENTER();
+
+	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA) {
+		PRINTM(MERROR, "Invalid interface structure\n");
+		LEAVE();
+		return -1;
+	}
+
+	PRINTM(MIOCTL, "Delete pmksa: bssid=" MACSTR "\n",
+	       MAC2STR(pmksa->bssid));
+	spin_lock_irqsave(&priv->pmksa_list_lock, flags);
+	list_for_each_entry_safe(entry, tmp, &priv->pmksa_cache_list, link) {
+		if (!memcmp(entry->bssid, pmksa->bssid, ETH_ALEN)) {
+			list_del(&entry->link);
+			kfree(entry);
+		}
+	}
+	spin_unlock_irqrestore(&priv->pmksa_list_lock, flags);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  This function flush pmksa entry list
+ *  @param wiphy        A pointer to struct wiphy
+ *  @param dev          A pointer to net_device structure
+ *  @return             success of failure
+ */
+int
+woal_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	if (!priv || priv->bss_type != MLAN_BSS_TYPE_STA)
+		return -1;
+
+	PRINTM(MIOCTL, "Flush pmksa list.\n");
+	return woal_flush_pmksa_list(priv);
+}
+#endif
+
+#if KERNEL_VERSION(3, 5, 0) > CFG80211_VERSION_CODE
+#if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
+/**
+ * @brief Request the driver to change the channel
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param chan            A pointer to ieee80211_channel structure
+ * @param channel_type    Channel type of nl80211_channel_type
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#else
+/**
+ * @brief Request the driver to change the channel
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param chan            A pointer to ieee80211_channel structure
+ * @param channel_type    Channel type of nl80211_channel_type
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+int
+woal_cfg80211_set_channel(struct wiphy *wiphy,
+#if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
+			  struct net_device *dev,
+#endif
+			  struct ieee80211_channel *chan,
+			  enum nl80211_channel_type channel_type)
+{
+	int ret = 0;
+	moal_private *priv = NULL;
+
+	ENTER();
+
+#if KERNEL_VERSION(3, 5, 0) > CFG80211_VERSION_CODE
+#if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
+	if (dev)
+		priv = woal_get_netdev_priv(dev);
+#endif
+#endif
+	if (!priv) {
+		moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+
+		if (handle)
+			priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	}
+	if (priv) {
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+			if (priv->media_connected == MTRUE) {
+				PRINTM(MERROR,
+				       "This configuration is valid only when station is not connected\n");
+				LEAVE();
+				return -EINVAL;
+			}
+			ret = woal_set_rf_channel(priv, chan, channel_type,
+						  MOAL_IOCTL_WAIT);
+		}
+#endif
+#endif
+		priv->channel =
+			ieee80211_frequency_to_channel(chan->center_freq);
+	}
+	/* set monitor channel support */
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
+static bool
+woal_is_pattern_supported(struct cfg80211_pkt_pattern *pat,
+			  t_u8 *byte_seq, t_u8 max_byte_seq)
+{
+	int j, k, valid_byte_cnt = 0;
+	bool dont_care_byte = false;
+
+	for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
+		for (k = 0; k < 8; k++) {
+			if (pat->mask[j] & 1 << k) {
+				moal_memcpy_ext(NULL, byte_seq + valid_byte_cnt,
+						&pat->pattern[j * 8 + k], 1,
+						(t_u32)max_byte_seq -
+						(t_u32)valid_byte_cnt);
+				valid_byte_cnt++;
+				if (dont_care_byte)
+					return false;
+			} else {
+				if (valid_byte_cnt)
+					dont_care_byte = true;
+			}
+
+			if (valid_byte_cnt > max_byte_seq)
+				return false;
+		}
+	}
+
+	byte_seq[max_byte_seq] = valid_byte_cnt;
+
+	return true;
+}
+
+static int
+woal_get_coalesce_pkt_type(t_u8 *byte_seq)
+{
+	const t_u8 ipv4_mc_mac[] = { 0x33, 0x33 };
+	const t_u8 ipv6_mc_mac[] = { 0x01, 0x00, 0x5e };
+	const t_u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff };
+
+	if ((byte_seq[0] & 0x01) && (byte_seq[COALESCE_MAX_BYTESEQ] == 1))
+		return PACKET_TYPE_UNICAST;
+	else if (!memcmp(byte_seq, bc_mac, 4))
+		return PACKET_TYPE_BROADCAST;
+	else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
+		  byte_seq[COALESCE_MAX_BYTESEQ] == 2) ||
+		 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
+		  byte_seq[COALESCE_MAX_BYTESEQ] == 3))
+		return PACKET_TYPE_MULTICAST;
+
+	return 0;
+}
+
+static int
+woal_fill_coalesce_rule_info(struct cfg80211_coalesce_rules *crule,
+			     struct coalesce_rule *mrule)
+{
+	t_u8 byte_seq[COALESCE_MAX_BYTESEQ + 1];
+	struct filt_field_param *param;
+	int i;
+
+	mrule->max_coalescing_delay = crule->delay;
+
+	param = mrule->params;
+
+	for (i = 0; i < crule->n_patterns; i++) {
+		memset(byte_seq, 0, sizeof(byte_seq));
+		if (!woal_is_pattern_supported(&crule->patterns[i], byte_seq,
+					       COALESCE_MAX_BYTESEQ)) {
+			PRINTM(MERROR, "Pattern not supported\n");
+			return -EOPNOTSUPP;
+		}
+
+		if (!crule->patterns[i].pkt_offset) {
+			u8 pkt_type;
+
+			pkt_type = woal_get_coalesce_pkt_type(byte_seq);
+			if (pkt_type && mrule->pkt_type) {
+				PRINTM(MERROR,
+				       "Multiple packet types not allowed\n");
+				return -EOPNOTSUPP;
+			} else if (pkt_type) {
+				mrule->pkt_type = pkt_type;
+				continue;
+			}
+		}
+
+		if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
+			param->operation = RECV_FILTER_MATCH_TYPE_EQ;
+		else
+			param->operation = RECV_FILTER_MATCH_TYPE_NE;
+
+		param->operand_len = byte_seq[COALESCE_MAX_BYTESEQ];
+		moal_memcpy_ext(NULL, param->operand_byte_stream, byte_seq,
+				param->operand_len, COALESCE_MAX_BYTESEQ);
+		param->offset = crule->patterns[i].pkt_offset;
+		param++;
+
+		mrule->num_of_fields++;
+	}
+
+	if (!mrule->pkt_type) {
+		PRINTM(MERROR, "Packet type can not be determined\n");
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+/**
+ *  @brief Set coalesce parameter
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *  @param coalesce_cfg     A pointer to coalesce structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_set_coalesce(moal_private *priv, t_u16 action,
+		  mlan_ds_coalesce_cfg * coalesce_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_COALESCE_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+
+	moal_memcpy_ext(priv->phandle, &misc_cfg->param.coalesce_cfg,
+			coalesce_cfg, sizeof(mlan_ds_coalesce_cfg),
+			sizeof(mlan_ds_coalesce_cfg));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to set the coalesce
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param coalesce        A pointer to cfg80211_coalesce structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_coalesce(struct wiphy *wiphy,
+			   struct cfg80211_coalesce *coalesce)
+{
+	int ret = 0;
+	int i;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv = NULL;
+	mlan_ds_coalesce_cfg coalesce_cfg;
+
+	ENTER();
+
+	if (!handle) {
+		PRINTM(MFATAL, "Unable to get handle\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
+	if (!coalesce) {
+		PRINTM(MMSG, "Disable coalesce and reset all previous rules\n");
+	} else {
+		coalesce_cfg.num_of_rules = coalesce->n_rules;
+		for (i = 0; i < coalesce->n_rules; i++) {
+			ret = woal_fill_coalesce_rule_info(&coalesce->rules[i],
+							   &coalesce_cfg.
+							   rule[i]);
+			if (ret) {
+				PRINTM(MERROR,
+				       "Recheck the patterns provided for rule %d\n",
+				       i + 1);
+				return ret;
+			}
+		}
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_coalesce(priv, MLAN_ACT_SET, &coalesce_cfg)) {
+		PRINTM(MERROR, "wlan: Fail to set coalesce\n");
+		ret = -EFAULT;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Request the driver to set the bitrate
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param peer            A pointer to peer address
+ * @param mask            A pointer to cfg80211_bitrate_mask structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+			       const u8 *peer,
+			       const struct cfg80211_bitrate_mask *mask)
+{
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_bss_info bss_info;
+	enum ieee80211_band band;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_rate *rate = NULL;
+	mlan_rate_cfg_t *rate_cfg = NULL;
+
+	ENTER();
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can not set data rate in disconnected state\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (status)
+		goto done;
+	band = woal_band_cfg_to_ieee_band(bss_info.bss_band);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate_cfg = &rate->param.rate_cfg;
+	rate->sub_command = MLAN_OID_RATE_CFG;
+	req->req_id = MLAN_IOCTL_RATE;
+	req->action = MLAN_ACT_SET;
+	rate_cfg->rate_type = MLAN_RATE_BITMAP;
+
+	/* Fill HR/DSSS rates. */
+	if (band == IEEE80211_BAND_2GHZ)
+		rate_cfg->bitmap_rates[0] = mask->control[band].legacy & 0x000f;
+
+	/* Fill OFDM rates */
+	if (band == IEEE80211_BAND_2GHZ)
+		rate_cfg->bitmap_rates[1] =
+			(mask->control[band].legacy & 0x0ff0) >> 4;
+	else
+		rate_cfg->bitmap_rates[1] = mask->control[band].legacy;
+
+#if KERNEL_VERSION(3, 4, 0) <= CFG80211_VERSION_CODE
+	/* Fill MCS rates */
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+	rate_cfg->bitmap_rates[2] = mask->control[band].ht_mcs[0];
+#else
+	rate_cfg->bitmap_rates[2] = mask->control[band].mcs[0];
+#endif
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+	rate_cfg->bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
+#else
+	rate_cfg->bitmap_rates[2] |= mask->control[band].mcs[1] << 8;
+#endif
+#endif
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if KERNEL_VERSION(2, 6, 38) <= CFG80211_VERSION_CODE
+/**
+ * @brief Request the driver to get antenna configuration
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param tx_ant          Bitmaps of allowed antennas to use for TX
+ * @param rx_ant          Bitmaps of allowed antennas to use for RX
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv = NULL;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+
+	ENTER();
+
+	if (!handle) {
+		PRINTM(MFATAL, "Unable to get handle\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (handle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+		*tx_ant = radio->param.ant_cfg.tx_antenna;
+		*rx_ant = radio->param.ant_cfg.rx_antenna;
+	} else {
+		*tx_ant = radio->param.ant_cfg_1x1.antenna;
+		*rx_ant = radio->param.ant_cfg_1x1.antenna;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	/* Driver must return -EINVAL to cfg80211 */
+	if (ret)
+		ret = -EINVAL;
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to set antenna configuration
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param tx_ant          Bitmaps of allowed antennas to use for TX
+ * @param rx_ant          Bitmaps of allowed antennas to use for RX
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv = NULL;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+
+	ENTER();
+
+	if (!handle) {
+		PRINTM(MFATAL, "Unable to get handle\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	req->action = MLAN_ACT_SET;
+	if (handle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+		radio->param.ant_cfg.tx_antenna = tx_ant;
+		radio->param.ant_cfg.rx_antenna = rx_ant;
+	} else {
+		radio->param.ant_cfg_1x1.antenna = tx_ant;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	/* Driver must return -EINVAL to cfg80211 */
+	if (ret)
+		ret = -EINVAL;
+	LEAVE();
+	return ret;
+}
+#endif
+/**
+ * @brief register/unregister mgmt frame forwarding
+ *
+ * @param priv             A pointer to moal_private structure
+ * @param frame_type      Bit mask for mgmt frame type
+ * @param reg             Register or unregister
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_mgmt_frame_register(moal_private *priv, u16 frame_type, bool reg)
+{
+	t_u32 mgmt_subtype_mask = 0x0;
+	t_u32 last_mgmt_subtype_mask = priv->mgmt_subtype_mask;
+
+	ENTER();
+
+#ifdef SDIO_SUSPEND_RESUME
+	if (priv->phandle->shutdown_hs_in_process) {
+		LEAVE();
+		return;
+	}
+#endif
+
+	if (reg == MTRUE) {
+		/* set mgmt_subtype_mask based on origin value */
+		mgmt_subtype_mask =
+			last_mgmt_subtype_mask | BIT(frame_type >> 4);
+	} else {
+		/* clear mgmt_subtype_mask */
+		mgmt_subtype_mask =
+			last_mgmt_subtype_mask & ~BIT(frame_type >> 4);
+	}
+	PRINTM(MIOCTL,
+	       "%s: frame_type=0x%x mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n",
+	       priv->netdev->name, frame_type, mgmt_subtype_mask,
+	       last_mgmt_subtype_mask);
+	if (mgmt_subtype_mask != last_mgmt_subtype_mask) {
+		last_mgmt_subtype_mask = mgmt_subtype_mask;
+		/* Notify driver that a mgmt frame type was registered.
+		 * Note that this callback may not sleep, and cannot run
+		 * concurrently with itself.
+		 */
+		woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET,
+				     &mgmt_subtype_mask, MOAL_NO_WAIT);
+		priv->mgmt_subtype_mask = last_mgmt_subtype_mask;
+	}
+
+	LEAVE();
+}
+
+#if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
+/**
+ * @brief register/unregister mgmt frame forwarding
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param frame_type      Bit mask for mgmt frame type
+ * @param reg             Register or unregister
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+				  struct net_device *dev, u16 frame_type,
+				  bool reg)
+#else
+#if KERNEL_VERSION(5, 8, 0) <= CFG80211_VERSION_CODE
+void
+woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+				  struct wireless_dev *wdev,
+				  struct mgmt_frame_regs *upd)
+#else
+/**
+ * @brief register/unregister mgmt frame forwarding
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param wdev            A pointer to wireless_dev structure
+ * @param frame_type      Bit mask for mgmt frame type
+ * @param reg             Register or unregister
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+				  struct wireless_dev *wdev,
+				  u16 frame_type, bool reg)
+#endif
+#endif
+{
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+	struct net_device *dev = wdev->netdev;
+#endif
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+#if KERNEL_VERSION(5, 8, 0) <= CFG80211_VERSION_CODE
+	if ((upd->interface_stypes & BIT(IEEE80211_STYPE_AUTH >> 4))
+		/** Supplicant 2.8 always register auth, FW will handle auth when
+		 *  host_mlme=0
+		 */
+	    && !moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
+		)
+		upd->interface_stypes &= ~BIT(IEEE80211_STYPE_AUTH >> 4);
+
+	if (priv->mgmt_subtype_mask != upd->interface_stypes) {
+		priv->mgmt_subtype_mask = upd->interface_stypes;
+		woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET,
+				     &upd->interface_stypes, MOAL_NO_WAIT);
+	}
+#else
+	if (frame_type == IEEE80211_STYPE_AUTH
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+	    /** Supplicant 2.8 always register auth, FW will handle auth when
+	     *  host_mlme=0
+	     */
+	    && !moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
+#endif
+		) {
+		LEAVE();
+		return;
+	}
+	woal_mgmt_frame_register(priv, frame_type, reg);
+#endif
+	LEAVE();
+}
+
+/*
+ * @brief  prepare and send WOAL_EVENT_CANCEL_CHANRPT
+ *
+ * @param priv           A pointer moal_private structure
+ *
+ * @return          N/A
+ */
+static void
+woal_cancel_chanrpt_event(moal_private *priv)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (!evt) {
+		PRINTM(MERROR, "Fail to alloc memory for deauth event\n");
+		LEAVE();
+		return;
+	}
+	evt->priv = priv;
+	evt->type = WOAL_EVENT_CANCEL_CHANRPT;
+	INIT_LIST_HEAD(&evt->link);
+	spin_lock_irqsave(&handle->evt_lock, flags);
+	list_add_tail(&evt->link, &handle->evt_queue);
+	spin_unlock_irqrestore(&handle->evt_lock, flags);
+	queue_work(handle->evt_workqueue, &handle->evt_work);
+}
+
+#if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
+#if KERNEL_VERSION(3, 3, 0) <= CFG80211_VERSION_CODE
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wdev                  A pointer to wireless_dev structure
+ * @param params                A pointer to cfg80211_mgmt_tx_params structure
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#else
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wdev                  A pointer to wireless_dev structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param offchan               Off channel or not
+ * @param wait                  Duration to wait
+ * @param buf                   Frame buffer
+ * @param len                   Frame length
+ * @param no_cck                No CCK check
+ * @param dont_wait_for_ack     Do not wait for ACK
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+#else
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wdev                  A pointer to wireless_dev structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param offchan               Off channel or not
+ * @param channel_type          Channel type
+ * @param channel_type_valid    Is channel type valid or not
+ * @param wait                  Duration to wait
+ * @param buf                   Frame buffer
+ * @param len                   Frame length
+ * @param no_cck                No CCK check
+ * @param dont_wait_for_ack     Do not wait for ACK
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+#else
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param offchan               Off channel or not
+ * @param channel_type          Channel type
+ * @param channel_type_valid    Is channel type valid or not
+ * @param wait                  Duration to wait
+ * @param buf                   Frame buffer
+ * @param len                   Frame length
+ * @param no_cck                No CCK check
+ * @param dont_wait_for_ack     Do not wait for ACK
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+#else
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param offchan               Off channel or not
+ * @param channel_type          Channel type
+ * @param channel_type_valid    Is channel type valid or not
+ * @param wait                  Duration to wait
+ * @param buf                   Frame buffer
+ * @param len                   Frame length
+ * @param no_cck                No CCK check
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+#else
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param offchan               Off channel or not
+ * @param channel_type          Channel type
+ * @param channel_type_valid    Is channel type valid or not
+ * @param wait                  Duration to wait
+ * @param buf                   Frame buffer
+ * @param len                   Frame length
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+int
+woal_cfg80211_mgmt_tx(struct wiphy *wiphy,
+#if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
+		      struct net_device *dev,
+#else
+		      struct wireless_dev *wdev,
+#endif
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+		      struct cfg80211_mgmt_tx_params *params,
+#else
+		      struct ieee80211_channel *chan, bool offchan,
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+		      enum nl80211_channel_type channel_type,
+		      bool channel_type_valid,
+#endif
+		      unsigned int wait, const u8 *buf, size_t len,
+#if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
+		      bool no_cck,
+#endif
+#if KERNEL_VERSION(3, 3, 0) <= CFG80211_VERSION_CODE
+		      bool dont_wait_for_ack,
+#endif
+#endif
+		      u64 * cookie)
+{
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+	struct net_device *dev = wdev->netdev;
+#endif
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+	struct ieee80211_channel *chan = params->chan;
+	unsigned int wait = params->wait;
+	const u8 *buf = params->buf;
+	size_t len = params->len;
+#endif
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+	pmlan_buffer pmbuf = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u16 packet_len = 0;
+	t_u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	t_u32 pkt_type;
+	t_u32 tx_control;
+#if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
+	t_u8 channel_status;
+	t_u32 duration;
+	moal_private *remain_priv = NULL;
+#endif
+
+	unsigned long flags;
+	struct sk_buff *skb = NULL;
+	struct tx_status_info *tx_info = NULL;
+	t_u32 remain_len = 0;
+	t_u16 fc, type, stype;
+
+	ENTER();
+
+	if (buf == NULL || len == 0) {
+		PRINTM(MERROR, "%s: corrupt data\n", __func__);
+		LEAVE();
+		return -EFAULT;
+	}
+
+	/* If the packet is probe response, that means we are in listen phase,
+	 * so we should not call remain_on_channel_cfg because
+	 * remain_on_channl already handled it. If the packet if action, that
+	 * means we are in PD/GO negotiation, so we should call
+	 * remain_on_channel_cfg in order to receive action frame from peer
+	 * device
+	 */
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		if (ieee80211_is_probe_resp(((struct ieee80211_mgmt *)buf)->
+					    frame_control)) {
+			PRINTM(MIOCTL, "Skip send probe_resp in GO/UAP mode\n");
+			goto done;
+		}
+		fc = le16_to_cpu(((struct ieee80211_mgmt *)buf)->frame_control);
+		type = fc & IEEE80211_FCTL_FTYPE;
+		stype = fc & IEEE80211_FCTL_STYPE;
+		if (type == IEEE80211_FTYPE_MGMT) {
+			switch (stype) {
+			case IEEE80211_STYPE_AUTH:
+				PRINTM(MMSG, "wlan: HostMlme %s send Auth\n",
+				       priv->netdev->name);
+				break;
+			case IEEE80211_STYPE_DEAUTH:
+			case IEEE80211_STYPE_DISASSOC:
+				PRINTM(MMSG,
+				       "wlan: HostMlme %s send deauth/disassoc\n",
+				       priv->netdev->name);
+				if (priv->phandle->is_cac_timer_set)
+					woal_cancel_chanrpt_event(priv);
+
+				break;
+			case IEEE80211_STYPE_ASSOC_RESP:
+			case IEEE80211_STYPE_REASSOC_RESP:
+				PRINTM(MMSG,
+				       "wlan: HostMlme %s send assoc/reassoc resp\n",
+				       priv->netdev->name);
+				break;
+			default:
+				break;
+			}
+		}
+	}
+#if KERNEL_VERSION(2, 6, 39) <= CFG80211_VERSION_CODE
+	if ((ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control))
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+	    || moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
+#endif
+		) {
+#ifdef WIFI_DIRECT_SUPPORT
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+			woal_cfg80211_display_p2p_actframe(buf, len, chan,
+							   MTRUE);
+		if (priv->phandle->is_go_timer_set) {
+			woal_cancel_timer(&priv->phandle->go_timer);
+			priv->phandle->is_go_timer_set = MFALSE;
+		}
+#endif
+		if (priv->phandle->is_remain_timer_set) {
+			woal_cancel_timer(&priv->phandle->remain_timer);
+			woal_remain_timer_func(priv->phandle);
+		}
+		/* With sd8777 We have difficulty to receive response packet in
+		 * 500ms
+		 */
+#define MGMT_TX_DEFAULT_WAIT_TIME 1500
+		if (priv->phandle->remain_on_channel)
+			remain_priv =
+				priv->phandle->priv[priv->phandle->
+						    remain_bss_index];
+		/** cancel previous remain on channel */
+		if (priv->phandle->remain_on_channel && remain_priv) {
+			if (woal_cfg80211_remain_on_channel_cfg
+			    (remain_priv, MOAL_IOCTL_WAIT, MTRUE,
+			     &channel_status, NULL, 0, 0))
+				PRINTM(MERROR,
+				       "mgmt_tx:Fail to cancel remain on channel\n");
+			if (priv->phandle->cookie) {
+				cfg80211_remain_on_channel_expired(
+#if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
+									  remain_priv->
+									  netdev,
+#else
+									  remain_priv->
+									  wdev,
+#endif
+									  priv->
+									  phandle->
+									  cookie,
+									  &priv->
+									  phandle->
+									  chan,
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+									  priv->
+									  phandle->
+									  channel_type,
+#endif
+									  GFP_ATOMIC);
+				priv->phandle->cookie = 0;
+			}
+			priv->phandle->remain_on_channel = MFALSE;
+		}
+#ifdef STA_CFG80211
+		/** cancel pending scan */
+		woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+
+		if (chan) {
+			duration = (wait > MGMT_TX_DEFAULT_WAIT_TIME) ?
+				wait : MGMT_TX_DEFAULT_WAIT_TIME;
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+			if (channel_type_valid)
+				ret = woal_cfg80211_remain_on_channel_cfg(priv,
+									  MOAL_IOCTL_WAIT,
+									  MFALSE,
+									  &channel_status,
+									  chan,
+									  channel_type,
+									  duration);
+			else
+#endif
+				ret = woal_cfg80211_remain_on_channel_cfg(priv,
+									  MOAL_IOCTL_WAIT,
+									  MFALSE,
+									  &channel_status,
+									  chan,
+									  0,
+									  duration);
+			if (ret) {
+				/* Return fail will cause p2p connection fail
+				 */
+				woal_sched_timeout(2);
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+				if (channel_type_valid)
+					ret = woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE, &channel_status, chan, channel_type, duration);
+				else
+#endif
+					ret = woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE, &channel_status, chan, 0, duration);
+				PRINTM(MERROR,
+				       "Try configure remain on channel again, ret=%d\n",
+				       ret);
+				ret = 0;
+			} else {
+				priv->phandle->remain_on_channel = MTRUE;
+				priv->phandle->remain_bss_index =
+					priv->bss_index;
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+				priv->phandle->channel_type = channel_type;
+#endif
+				moal_memcpy_ext(priv->phandle,
+						&priv->phandle->chan, chan,
+						sizeof(struct
+						       ieee80211_channel),
+						sizeof(struct
+						       ieee80211_channel));
+				PRINTM(MIOCTL,
+				       "%s: Mgmt Tx: Set remain channel=%d duration=%d\n",
+				       dev->name,
+				       ieee80211_frequency_to_channel(chan->
+								      center_freq),
+				       duration);
+			}
+		}
+	}
+#endif
+
+	/* pkt_type + tx_control */
+#define HEADER_SIZE 8
+	packet_len = (t_u16)len + MLAN_MAC_ADDR_LENGTH;
+	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
+				       MLAN_MIN_DATA_HEADER_LEN + HEADER_SIZE +
+				       packet_len + sizeof(packet_len));
+	if (!pmbuf) {
+		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+#if KERNEL_VERSION(3, 8, 0) > LINUX_VERSION_CODE
+	*cookie = random32() | 1;
+#else
+	*cookie = prandom_u32() | 1;
+#endif
+	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
+	pkt_type = MRVL_PKT_TYPE_MGMT_FRAME;
+	tx_control = 0;
+	remain_len = HEADER_SIZE + packet_len + sizeof(packet_len);
+	/* Add pkt_type and tx_control */
+	moal_memcpy_ext(priv->phandle, pmbuf->pbuf + pmbuf->data_offset,
+			&pkt_type, sizeof(pkt_type), remain_len);
+	remain_len -= sizeof(pkt_type);
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+			&tx_control, sizeof(tx_control), remain_len);
+	remain_len -= sizeof(tx_control);
+	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
+#define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2)
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE,
+			&packet_len, sizeof(packet_len), remain_len);
+	remain_len -= sizeof(packet_len);
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+			sizeof(packet_len), buf, PACKET_ADDR4_POS, remain_len);
+	remain_len -= PACKET_ADDR4_POS;
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+			sizeof(packet_len) + PACKET_ADDR4_POS,
+			addr, MLAN_MAC_ADDR_LENGTH, remain_len);
+	remain_len -= MLAN_MAC_ADDR_LENGTH;
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE +
+			sizeof(packet_len) + PACKET_ADDR4_POS +
+			MLAN_MAC_ADDR_LENGTH,
+			buf + PACKET_ADDR4_POS, len - PACKET_ADDR4_POS,
+			remain_len);
+
+	pmbuf->data_len = HEADER_SIZE + packet_len + sizeof(packet_len);
+	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
+	pmbuf->bss_index = priv->bss_index;
+	if ((ieee80211_is_action(((struct ieee80211_mgmt *)buf)->frame_control))
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+	    || moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
+#endif
+		) {
+		pmbuf->flags = MLAN_BUF_FLAG_TX_STATUS;
+		if (!priv->tx_seq_num)
+			priv->tx_seq_num++;
+		pmbuf->tx_seq_num = priv->tx_seq_num++;
+		tx_info = kzalloc(sizeof(struct tx_status_info), GFP_ATOMIC);
+		if (tx_info) {
+			skb = alloc_skb(len, GFP_ATOMIC);
+			if (skb) {
+				moal_memcpy_ext(priv->phandle, skb->data, buf,
+						len, len);
+				skb_put(skb, len);
+				spin_lock_irqsave(&priv->tx_stat_lock, flags);
+				tx_info->tx_cookie = *cookie;
+				tx_info->tx_skb = skb;
+				tx_info->tx_seq_num = pmbuf->tx_seq_num;
+				if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
+				    (priv->phandle->remain_on_channel && !wait))
+					tx_info->cancel_remain_on_channel =
+						MTRUE;
+				INIT_LIST_HEAD(&tx_info->link);
+				list_add_tail(&tx_info->link,
+					      &priv->tx_stat_queue);
+				spin_unlock_irqrestore(&priv->tx_stat_lock,
+						       flags);
+			} else {
+				kfree(tx_info);
+				tx_info = NULL;
+			}
+		}
+	}
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+
+		/* Delay 30ms to guarantee the packet has been already tx'ed,
+		 * because if we call cfg80211_mgmt_tx_status() immediately,
+		 * then wpa_supplicant will call cancel_remain_on_channel(),
+		 * which may affect the mgmt frame tx. Meanwhile it is only
+		 * necessary for P2P action handshake to wait 30ms.
+		 */
+		if ((ieee80211_is_action(((struct ieee80211_mgmt *)buf)->
+					 frame_control))
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+		    || moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
+#endif
+			) {
+			if (tx_info)
+				break;
+			else
+				woal_sched_timeout(30);
+		}
+		/* Notify the mgmt tx status */
+#if KERNEL_VERSION(2, 6, 37) <= CFG80211_VERSION_CODE
+#if KERNEL_VERSION(3, 6, 0) > CFG80211_VERSION_CODE
+		cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true,
+					GFP_ATOMIC);
+#else
+		cfg80211_mgmt_tx_status(priv->wdev, *cookie, buf, len, true,
+					GFP_ATOMIC);
+#endif
+#endif
+		break;
+	case MLAN_STATUS_SUCCESS:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		ret = -EFAULT;
+		break;
+	}
+
+done:
+
+	if (status != MLAN_STATUS_PENDING) {
+		if (tx_info)
+			woal_remove_tx_info(priv, tx_info->tx_seq_num);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Add custom ie to mgmt frames.
+ *
+ * @param priv                  A pointer to moal private structure
+ * @param beacon_ies_data       Beacon ie
+ * @param beacon_index          The index for beacon when auto index
+ * @param proberesp_ies_data    Probe resp ie
+ * @param proberesp_index       The index for probe resp when auto index
+ * @param assocresp_ies_data    Assoc resp ie
+ * @param assocresp_index       The index for assoc resp when auto index
+ * @param probereq_ies_data     Probe req ie
+ * @param probereq_index        The index for probe req when auto index
+ * @param wait_option           wait option
+ *
+ * @return              0 -- success, otherwise fail
+ */
+static mlan_status
+woal_cfg80211_custom_ie(moal_private *priv, custom_ie *beacon_ies_data,
+			t_u16 *beacon_index, custom_ie *proberesp_ies_data,
+			t_u16 *proberesp_index, custom_ie *assocresp_ies_data,
+			t_u16 *assocresp_index, custom_ie *probereq_ies_data,
+			t_u16 *probereq_index, t_u8 wait_option)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_custom_ie *pcustom_ie = NULL;
+	t_u8 *pos = NULL;
+	t_u16 len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u32 remain_len = 0;
+
+	ENTER();
+
+	pcustom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL);
+	if (!pcustom_ie) {
+		PRINTM(MERROR, "Fail to allocate custome_ie\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	pcustom_ie->type = TLV_TYPE_MGMT_IE;
+
+	pos = (t_u8 *)pcustom_ie->ie_data_list;
+	remain_len = sizeof(pcustom_ie->ie_data_list);
+	if (beacon_ies_data) {
+		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE +
+			beacon_ies_data->ie_length;
+		moal_memcpy_ext(priv->phandle, pos, beacon_ies_data, len,
+				remain_len);
+		pos += len;
+		remain_len -= len;
+		pcustom_ie->len += len;
+	}
+
+	if (proberesp_ies_data) {
+		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE +
+			proberesp_ies_data->ie_length;
+		moal_memcpy_ext(priv->phandle, pos, proberesp_ies_data, len,
+				remain_len);
+		pos += len;
+		remain_len -= len;
+		pcustom_ie->len += len;
+	}
+
+	if (assocresp_ies_data) {
+		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE +
+			assocresp_ies_data->ie_length;
+		moal_memcpy_ext(priv->phandle, pos, assocresp_ies_data, len,
+				remain_len);
+		pos += len;
+		remain_len -= len;
+		pcustom_ie->len += len;
+	}
+
+	if (probereq_ies_data) {
+		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE +
+			probereq_ies_data->ie_length;
+		moal_memcpy_ext(priv->phandle, pos, probereq_ies_data, len,
+				remain_len);
+		pos += len;
+		remain_len -= len;
+		pcustom_ie->len += len;
+	}
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		PRINTM(MERROR, "Fail to allocate ioctl_req\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, &misc->param.cust_ie, pcustom_ie,
+			sizeof(mlan_ds_misc_custom_ie),
+			sizeof(mlan_ds_misc_custom_ie));
+
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* get the assigned index */
+	pos = (t_u8 *)(&misc->param.cust_ie.ie_data_list[0].ie_index);
+	if (beacon_ies_data && beacon_ies_data->ie_length &&
+	    beacon_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+		/* save beacon ie index after auto-indexing */
+		*beacon_index = misc->param.cust_ie.ie_data_list[0].ie_index;
+		len = sizeof(*beacon_ies_data) - MAX_IE_SIZE +
+			beacon_ies_data->ie_length;
+		pos += len;
+	}
+
+	if (proberesp_ies_data && proberesp_ies_data->ie_length &&
+	    proberesp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+		/* save probe resp ie index after auto-indexing */
+		*proberesp_index = *((t_u16 *)pos);
+		len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE +
+			proberesp_ies_data->ie_length;
+		pos += len;
+	}
+
+	if (assocresp_ies_data && assocresp_ies_data->ie_length &&
+	    assocresp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+		/* save assoc resp ie index after auto-indexing */
+		*assocresp_index = *((t_u16 *)pos);
+		len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE +
+			assocresp_ies_data->ie_length;
+		pos += len;
+	}
+	if (probereq_ies_data && probereq_ies_data->ie_length &&
+	    probereq_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+		/* save probe resp ie index after auto-indexing */
+		*probereq_index = *((t_u16 *)pos);
+		len = sizeof(*probereq_ies_data) - MAX_IE_SIZE +
+			probereq_ies_data->ie_length;
+		pos += len;
+	}
+	// TODO why we check status_code at end
+	if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL)
+		status = MLAN_STATUS_FAILURE;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	kfree(pcustom_ie);
+	LEAVE();
+	return status;
+}
+
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+/**
+ * @brief set Qos map
+ *
+ * @param wiphy         A pointer to wiphy structure
+ * @param dev           A pointer to net_device structure
+ * @param qos_map       A pointer to cfg80211_qos_map structure
+ *
+ *
+ * @return              0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_qos_map(struct wiphy *wiphy, struct net_device *dev,
+			  struct cfg80211_qos_map *qos_map)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int i, j, ret = 0;
+
+	ENTER();
+	/**clear dscp map*/
+	if (!qos_map) {
+		memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
+		goto done;
+	}
+
+	/**update dscp map*/
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		PRINTM(MINFO, "TID %d: dscp_low=%d, dscp_high=%d\n", i,
+		       qos_map->up[i].low, qos_map->up[i].high);
+		if (qos_map->up[i].low != 0xff && qos_map->up[i].high != 0xff &&
+		    qos_map->up[i].high <= 63) {
+			for (j = qos_map->up[i].low; j <= qos_map->up[i].high;
+			     j++)
+				priv->dscp_map[j] = i;
+		}
+	}
+
+	for (i = 0; i < qos_map->num_des; i++) {
+		if ((qos_map->dscp_exception[i].dscp <= 63) &&
+		    (qos_map->dscp_exception[i].up <= 7)) {
+			PRINTM(MINFO, "dscp excpt: value=%d priority=%d\n",
+			       qos_map->dscp_exception[i].dscp,
+			       qos_map->dscp_exception[i].up);
+			priv->dscp_map[qos_map->dscp_exception[i].dscp] =
+				qos_map->dscp_exception[i].up;
+		}
+	}
+
+	/**UAP update (re)associate response*/
+	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		IEEEtypes_Generic_t qos_map_ie;
+		t_u16 qos_map_ies_len;
+
+		qos_map_ie.ieee_hdr.element_id = QOS_MAPPING;
+		qos_map_ie.ieee_hdr.len =
+			2 * qos_map->num_des + sizeof(qos_map->up);
+		qos_map_ies_len =
+			qos_map_ie.ieee_hdr.len + sizeof(qos_map_ie.ieee_hdr);
+
+		if (qos_map_ies_len > sizeof(qos_map_ie.data)) {
+			PRINTM(MERROR,
+			       "QoS MAP IE size exceeds the buffer len\n");
+			goto done;
+		}
+		moal_memcpy_ext(priv->phandle, qos_map_ie.data,
+				(t_u8 *)qos_map->dscp_exception,
+				2 * qos_map->num_des, sizeof(qos_map_ie.data));
+		moal_memcpy_ext(priv->phandle,
+				&qos_map_ie.data[2 * qos_map->num_des],
+				(t_u8 *)qos_map->up, sizeof(qos_map->up),
+				sizeof(qos_map_ie.data) - 2 * qos_map->num_des);
+
+		/* set the assoc response ies */
+		ret = woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0,
+						  (t_u8 *)&qos_map_ie,
+						  qos_map_ies_len, NULL, 0,
+						  MGMT_MASK_ASSOC_RESP_QOS_MAP,
+						  MOAL_IOCTL_WAIT);
+		if (ret) {
+			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
+			goto done;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief get specific ie
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ * @param ie_out          Pointer to out IE buf
+ * @param ie_out_len    Total length of ie_out
+ * @param mask            IE mask
+ *
+ * @return                out IE length
+ */
+static t_u16
+woal_get_specific_ie(const t_u8 *ie, int len, t_u8 *ie_out,
+		     t_u32 ie_out_len, t_u16 mask)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	int length;
+	t_u8 id = 0;
+	t_u16 out_len = 0;
+	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
+	const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
+	const u8 p2p_oui[4] = { 0x50, 0x6f, 0x9a, 0x09 };
+	const u8 wfd_oui[4] = { 0x50, 0x6f, 0x9a, 0x0a };
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+
+	ENTER();
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+		if ((length + 2) > left_len)
+			break;
+		if (id == VENDOR_SPECIFIC_221) {
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    pvendor_ie->vend_hdr.oui_type == wmm_oui[3]) {
+				PRINTM(MIOCTL, "find WMM IE\n");
+			} else if (!memcmp(pvendor_ie->vend_hdr.oui, p2p_oui,
+					   sizeof(pvendor_ie->vend_hdr.oui)) &&
+				   pvendor_ie->vend_hdr.oui_type ==
+				   p2p_oui[3]) {
+				if (mask & IE_MASK_P2P) {
+					/** only get first p2p ie here */
+					moal_memcpy_ext(NULL, ie_out + out_len,
+							pos, length + 2,
+							ie_out_len - out_len);
+					out_len += length + 2;
+					break;
+				}
+			} else if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
+					   sizeof(pvendor_ie->vend_hdr.oui)) &&
+				   pvendor_ie->vend_hdr.oui_type ==
+				   wps_oui[3]) {
+				if (mask & IE_MASK_WPS) {
+					if ((out_len + length + 2) <
+					    (int)ie_out_len) {
+						moal_memcpy_ext(NULL,
+								ie_out +
+								out_len, pos,
+								length + 2,
+								ie_out_len -
+								out_len);
+						out_len += length + 2;
+					} else {
+						PRINTM(MERROR,
+						       "get_specific_ie: IE too big, fail copy WPS IE\n");
+						break;
+					}
+				}
+			} else if (!memcmp(pvendor_ie->vend_hdr.oui, wfd_oui,
+					   sizeof(pvendor_ie->vend_hdr.oui)) &&
+				   pvendor_ie->vend_hdr.oui_type ==
+				   wfd_oui[3]) {
+				if (mask & IE_MASK_WFD) {
+					if ((out_len + length + 2) <
+					    (int)ie_out_len) {
+						moal_memcpy_ext(NULL,
+								ie_out +
+								out_len, pos,
+								length + 2,
+								ie_out_len -
+								out_len);
+						out_len += length + 2;
+					} else {
+						PRINTM(MERROR,
+						       "get_specific_ie: IE too big, fail copy WFD IE\n");
+						break;
+					}
+				}
+			} else if (mask & IE_MASK_VENDOR) {
+				if ((out_len + length + 2) < (int)ie_out_len) {
+					moal_memcpy_ext(NULL, ie_out + out_len,
+							pos, length + 2,
+							ie_out_len - out_len);
+					out_len += length + 2;
+				} else {
+					PRINTM(MERROR,
+					       "get_specific_ie:IE too big, fail copy VENDOR IE\n");
+					break;
+				}
+			}
+		}
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+	LEAVE();
+	return out_len;
+}
+
+/**
+ * @brief Find specific IE from IE buffer
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ * @param spec_ie         Pointer to specific IE buffer
+ * @param spec_len        Total length of specific IE
+ *
+ * @return                out IE length
+ */
+static t_u8
+woal_find_ie(const t_u8 *ie, int len, const t_u8 *spec_ie, int spec_len)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	int length;
+
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		if ((length + 2) > left_len)
+			break;
+		if ((length + 2) == spec_len) {
+			if (!memcmp(pos, spec_ie, spec_len))
+				return MTRUE;
+		}
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+	return MFALSE;
+}
+
+/**
+ * @brief Filter specific IE in ie buf
+ *
+ * @param priv            pointer to moal private structure
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ * @param ie_out		  Pointer to out IE buf
+ * @param ie_out_len      Total length of ie_out
+ * @param wps_flag	      flag for wps/p2p
+ * @param dup_ie          Pointer to duplicate ie
+ * @param dup_ie_len	  duplicate IE len
+ *
+ * @return                out IE length
+ */
+static t_u16
+woal_filter_beacon_ies(moal_private *priv, const t_u8 *ie, int len,
+		       t_u8 *ie_out, t_u32 ie_out_len,
+		       t_u16 wps_flag, const t_u8 *dup_ie, int dup_ie_len)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	int length;
+	t_u8 id = 0;
+	t_u16 out_len = 0;
+	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
+	const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
+	const u8 p2p_oui[4] = { 0x50, 0x6f, 0x9a, 0x09 };
+	const u8 wfd_oui[4] = { 0x50, 0x6f, 0x9a, 0x0a };
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+	t_u8 find_p2p_ie = MFALSE;
+	t_u8 enable_11d = MFALSE;
+	t_u8 ext_id = 0;
+	int ie_len;
+
+	/* ERP_INFO/EXTENDED_SUPPORT_RATES/HT_CAPABILITY/HT_OPERATION/WMM
+	 * and WPS/P2P/WFD IE will be fileter out
+	 */
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+		if ((length + 2) > left_len)
+			break;
+		if (dup_ie && dup_ie_len &&
+		    woal_find_ie(dup_ie, dup_ie_len, pos, length + 2)) {
+			PRINTM(MIOCTL, "skip duplicate IE\n");
+			pos += (length + 2);
+			left_len -= (length + 2);
+			continue;
+		}
+		switch (id) {
+		case COUNTRY_INFO:
+			enable_11d = MTRUE;
+			if ((out_len + length + 2) < (int)ie_out_len) {
+				moal_memcpy_ext(priv->phandle, ie_out + out_len,
+						pos, length + 2,
+						ie_out_len - out_len);
+				out_len += length + 2;
+			} else {
+				PRINTM(MERROR,
+				       "IE too big, fail copy COUNTRY INFO IE\n");
+			}
+			break;
+		case HT_CAPABILITY:
+		case HT_OPERATION:
+		case VHT_CAPABILITY:
+		case VHT_OPERATION:
+			if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) {
+				if ((out_len + length + 2) < (int)ie_out_len) {
+					moal_memcpy_ext(priv->phandle,
+							ie_out + out_len, pos,
+							length + 2,
+							ie_out_len - out_len);
+					out_len += length + 2;
+				} else {
+					PRINTM(MERROR,
+					       "IE too big, fail copy COUNTRY INFO IE\n");
+				}
+			}
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+		case WLAN_EID_ERP_INFO:
+			/* Fall Through */
+		case REGULATORY_CLASS:
+			/* Fall Through */
+		case OVERLAPBSSSCANPARAM:
+			/* Fall Through */
+		case WAPI_IE:
+			break;
+		case EXTENSION:
+			ext_id = *(pos + 2);
+			if ((ext_id == HE_CAPABILITY || ext_id == HE_OPERATION)
+			    && !moal_extflg_isset(priv->phandle, EXT_HOST_MLME)
+				)
+				break;
+			else {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
+				if (ext_id == HE_CAPABILITY) {
+					mlan_ds_11ax_he_cfg he_cfg;
+					IEEEtypes_HECap_t *hecap_ie;
+
+					if (priv->channel <= 14)
+						he_cfg.band = MBIT(0);
+					else
+						he_cfg.band = MBIT(1);
+
+					PRINTM(MCMND,
+					       "Retrieve 11ax cfg by channel=%d band=%d\n",
+					       priv->channel, he_cfg.band);
+
+					if (0 ==
+					    woal_11ax_cfg(priv, MLAN_ACT_GET,
+							  &he_cfg)) {
+						hecap_ie =
+							(IEEEtypes_HECap_t *) &
+							he_cfg.he_cap.len;
+
+						hecap_ie->ieee_hdr.len =
+							he_cfg.he_cap.len;
+						hecap_ie->ieee_hdr.element_id =
+							he_cfg.he_cap.id;
+
+						moal_memcpy_ext(priv->phandle,
+								ie_out +
+								out_len,
+								hecap_ie,
+								hecap_ie->
+								ieee_hdr.len +
+								2,
+								ie_out_len -
+								out_len);
+
+						out_len +=
+							hecap_ie->ieee_hdr.len +
+							2;
+					} else {
+						PRINTM(MERROR,
+						       "Fail to get 11ax he_cap parameters\n");
+					}
+				} else
+#endif
+				{
+					if ((out_len + length + 2) <
+					    (int)ie_out_len) {
+						moal_memcpy_ext(priv->phandle,
+								ie_out +
+								out_len, pos,
+								length + 2,
+								ie_out_len -
+								out_len);
+						out_len += length + 2;
+					} else {
+						PRINTM(MERROR,
+						       "IE too big, fail copy EXTENSION IE\n");
+					}
+				}
+				break;
+			}
+		case EXT_CAPABILITY:
+			/* filter out EXTCAP */
+			if (wps_flag & IE_MASK_EXTCAP) {
+				ie_len = length + 2;
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+							(t_u8 *)pos, &ie_len,
+							MOAL_IOCTL_WAIT))
+					PRINTM(MERROR,
+					       "Fail to set EXTCAP IE\n");
+				break;
+			}
+			if ((out_len + length + 2) < (int)ie_out_len) {
+				moal_memcpy_ext(priv->phandle, ie_out + out_len,
+						pos, length + 2,
+						ie_out_len - out_len);
+				out_len += length + 2;
+			} else {
+				PRINTM(MERROR,
+				       "IE too big, fail copy EXTCAP IE\n");
+			}
+			break;
+		case VENDOR_SPECIFIC_221:
+			/* filter out wmm ie */
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    pvendor_ie->vend_hdr.oui_type == wmm_oui[3]) {
+				break;
+			}
+			/* filter out wps ie */
+			else if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
+					 sizeof(pvendor_ie->vend_hdr.oui)) &&
+				 pvendor_ie->vend_hdr.oui_type == wps_oui[3]) {
+				if (wps_flag & IE_MASK_WPS)
+					break;
+			}
+			/* filter out first p2p ie */
+			else if (!memcmp(pvendor_ie->vend_hdr.oui, p2p_oui,
+					 sizeof(pvendor_ie->vend_hdr.oui)) &&
+				 pvendor_ie->vend_hdr.oui_type == p2p_oui[3]) {
+				if (!find_p2p_ie && (wps_flag & IE_MASK_P2P)) {
+					find_p2p_ie = MTRUE;
+					break;
+				}
+			}
+			/* filter out wfd ie */
+			else if (!memcmp(pvendor_ie->vend_hdr.oui, wfd_oui,
+					 sizeof(pvendor_ie->vend_hdr.oui)) &&
+				 pvendor_ie->vend_hdr.oui_type == wfd_oui[3]) {
+				if (wps_flag & IE_MASK_WFD)
+					break;
+			} else if (wps_flag & IE_MASK_VENDOR) {
+				// filter out vendor IE
+				break;
+			}
+			if ((out_len + length + 2) < (int)ie_out_len) {
+				moal_memcpy_ext(priv->phandle, ie_out + out_len,
+						pos, length + 2,
+						ie_out_len - out_len);
+				out_len += length + 2;
+			} else {
+				PRINTM(MERROR,
+				       "IE too big, fail copy VENDOR_SPECIFIC_221 IE\n");
+			}
+			break;
+		default:
+			if ((out_len + length + 2) < (int)ie_out_len) {
+				moal_memcpy_ext(priv->phandle, ie_out + out_len,
+						pos, length + 2,
+						ie_out_len - out_len);
+				out_len += length + 2;
+			} else {
+				PRINTM(MERROR, "IE too big, fail copy %d IE\n",
+				       id);
+			}
+			break;
+		}
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+
+	if (enable_11d)
+		woal_set_11d(priv, MOAL_IOCTL_WAIT, MTRUE);
+	return out_len;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ * @brief Check if selected_registrar_on in wps_ie
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ *
+ * @return                MTRUE/MFALSE
+ */
+static t_u8
+is_selected_registrar_on(const t_u8 *ie, int len)
+{
+#define WPS_IE_FIX_LEN 6
+#define TLV_ID_SELECTED_REGISTRAR 0x1041
+	int left_len = len - WPS_IE_FIX_LEN;
+
+	TLV_Generic_t *tlv = (TLV_Generic_t *)(ie + WPS_IE_FIX_LEN);
+	u16 tlv_type, tlv_len;
+	u8 *pos = NULL;
+
+	while (left_len > (int)sizeof(TLV_Generic_t)) {
+		tlv_type = ntohs((__force __be16) tlv->type);
+		tlv_len = ntohs((__force __be16) tlv->len);
+		if (tlv_type == TLV_ID_SELECTED_REGISTRAR) {
+			PRINTM(MIOCTL, "Selected Registrar found !");
+			pos = (u8 *)tlv + sizeof(TLV_Generic_t);
+			if (*pos == 1)
+				return MTRUE;
+			else
+				return MFALSE;
+		}
+		tlv = (TLV_Generic_t *)((u8 *)tlv + tlv_len +
+					sizeof(TLV_Generic_t));
+		left_len -= tlv_len + sizeof(TLV_Generic_t);
+	}
+	return MFALSE;
+}
+
+/**
+ * @brief Check if selected_registrar_on in ies
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ *
+ *
+ * @return                MTRUE/MFALSE
+ */
+static t_u16
+woal_is_selected_registrar_on(const t_u8 *ie, int len)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	int length;
+	t_u8 id = 0;
+	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
+	const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
+
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+		if ((length + 2) > left_len)
+			break;
+		switch (id) {
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    pvendor_ie->vend_hdr.oui_type == wps_oui[3]) {
+				PRINTM(MIOCTL, "Find WPS ie\n");
+				return is_selected_registrar_on(pos,
+								length + 2);
+			}
+			break;
+		default:
+			break;
+		}
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+	return MFALSE;
+}
+#endif
+
+/**
+ * @brief config AP or GO for mgmt frame ies.
+ *
+ * @param priv                  A pointer to moal private structure
+ * @param beacon_ies            A pointer to beacon ies
+ * @param beacon_ies_len        Beacon ies length
+ * @param proberesp_ies         A pointer to probe resp ies
+ * @param proberesp_ies_len     Probe resp ies length
+ * @param assocresp_ies         A pointer to probe resp ies
+ * @param assocresp_ies_len     Assoc resp ies length
+ * @param probereq_ies          A pointer to probe req ies
+ * @param probereq_ies_len      Probe req ies length *
+ * @param mask					Mgmt frame mask
+ * @param wait_option           wait_option
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_mgmt_frame_ie(moal_private *priv, const t_u8 *beacon_ies,
+			    size_t beacon_ies_len, const t_u8 *proberesp_ies,
+			    size_t proberesp_ies_len, const t_u8 *assocresp_ies,
+			    size_t assocresp_ies_len, const t_u8 *probereq_ies,
+			    size_t probereq_ies_len, t_u16 mask,
+			    t_u8 wait_option)
+{
+	int ret = 0;
+	t_u8 *pos = NULL;
+	custom_ie *beacon_ies_data = NULL;
+	custom_ie *proberesp_ies_data = NULL;
+	custom_ie *assocresp_ies_data = NULL;
+	custom_ie *probereq_ies_data = NULL;
+
+	/* static variables for mgmt frame ie auto-indexing */
+	t_u16 beacon_index = priv->beacon_index;
+	t_u16 proberesp_index = priv->proberesp_index;
+	t_u16 assocresp_index = priv->assocresp_index;
+	t_u16 probereq_index = priv->probereq_index;
+	t_u16 beacon_wps_index = priv->beacon_wps_index;
+	t_u16 proberesp_p2p_index = priv->proberesp_p2p_index;
+	t_u16 assocrep_qos_map_index = priv->assocresp_qos_map_index;
+	t_u16 beacon_vendor_index = priv->beacon_vendor_index;
+
+	ENTER();
+
+	/* we need remove vendor IE from beacon extra IE, vendor IE will be
+	 * configure through proberesp_vendor_index
+	 */
+	if (mask & MGMT_MASK_BEACON_WPS_P2P) {
+		beacon_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
+		if (!beacon_ies_data) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		if (beacon_ies && beacon_ies_len) {
+#ifdef WIFI_DIRECT_SUPPORT
+			if (woal_is_selected_registrar_on(beacon_ies,
+							  beacon_ies_len)) {
+				PRINTM(MIOCTL, "selected_registrar is on\n");
+				priv->phandle->is_go_timer_set = MTRUE;
+				woal_mod_timer(&priv->phandle->go_timer,
+					       MOAL_TIMER_10S);
+			} else
+				PRINTM(MIOCTL, "selected_registrar is off\n");
+#endif
+			beacon_ies_data->ie_index = beacon_wps_index;
+			beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON;
+			beacon_ies_data->ie_length =
+				woal_filter_beacon_ies(priv, beacon_ies,
+						       beacon_ies_len,
+						       beacon_ies_data->
+						       ie_buffer, MAX_IE_SIZE,
+						       IE_MASK_VENDOR, NULL, 0);
+			DBG_HEXDUMP(MCMD_D, "beacon extra ie",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		} else {
+			/* clear the beacon wps ies */
+			if (beacon_wps_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid beacon wps index for mgmt frame ie.\n");
+				goto done;
+			}
+
+			beacon_ies_data->ie_index = beacon_wps_index;
+			beacon_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			beacon_ies_data->ie_length = 0;
+			beacon_wps_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+		if ((beacon_ies && beacon_ies_len &&
+		     beacon_ies_data->ie_length) ||
+		    (beacon_ies_data->mgmt_subtype_mask ==
+		     MLAN_CUSTOM_IE_DELETE_MASK)) {
+			if (MLAN_STATUS_FAILURE ==
+			    woal_cfg80211_custom_ie(priv, beacon_ies_data,
+						    &beacon_wps_index,
+						    proberesp_ies_data,
+						    &proberesp_index,
+						    assocresp_ies_data,
+						    &assocresp_index,
+						    probereq_ies_data,
+						    &probereq_index,
+						    wait_option)) {
+				PRINTM(MERROR, "Fail to set beacon wps IE\n");
+				ret = -EFAULT;
+			}
+			priv->beacon_wps_index = beacon_wps_index;
+			PRINTM(MCMND, "beacon_wps_index=0x%x len=%d\n",
+			       beacon_wps_index, beacon_ies_data->ie_length);
+			goto done;
+		}
+		kfree(beacon_ies_data);	// Further allocation of beacon_ies_data
+		// is happening, so need to free here.
+		beacon_ies_data = NULL;
+	}
+
+	if (mask & MGMT_MASK_ASSOC_RESP_QOS_MAP) {
+		assocresp_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
+		if (!assocresp_ies_data) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		if (assocresp_ies && assocresp_ies_len) {
+			/* set the assoc response qos map ies */
+			assocresp_ies_data->ie_index = assocrep_qos_map_index;
+			assocresp_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_ASSOC_RESP;
+			if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
+			    assocrep_qos_map_index)
+				assocresp_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			if (assocresp_ies_len > MAX_IE_SIZE) {
+				PRINTM(MERROR,
+				       "IE too big: assocresp_ies_len=%d\n",
+				       (int)assocresp_ies_len);
+				goto done;
+			}
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			moal_memcpy_ext(priv->phandle, pos, assocresp_ies,
+					assocresp_ies_len, MAX_IE_SIZE);
+			DBG_HEXDUMP(MCMD_D, "Qos Map",
+				    assocresp_ies_data->ie_buffer,
+				    assocresp_ies_data->ie_length);
+		} else {
+			/* clear the assoc response qos map ie */
+			if (assocrep_qos_map_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid Qos map index for mgmt frame ie.\n");
+				goto done;
+			}
+
+			assocresp_ies_data->ie_index = assocrep_qos_map_index;
+			assocresp_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			assocresp_ies_data->ie_length = 0;
+			assocrep_qos_map_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+		if (MLAN_STATUS_FAILURE ==
+		    woal_cfg80211_custom_ie(priv, NULL, &beacon_wps_index, NULL,
+					    &proberesp_index,
+					    assocresp_ies_data,
+					    &assocrep_qos_map_index, NULL,
+					    &probereq_index, wait_option)) {
+			PRINTM(MERROR, "Fail to set Qos map IE\n");
+			ret = -EFAULT;
+		}
+		priv->assocresp_qos_map_index = assocrep_qos_map_index;
+		PRINTM(MCMND, "qos map ie index=0x%x len=%d\n",
+		       assocrep_qos_map_index, assocresp_ies_data->ie_length);
+		goto done;
+	}
+
+	if (mask & MGMT_MASK_BEACON) {
+		beacon_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
+		if (!beacon_ies_data) {
+			ret = -ENOMEM;
+			goto done;
+		}
+	}
+
+	if (mask & MGMT_MASK_PROBE_RESP) {
+		/** set or clear proberesp ie */
+		if (proberesp_ies_len ||
+		    (!proberesp_ies_len && !beacon_ies_len)) {
+			proberesp_ies_data =
+				kzalloc(sizeof(custom_ie), GFP_KERNEL);
+			if (!proberesp_ies_data) {
+				ret = -ENOMEM;
+				goto done;
+			}
+		}
+	}
+
+	if (mask & MGMT_MASK_ASSOC_RESP) {
+		/** set or clear assocresp ie */
+		if (assocresp_ies_len ||
+		    (!assocresp_ies_len && !beacon_ies_len)) {
+			assocresp_ies_data =
+				kzalloc(sizeof(custom_ie), GFP_KERNEL);
+			if (!assocresp_ies_data) {
+				ret = -ENOMEM;
+				goto done;
+			}
+		}
+	}
+	if (mask & MGMT_MASK_PROBE_REQ) {
+		probereq_ies_data = kzalloc(sizeof(custom_ie), GFP_KERNEL);
+		if (!probereq_ies_data) {
+			ret = -ENOMEM;
+			goto done;
+		}
+	}
+
+	if (beacon_ies_data) {
+		if (beacon_ies && beacon_ies_len) {
+			/* set the probe response/beacon vendor ies which
+			 * includes wpa IE
+			 */
+			beacon_ies_data->ie_index = beacon_vendor_index;
+			beacon_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_PROBE_RESP | MGMT_MASK_BEACON;
+			if (beacon_vendor_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+				beacon_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			beacon_ies_data->ie_length =
+				woal_get_specific_ie(beacon_ies, beacon_ies_len,
+						     beacon_ies_data->ie_buffer,
+						     MAX_IE_SIZE,
+						     IE_MASK_VENDOR);
+			DBG_HEXDUMP(MCMD_D, "beacon vendor IE",
+				    beacon_ies_data->ie_buffer,
+				    beacon_ies_data->ie_length);
+		}
+		if (beacon_vendor_index !=
+		    MLAN_CUSTOM_IE_AUTO_IDX_MASK &&
+		    !beacon_ies_data->ie_length) {
+			/* clear the beacon vendor ies */
+			if (beacon_vendor_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid beacon_vendor_index for mgmt frame ie.\n");
+				goto done;
+			}
+			beacon_ies_data->ie_index = beacon_vendor_index;
+			beacon_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			beacon_ies_data->ie_length = 0;
+			beacon_vendor_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+		if ((beacon_ies && beacon_ies_len &&
+		     beacon_ies_data->ie_length) ||
+		    (beacon_ies_data->mgmt_subtype_mask ==
+		     MLAN_CUSTOM_IE_DELETE_MASK)) {
+			if (MLAN_STATUS_FAILURE ==
+			    woal_cfg80211_custom_ie(priv, beacon_ies_data,
+						    &beacon_vendor_index, NULL,
+						    &proberesp_index, NULL,
+						    &assocresp_index, NULL,
+						    &probereq_index,
+						    wait_option)) {
+				PRINTM(MERROR,
+				       "Fail to set beacon vendor IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			priv->beacon_vendor_index = beacon_vendor_index;
+			PRINTM(MCMND, "beacon_vendor=0x%x len=%d\n",
+			       beacon_vendor_index, beacon_ies_data->ie_length);
+		}
+		memset(beacon_ies_data, 0x00, sizeof(custom_ie));
+		if (beacon_ies && beacon_ies_len) {
+			/* set the beacon ies */
+			/* we need remove vendor IE from beacon tail, vendor/wpa
+			 * IE will be configure through beacon_vendor_index
+			 */
+			beacon_ies_data->ie_index = beacon_index;
+			beacon_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_BEACON | MGMT_MASK_ASSOC_RESP |
+				MGMT_MASK_PROBE_RESP;
+			beacon_ies_data->ie_length =
+				woal_filter_beacon_ies(priv, beacon_ies,
+						       beacon_ies_len,
+						       beacon_ies_data->
+						       ie_buffer, MAX_IE_SIZE,
+						       IE_MASK_WPS | IE_MASK_WFD
+						       | IE_MASK_P2P |
+						       IE_MASK_VENDOR,
+						       proberesp_ies,
+						       proberesp_ies_len);
+			if (beacon_ies_data->ie_length)
+				DBG_HEXDUMP(MCMD_D, "beacon ie",
+					    beacon_ies_data->ie_buffer,
+					    beacon_ies_data->ie_length);
+			else {
+				kfree(beacon_ies_data);
+				beacon_ies_data = NULL;
+			}
+		} else {
+			/* clear the beacon ies */
+			if (beacon_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MINFO,
+				       "Invalid beacon index for mgmt frame ie.\n");
+				goto done;
+			}
+
+			beacon_ies_data->ie_index = beacon_index;
+			beacon_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			beacon_ies_data->ie_length = 0;
+			beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+	}
+
+	if (proberesp_ies_data) {
+		if (proberesp_ies && proberesp_ies_len) {
+			/* set the probe response p2p ies */
+			proberesp_ies_data->ie_index = proberesp_p2p_index;
+			proberesp_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_PROBE_RESP;
+			proberesp_ies_data->ie_length =
+				woal_get_specific_ie(proberesp_ies,
+						     proberesp_ies_len,
+						     proberesp_ies_data->
+						     ie_buffer, MAX_IE_SIZE,
+						     IE_MASK_P2P);
+			DBG_HEXDUMP(MCMD_D, "proberesp p2p ie",
+				    proberesp_ies_data->ie_buffer,
+				    proberesp_ies_data->ie_length);
+		} else if (proberesp_p2p_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
+			/* clear the probe response p2p ies */
+			if (proberesp_p2p_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid proberesp_p2p_index for mgmt frame ie.\n");
+				goto done;
+			}
+			proberesp_ies_data->ie_index = proberesp_p2p_index;
+			proberesp_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			proberesp_ies_data->ie_length = 0;
+			proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+		if ((proberesp_ies && proberesp_ies_len &&
+		     proberesp_ies_data->ie_length) ||
+		    (proberesp_ies_data->mgmt_subtype_mask ==
+		     MLAN_CUSTOM_IE_DELETE_MASK)) {
+			if (MLAN_STATUS_FAILURE ==
+			    woal_cfg80211_custom_ie(priv, NULL, &beacon_index,
+						    proberesp_ies_data,
+						    &proberesp_p2p_index, NULL,
+						    &assocresp_index, NULL,
+						    &probereq_index,
+						    wait_option)) {
+				PRINTM(MERROR,
+				       "Fail to set proberesp p2p IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			priv->proberesp_p2p_index = proberesp_p2p_index;
+			PRINTM(MCMND, "proberesp_p2p=0x%x len=%d\n",
+			       proberesp_p2p_index,
+			       proberesp_ies_data->ie_length);
+		}
+		memset(proberesp_ies_data, 0x00, sizeof(custom_ie));
+		if (proberesp_ies && proberesp_ies_len) {
+			/* set the probe response ies */
+			proberesp_ies_data->ie_index = proberesp_index;
+			proberesp_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_PROBE_RESP;
+			if (proberesp_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+				proberesp_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			proberesp_ies_data->ie_length =
+				woal_filter_beacon_ies(priv, proberesp_ies,
+						       proberesp_ies_len,
+						       proberesp_ies_data->
+						       ie_buffer, MAX_IE_SIZE,
+						       IE_MASK_P2P |
+						       IE_MASK_VENDOR, NULL, 0);
+			if (proberesp_ies_data->ie_length) {
+				DBG_HEXDUMP(MCMD_D, "proberesp ie",
+					    proberesp_ies_data->ie_buffer,
+					    proberesp_ies_data->ie_length);
+			} else {
+				kfree(proberesp_ies_data);
+				proberesp_ies_data = NULL;
+			}
+		} else {
+			/* clear the probe response ies */
+			if (proberesp_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid probe resp index for mgmt frame ie.\n");
+				goto done;
+			}
+			proberesp_ies_data->ie_index = proberesp_index;
+			proberesp_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			proberesp_ies_data->ie_length = 0;
+			proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+	}
+	if (assocresp_ies_data) {
+		if (assocresp_ies && assocresp_ies_len) {
+			/* set the assoc response ies */
+			assocresp_ies_data->ie_index = assocresp_index;
+			assocresp_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_ASSOC_RESP;
+			if (assocresp_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+				assocresp_ies_data->mgmt_subtype_mask |=
+					MLAN_CUSTOM_IE_NEW_MASK;
+			if (assocresp_ies_len > MAX_IE_SIZE) {
+				PRINTM(MERROR,
+				       "IE too big, assocresp_ies_len=%d\n",
+				       (int)assocresp_ies_len);
+				goto done;
+			}
+			assocresp_ies_data->ie_length = assocresp_ies_len;
+			pos = assocresp_ies_data->ie_buffer;
+			moal_memcpy_ext(priv->phandle, pos, assocresp_ies,
+					assocresp_ies_len, MAX_IE_SIZE);
+			DBG_HEXDUMP(MCMD_D, "assocresp ie",
+				    assocresp_ies_data->ie_buffer,
+				    assocresp_ies_data->ie_length);
+		} else {
+			/* clear the assoc response ies */
+			if (assocresp_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid assoc resp index for mgmt frame ie.\n");
+				goto done;
+			}
+
+			assocresp_ies_data->ie_index = assocresp_index;
+			assocresp_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			assocresp_ies_data->ie_length = 0;
+			assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+	}
+
+	if (probereq_ies_data) {
+		if (probereq_ies && probereq_ies_len) {
+			/* set the probe req ies */
+			probereq_ies_data->ie_index = probereq_index;
+			probereq_ies_data->mgmt_subtype_mask =
+				MGMT_MASK_PROBE_REQ;
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+				/* filter out P2P/WFD ie/EXT_CAP ie */
+				probereq_ies_data->ie_length =
+					woal_filter_beacon_ies(priv,
+							       probereq_ies,
+							       probereq_ies_len,
+							       probereq_ies_data->
+							       ie_buffer,
+							       MAX_IE_SIZE,
+							       IE_MASK_P2P |
+							       IE_MASK_WFD |
+							       IE_MASK_EXTCAP,
+							       NULL, 0);
+			} else {
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+				if (probereq_ies_len > MAX_IE_SIZE) {
+					PRINTM(MERROR,
+					       "IE too big, probereq_ies_len=%d\n",
+					       (int)probereq_ies_len);
+					goto done;
+				}
+				probereq_ies_data->ie_length = probereq_ies_len;
+				pos = probereq_ies_data->ie_buffer;
+				moal_memcpy_ext(priv->phandle, pos,
+						probereq_ies, probereq_ies_len,
+						MAX_IE_SIZE);
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			}
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+			if (probereq_ies_data->ie_length)
+				DBG_HEXDUMP(MCMD_D, "probereq ie",
+					    probereq_ies_data->ie_buffer,
+					    probereq_ies_data->ie_length);
+			else {
+				kfree(probereq_ies_data);
+				probereq_ies_data = NULL;
+			}
+		} else {
+			/* clear the probe req ies */
+			if (probereq_index > MAX_MGMT_IE_INDEX) {
+				PRINTM(MERROR,
+				       "Invalid probe req index for mgmt frame ie.\n");
+				goto done;
+			}
+			probereq_ies_data->ie_index = probereq_index;
+			probereq_ies_data->mgmt_subtype_mask =
+				MLAN_CUSTOM_IE_DELETE_MASK;
+			probereq_ies_data->ie_length = 0;
+			probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+		}
+	}
+
+	if (beacon_ies_data || proberesp_ies_data || assocresp_ies_data ||
+	    probereq_ies_data) {
+		if (MLAN_STATUS_FAILURE ==
+		    woal_cfg80211_custom_ie(priv, beacon_ies_data,
+					    &beacon_index, proberesp_ies_data,
+					    &proberesp_index,
+					    assocresp_ies_data,
+					    &assocresp_index, probereq_ies_data,
+					    &probereq_index, wait_option)) {
+			PRINTM(MERROR,
+			       "Fail to set beacon proberesp assoc probereq IES\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	if (beacon_ies_data) {
+		priv->beacon_index = beacon_index;
+		PRINTM(MCMND, "beacon ie length = %d\n",
+		       beacon_ies_data->ie_length);
+	}
+	if (assocresp_ies_data) {
+		priv->assocresp_index = assocresp_index;
+		PRINTM(MCMND, "assocresp ie length = %d\n",
+		       assocresp_ies_data->ie_length);
+	}
+	if (proberesp_ies_data) {
+		priv->proberesp_index = proberesp_index;
+		PRINTM(MCMND, "proberesp ie length = %d\n",
+		       proberesp_ies_data->ie_length);
+	}
+	if (probereq_ies_data) {
+		priv->probereq_index = probereq_index;
+		PRINTM(MCMND, "probereq ie length = %d\n",
+		       probereq_ies_data->ie_length);
+	}
+	PRINTM(MCMND, "beacon=%x assocresp=%x proberesp=%x probereq=%x\n",
+	       beacon_index, assocresp_index, proberesp_index, probereq_index);
+done:
+	kfree(beacon_ies_data);
+	kfree(proberesp_ies_data);
+	kfree(assocresp_ies_data);
+	kfree(probereq_ies_data);
+
+	LEAVE();
+
+	return ret;
+}
+
+/**
+ *  @brief Sets up the CFG802.11 specific HT capability fields
+ *  with default values
+ *
+ *  @param ht_info      A pointer to ieee80211_sta_ht_cap structure
+ *  @param dev_cap      Device capability information
+ *  @param mcs_set      Device MCS sets
+ *
+ *  @return             N/A
+ */
+void
+woal_cfg80211_setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info,
+			   t_u32 dev_cap, t_u8 *mcs_set)
+{
+	ENTER();
+
+	ht_info->ht_supported = true;
+	ht_info->ampdu_factor = 0x3;
+	ht_info->ampdu_density = 0;
+
+	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+	ht_info->cap = 0;
+	if (mcs_set)
+		moal_memcpy_ext(NULL, ht_info->mcs.rx_mask, mcs_set,
+				sizeof(ht_info->mcs.rx_mask),
+				sizeof(ht_info->mcs.rx_mask));
+	if (dev_cap & MBIT(8))	/* 40Mhz intolarance enabled */
+		ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+	if (dev_cap & MBIT(17))	/* Channel width 20/40Mhz support */
+		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	if ((dev_cap >> 20) & 0x03)	/* Delayed ACK supported */
+		ht_info->cap |= IEEE80211_HT_CAP_DELAY_BA;
+	if (dev_cap & MBIT(22))	/* Rx LDPC supported */
+		ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
+	if (dev_cap & MBIT(23))	/* Short GI @ 20Mhz supported */
+		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+	if (dev_cap & MBIT(24))	/* Short GI @ 40Mhz supported */
+		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+	if (dev_cap & MBIT(25))	/* Tx STBC supported */
+		ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
+	if (dev_cap & MBIT(26))	/* Rx STBC supported */
+		ht_info->cap |= IEEE80211_HT_CAP_RX_STBC;
+	if (dev_cap & MBIT(27))	/* MIMO PS supported */
+		ht_info->cap |= 0;	/* WLAN_HT_CAP_SM_PS_STATIC */
+	else			/* Disable HT SM PS */
+		ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
+	if (dev_cap & MBIT(29))	/* Green field supported */
+		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
+	if (dev_cap & MBIT(31))	/* MAX AMSDU supported */
+		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+	/* DSSS/CCK in 40Mhz supported */
+	ht_info->cap |= IEEE80211_HT_CAP_DSSSCCK40;
+	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+
+	LEAVE();
+}
+
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+/**
+ *  @brief Sets up the CFG802.11 specific VHT capability fields
+ *  with default values
+ *
+ * @param priv         A pointer to moal private structure
+ *  @param vht_cap      A pointer to ieee80211_sta_vht_cap structure
+ *
+ *  @return             N/A
+ */
+void
+woal_cfg80211_setup_vht_cap(moal_private *priv,
+			    struct ieee80211_sta_vht_cap *vht_cap)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ac_cfg *cfg_11ac = NULL;
+	mlan_status status;
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		PRINTM(MERROR, "Fail to allocate buf for setup vht_cap\n");
+		goto done;
+	}
+	cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
+	cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
+	req->req_id = MLAN_IOCTL_11AC_CFG;
+	req->action = MLAN_ACT_GET;
+	cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
+	cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_RX;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Fail to get vht_cfg\n");
+		goto done;
+	}
+	vht_cap->vht_supported = true;
+	vht_cap->cap = cfg_11ac->param.vht_cfg.vht_cap_info;
+	vht_cap->vht_mcs.rx_mcs_map =
+		(__force __le16) cfg_11ac->param.vht_cfg.vht_rx_mcs;
+	vht_cap->vht_mcs.rx_highest =
+		(__force __le16) cfg_11ac->param.vht_cfg.vht_rx_max_rate;
+	vht_cap->vht_mcs.tx_mcs_map =
+		(__force __le16) cfg_11ac->param.vht_cfg.vht_tx_mcs;
+	vht_cap->vht_mcs.tx_highest =
+		(__force __le16) cfg_11ac->param.vht_cfg.vht_tx_max_rate;
+	PRINTM(MCMND,
+	       "vht_cap=0x%x rx_mcs_map=0x%x rx_max=0x%x tx_mcs_map=0x%x tx_max=0x%x\n",
+	       vht_cap->cap, vht_cap->vht_mcs.rx_mcs_map,
+	       vht_cap->vht_mcs.rx_highest, vht_cap->vht_mcs.tx_mcs_map,
+	       vht_cap->vht_mcs.tx_highest);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+}
+#endif
+
+#if KERNEL_VERSION(4, 20, 0) <= CFG80211_VERSION_CODE
+/*
+===============
+11AX CAP for uAP
+===============
+Note: bits not mentioned below are set to 0.
+
+5G
+===
+HE MAC Cap:
+Bit0:  1  (+HTC HE Support)
+Bit25: 1  (OM Control Support. But uAP does not support
+           Tx OM received from the STA, as it does not support UL OFDMA)
+
+HE PHY Cap:
+Bit1-7: 0x2 (Supported Channel Width Set.
+             Note it would be changed after 80+80 MHz is supported)
+Bit8-11: 0x3 (Punctured Preamble Rx.
+              Note: it would be changed after 80+80 MHz is supported)
+Bit12: 0x0 (Device Class)
+Bit13: 0x1 (LDPC coding in Payload)
+Bit17: 0x1 (NDP with 4xHE-LTF+3.2usGI)
+Bit18: 0x1 (STBC Tx <= 80 MHz)
+Bit19: 0x1 (STBC Rx <= 80 MHz)
+Bit20: 0x1 (Doppler Tx)
+Bit21: 0x1 (Doppler Rx)
+Bit27-28: 0x1 (DCM Max Constellation Rx)
+Bit31: 0x1 (SU Beamformer)
+Bit32: 0x1 (SU BeamFormee)
+Bit34-36: 0x7 (Beamformee STS <= 80 MHz)
+Bit40-42: 0x1 (Number of Sounding Dimentions <= 80 MHz)
+Bit53: 0x1 (Partial Bandwidth Extended Range)
+Bit55: 0x1 (PPE Threshold Present.
+            Note: PPE threshold may have some changes later)
+Bit58: 0x1 (HE SU PPDU and HE MU PPDU with 4xHE-LTF+0.8usGI)
+Bit59-61: 0x1 (Max Nc)
+Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
+*/
+
+#define UAP_HE_MAC_CAP0_MASK   0x00
+#define UAP_HE_MAC_CAP1_MASK   0x00
+#define UAP_HE_MAC_CAP2_MASK   0x00
+#define UAP_HE_MAC_CAP3_MASK   0x02
+#define UAP_HE_MAC_CAP4_MASK   0x00
+#define UAP_HE_MAC_CAP5_MASK   0x00
+#define UAP_HE_PHY_CAP0_MASK   0x04
+#define UAP_HE_PHY_CAP1_MASK   0x23
+#define UAP_HE_PHY_CAP2_MASK   0x3E
+#define UAP_HE_PHY_CAP3_MASK   0x88
+#define UAP_HE_PHY_CAP4_MASK   0x1D
+#define UAP_HE_PHY_CAP5_MASK   0x01
+#define UAP_HE_PHY_CAP6_MASK   0xA0
+#define UAP_HE_PHY_CAP7_MASK   0x0C
+#define UAP_HE_PHY_CAP8_MASK   0x00
+#define UAP_HE_PHY_CAP9_MASK   0x08
+#define UAP_HE_PHY_CAP10_MASK  0x00
+
+/*
+2G
+===
+HE MAC Cap:
+Bit0:   1  (+HTC HE Support)
+Bit25: 1  (OM Control Support. Note: uAP does not support
+        Tx OM received from the STA, as it does not support UL OFDMA)
+
+HE PHY Cap:
+Bit1-7: 0x1 (Supported Channel Width Set)
+Bit8-11: 0x0 (Punctured Preamble Rx)
+Bit12: 0x0 (Device Class)
+Bit13: 0x1 (LDPC coding in Payload)
+Bit17: 0x1 (NDP with 4xLTF+3.2usGI)
+Bit18: 0x1 (STBC Tx <= 80 MHz)
+Bit19: 0x1 (STBC Rx <= 80 MHz)
+Bit20: 0x1 (Doppler Tx)
+Bit21: 0x1 (Doppler Rx)
+Bit27-28: 0x1 (DCM Max Constellation Rx)
+Bit31: 0x1 (SU Beamformer)
+Bit32: 0x1 (SU BeamFormee)
+Bit34-36: 0x7 (Beamformee STS <= 80 MHz)
+Bit40-42: 0x1 (Number of Sounding Dimentions <= 80 MHz)
+Bit53: 0x1 (Partial Bandwidth Extended Range)
+Bit55: 0x1 (PPE Threshold Present.
+            Note: PPE threshold may have some changes later)
+Bit58: 0x1 (HE SU PPDU and HE MU PPDU with 4xHE-LTF+0.8usGI)
+Bit59-61: 0x1 (Max Nc)
+Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
+*/
+#define UAP_HE_2G_MAC_CAP0_MASK   0x00
+#define UAP_HE_2G_MAC_CAP1_MASK   0x00
+#define UAP_HE_2G_MAC_CAP2_MASK   0x00
+#define UAP_HE_2G_MAC_CAP3_MASK   0x02
+#define UAP_HE_2G_MAC_CAP4_MASK   0x00
+#define UAP_HE_2G_MAC_CAP5_MASK   0x00
+#define UAP_HE_2G_PHY_CAP0_MASK   0x04
+#define UAP_HE_2G_PHY_CAP1_MASK   0x20
+#define UAP_HE_2G_PHY_CAP2_MASK   0x3E
+#define UAP_HE_2G_PHY_CAP3_MASK   0x88
+#define UAP_HE_2G_PHY_CAP4_MASK   0x1D
+#define UAP_HE_2G_PHY_CAP5_MASK   0x01
+#define UAP_HE_2G_PHY_CAP6_MASK   0xA0
+#define UAP_HE_2G_PHY_CAP7_MASK   0x0C
+#define UAP_HE_2G_PHY_CAP8_MASK   0x00
+#define UAP_HE_2G_PHY_CAP9_MASK   0x08
+#define UAP_HE_2G_PHY_CAP10_MASK  0x00
+
+/**
+ *  @brief update 11ax ie for AP mode *
+ *  @param band     band config
+ *  @hecap_ie      a pointer to mlan_ds_11ax_he_capa
+ *
+ *  @return         0--success, otherwise failure
+ */
+void
+woal_uap_update_11ax_ie(t_u8 band, mlan_ds_11ax_he_capa * hecap_ie)
+{
+	if (band == BAND_5GHZ) {
+		hecap_ie->he_mac_cap[0] &= UAP_HE_MAC_CAP0_MASK;
+		hecap_ie->he_mac_cap[1] &= UAP_HE_MAC_CAP1_MASK;
+		hecap_ie->he_mac_cap[2] &= UAP_HE_MAC_CAP2_MASK;
+		hecap_ie->he_mac_cap[3] &= UAP_HE_MAC_CAP3_MASK;
+		hecap_ie->he_mac_cap[4] &= UAP_HE_MAC_CAP4_MASK;
+		hecap_ie->he_mac_cap[5] &= UAP_HE_MAC_CAP5_MASK;
+		hecap_ie->he_phy_cap[0] &= UAP_HE_PHY_CAP0_MASK;
+		hecap_ie->he_phy_cap[1] &= UAP_HE_PHY_CAP1_MASK;
+		hecap_ie->he_phy_cap[2] &= UAP_HE_PHY_CAP2_MASK;
+		hecap_ie->he_phy_cap[3] &= UAP_HE_PHY_CAP3_MASK;
+		hecap_ie->he_phy_cap[4] &= UAP_HE_PHY_CAP4_MASK;
+		hecap_ie->he_phy_cap[5] &= UAP_HE_PHY_CAP5_MASK;
+		hecap_ie->he_phy_cap[6] &= UAP_HE_PHY_CAP6_MASK;
+		hecap_ie->he_phy_cap[7] &= UAP_HE_PHY_CAP7_MASK;
+		hecap_ie->he_phy_cap[8] &= UAP_HE_PHY_CAP8_MASK;
+		hecap_ie->he_phy_cap[9] &= UAP_HE_PHY_CAP9_MASK;
+		hecap_ie->he_phy_cap[10] &= UAP_HE_PHY_CAP10_MASK;
+	} else {
+		hecap_ie->he_mac_cap[0] &= UAP_HE_2G_MAC_CAP0_MASK;
+		hecap_ie->he_mac_cap[1] &= UAP_HE_2G_MAC_CAP1_MASK;
+		hecap_ie->he_mac_cap[2] &= UAP_HE_2G_MAC_CAP2_MASK;
+		hecap_ie->he_mac_cap[3] &= UAP_HE_2G_MAC_CAP3_MASK;
+		hecap_ie->he_mac_cap[4] &= UAP_HE_2G_MAC_CAP4_MASK;
+		hecap_ie->he_mac_cap[5] &= UAP_HE_2G_MAC_CAP5_MASK;
+		hecap_ie->he_phy_cap[0] &= UAP_HE_2G_PHY_CAP0_MASK;
+		hecap_ie->he_phy_cap[1] &= UAP_HE_2G_PHY_CAP1_MASK;
+		hecap_ie->he_phy_cap[2] &= UAP_HE_2G_PHY_CAP2_MASK;
+		hecap_ie->he_phy_cap[3] &= UAP_HE_2G_PHY_CAP3_MASK;
+		hecap_ie->he_phy_cap[4] &= UAP_HE_2G_PHY_CAP4_MASK;
+		hecap_ie->he_phy_cap[5] &= UAP_HE_2G_PHY_CAP5_MASK;
+		hecap_ie->he_phy_cap[6] &= UAP_HE_2G_PHY_CAP6_MASK;
+		hecap_ie->he_phy_cap[7] &= UAP_HE_2G_PHY_CAP7_MASK;
+		hecap_ie->he_phy_cap[8] &= UAP_HE_2G_PHY_CAP8_MASK;
+		hecap_ie->he_phy_cap[9] &= UAP_HE_2G_PHY_CAP9_MASK;
+		hecap_ie->he_phy_cap[10] &= UAP_HE_2G_PHY_CAP10_MASK;
+	}
+	return;
+}
+
+/**
+ *  @brief Sets up the CFG802.11 specific HE capability fields *  with default
+ * values
+ *
+ *  @param priv         A pointer to moal private structure
+ *  @param iftype_data  A pointer to ieee80211_sband_iftype_data structure
+ *
+ *  @return             N/A
+ */
+void
+woal_cfg80211_setup_he_cap(moal_private *priv,
+			   struct ieee80211_supported_band *band)
+{
+	mlan_fw_info fw_info;
+	struct ieee80211_sband_iftype_data *iftype_data = NULL;
+	t_u8 extra_mcs_size = 0;
+	int ppe_threshold_len = 0;
+	mlan_ds_11ax_he_capa *phe_cap = NULL;
+	t_u8 hw_hecap_len;
+
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (band->band == NL80211_BAND_5GHZ) {
+		phe_cap = (mlan_ds_11ax_he_capa *) fw_info.hw_he_cap;
+		hw_hecap_len = fw_info.hw_hecap_len;
+		woal_uap_update_11ax_ie(BAND_5GHZ, phe_cap);
+	} else {
+		phe_cap = (mlan_ds_11ax_he_capa *) fw_info.hw_2g_he_cap;
+		hw_hecap_len = fw_info.hw_2g_hecap_len;
+		woal_uap_update_11ax_ie(BAND_2GHZ, phe_cap);
+	}
+
+	if (!hw_hecap_len)
+		return;
+	DBG_HEXDUMP(MCMD_D, "Setup HECAP", (u8 *)phe_cap, hw_hecap_len);
+	iftype_data =
+		kmalloc(sizeof(struct ieee80211_sband_iftype_data), GFP_KERNEL);
+	if (!iftype_data) {
+		PRINTM(MERROR, "Fail to allocate iftype data\n");
+		goto done;
+	}
+	iftype_data->types_mask =
+		MBIT(NL80211_IFTYPE_STATION) | MBIT(NL80211_IFTYPE_AP) |
+		MBIT(NL80211_IFTYPE_P2P_CLIENT) | MBIT(NL80211_IFTYPE_P2P_GO);
+	iftype_data->he_cap.has_he = true;
+	moal_memcpy_ext(priv->phandle,
+			iftype_data->he_cap.he_cap_elem.mac_cap_info,
+			phe_cap->he_mac_cap, sizeof(phe_cap->he_mac_cap),
+			sizeof(iftype_data->he_cap.he_cap_elem.mac_cap_info));
+	moal_memcpy_ext(priv->phandle,
+			iftype_data->he_cap.he_cap_elem.phy_cap_info,
+			phe_cap->he_phy_cap, sizeof(phe_cap->he_phy_cap),
+			sizeof(iftype_data->he_cap.he_cap_elem.phy_cap_info));
+	memset(&iftype_data->he_cap.he_mcs_nss_supp, 0xff,
+	       sizeof(struct ieee80211_he_mcs_nss_supp));
+	moal_memcpy_ext(priv->phandle, &iftype_data->he_cap.he_mcs_nss_supp,
+			phe_cap->he_txrx_mcs_support,
+			sizeof(phe_cap->he_txrx_mcs_support),
+			sizeof(struct ieee80211_he_mcs_nss_supp));
+	// Support 160Mhz
+	if (phe_cap->he_phy_cap[0] & MBIT(3))
+		extra_mcs_size += 4;
+
+	// Support 80+80
+	if (phe_cap->he_phy_cap[0] & MBIT(4))
+		extra_mcs_size += 4;
+	if (extra_mcs_size)
+		moal_memcpy_ext(priv->phandle,
+				(t_u8 *)&iftype_data->he_cap.he_mcs_nss_supp.
+				rx_mcs_160, phe_cap->val, extra_mcs_size,
+				sizeof(struct ieee80211_he_mcs_nss_supp) - 4);
+
+#define HE_CAP_FIX_SIZE 22
+	// Support PPE threshold
+	ppe_threshold_len = phe_cap->len - HE_CAP_FIX_SIZE - extra_mcs_size;
+	if (phe_cap->he_phy_cap[6] & MBIT(7) && ppe_threshold_len) {
+		moal_memcpy_ext(priv->phandle, iftype_data->he_cap.ppe_thres,
+				&phe_cap->val[extra_mcs_size],
+				ppe_threshold_len,
+				sizeof(iftype_data->he_cap.ppe_thres));
+	} else {
+		iftype_data->he_cap.he_cap_elem.phy_cap_info[6] &= ~MBIT(7);
+		PRINTM(MCMND, "Clear PPE threshold 0x%x\n",
+		       iftype_data->he_cap.he_cap_elem.phy_cap_info[7]);
+	}
+	band->n_iftype_data = 1;
+	band->iftype_data = iftype_data;
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief free iftype_data
+ *
+ *  @param wiphy        A pointer to struct wiphy
+ *
+ *
+ *  @return             N/A
+ */
+void
+woal_cfg80211_free_iftype_data(struct wiphy *wiphy)
+{
+	enum nl80211_band band;
+
+	for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; ++band) {
+		if (!wiphy->bands[band])
+			continue;
+		if (!wiphy->bands[band]->iftype_data)
+			continue;
+		kfree(wiphy->bands[band]->iftype_data);
+		wiphy->bands[band]->n_iftype_data = 0;
+	}
+}
+#endif
+
+/*
+ * @brief  prepare and send fake deauth packet to cfg80211 to
+ *         notify wpa_supplicant about disconnection
+ *	       <host_mlme, wiphy suspend case>
+ *
+ * @param priv           A pointer moal_private structure
+ * @param reason_code    disconnect reason code
+ *
+ * @return          N/A
+ */
+void
+woal_deauth_event(moal_private *priv, int reason_code)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (!evt) {
+		PRINTM(MERROR, "Fail to alloc memory for deauth event\n");
+		LEAVE();
+		return;
+	}
+	evt->priv = priv;
+	evt->type = WOAL_EVENT_DEAUTH;
+	evt->reason_code = reason_code;
+	INIT_LIST_HEAD(&evt->link);
+	spin_lock_irqsave(&handle->evt_lock, flags);
+	list_add_tail(&evt->link, &handle->evt_queue);
+	spin_unlock_irqrestore(&handle->evt_lock, flags);
+	queue_work(handle->evt_workqueue, &handle->evt_work);
+}
+
+#ifdef STA_CFG80211
+#if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
+/**
+ * @brief   prepare woal_bgscan_stop event
+ *
+ * @param priv          A pointer moal_private structure
+ * @param pchan_info    A pointer to chan_band structure
+ *
+ * @return          N/A
+ */
+void
+woal_bgscan_stop_event(moal_private *priv)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (evt) {
+		evt->priv = priv;
+		evt->type = WOAL_EVENT_BGSCAN_STOP;
+		INIT_LIST_HEAD(&evt->link);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+		list_add_tail(&evt->link, &handle->evt_queue);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		queue_work(handle->evt_workqueue, &handle->evt_work);
+	}
+}
+
+/**
+ * @brief Notify cfg80211 schedule scan stopped
+ *
+ * @param priv          A pointer moal_private structure
+ *
+ * @return          N/A
+ */
+void
+woal_cfg80211_notify_sched_scan_stop(moal_private *priv)
+{
+	cfg80211_sched_scan_stopped(priv->wdev->wiphy
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+				    , 0
+#endif
+		);
+	priv->sched_scanning = MFALSE;
+	PRINTM(MEVENT, "Notify sched scan stopped\n");
+}
+
+/**
+ * @brief sched_scan work handler
+ *
+ * @param work            a pointer to work_struct
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_sched_scan_work_queue(struct work_struct *work)
+{
+	struct delayed_work *delayed_work =
+		container_of(work, struct delayed_work, work);
+	moal_private *priv = container_of(delayed_work, moal_private,
+					  sched_scan_work);
+	ENTER();
+
+	if (priv->sched_scanning)
+		woal_cfg80211_notify_sched_scan_stop(priv);
+
+	LEAVE();
+}
+
+/**
+ * @brief report sched_scan result to kernel
+ *
+ * @param priv          A pointer moal_private structure
+ *
+ * @return          N/A
+ */
+void
+woal_report_sched_scan_result(moal_private *priv)
+{
+	cfg80211_sched_scan_results(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+				    , priv->bg_scan_reqid
+#endif
+		);
+	queue_delayed_work(priv->sched_scan_workqueue, &priv->sched_scan_work,
+			   msecs_to_jiffies(2000));
+
+}
+#endif
+#endif
+
+#if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
+/**
+ * @brief   Handle woal_channel_switch event
+ *
+ * @param priv          A pointer moal_private structure
+ * @param pchan_info    A pointer to chan_band structure
+ *
+ * @return          N/A
+ */
+void
+woal_channel_switch_event(moal_private *priv, chan_band_info * pchan_info)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (evt) {
+		evt->priv = priv;
+		evt->type = WOAL_EVENT_CHAN_SWITCH;
+		moal_memcpy_ext(priv->phandle, &evt->chan_info, pchan_info,
+				sizeof(chan_band_info), sizeof(chan_band_info));
+		INIT_LIST_HEAD(&evt->link);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+		list_add_tail(&evt->link, &handle->evt_queue);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		queue_work(handle->evt_workqueue, &handle->evt_work);
+	}
+}
+
+/**
+ * @brief Notify cfg80211 supplicant channel changed
+ *
+ * @param priv          A pointer moal_private structure
+ * @param pchan_info    A pointer to chan_band structure
+ *
+ * @return          N/A
+ */
+void
+woal_cfg80211_notify_channel(moal_private *priv, chan_band_info * pchan_info)
+{
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+	struct cfg80211_chan_def chandef;
+#else
+#if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
+	enum nl80211_channel_type type;
+	enum ieee80211_band band;
+	int freq = 0;
+#endif
+#endif
+	ENTER();
+
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_chandef_create(priv, &chandef, pchan_info)) {
+		cfg80211_ch_switch_notify(priv->netdev, &chandef);
+		priv->channel = pchan_info->channel;
+#ifdef UAP_CFG80211
+		moal_memcpy_ext(priv->phandle, &priv->chan, &chandef,
+				sizeof(struct cfg80211_chan_def),
+				sizeof(struct cfg80211_chan_def));
+#endif
+	}
+#else
+#if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
+	if (pchan_info->bandcfg.chanBand == BAND_2GHZ)
+		band = IEEE80211_BAND_2GHZ;
+	else if (pchan_info->bandcfg.chanBand == BAND_5GHZ)
+		band = IEEE80211_BAND_5GHZ;
+	else {
+		LEAVE();
+		return;
+	}
+	priv->channel = pchan_info->channel;
+	freq = ieee80211_channel_to_frequency(pchan_info->channel, band);
+	switch (pchan_info->bandcfg.chanWidth) {
+	case CHAN_BW_20MHZ:
+		if (pchan_info->is_11n_enabled)
+			type = NL80211_CHAN_HT20;
+		else
+			type = NL80211_CHAN_NO_HT;
+		break;
+	default:
+		if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
+			type = NL80211_CHAN_HT40PLUS;
+		else if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_BELOW)
+			type = NL80211_CHAN_HT40MINUS;
+		else
+			type = NL80211_CHAN_HT20;
+		break;
+	}
+	cfg80211_ch_switch_notify(priv->netdev, freq, type);
+#endif
+#endif
+	LEAVE();
+}
+#endif
+
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+/**
+ * @brief Notify cfg80211 supplicant ant cfg changed
+ *
+ * @param priv          A pointer moal_private structure
+ * @param wiphy         A pointer structure wiphy
+ * @param radio         A pointer to radio cfg structure
+ *
+ * @return              N/A
+ */
+void
+woal_cfg80211_notify_antcfg(moal_private *priv,
+			    struct wiphy *wiphy, mlan_ds_radio_cfg *radio)
+{
+	if (IS_STA_OR_UAP_CFG80211(priv->phandle->params.cfg80211_wext) &&
+	    wiphy) {
+		if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+			struct ieee80211_supported_band *bands =
+				wiphy->bands[IEEE80211_BAND_2GHZ];
+
+			if (((radio->param.ant_cfg.tx_antenna & 0xFF) != 3 &&
+			     (radio->param.ant_cfg.tx_antenna & 0xFF) != 0) ||
+			    ((radio->param.ant_cfg.rx_antenna & 0xFF) != 3 &&
+			     (radio->param.ant_cfg.rx_antenna & 0xFF) != 0)) {
+				bands->ht_cap.mcs.rx_mask[1] = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+				if (bands->n_iftype_data && bands->iftype_data
+				    && bands->iftype_data->he_cap.has_he) {
+					t_u16 mcs_nss[2];
+
+					mcs_nss[0] =
+						bands->iftype_data->he_cap.
+						he_mcs_nss_supp.rx_mcs_80;
+					mcs_nss[1] = mcs_nss[0] |= 0x0c;
+					moal_memcpy_ext(priv->phandle,
+							(t_void *)&bands->
+							iftype_data->he_cap.
+							he_mcs_nss_supp.
+							rx_mcs_80,
+							(t_void *)&mcs_nss,
+							sizeof(mcs_nss),
+							sizeof(bands->
+							       iftype_data->
+							       he_cap.
+							       he_mcs_nss_supp));
+				}
+#endif
+			} else if ((radio->param.ant_cfg.tx_antenna & 0xFF) == 3
+				   || (radio->param.ant_cfg.
+				       rx_antenna & 0xFF) == 3) {
+				bands->ht_cap.mcs.rx_mask[1] = 0xff;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+				if (bands->n_iftype_data && bands->iftype_data
+				    && bands->iftype_data->he_cap.has_he) {
+					t_u16 mcs_nss[2];
+
+					mcs_nss[0] =
+						bands->iftype_data->he_cap.
+						he_mcs_nss_supp.rx_mcs_80;
+					mcs_nss[1] = mcs_nss[0] =
+						(mcs_nss[0] & ~0x0c) |
+						((mcs_nss[0] & 0x3) << 2);
+
+					moal_memcpy_ext(priv->phandle,
+							(t_void *)&bands->
+							iftype_data->he_cap.
+							he_mcs_nss_supp.
+							rx_mcs_80,
+							(t_void *)&mcs_nss,
+							sizeof(mcs_nss),
+							sizeof(bands->
+							       iftype_data->
+							       he_cap.
+							       he_mcs_nss_supp));
+				}
+#endif
+			}
+			bands->ht_cap.mcs.rx_mask[4] = 0;
+		}
+
+		if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+			struct ieee80211_supported_band *bands =
+				wiphy->bands[IEEE80211_BAND_5GHZ];
+
+			if (((radio->param.ant_cfg.tx_antenna & 0xFF00) != 0x300
+			     && (radio->param.ant_cfg.tx_antenna & 0xFF00) != 0)
+			    || ((radio->param.ant_cfg.rx_antenna & 0xFF00) !=
+				0x300 &&
+				(radio->param.ant_cfg.rx_antenna & 0xFF00) !=
+				0)) {
+				bands->ht_cap.mcs.rx_mask[1] = 0;
+				bands->vht_cap.vht_mcs.rx_mcs_map =
+					(__force __le16) 0xfffe;
+				bands->vht_cap.vht_mcs.tx_mcs_map =
+					(__force __le16) 0xfffe;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+				if (bands->n_iftype_data && bands->iftype_data
+				    && bands->iftype_data->he_cap.has_he) {
+					t_u16 mcs_nss[2];
+
+					mcs_nss[0] =
+						bands->iftype_data->he_cap.
+						he_mcs_nss_supp.rx_mcs_80;
+					mcs_nss[1] = mcs_nss[0] |= 0x0c;
+					moal_memcpy_ext(priv->phandle,
+							(t_void *)&bands->
+							iftype_data->he_cap.
+							he_mcs_nss_supp.
+							rx_mcs_80,
+							(t_void *)&mcs_nss,
+							sizeof(mcs_nss),
+							sizeof(bands->
+							       iftype_data->
+							       he_cap.
+							       he_mcs_nss_supp));
+				}
+#endif
+			} else if ((radio->param.ant_cfg.tx_antenna & 0xFF00) ==
+				   0x300 ||
+				   (radio->param.ant_cfg.rx_antenna & 0xFF00) ==
+				   0x300) {
+				bands->ht_cap.mcs.rx_mask[1] = 0xff;
+				bands->vht_cap.vht_mcs.rx_mcs_map =
+					(__force __le16) 0xfffa;
+				bands->vht_cap.vht_mcs.tx_mcs_map =
+					(__force __le16) 0xfffa;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+				if (bands->n_iftype_data && bands->iftype_data
+				    && bands->iftype_data->he_cap.has_he) {
+					t_u16 mcs_nss[2];
+
+					mcs_nss[0] =
+						bands->iftype_data->he_cap.
+						he_mcs_nss_supp.rx_mcs_80;
+					mcs_nss[1] = mcs_nss[0] =
+						(mcs_nss[0] & ~0x0c) |
+						((mcs_nss[0] & 0x3) << 2);
+
+					moal_memcpy_ext(priv->phandle,
+							(t_void *)&bands->
+							iftype_data->he_cap.
+							he_mcs_nss_supp.
+							rx_mcs_80,
+							(t_void *)&mcs_nss,
+							sizeof(mcs_nss),
+							sizeof(bands->
+							       iftype_data->
+							       he_cap.
+							       he_mcs_nss_supp));
+				}
+#endif
+			}
+		}
+	}
+}
+#endif
+
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+/**
+ * @brief create cfg80211_chan_def structure based on chan_band info
+ *
+ * @param priv          A pointer moal_private structure
+ * @param chandef       A pointer to cfg80211_chan_def structure
+ * @param pchan_info    A pointer to chan_band_info structure
+ *
+ * @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_chandef_create(moal_private *priv,
+		    struct cfg80211_chan_def *chandef,
+		    chan_band_info * pchan_info)
+{
+	enum ieee80211_band band = IEEE80211_BAND_2GHZ;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(chandef, 0, sizeof(struct cfg80211_chan_def));
+	chandef->center_freq2 = 0;
+	if (pchan_info->bandcfg.chanBand == BAND_2GHZ)
+		band = IEEE80211_BAND_2GHZ;
+	else if (pchan_info->bandcfg.chanBand == BAND_5GHZ)
+		band = IEEE80211_BAND_5GHZ;
+	chandef->chan = ieee80211_get_channel(priv->wdev->wiphy,
+					      ieee80211_channel_to_frequency
+					      (pchan_info->channel, band));
+	if (chandef->chan == NULL) {
+		PRINTM(MERROR,
+		       "Fail on ieee80211_get_channel, channel=%d, band=%d\n",
+		       pchan_info->channel, band);
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	switch (pchan_info->bandcfg.chanWidth) {
+	case CHAN_BW_20MHZ:
+		if (pchan_info->is_11n_enabled)
+			chandef->width = NL80211_CHAN_WIDTH_20;
+		else
+			chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+		chandef->center_freq1 = chandef->chan->center_freq;
+		break;
+	case CHAN_BW_40MHZ:
+		chandef->width = NL80211_CHAN_WIDTH_40;
+		if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
+			chandef->center_freq1 = chandef->chan->center_freq + 10;
+		else if (pchan_info->bandcfg.chan2Offset == SEC_CHAN_BELOW)
+			chandef->center_freq1 = chandef->chan->center_freq - 10;
+		break;
+	case CHAN_BW_80MHZ:
+		chandef->width = NL80211_CHAN_WIDTH_80;
+		chandef->center_freq1 =
+			ieee80211_channel_to_frequency(pchan_info->center_chan,
+						       band);
+		break;
+	default:
+		break;
+	}
+done:
+	LEAVE();
+	return status;
+}
+#endif
diff --git a/wlan_sd8987/mlinux/moal_cfg80211.h b/wlan_sd8987/mlinux/moal_cfg80211.h
new file mode 100755
index 0000000..279a051
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfg80211.h
@@ -0,0 +1,520 @@
+/** @file moal_cfg80211.h
+ *
+ * @brief This file contains the CFG80211 specific defines.
+ *
+ *
+ * Copyright 2011-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#ifndef _MOAL_CFG80211_H_
+#define _MOAL_CFG80211_H_
+
+#include "moal_main.h"
+
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR
+#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR
+#endif
+
+#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE
+#define MAX_CSA_COUNTERS_NUM 2
+#endif
+
+/* Clear all key indexes */
+#define KEY_INDEX_CLEAR_ALL (0x0000000F)
+
+/** RTS/FRAG disabled value */
+#define MLAN_FRAG_RTS_DISABLED (0xFFFFFFFF)
+
+#ifndef WLAN_CIPHER_SUITE_SMS4
+#define WLAN_CIPHER_SUITE_SMS4 0x00000020
+#endif
+
+#ifndef WLAN_CIPHER_SUITE_AES_CMAC
+#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+#endif
+#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE
+#ifndef WLAN_CIPHER_SUITE_BIP_GMAC_128
+#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
+#endif
+#ifndef WLAN_CIPHER_SUITE_BIP_GMAC_256
+#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
+#endif
+#endif
+
+/* define for custom ie operation */
+#define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff
+#define MLAN_CUSTOM_IE_NEW_MASK 0x8000
+#define IE_MASK_WPS 0x0001
+#define IE_MASK_P2P 0x0002
+#define IE_MASK_WFD 0x0004
+#define IE_MASK_VENDOR 0x0008
+#define IE_MASK_EXTCAP 0x0010
+
+#define MRVL_PKT_TYPE_MGMT_FRAME 0xE5
+
+mlan_status woal_cfg80211_set_key(moal_private *priv, t_u8 is_enable_wep,
+				  t_u32 cipher, const t_u8 *key, int key_len,
+				  const t_u8 *seq, int seq_len, t_u8 key_index,
+				  const t_u8 *addr, int disable,
+				  t_u8 wait_option);
+
+mlan_status woal_cfg80211_set_wep_keys(moal_private *priv, const t_u8 *key,
+				       int key_len, t_u8 index,
+				       t_u8 wait_option);
+
+t_u8 is_cfg80211_special_region_code(t_u8 *region_string);
+
+/**
+ * If multiple wiphys are registered e.g. a regular netdev with
+ * assigned ieee80211_ptr and you won't know whether it points
+ * to a wiphy your driver has registered or not. Assign this to
+ * something global to your driver to help determine whether
+ * you own this wiphy or not.
+ */
+static const void *const mrvl_wiphy_privid = &mrvl_wiphy_privid;
+
+/* Get the private structure from wiphy */
+void *woal_get_wiphy_priv(struct wiphy *wiphy);
+
+/* Get the private structure from net device */
+void *woal_get_netdev_priv(struct net_device *dev);
+#ifdef STA_SUPPORT
+/** get scan interface */
+pmoal_private woal_get_scan_interface(pmoal_handle handle);
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+/** AUTH pending flag */
+#define HOST_MLME_AUTH_PENDING MBIT(0)
+/** AUTH complete flag */
+#define HOST_MLME_AUTH_DONE MBIT(1)
+#define HOST_MLME_ASSOC_PENDING MBIT(2)
+#define HOST_MLME_ASSOC_DONE MBIT(3)
+void woal_host_mlme_disconnect(pmoal_private priv, u16 reason_code, u8 *sa);
+void woal_host_mlme_work_queue(struct work_struct *work);
+void woal_host_mlme_process_assoc_resp(moal_private *priv,
+				       mlan_ds_misc_assoc_rsp *assoc_rsp);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+void woal_regulatory_work_queue(struct work_struct *work);
+#endif
+
+t_u8 woal_band_cfg_to_ieee_band(t_u32 band);
+
+int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy,
+				      struct net_device *dev,
+				      enum nl80211_iftype type,
+#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE
+				      u32 *flags,
+#endif
+				      struct vif_params *params);
+
+int woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+
+int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+			  t_u8 key_index,
+#if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
+			  bool pairwise,
+#endif
+			  const t_u8 *mac_addr, struct key_params *params);
+
+int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+			  t_u8 key_index,
+#if KERNEL_VERSION(2, 6, 36) < CFG80211_VERSION_CODE
+			  bool pairwise,
+#endif
+			  const t_u8 *mac_addr);
+#ifdef STA_SUPPORT
+/** Opportunistic Key Caching APIs support */
+struct pmksa_entry *woal_get_pmksa_entry(pmoal_private priv, const u8 *bssid);
+
+int woal_flush_pmksa_list(moal_private *priv);
+
+int woal_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+			    struct cfg80211_pmksa *pmksa);
+
+int woal_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+			    struct cfg80211_pmksa *pmksa);
+
+int woal_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev);
+#endif
+
+int woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+				   const u8 *peer,
+				   const struct cfg80211_bitrate_mask *mask);
+#if KERNEL_VERSION(2, 6, 38) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
+int woal_cfg80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
+#endif
+
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_qos_map(struct wiphy *wiphy, struct net_device *dev,
+			      struct cfg80211_qos_map *qos_map);
+#endif
+
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+int woal_set_rf_channel(moal_private *priv, struct ieee80211_channel *chan,
+			enum nl80211_channel_type channel_type,
+			t_u8 wait_option);
+
+static inline int
+woal_cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
+{
+#if KERNEL_VERSION(4, 8, 0) <= CFG80211_VERSION_CODE
+	struct cfg80211_scan_info info;
+
+	info.aborted = aborted;
+	cfg80211_scan_done(request, &info);
+#else
+	cfg80211_scan_done(request, aborted);
+#endif
+	return 0;
+}
+
+mlan_status woal_inform_bss_from_scan_result(moal_private *priv,
+					     pmlan_ssid_bssid ssid_bssid,
+					     t_u8 wait_option);
+#endif
+#endif
+
+#if KERNEL_VERSION(3, 5, 0) > CFG80211_VERSION_CODE
+int woal_cfg80211_set_channel(struct wiphy *wiphy,
+#if KERNEL_VERSION(2, 6, 34) < CFG80211_VERSION_CODE
+			      struct net_device *dev,
+#endif
+			      struct ieee80211_channel *chan,
+			      enum nl80211_channel_type channel_type);
+#endif
+
+#if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE
+int woal_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *dev,
+				  t_u8 key_index, bool ucast, bool mcast);
+#else
+int woal_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *dev,
+				  t_u8 key_index);
+#endif
+
+#if KERNEL_VERSION(2, 6, 30) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
+				       struct net_device *netdev,
+				       t_u8 key_index);
+#endif
+
+#if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
+					 struct net_device *netdev,
+					 t_u8 key_index);
+#endif
+
+#if KERNEL_VERSION(3, 1, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_gtk_rekey_data *data);
+#endif
+void woal_mgmt_frame_register(moal_private *priv, u16 frame_type, bool reg);
+void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+				       struct wireless_dev *wdev,
+#else
+				       struct net_device *dev,
+#endif
+#if KERNEL_VERSION(5, 8, 0) <= CFG80211_VERSION_CODE
+				       struct mgmt_frame_regs *upd
+#else
+				       t_u16 frame_type, bool reg
+#endif
+	);
+
+int woal_cfg80211_mgmt_tx(struct wiphy *wiphy,
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+			  struct wireless_dev *wdev,
+#else
+			  struct net_device *dev,
+#endif
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+			  struct cfg80211_mgmt_tx_params *params,
+#else
+			  struct ieee80211_channel *chan, bool offchan,
+#if KERNEL_VERSION(3, 8, 0) > CFG80211_VERSION_CODE
+			  enum nl80211_channel_type channel_type,
+			  bool channel_type_valid,
+#endif
+			  unsigned int wait, const u8 *buf, size_t len,
+#if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
+			  bool no_cck,
+#endif
+#if KERNEL_VERSION(3, 3, 0) <= CFG80211_VERSION_CODE
+			  bool dont_wait_for_ack,
+#endif
+#endif
+			  u64 * cookie);
+
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+void woal_update_radar_chans_dfs_state(struct wiphy *wiphy);
+#endif
+
+mlan_status woal_register_cfg80211(moal_private *priv);
+
+extern struct ieee80211_supported_band cfg80211_band_2ghz;
+extern struct ieee80211_supported_band cfg80211_band_5ghz;
+extern struct ieee80211_supported_band mac1_cfg80211_band_2ghz;
+extern struct ieee80211_supported_band mac1_cfg80211_band_5ghz;
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+int woal_cfg80211_bss_role_cfg(moal_private *priv, t_u16 action,
+			       t_u8 *bss_role);
+#endif
+#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE
+struct wireless_dev *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
+						    const char *name,
+						    unsigned char
+						    name_assign_type,
+						    enum nl80211_iftype type,
+#if KERNEL_VERSION(4, 12, 0) > CFG80211_VERSION_CODE
+						    u32 *flags,
+#endif
+						    struct vif_params *params);
+#else
+#if KERNEL_VERSION(3, 7, 0) <= CFG80211_VERSION_CODE
+struct wireless_dev *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
+						    const char *name,
+						    enum nl80211_iftype type,
+						    u32 *flags,
+						    struct vif_params *params);
+#else
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+struct wireless_dev *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
+						    char *name,
+						    enum nl80211_iftype type,
+						    u32 *flags,
+						    struct vif_params *params);
+#else
+#if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE
+struct net_device *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
+						  char *name,
+						  enum nl80211_iftype type,
+						  u32 *flags,
+						  struct vif_params *params);
+#else
+int woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
+				   enum nl80211_iftype type, u32 *flags,
+				   struct vif_params *params);
+#endif
+#endif
+#endif
+#endif
+int woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev);
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy,
+				   struct wireless_dev *wdev);
+#else
+int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+void woal_remove_virtual_interface(moal_handle *handle);
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/* Group Owner Negotiation Req */
+#define P2P_GO_NEG_REQ 0
+/* Group Owner Negotiation Rsp */
+#define P2P_GO_NEG_RSP 1
+/* Group Owner Negotiation Confirm */
+#define P2P_GO_NEG_CONF 2
+/* P2P Invitation Request */
+#define P2P_INVITE_REQ 3
+/* P2P Invitation Response */
+#define P2P_INVITE_RSP 4
+/* Device Discoverability Request */
+#define P2P_DEVDIS_REQ 5
+/* Device Discoverability Response */
+#define P2P_DEVDIS_RSP 6
+/* Provision Discovery Request */
+#define P2P_PROVDIS_REQ 7
+/* Provision Discovery Response */
+#define P2P_PROVDIS_RSP 8
+/** P2P category */
+#define P2P_ACT_FRAME_CATEGORY 0x04
+/** P2P oui offset */
+#define P2P_ACT_FRAME_OUI_OFFSET 26
+/** P2P subtype offset */
+#define P2P_ACT_FRAME_OUI_SUBTYPE_OFFSET 30
+void woal_cfg80211_display_p2p_actframe(const t_u8 *buf, int len,
+					struct ieee80211_channel *chan,
+					const t_u8 flag);
+
+/** Define kernel version for wifi direct */
+#define WIFI_DIRECT_KERNEL_VERSION KERNEL_VERSION(2, 6, 39)
+
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+
+int woal_cfg80211_init_p2p_client(moal_private *priv);
+
+int woal_cfg80211_init_p2p_go(moal_private *priv);
+
+int woal_cfg80211_deinit_p2p(moal_private *priv);
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+
+/** Define for remain on channel duration timer */
+#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
+
+int woal_cfg80211_remain_on_channel_cfg(moal_private *priv, t_u8 wait_option,
+					t_u8 remove, t_u8 *status,
+					struct ieee80211_channel *chan,
+					enum mlan_channel_type channel_type,
+					t_u32 duration);
+
+#ifdef UAP_CFG80211
+int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE
+				  const u8 *mac,
+#else
+				  u8 *mac,
+#endif
+				  struct station_info *stainfo);
+
+int woal_uap_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
+				   int idx, t_u8 *mac,
+				   struct station_info *sinfo);
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
+			     struct bss_parameters *params);
+#endif
+#if KERNEL_VERSION(3, 9, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
+			      const struct cfg80211_acl_data *params);
+#endif
+#if KERNEL_VERSION(3, 1, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
+				 struct ieee80211_txq_params *params);
+#endif
+
+#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_set_coalesce(struct wiphy *wiphy,
+			       struct cfg80211_coalesce *coalesce);
+#endif
+
+#if KERNEL_VERSION(3, 4, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
+			     struct cfg80211_ap_settings *params);
+
+int woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+			     struct cfg80211_beacon_data *params);
+#else
+int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
+			     struct beacon_parameters *params);
+
+int woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+			     struct beacon_parameters *params);
+#endif
+
+int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev);
+int woal_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
+#if KERNEL_VERSION(3, 19, 0) <= CFG80211_VERSION_CODE
+			      struct station_del_parameters *param);
+#else
+#if KERNEL_VERSION(3, 16, 0) <= CFG80211_VERSION_CODE
+			      const u8 *mac_addr);
+#else
+			      u8 *mac_addr);
+#endif
+#endif
+
+#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
+#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE
+int woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
+					struct net_device *dev,
+					struct cfg80211_chan_def *chandef,
+					u32 cac_time_ms);
+#else
+int woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
+					struct net_device *dev,
+					struct cfg80211_chan_def *chandef);
+#endif
+
+int woal_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_csa_settings *params);
+
+void woal_process_cancel_chanrpt_event(moal_private *priv);
+
+void woal_cac_timer_func(void *context);
+void woal_csa_work_queue(struct work_struct *work);
+#endif
+#endif /* UAP_CFG80211 */
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if KERNEL_VERSION(3, 5, 0) <= CFG80211_VERSION_CODE
+void woal_cfg80211_notify_channel(moal_private *priv,
+				  chan_band_info * pchan_info);
+void woal_channel_switch_event(moal_private *priv, chan_band_info * pchan_info);
+#endif
+#endif
+
+#ifdef STA_CFG80211
+#if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE
+void woal_bgscan_stop_event(moal_private *priv);
+void woal_cfg80211_notify_sched_scan_stop(moal_private *priv);
+void woal_sched_scan_work_queue(struct work_struct *work);
+void woal_report_sched_scan_result(moal_private *priv);
+#endif
+#endif
+
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+
+void woal_cfg80211_notify_antcfg(moal_private *priv,
+				 struct wiphy *wiphy, mlan_ds_radio_cfg *radio);
+#endif
+
+void woal_deauth_event(moal_private *priv, int reason_code);
+
+#if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
+mlan_status woal_chandef_create(moal_private *priv,
+				struct cfg80211_chan_def *chandef,
+				chan_band_info * pchan_info);
+#endif
+
+#if KERNEL_VERSION(4, 20, 0) <= CFG80211_VERSION_CODE
+void woal_cfg80211_setup_he_cap(moal_private *priv,
+				struct ieee80211_supported_band *band);
+void woal_cfg80211_free_iftype_data(struct wiphy *wiphy);
+#endif
+
+void woal_clear_all_mgmt_ies(moal_private *priv, t_u8 wait_option);
+int woal_cfg80211_mgmt_frame_ie(moal_private *priv, const t_u8 *beacon_ies,
+				size_t beacon_ies_len,
+				const t_u8 *proberesp_ies,
+				size_t proberesp_ies_len,
+				const t_u8 *assocresp_ies,
+				size_t assocresp_ies_len,
+				const t_u8 *probereq_ies,
+				size_t probereq_ies_len, t_u16 mask,
+				t_u8 wait_option);
+
+int woal_get_active_intf_freq(moal_private *priv);
+
+void woal_cfg80211_setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info,
+				t_u32 dev_cap, t_u8 *mcs_set);
+#if KERNEL_VERSION(3, 6, 0) <= CFG80211_VERSION_CODE
+void woal_cfg80211_setup_vht_cap(moal_private *priv,
+				 struct ieee80211_sta_vht_cap *vht_cap);
+#endif
+int woal_cfg80211_assoc(moal_private *priv, void *sme, t_u8 wait_option,
+			pmlan_ds_misc_assoc_rsp assoc_rsp);
+
+#endif /* _MOAL_CFG80211_H_ */
diff --git a/wlan_sd8987/mlinux/moal_cfg80211_util.c b/wlan_sd8987/mlinux/moal_cfg80211_util.c
new file mode 100755
index 0000000..0a65618
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfg80211_util.c
@@ -0,0 +1,4302 @@
+/** @file moal_cfg80211_util.c
+ *
+ * @brief This file contains the functions for CFG80211 vendor.
+ *
+ *
+ * Copyright 2015-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include "moal_cfg80211_util.h"
+#include "moal_cfg80211.h"
+
+/********************************************************
+ *				Local Variables
+ ********************************************************/
+
+/********************************************************
+ *				Global Variables
+ ********************************************************/
+
+/********************************************************
+ *				Local Functions
+ ********************************************************/
+
+/********************************************************
+ *				Global Functions
+ ********************************************************/
+
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+/**nxp vendor command and event*/
+#define MRVL_VENDOR_ID 0x005043
+/** vendor events */
+static const struct nl80211_vendor_cmd_info vendor_events[] = {
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_hang,
+	 },			/*event_id 0 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_fw_dump_done,
+	 },			/*event_id 1 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_rssi_monitor,
+	 },			/*event_id 0x1501 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_cloud_keep_alive,
+	 },			/*event_id 0x10003 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_dfs_radar_detected,
+	 },			/*event_id 0x10004 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_dfs_cac_started,
+	 },			/*event_id 0x10005 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_dfs_cac_finished,
+	 },			/*event_id 0x10006 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_dfs_cac_aborted,
+	 },			/*event_id 0x10007 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_dfs_nop_finished,
+	 },			/*event_id 0x10008 */
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_wifi_logger_ring_buffer_data,
+	 },
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_wifi_logger_alert,
+	 },
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_packet_fate_monitor,
+	 },
+	{
+	 .vendor_id = MRVL_VENDOR_ID,
+	 .subcmd = event_wake_reason_report,
+	 },
+	/**add vendor event here*/
+};
+
+/**nxp vendor policies*/
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+
+static const struct
+nla_policy woal_ll_stat_policy[ATTR_LL_STATS_MAX + 1] = {
+	[ATTR_LL_STATS_MPDU_SIZE_THRESHOLD] = {.type = NLA_U32},
+	[ATTR_LL_STATS_AGGRESSIVE_STATS_GATHERING] = {.type = NLA_U32},
+	[ATTR_LL_STATS_CLEAR_REQ_MASK] = {.type = NLA_U32},
+	[ATTR_LL_STATS_STOP_REQ] = {.type = NLA_U8}
+};
+
+static const struct
+nla_policy woal_logger_policy[ATTR_WIFI_LOGGER_MAX + 1] = {
+	[ATTR_WIFI_LOGGER_RING_ID] = {.type = NLA_STRING},
+	[ATTR_WIFI_LOGGER_VERBOSE_LEVEL] = {.type = NLA_U32},
+	[ATTR_WIFI_LOGGER_FLAGS] = {.type = NLA_U32},
+	[ATTR_WIFI_LOGGER_MIN_DATA_SIZE] = {.type = NLA_U32},
+	[ATTR_WIFI_LOGGER_MAX_INTERVAL_SEC] = {.type = NLA_U32}
+};
+
+static const struct
+nla_policy woal_attr_policy[ATTR_WIFI_MAX + 1] = {
+	[ATTR_CHANNELS_BAND] = {.type = NLA_U32},
+	[ATTR_SCAN_MAC_OUI_SET] = {.type = NLA_STRING,.len = 3},
+	[ATTR_NODFS_VALUE] = {.type = NLA_U32},
+	[ATTR_GET_CONCURRENCY_MATRIX_SET_SIZE_MAX] = {.type = NLA_U32},
+	[ATTR_WIFI_LATENCY_MODE] = {.type = NLA_U8},
+};
+
+// clang-format off
+static const struct nla_policy
+ woal_nd_offload_policy[ATTR_ND_OFFLOAD_MAX + 1] = {
+	[ATTR_ND_OFFLOAD_CONTROL] = {.type = NLA_U8},
+};
+
+// clang-format on
+
+static const struct
+nla_policy woal_rssi_monitor_policy[ATTR_RSSI_MONITOR_MAX + 1] = {
+	[ATTR_RSSI_MONITOR_CONTROL] = {.type = NLA_U32},
+	[ATTR_RSSI_MONITOR_MIN_RSSI] = {.type = NLA_S8},
+	[ATTR_RSSI_MONITOR_MAX_RSSI] = {.type = NLA_S8},
+};
+
+static const struct
+nla_policy woal_packet_filter_policy[ATTR_PACKET_FILTER_MAX + 1] = {
+	[ATTR_PACKET_FILTER_TOTAL_LENGTH] = {.type = NLA_U32},
+	[ATTR_PACKET_FILTER_PROGRAM] = {.type = NLA_STRING},
+};
+
+// clang-format off
+static const struct nla_policy
+ woal_fw_roaming_policy[MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_MAX + 1] = {
+	[MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONTROL] = {.type = NLA_U32},
+	[MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_BSSID] = {
+							   .type = NLA_BINARY},
+	[MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_SSID] = {
+							  .type = NLA_BINARY},
+};
+
+// clang-format on
+
+static const struct
+nla_policy woal_keep_alive_policy[MKEEP_ALIVE_ATTRIBUTE_MAX + 1] = {
+	[MKEEP_ALIVE_ATTRIBUTE_ID] = {.type = NLA_U8},
+	[MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE] = {.type = NLA_U16},
+	[MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = {.type = NLA_BINARY},
+	[MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = {.type = NLA_U16},
+	[MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = {.type = NLA_STRING,.len =
+						ETH_ALEN},
+	[MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = {.type = NLA_STRING,.len =
+						ETH_ALEN},
+	[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = {.type = NLA_U32},
+	[MKEEP_ALIVE_ATTRIBUTE_RETRY_INTERVAL] = {.type = NLA_U32},
+	[MKEEP_ALIVE_ATTRIBUTE_RETRY_CNT] = {.type = NLA_U8},
+};
+#endif
+
+/**
+ * @brief get the event id of the events array
+ *
+ * @param event     vendor event
+ *
+ * @return    index of events array
+ */
+static int
+woal_get_event_id(int event)
+{
+	int i = 0;
+
+	for (i = 0; i < (int)ARRAY_SIZE(vendor_events); i++) {
+		if ((int)vendor_events[i].subcmd == event)
+			return i;
+	}
+
+	return event_max;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param event    vendor event
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_cfg80211_vendor_event(moal_private *priv, int event, t_u8 *data, int len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+	t_u8 *pos = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		LEAVE();
+		return ret;
+	}
+	wiphy = priv->wdev->wiphy;
+	PRINTM(MEVENT, "vendor event :0x%x\n", event);
+	event_id = woal_get_event_id(event);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d\n", event_id);
+		ret = 1;
+		LEAVE();
+		return ret;
+	}
+
+	/**allocate skb*/
+#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE
+	skb = cfg80211_vendor_event_alloc(wiphy, priv->wdev, len, event_id,
+					  GFP_ATOMIC);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, GFP_ATOMIC);
+#endif
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = 1;
+		LEAVE();
+		return ret;
+	}
+	pos = skb_put(skb, len);
+	moal_memcpy_ext(priv->phandle, pos, data, len, len);
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send fw dump complete event to vendorhal
+ *
+ * @param priv       A pointer to moal_private
+ *
+ * @return      N/A
+ */
+void
+woal_cfg80211_vendor_event_fw_dump(moal_private *priv)
+{
+	PRINTM(MEVENT, "wlan: Notify FW dump complete event\n");
+	woal_cfg80211_vendor_event(priv, event_fw_dump_done,
+				   CUS_EVT_FW_DUMP, strlen(CUS_EVT_FW_DUMP));
+
+}
+
+/**
+ * @brief send dfs vendor event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param event      dfs vendor event
+ * @param chandef    a pointer to struct cfg80211_chan_def
+ *
+ * @return      N/A
+ */
+void
+woal_cfg80211_dfs_vendor_event(moal_private *priv, int event,
+			       struct cfg80211_chan_def *chandef)
+{
+	dfs_event evt;
+
+	ENTER();
+	if (!chandef) {
+		LEAVE();
+		return;
+	}
+	memset(&evt, 0, sizeof(dfs_event));
+	evt.freq = chandef->chan->center_freq;
+	evt.chan_width = chandef->width;
+	evt.cf1 = chandef->center_freq1;
+	evt.cf2 = chandef->center_freq2;
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_20_NOHT:
+		evt.ht_enabled = 0;
+		break;
+	case NL80211_CHAN_WIDTH_20:
+		evt.ht_enabled = 1;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		evt.ht_enabled = 1;
+		if (chandef->center_freq1 < chandef->chan->center_freq)
+			evt.chan_offset = -1;
+		else
+			evt.chan_offset = 1;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+		evt.ht_enabled = 1;
+		break;
+	default:
+		break;
+	}
+	woal_cfg80211_vendor_event(priv, event, (t_u8 *)&evt,
+				   sizeof(dfs_event));
+	LEAVE();
+}
+
+/**
+ * @brief vendor command to set drvdbg
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_set_drvdbg(struct wiphy *wiphy,
+				struct wireless_dev *wdev,
+				const void *data, int data_len)
+{
+#ifdef DEBUG_LEVEL1
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	t_u8 *pos = NULL;
+#endif
+	int ret = 1;
+
+	ENTER();
+#ifdef DEBUG_LEVEL1
+	/**handle this sub command*/
+	DBG_HEXDUMP(MCMD_D, "Vendor drvdbg", (t_u8 *)data, data_len);
+
+	if (data_len) {
+		/* Get the driver debug bit masks from user */
+		drvdbg = *((t_u32 *)data);
+		PRINTM(MIOCTL, "new drvdbg %x\n", drvdbg);
+		/* Set the driver debug bit masks into mlan */
+		if (woal_set_drvdbg(priv, drvdbg)) {
+			PRINTM(MERROR, "Set drvdbg failed!\n");
+			ret = 1;
+		}
+	}
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(drvdbg));
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = 1;
+		LEAVE();
+		return ret;
+	}
+	pos = skb_put(skb, sizeof(drvdbg));
+	moal_memcpy_ext(priv->phandle, pos, &drvdbg, sizeof(drvdbg),
+			sizeof(drvdbg));
+	ret = cfg80211_vendor_cmd_reply(skb);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief process one channel in bucket
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @param channel     a pointer to channel
+ *
+ * @return      0: success  other: fail
+ */
+static mlan_status
+woal_band_to_valid_channels(moal_private *priv,
+			    wifi_band w_band, int channel[], t_u32 *nchannel)
+{
+	int band = 0;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int i = 0;
+	t_u8 cnt = 0;
+	int *ch_ptr = channel;
+
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		if (!priv->wdev->wiphy->bands[band])
+			continue;
+		if ((band == IEEE80211_BAND_2GHZ) && !(w_band & WIFI_BAND_BG))
+			continue;
+		if ((band == IEEE80211_BAND_5GHZ) &&
+		    !((w_band & WIFI_BAND_A) || (w_band & WIFI_BAND_A_DFS)))
+			continue;
+		sband = priv->wdev->wiphy->bands[band];
+		for (i = 0; (i < sband->n_channels); i++) {
+			ch = &sband->channels[i];
+			if (ch->flags & IEEE80211_CHAN_DISABLED) {
+				PRINTM(MERROR, "Skip DISABLED channel %d\n",
+				       ch->center_freq);
+				continue;
+			}
+			if (band == IEEE80211_BAND_5GHZ) {
+				if (((ch->flags & IEEE80211_CHAN_RADAR) &&
+				     !(w_band & WIFI_BAND_A_DFS)) ||
+				    (!(ch->flags & IEEE80211_CHAN_RADAR) &&
+				     !(w_band & WIFI_BAND_A)))
+					continue;
+			}
+			if (cnt >= *nchannel) {
+				PRINTM(MERROR,
+				       "cnt=%d is exceed %d, cur ch=%d %dMHz\n",
+				       cnt, *nchannel, ch->hw_value,
+				       ch->center_freq);
+				break;
+			}
+			*ch_ptr = ch->center_freq;
+			ch_ptr++;
+			cnt++;
+		}
+	}
+
+	PRINTM(MCMND, "w_band=%d cnt=%d\n", w_band, cnt);
+	*nchannel = cnt;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief GSCAN subcmd - enable full scan results
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ *
+ * @param data     a pointer to data
+ * @param  data_len     data length
+ *
+ * @return      0: success  other: fail
+ */
+static int
+woal_cfg80211_subcmd_get_valid_channels(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct nlattr *tb[ATTR_WIFI_MAX + 1];
+	t_u32 band = 0;
+	int ch_out[MAX_CHANNEL_NUM];
+	t_u32 nchannel = 0;
+	t_u32 mem_needed = 0;
+	struct sk_buff *skb = NULL;
+	int err = 0;
+
+	ENTER();
+	PRINTM(MCMND, "Enter %s()\n", __func__);
+
+	err = nla_parse(tb, ATTR_WIFI_MAX, data, len, NULL
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+			, NULL
+#endif
+		);
+	if (err) {
+		PRINTM(MERROR, "%s: nla_parse fail\n", __func__);
+		err = -EFAULT;
+		goto done;
+	}
+
+	if (!tb[ATTR_CHANNELS_BAND]) {
+		PRINTM(MERROR, "%s: null attr: tb[ATTR_GET_CH]=%p\n",
+		       __func__, tb[ATTR_CHANNELS_BAND]);
+		err = -EINVAL;
+		goto done;
+	}
+	band = nla_get_u32(tb[ATTR_CHANNELS_BAND]);
+	if (band > WIFI_BAND_MAX) {
+		PRINTM(MERROR, "%s: invalid band=%d\n", __func__, band);
+		err = -EINVAL;
+		goto done;
+	}
+
+	memset(ch_out, 0x00, sizeof(ch_out));
+	nchannel = MAX_CHANNEL_NUM;
+	if (woal_band_to_valid_channels(priv, band, ch_out, &nchannel) !=
+	    MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "get_channel_list: woal_band_to_valid_channels fail\n");
+		return -EFAULT;
+	}
+
+	mem_needed = nla_total_size(nchannel * sizeof(ch_out[0])) +
+		nla_total_size(sizeof(nchannel)) + VENDOR_REPLY_OVERHEAD;
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed");
+		err = -ENOMEM;
+		goto done;
+	}
+
+	if (nla_put_u32(skb, ATTR_NUM_CHANNELS, nchannel) ||
+	    nla_put(skb, ATTR_CHANNEL_LIST, nchannel * sizeof(ch_out[0]),
+		    ch_out)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		err = -ENOMEM;
+		goto done;
+	}
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (err) {
+		PRINTM(MERROR, "Vendor Command reply failed ret:%d\n", err);
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return err;
+}
+
+/**
+ * @brief vendor command to get driver version
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_drv_version(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	t_u32 drv_len = 0;
+	char drv_version[MLAN_MAX_VER_STR_LEN] = { 0 };
+	char *pos;
+
+	ENTER();
+	moal_memcpy_ext(priv->phandle, drv_version,
+			&priv->phandle->driver_version, MLAN_MAX_VER_STR_LEN,
+			MLAN_MAX_VER_STR_LEN);
+	drv_len = strlen(drv_version);
+	pos = strstr(drv_version, "%s");
+	/* remove 3 char "-%s" in driver_version string */
+	if (pos != NULL)
+		moal_memcpy_ext(priv->phandle, pos, pos + 3, strlen(pos) - 3,
+				strlen(pos));
+
+	reply_len = strlen(drv_version) + 1;
+	drv_len -= 3;
+	drv_version[drv_len] = '\0';
+
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_NAME, reply_len,
+		(t_u8 *)drv_version);
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get firmware version
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_fw_version(struct wiphy *wiphy,
+				    struct wireless_dev *wdev,
+				    const void *data, int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	char end_c = '\0';
+	int ret = 0;
+	char fw_ver[32] = { 0 };
+	union {
+		t_u32 l;
+		t_u8 c[4];
+	} ver;
+
+	ENTER();
+
+	ver.l = priv->phandle->fw_release_number;
+	snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u%c", ver.c[2], ver.c[1],
+		 ver.c[0], ver.c[3], end_c);
+	reply_len = strlen(fw_ver) + 1;
+
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_NAME, reply_len, (t_u8 *)fw_ver);
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get firmware memory dump
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_fw_dump(struct wiphy *wiphy,
+				 struct wireless_dev *wdev,
+				 const void *data, int data_len)
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = NULL;
+	moal_handle *handle = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+	int length = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	handle = priv->phandle;
+	if (handle) {
+		memset(handle->firmware_dump_file, 0,
+		       sizeof(handle->firmware_dump_file));
+	}
+	length = sizeof(handle->firmware_dump_file);
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length);
+	if (!skb) {
+		PRINTM(MERROR, "Failed to allocate memory for skb\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	nla_put(skb, ATTR_FW_DUMP_PATH, sizeof(handle->firmware_dump_file),
+		handle->firmware_dump_file);
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get driver memory dump
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_drv_dump(struct wiphy *wiphy,
+				  struct wireless_dev *wdev,
+				  const void *data, int data_len)
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = NULL;
+	moal_handle *handle = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+	int length = 0;
+	char driver_dump_file[128];
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	handle = priv->phandle;
+	memset(driver_dump_file, 0, sizeof(driver_dump_file));
+	sprintf(driver_dump_file, "/proc/mwlan/");
+	if (handle->handle_idx)
+		sprintf(driver_dump_file, "drv_dump%d", handle->handle_idx);
+	else
+		sprintf(driver_dump_file, "drv_dump");
+	PRINTM(MMSG, "driver dump file is %s\n", driver_dump_file);
+	length = sizeof(driver_dump_file);
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length);
+	if (!skb) {
+		PRINTM(MERROR, "Failed to allocate memory for skb\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (nla_put_string(skb, ATTR_DRV_DUMP_PATH, driver_dump_file)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		ret = -ENOMEM;
+		goto done;
+	}
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get supported feature set
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_supp_feature_set(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int data_len)
+{
+	struct sk_buff *skb = NULL;
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_fw_info fw_info;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	t_u32 supp_feature_set = 0;
+
+	ENTER();
+
+	supp_feature_set = WLAN_FEATURE_INFRA
+#if defined(UAP_SUPPORT) && defined(STA_SUPPORT)
+		| WLAN_FEATURE_AP_STA
+#endif
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+		| WLAN_FEATURE_SET_LATENCY_MODE
+#endif
+		| WLAN_FEATURE_LINK_LAYER_STATS
+		| WLAN_FEATURE_LOGGER
+		| WLAN_FEATURE_RSSI_MONITOR | WLAN_FEATURE_CONFIG_NDO
+		| WLAN_FEATURE_CONTROL_ROAMING | WLAN_FEATURE_SCAN_RAND
+//#ifdef RTT_SUPPORT
+//                         | WLAN_FEATURE_D2AP_RTT
+//#endif
+		| WLAN_FEATURE_MKEEP_ALIVE;
+
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (fw_info.fw_bands & BAND_A)
+		supp_feature_set |= WLAN_FEATURE_INFRA_5G;
+
+	reply_len = sizeof(supp_feature_set);
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (nla_put_u32(skb, ATTR_FEATURE_SET, supp_feature_set)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		ret = -ENOMEM;
+		goto done;
+	}
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+/**
+ * @brief vendor command to set Wi-Fi latency mode
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int woal_cfg80211_subcmd_set_wifi_latency_mode(struct wiphy *wiphy,
+		struct wireless_dev *wdev,
+		const void *data, int data_len)
+{
+	int ret, rem, type;
+	u8 latency_mode;
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	const struct nlattr *iter;
+	t_u32 reply_len = 0;
+	struct sk_buff *skb = NULL;
+	mlan_status op_status = MLAN_STATUS_SUCCESS;
+
+	PRINTM(MMSG, "wlan: enter subcmd_set_wifi_latency_mode");
+	ENTER();
+
+	nla_for_each_attr(iter, data, data_len, rem) {
+		type = nla_type(iter);
+		if (ATTR_WIFI_LATENCY_MODE != type) {
+			PRINTM(MERROR, "%s. Unknown type: %d\n", __FUNCTION__, type);
+			ret = 1;
+			goto done;
+		}
+
+		latency_mode = nla_get_u8(iter);
+		/* WIFI_LATENCY_MODE_LOW : 1, WIFI_LATENCY_MODE_NORMAL : 0 */
+		if (1 != latency_mode && 0 != latency_mode) {
+			PRINTM(MERROR, "%s. Invalid Wi-Fi latency mode: %d\n", __FUNCTION__, latency_mode);
+			ret = 1;
+			goto done;
+		}
+		op_status = woal_set_wifi_low_latency_mode(priv, latency_mode);
+
+		if (MLAN_STATUS_SUCCESS != op_status) {
+			PRINTM(MERROR, "Set latency mode to %d failed", latency_mode);
+			ret = 1;
+			goto done;
+		}
+	}
+
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "Allocate memory fail for vendor cmd\n");
+		ret = 1;
+		goto done;
+	}
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret) {
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+		ret = 1;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif  // defined(WIFI_LATENCY_MODE_SUPPORT)
+
+/**
+ * @brief vendor command to set country code
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_set_country_code(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      const void *data, int data_len)
+{
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	int ret = 0, rem, type;
+	const struct nlattr *iter;
+	char country[COUNTRY_CODE_LEN] = { 0 };
+
+	ENTER();
+
+	nla_for_each_attr(iter, data, data_len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case ATTR_COUNTRY_CODE:
+			strncpy(country, nla_data(iter),
+				MIN((int)sizeof(country) - 1, nla_len(iter)));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			return ret;
+		}
+	}
+
+	if (!moal_extflg_isset((moal_handle *)woal_get_wiphy_priv(wiphy),
+			       EXT_DISABLE_REGD_BY_DRIVER))
+		regulatory_hint(wiphy, country);
+
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get supported feature set
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_wifi_logger_supp_feature_set(struct wiphy *wiphy,
+						      struct wireless_dev *wdev,
+						      const void *data,
+						      int data_len)
+{
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	t_u32 supp_feature_set = 0;
+
+	ENTER();
+
+	supp_feature_set = WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
+	reply_len = sizeof(supp_feature_set);
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (nla_put_u32(skb, ATTR_WIFI_LOGGER_FEATURE_SET, supp_feature_set)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		ret = -ENOMEM;
+		goto done;
+	}
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief get ring status
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring_id    ring buffer id
+ * @param status     a pointer to wifi_ring_buffer_status
+ *
+ * @return    void
+ */
+static void
+woal_get_ring_status(moal_private *priv, int ring_id,
+		     wifi_ring_buffer_status * status)
+{
+	int id = 0;
+	wifi_ring_buffer *ring;
+
+	ENTER();
+	for (id = 0; id < RING_ID_MAX; id++) {
+		ring = (wifi_ring_buffer *) priv->rings[id];
+		if (ring && VALID_RING(ring->ring_id) &&
+		    ring_id == ring->ring_id) {
+			strncpy(status->name, ring->name,
+				sizeof(status->name) - 1);
+			status->ring_id = ring->ring_id;
+			status->ring_buffer_byte_size = ring->ring_size;
+			status->written_bytes = ring->ctrl.written_bytes;
+			status->written_records = ring->ctrl.written_records;
+			status->read_bytes = ring->ctrl.read_bytes;
+			status->verbose_level = ring->log_level;
+			PRINTM(MINFO,
+			       "%s, name: %s, ring_id: %d, ring_size : %d, written_bytes: %d, written_records: %d, read_bytes: %d\n",
+			       __func__, status->name, status->ring_id,
+			       status->ring_buffer_byte_size,
+			       status->written_bytes, status->written_records,
+			       status->read_bytes);
+			break;
+		}
+	}
+	LEAVE();
+}
+
+/**
+ * @brief vendor command to get ring buffer status
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_ring_buff_status(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	t_u8 ringIdx, ring_cnt = 0;
+	int ret = 0;
+	wifi_ring_buffer_status status[RING_ID_MAX];
+	wifi_ring_buffer_status ring_status;
+
+	ENTER();
+	reply_len =
+		RING_ID_MAX * sizeof(wifi_ring_buffer_status) + sizeof(t_u32);
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* should sync with HAL side to decide payload layout.
+	 * just ring buffer status or ring buffer num + ring buffer status
+	 * currently only have ring buffer status
+	 */
+	for (ringIdx = 0; ringIdx < RING_ID_MAX; ringIdx++) {
+		memset(&ring_status, 0, sizeof(wifi_ring_buffer_status));
+		woal_get_ring_status(priv, ringIdx, &ring_status);
+		moal_memcpy_ext(priv->phandle, &status[ring_cnt++],
+				&ring_status, sizeof(wifi_ring_buffer_status),
+				sizeof(wifi_ring_buffer_status));
+	}
+
+	if (nla_put_u32(skb, ATTR_NUM_RINGS, ring_cnt) ||
+	    nla_put(skb, ATTR_RING_BUFFER_STATUS,
+		    sizeof(wifi_ring_buffer_status) * ring_cnt, status)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief return ring_id based on ring_name
+ *
+ * @param priv          A pointer to moal_private struct
+ * @param ring_name     A pointer to ring_name
+ *
+ * @return      An invalid ring id for failure or valid ring id on success.
+ */
+int
+woal_get_ring_id_by_name(moal_private *priv, char *ring_name)
+{
+	int id;
+	wifi_ring_buffer *ring;
+
+	ENTER();
+
+	for (id = 0; id < RING_ID_MAX; id++) {
+		ring = (wifi_ring_buffer *) priv->rings[id];
+		if (ring &&
+		    !strncmp(ring->name, ring_name, sizeof(ring->name) - 1))
+			break;
+	}
+
+	LEAVE();
+	return id;
+}
+
+/**
+ * @brief start logger
+ *
+ * @param priv          A pointer to moal_private struct
+ * @param ring_name     string ring_name
+ * @param log_level     log level to record
+ * @param flags         reserved
+ * @param time_intval   interval to report log to HAL
+ * @param threshold     buffer threshold to report log to HAL
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_start_logging(moal_private *priv, char *ring_name, int log_level,
+		   int flags, int time_intval, int threshold)
+{
+	int ret = 0;
+	int ring_id;
+	wifi_ring_buffer *ring_buffer;
+	unsigned long lock_flags;
+
+	ENTER();
+
+	ring_id = woal_get_ring_id_by_name(priv, ring_name);
+	if (!VALID_RING(ring_id)) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	PRINTM(MCMND,
+	       "%s , log_level : %d, time_intval : %d, threshod %d Bytes\n",
+	       __func__, log_level, time_intval, threshold);
+
+	ring_buffer = (wifi_ring_buffer *) priv->rings[ring_id];
+	if (!ring_buffer || ring_buffer->state == RING_STOP) {
+		PRINTM(MERROR, "Ring is stopped!\n");
+		ret = -EAGAIN;
+		goto done;
+	}
+
+	spin_lock_irqsave(&ring_buffer->lock, lock_flags);
+	ring_buffer->log_level = log_level;
+	ring_buffer->threshold = threshold;
+	if (log_level == 0)
+		ring_buffer->state = RING_SUSPEND;
+	else
+		ring_buffer->state = RING_ACTIVE;
+	ring_buffer->interval = msecs_to_jiffies(time_intval * MSEC_PER_SEC);
+	spin_unlock_irqrestore(&ring_buffer->lock, lock_flags);
+
+	if (log_level == 0) {
+		cancel_delayed_work_sync(&ring_buffer->work);
+	} else {
+		if (ring_buffer->interval)
+			schedule_delayed_work(&ring_buffer->work,
+					      ring_buffer->interval);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to start logging
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_start_logging(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   const void *data, int len)
+{
+	int ret = 0, rem, type;
+	char ring_name[RING_NAME_MAX] = { 0 };
+	int log_level = 0, flags = 0, time_intval = 0, threshold = 0;
+	const struct nlattr *iter;
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case ATTR_WIFI_LOGGER_RING_ID:
+			strncpy(ring_name, nla_data(iter),
+				MIN(sizeof(ring_name) - 1, nla_len(iter)));
+			break;
+		case ATTR_WIFI_LOGGER_VERBOSE_LEVEL:
+			log_level = nla_get_u32(iter);
+			break;
+		case ATTR_WIFI_LOGGER_FLAGS:
+			flags = nla_get_u32(iter);
+			break;
+		case ATTR_WIFI_LOGGER_MAX_INTERVAL_SEC:
+			time_intval = nla_get_u32(iter);
+			break;
+		case ATTR_WIFI_LOGGER_MIN_DATA_SIZE:
+			threshold = nla_get_u32(iter);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	ret = woal_start_logging(priv, ring_name, log_level, flags, time_intval,
+				 threshold);
+	if (ret < 0)
+		PRINTM(MERROR, "Start_logging is failed ret: %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief get log data in ring buffer
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring_name  ring name string
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_trigger_get_ring_data(moal_private *priv, char *ring_name)
+{
+	int ret = 0;
+	int ring_id;
+	wifi_ring_buffer *ring_buffer;
+
+	ENTER();
+
+	ring_id = woal_get_ring_id_by_name(priv, ring_name);
+	if (!VALID_RING(ring_id)) {
+		PRINTM(MERROR, "invalid ring_id\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ring_buffer = (wifi_ring_buffer *) priv->rings[ring_id];
+	if (!ring_buffer) {
+		PRINTM(MERROR, "invalid ring_buffer\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (ring_buffer->interval)
+		cancel_delayed_work_sync(&ring_buffer->work);
+	schedule_delayed_work(&ring_buffer->work, 0);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get ring buffer data
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_ring_data(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   const void *data, int len)
+{
+	int ret = 0, rem, type;
+	char ring_name[RING_NAME_MAX] = { 0 };
+	const struct nlattr *iter;
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case ATTR_WIFI_LOGGER_RING_ID:
+			strncpy(ring_name, nla_data(iter),
+				MIN(sizeof(ring_name) - 1, nla_len(iter)));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	ret = woal_trigger_get_ring_data(priv, ring_name);
+	if (ret < 0)
+		PRINTM(MERROR, "trigger_get_data failed ret:%d\n", ret);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief ring reset
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring    A pointer to wifi_ring_buffer
+ *
+ * @return    void
+ */
+static void
+woal_ring_reset(wifi_ring_buffer * ring)
+{
+	ENTER();
+	ring->wp = 0;
+	ring->rp = 0;
+	memset(&(ring->ctrl), 0x00, sizeof(ring->ctrl));
+	memset(ring->ring_buf, 0, ring->ring_size);
+
+	LEAVE();
+}
+
+/**
+ * @brief get ring buffer entry
+ *
+ * @param ring       A pointer to wifi_ring_buffer struct
+ * @param offset     entry offset
+ *
+ * @return     A pointer to wifi_ring_buffer_entry struct
+ */
+static wifi_ring_buffer_entry *
+woal_get_ring_entry(wifi_ring_buffer * ring, t_u32 offset)
+{
+	wifi_ring_buffer_entry *entry =
+		(wifi_ring_buffer_entry *) (ring->ring_buf + offset);
+
+	ENTER();
+
+	if (!entry->entry_size)
+		return (wifi_ring_buffer_entry *) ring->ring_buf;
+
+	LEAVE();
+	return entry;
+}
+
+/**
+ * @brief get next ring buffer entry
+ *
+ * @param ring       A pointer to wifi_ring_buffer struct
+ * @param offset     next entry offset
+ *
+ * @return     offset of next entry
+ */
+static t_u32
+woal_get_ring_next_entry(wifi_ring_buffer * ring, t_u32 offset)
+{
+	wifi_ring_buffer_entry *entry =
+		(wifi_ring_buffer_entry *) (ring->ring_buf + offset);
+	wifi_ring_buffer_entry *next_entry = NULL;
+
+	ENTER();
+
+	if (!entry->entry_size) {
+		entry = (wifi_ring_buffer_entry *) ring->ring_buf;
+		LEAVE();
+		return ENTRY_LENGTH(entry);
+	}
+	if ((offset + ENTRY_LENGTH(entry)) >= ring->ring_size) {
+		/* move to head */
+		LEAVE();
+		return 0;
+	}
+	next_entry = (wifi_ring_buffer_entry *) (ring->ring_buf + offset +
+						 ENTRY_LENGTH(entry));
+	if (!next_entry->entry_size) {
+		/* move to head */
+		LEAVE();
+		return 0;
+	}
+	LEAVE();
+	return offset + ENTRY_LENGTH(entry);
+}
+
+/**
+ * @brief prepare log data to send to HAL
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring_id    ring ID
+ * @param data       A pointer to data buffer
+ * @param buf_len    log data length
+ *
+ * @return      data length
+ */
+int
+woal_ring_pull_data(moal_private *priv, int ring_id, void *data, t_s32 buf_len)
+{
+	t_s32 r_len = 0;
+	wifi_ring_buffer *ring;
+	wifi_ring_buffer_entry *hdr;
+	t_s32 buf_left = buf_len;
+
+	ENTER();
+
+	ring = (wifi_ring_buffer *) priv->rings[ring_id];
+
+	/* get a fresh pending length */
+	while (buf_left > 0) {
+		hdr = woal_get_ring_entry(ring, ring->rp);
+		if (buf_left < ENTRY_LENGTH(hdr))
+			break;
+		moal_memcpy_ext(priv->phandle, data, hdr, ENTRY_LENGTH(hdr),
+				buf_left);
+		r_len += ENTRY_LENGTH(hdr);
+		data += ENTRY_LENGTH(hdr);
+		buf_left -= ENTRY_LENGTH(hdr);
+		ring->ctrl.read_bytes += ENTRY_LENGTH(hdr);
+		if (!buf_left) {
+			ring->rp += ENTRY_LENGTH(hdr);
+			break;
+		}
+		ring->rp = woal_get_ring_next_entry(ring, ring->rp);
+	}
+	PRINTM(MDATA, "Ring pull data: [wp=%d rp=%d] r_len=%d buf_len=%d\n",
+	       ring->wp, ring->rp, r_len, buf_len);
+
+	LEAVE();
+	return r_len;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param event    vendor event
+ * @param data     a pointer to data
+ * @param  len     data length
+ * @param ring_status    A pointer to wifi_ring_buffer status struct
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_ring_buffer_data_vendor_event(moal_private *priv, int ring_id,
+				   t_u8 *data, int len,
+				   wifi_ring_buffer_status * ring_status)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "priv is null\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	wiphy = priv->wdev->wiphy;
+	PRINTM(MEVENT, "%s ring_id:%d\n", __func__, ring_id);
+	event_id = woal_get_event_id(event_wifi_logger_ring_buffer_data);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d\n", event_id);
+		ret = -EINVAL;
+		goto done;
+	}
+
+/**allocate skb*/
+#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE
+	skb = cfg80211_vendor_event_alloc(wiphy, priv->wdev,
+					  len + sizeof(wifi_ring_buffer_status),
+					  event_id, GFP_ATOMIC);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy,
+					  len + sizeof(wifi_ring_buffer_status),
+					  event_id, GFP_ATOMIC);
+#endif
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	nla_put(skb, ATTR_RING_BUFFER_STATUS, sizeof(wifi_ring_buffer_status),
+		ring_status);
+	DBG_HEXDUMP(MEVT_D, "ring_buffer_data", data, len);
+	nla_put(skb, ATTR_RING_BUFFER, len, data);
+
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send log data to HAL
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring_id    ring ID
+ * @param data       A pointer to data buffer
+ * @param len    log data length
+ * @param ring_status    A pointer to wifi_ring_buffer status struct
+ *
+ * @return void
+ */
+static void
+woal_ring_data_send(moal_private *priv, int ring_id,
+		    const void *data, const t_u32 len,
+		    wifi_ring_buffer_status * ring_status)
+{
+	struct net_device *ndev = priv->netdev;
+
+	ENTER();
+
+	if (!ndev)
+		goto done;
+	woal_ring_buffer_data_vendor_event(priv, ring_id, (t_u8 *)data, len,
+					   ring_status);
+
+done:
+	LEAVE();
+}
+
+/**
+ * @brief main thread to send log data
+ *
+ * @param work       A pointer to work_struct struct
+ *
+ * @return void
+ */
+void
+woal_ring_poll_worker(struct work_struct *work)
+{
+	struct delayed_work *d_work = to_delayed_work(work);
+	wifi_ring_buffer *ring_info =
+		container_of(d_work, wifi_ring_buffer, work);
+	moal_private *priv = ring_info->priv;
+	int ringid = ring_info->ring_id;
+	wifi_ring_buffer_status ring_status;
+	void *buf = NULL;
+	wifi_ring_buffer_entry *hdr;
+	t_s32 buflen, rlen;
+	unsigned long flags;
+
+	ENTER();
+	if (ring_info->state != RING_ACTIVE) {
+		PRINTM(MERROR, "Ring is not active!\n");
+		goto exit;
+	}
+	buf = kmalloc(ring_info->ring_size, GFP_KERNEL);
+	if (!buf) {
+		PRINTM(MERROR, "Fail to allocate buffer for poll work\n");
+		goto exit;
+	}
+	spin_lock_irqsave(&ring_info->lock, flags);
+	memset(&ring_status, 0, sizeof(ring_status));
+	woal_get_ring_status(priv, ringid, &ring_status);
+	PRINTM(MDATA, "Ring work: ringid %d write %d, read %d, size %d\n",
+	       ringid, ring_status.written_bytes, ring_status.read_bytes,
+	       ring_status.ring_buffer_byte_size);
+	if (ring_status.written_bytes > ring_status.read_bytes) {
+		buflen = ring_status.written_bytes - ring_status.read_bytes;
+		if (buflen > ring_info->ring_size) {
+			PRINTM(MERROR, "Pending data bigger than ring size\n");
+			spin_unlock_irqrestore(&ring_info->lock, flags);
+			goto exit;
+		}
+	} else {
+		spin_unlock_irqrestore(&ring_info->lock, flags);
+		PRINTM(MINFO, "No new records\n");
+		goto exit;
+	}
+
+	rlen = woal_ring_pull_data(priv, ringid, buf, buflen);
+	spin_unlock_irqrestore(&ring_info->lock, flags);
+	hdr = (wifi_ring_buffer_entry *) buf;
+	while (rlen > 0) {
+		ring_status.read_bytes += ENTRY_LENGTH(hdr);
+		woal_ring_data_send(priv, ringid, hdr,
+				    ENTRY_LENGTH(hdr), &ring_status);
+		rlen -= ENTRY_LENGTH(hdr);
+		hdr = (wifi_ring_buffer_entry *) ((void *)hdr +
+						  ENTRY_LENGTH(hdr));
+	}
+exit:
+	kfree(buf);
+	if (ring_info->interval)
+		schedule_delayed_work(&ring_info->work, ring_info->interval);
+
+	LEAVE();
+}
+
+/**
+ * @brief add log data to ring buffer
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring_id    ring ID
+ * @param hdr        A pointer to wifi_ring_buffer_entry struct
+ * @param data       A pointer to data buffer
+ *
+ * @return      0: success  -1: fail
+ */
+int
+woal_ring_push_data(moal_private *priv, int ring_id,
+		    wifi_ring_buffer_entry * hdr, void *data)
+{
+	unsigned long flags;
+	t_u32 w_len;
+	wifi_ring_buffer *ring;
+	wifi_ring_buffer_entry *w_entry;
+	int ret = 0;
+
+	ENTER();
+
+	ring = (wifi_ring_buffer *) priv->rings[ring_id];
+
+	if (!ring || ring->state != RING_ACTIVE) {
+		PRINTM(MERROR, "Ring is not active\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	w_len = ENTRY_LENGTH(hdr);
+	if (w_len > ring->ring_size) {
+		PRINTM(MERROR, "event size too big =%d\n", w_len);
+		ret = -EINVAL;
+		goto done;
+	}
+	spin_lock_irqsave(&ring->lock, flags);
+	PRINTM(MDATA, "Ring push data: rp=%d  wp=%d, w_len=%d\n", ring->rp,
+	       ring->wp, w_len);
+	/* prep the space */
+	do {
+		if (ring->rp == ring->wp) {
+			if (ring->ctrl.read_bytes == ring->ctrl.written_bytes) {
+				if (ring->wp)
+					woal_ring_reset(ring);
+				break;
+			} else {
+				/* full, we should drop one entry */
+				w_entry =
+					(wifi_ring_buffer_entry
+					 *) (ring->ring_buf + ring->rp);
+				ring->rp = woal_get_ring_next_entry(ring,
+								    ring->rp);
+				ring->ctrl.written_bytes -=
+					ENTRY_LENGTH(w_entry);
+				memset((u8 *)w_entry, 0, ENTRY_LENGTH(w_entry));
+				ring->ctrl.written_records--;
+				continue;
+			}
+		}
+		if (ring->rp < ring->wp) {
+			if (ring->ring_size - ring->wp >= w_len) {
+				break;
+			} else if (ring->ring_size - ring->wp < w_len) {
+				if (ring->rp == 0) {
+					/** drop one entry */
+					w_entry = (wifi_ring_buffer_entry
+						   *) (ring->ring_buf +
+						       ring->rp);
+					ring->rp =
+						woal_get_ring_next_entry(ring,
+									 ring->
+									 rp);
+					ring->ctrl.written_bytes -=
+						ENTRY_LENGTH(w_entry);
+					memset((u8 *)w_entry, 0,
+					       ENTRY_LENGTH(w_entry));
+					ring->ctrl.written_records--;
+				}
+				ring->wp = 0;
+				continue;
+			}
+		}
+		if (ring->rp > ring->wp) {
+			if (ring->rp - ring->wp < w_len) {
+				/** drop one entry */
+				w_entry =
+					(wifi_ring_buffer_entry
+					 *) (ring->ring_buf + ring->rp);
+				ring->rp = woal_get_ring_next_entry(ring,
+								    ring->rp);
+				ring->ctrl.written_bytes -=
+					ENTRY_LENGTH(w_entry);
+				memset((u8 *)w_entry, 0, ENTRY_LENGTH(w_entry));
+				ring->ctrl.written_records--;
+				continue;
+			} else {
+				break;
+			}
+		}
+	} while (1);
+
+	if ((ring->wp + w_len) > ring->ring_size ||
+	    (ring->ctrl.written_bytes + w_len) > ring->ring_size) {
+		PRINTM(MERROR,
+		       "Ring push buffer overflow: rp=%d  wp=%d, write_bytes=%d\n",
+		       ring->rp, ring->wp, ring->ctrl.written_bytes);
+		goto done;
+	}
+
+	w_entry = (wifi_ring_buffer_entry *) (ring->ring_buf + ring->wp);
+	/* header */
+	moal_memcpy_ext(priv->phandle, w_entry, hdr, RING_ENTRY_SIZE,
+			ENTRY_LENGTH(w_entry));
+	/* payload */
+	moal_memcpy_ext(priv->phandle, (char *)w_entry + RING_ENTRY_SIZE, data,
+			w_entry->entry_size, w_entry->entry_size);
+	/* update write pointer */
+	ring->wp += w_len;
+	/* update statistics */
+	ring->ctrl.written_records++;
+	ring->ctrl.written_bytes += w_len;
+	spin_unlock_irqrestore(&ring->lock, flags);
+
+	PRINTM(MDATA,
+	       "Ring push data: wp=%d rp=%d  write_bytes=%d, read_bytes=%d\n",
+	       ring->wp, ring->rp, ring->ctrl.written_bytes,
+	       ring->ctrl.read_bytes);
+
+	/* if the current pending size is bigger than threshold */
+	if (ring->threshold && (READ_AVAIL_SPACE(ring) >= ring->threshold)) {
+		PRINTM(MDATA, "Ring threshold reached\n");
+		if (ring->interval)
+			cancel_delayed_work_sync(&ring->work);
+		schedule_delayed_work(&ring->work, 0);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will init wifi logger ring buffer
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param ring_buff     A pointer to wifi_ring_buffer structure
+ *  @param ringIdx       Ring buffer ID
+ *  @param name          Ring buffer name
+ *  @param ring_sz       Ring buffer size
+ *
+ *  @return        0 - success
+ */
+static int
+woal_init_ring_buffer_internal(moal_private *priv, void **ring,
+			       t_u16 ringIdx, t_u8 *name, t_u32 ring_sz)
+{
+	unsigned long flags;
+	wifi_ring_buffer *ring_buff;
+
+	ENTER();
+
+	*ring = vmalloc(sizeof(wifi_ring_buffer));
+	if (!unlikely(*ring)) {
+		PRINTM(MERROR, "WiFi Logger: ring alloc failed\n");
+		goto done;
+	}
+	memset(*ring, 0, sizeof(wifi_ring_buffer));
+	ring_buff = (wifi_ring_buffer *) * ring;
+
+	ring_buff->ring_buf = vmalloc(ring_sz);
+	if (!unlikely(ring_buff->ring_buf)) {
+		PRINTM(MERROR, "WiFi Logger: ring buffer data alloc failed\n");
+		vfree(ring_buff);
+		*ring = NULL;
+		goto done;
+	}
+	memset(ring_buff->ring_buf, 0, ring_sz);
+	spin_lock_init(&ring_buff->lock);
+	spin_lock_irqsave(&ring_buff->lock, flags);
+	ring_buff->rp = ring_buff->wp = 0;
+	INIT_DELAYED_WORK(&ring_buff->work, woal_ring_poll_worker);
+	moal_memcpy_ext(priv->phandle, ring_buff->name, name, strlen(name),
+			RING_NAME_MAX - 1);
+	ring_buff->name[RING_NAME_MAX - 1] = 0;
+	ring_buff->ring_id = ringIdx;
+	ring_buff->ring_size = ring_sz;
+	ring_buff->state = RING_SUSPEND;
+	ring_buff->threshold = ring_buff->ring_size / 2;
+	ring_buff->priv = priv;
+	spin_unlock_irqrestore(&ring_buff->lock, flags);
+done:
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief init each ring in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      data length
+ */
+static int
+woal_init_ring_buffer(moal_private *priv)
+{
+	ENTER();
+	woal_init_ring_buffer_internal(priv, &priv->rings[VERBOSE_RING_ID],
+				       VERBOSE_RING_ID, VERBOSE_RING_NAME,
+				       DEFAULT_RING_BUFFER_SIZE);
+	woal_init_ring_buffer_internal(priv, &priv->rings[EVENT_RING_ID],
+				       EVENT_RING_ID, EVENT_RING_NAME,
+				       DEFAULT_RING_BUFFER_SIZE);
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief deinit each ring in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      data length
+ */
+static int
+woal_deinit_ring_buffer(moal_private *priv)
+{
+	int i;
+	enum ring_state ring_state = RING_STOP;
+	unsigned long lock_flags = 0;
+	wifi_ring_buffer *ring_buff;
+
+	ENTER();
+
+	for (i = 0; i < RING_ID_MAX; i++) {
+		ring_buff = (wifi_ring_buffer *) priv->rings[i];
+		if (!ring_buff)
+			continue;
+		spin_lock_irqsave(&ring_buff->lock, lock_flags);
+		ring_state = ring_buff->state;
+		if (ring_state == RING_ACTIVE)
+			ring_buff->state = RING_STOP;
+		spin_unlock_irqrestore(&ring_buff->lock, lock_flags);
+		if (ring_state == RING_ACTIVE)
+			cancel_delayed_work_sync(&ring_buff->work);
+		vfree(ring_buff->ring_buf);
+		ring_buff->ring_buf = NULL;
+		vfree(ring_buff);
+		priv->rings[i] = NULL;
+	}
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief add log data to ring buffer
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param ring_id    ring ID
+ * @param hdr        A pointer to wifi_ring_buffer_entry struct
+ * @param data       A pointer to data buffer
+ *
+ * @return      0: success  -1: fail
+ */
+int
+woal_ring_event_logger(moal_private *priv, int ring_id, pmlan_event pmevent)
+{
+	t_u8 event_buf[100] = { 0 };
+	wifi_ring_buffer_driver_connectivity_event *connectivity_event;
+	tlv_log *tlv;
+	t_u8 *pos;
+	wifi_ring_buffer_entry msg_hdr;
+	wifi_ring_buffer *ring;
+
+	ENTER();
+	ring = (wifi_ring_buffer *) priv->rings[ring_id];
+
+	if (!ring || ring->state != RING_ACTIVE) {
+		PRINTM(MINFO, "Ring is not active\n");
+		goto done;
+	}
+
+	switch (pmevent->event_id) {
+	case MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER:
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+			assoc_logger_data *pbss_desc =
+				(assoc_logger_data *) pmevent->event_buf;
+			memset(&msg_hdr, 0, sizeof(msg_hdr));
+			msg_hdr.flags |= RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
+			msg_hdr.type = ENTRY_TYPE_CONNECT_EVENT;
+			connectivity_event =
+				(wifi_ring_buffer_driver_connectivity_event *)
+				event_buf;
+			connectivity_event->event = WIFI_EVENT_ASSOC_COMPLETE;
+			pos = (t_u8 *)connectivity_event->tlvs;
+
+			tlv = (tlv_log *) pos;
+			tlv->tag = WIFI_TAG_VENDOR_SPECIFIC;
+			tlv->length = MLAN_MAC_ADDR_LENGTH / 2;
+			moal_memcpy_ext(priv->phandle, tlv->value,
+					pbss_desc->oui, tlv->length,
+					sizeof(event_buf) -
+					(tlv->value - event_buf));
+			msg_hdr.entry_size += tlv->length + TLV_LOG_HEADER_LEN;
+			pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+
+			tlv = (tlv_log *) pos;
+			tlv->tag = WIFI_TAG_BSSID;
+			tlv->length = sizeof(pbss_desc->bssid);
+			moal_memcpy_ext(priv->phandle, tlv->value,
+					pbss_desc->bssid,
+					sizeof(pbss_desc->bssid),
+					sizeof(event_buf) - (tlv->value -
+							     event_buf));
+			msg_hdr.entry_size += tlv->length + TLV_LOG_HEADER_LEN;
+			pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+
+			tlv = (tlv_log *) pos;
+			tlv->tag = WIFI_TAG_SSID;
+			tlv->length = strlen(pbss_desc->ssid);
+			moal_memcpy_ext(priv->phandle, tlv->value,
+					pbss_desc->ssid, tlv->length,
+					sizeof(event_buf) -
+					(tlv->value - event_buf));
+			msg_hdr.entry_size += tlv->length + TLV_LOG_HEADER_LEN;
+			pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+
+			if (pbss_desc->rssi) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_RSSI;
+				tlv->length = sizeof(pbss_desc->rssi);
+				moal_memcpy_ext(priv->phandle, tlv->value,
+						&pbss_desc->rssi, tlv->length,
+						sizeof(event_buf) -
+						(tlv->value - event_buf));
+				msg_hdr.entry_size +=
+					tlv->length + TLV_LOG_HEADER_LEN;
+				pos = pos + tlv->length + TLV_LOG_HEADER_LEN;
+			}
+			if (pbss_desc->channel) {
+				tlv = (tlv_log *) pos;
+				tlv->tag = WIFI_TAG_CHANNEL;
+				tlv->length = sizeof(pbss_desc->channel);
+				moal_memcpy_ext(priv->phandle, tlv->value,
+						&pbss_desc->channel,
+						sizeof(pbss_desc->channel),
+						sizeof(event_buf) -
+						(tlv->value - event_buf));
+				msg_hdr.entry_size +=
+					tlv->length + TLV_LOG_HEADER_LEN;
+			}
+			msg_hdr.entry_size += sizeof(connectivity_event->event);
+			DBG_HEXDUMP(MCMD_D, "connectivity_event",
+				    (t_u8 *)connectivity_event,
+				    msg_hdr.entry_size);
+			woal_ring_push_data(priv, ring_id, &msg_hdr,
+					    connectivity_event);
+		}
+		break;
+	case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER:
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+			int status_code = *(int *)pmevent->event_buf;
+
+			memset(&msg_hdr, 0, sizeof(msg_hdr));
+			msg_hdr.flags |= RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
+			msg_hdr.type = ENTRY_TYPE_CONNECT_EVENT;
+			connectivity_event =
+				(wifi_ring_buffer_driver_connectivity_event *)
+				event_buf;
+			connectivity_event->event = WIFI_EVENT_ASSOC_COMPLETE;
+			pos = (t_u8 *)connectivity_event->tlvs;
+			tlv = (tlv_log *) pos;
+			tlv->tag = WIFI_TAG_STATUS;
+			tlv->length = sizeof(status_code);
+			moal_memcpy_ext(priv->phandle, tlv->value, &status_code,
+					sizeof(status_code),
+					sizeof(event_buf) -
+					(tlv->value - event_buf));
+			msg_hdr.entry_size += tlv->length + 4;
+			msg_hdr.entry_size += sizeof(connectivity_event->event);
+			woal_ring_push_data(priv, ring_id, &msg_hdr,
+					    connectivity_event);
+		}
+		break;
+	case MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER:
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+			t_u16 reason_code = *(t_u16 *)pmevent->event_buf;
+
+			memset(&msg_hdr, 0, sizeof(msg_hdr));
+			msg_hdr.flags |= RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
+			msg_hdr.type = ENTRY_TYPE_CONNECT_EVENT;
+			connectivity_event =
+				(wifi_ring_buffer_driver_connectivity_event *)
+				event_buf;
+			connectivity_event->event = WIFI_EVENT_ASSOC_COMPLETE;
+			pos = (t_u8 *)connectivity_event->tlvs;
+			tlv = (tlv_log *) pos;
+			tlv->tag = WIFI_TAG_REASON_CODE;
+			tlv->length = sizeof(reason_code);
+			moal_memcpy_ext(priv->phandle, tlv->value, &reason_code,
+					sizeof(reason_code),
+					sizeof(event_buf) -
+					(tlv->value - event_buf));
+			msg_hdr.entry_size += tlv->length + 4;
+			msg_hdr.entry_size += sizeof(connectivity_event->event);
+			woal_ring_push_data(priv, ring_id, &msg_hdr,
+					    connectivity_event);
+		}
+		break;
+	default:
+		break;
+	}
+done:
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv               A pointer to moal_private struct
+ * @param wake_reason        wake_reason
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_wake_reason_vendor_event(moal_private *priv,
+			      mlan_ds_hs_wakeup_reason wake_reason)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "priv is null\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	wiphy = priv->wdev->wiphy;
+
+	event_id = woal_get_event_id(event_wake_reason_report);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d\n", event_id);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+/**allocate skb*/
+#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE
+	skb = cfg80211_vendor_event_alloc(wiphy, priv->wdev,
+					  sizeof(wake_reason.hs_wakeup_reason),
+					  event_id, GFP_ATOMIC);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy,
+					  sizeof(wake_reason.hs_wakeup_reason),
+					  event_id, GFP_ATOMIC);
+#endif
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	PRINTM(MINFO, "wake_reason.hs_wakeup_reason = %d\n",
+	       wake_reason.hs_wakeup_reason);
+	nla_put_u16(skb, ATTR_WAKE_REASON_STAT, wake_reason.hs_wakeup_reason);
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+done:
+	PRINTM(MINFO, "wake reason vendor event ret %d\n", ret);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief log wake reason
+ *
+ * @param priv       A pointer to moal_private struct
+ * @param wake_reason    wake_reason
+ *
+ * @return      0: success  -1: fail
+ */
+int
+woal_wake_reason_logger(moal_private *priv,
+			mlan_ds_hs_wakeup_reason wake_reason)
+{
+	int ret = 0;
+
+	ENTER();
+
+	ret = woal_wake_reason_vendor_event(priv, wake_reason);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to start packet fate monitor
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_start_packet_fate_monitor(struct wiphy *wiphy,
+					       struct wireless_dev *wdev,
+					       const void *data, int data_len)
+{
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	int ret = 0;
+
+	/* TODO: Tune pkt fate monitor for TP, Disabling it for now */
+	// struct net_device *dev = wdev->netdev;
+	// moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* TODO: Tune pkt fate monitor for TP, Disabling it for now */
+	// priv->pkt_fate_monitor_enable = MTRUE;
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send vendor event to kernel
+ *
+ * @param priv               A pointer to moal_private struct
+ * @param pkt_type           tx or rx
+ * @param fate               packet fate
+ * @param payload_type       type of payload
+ * @param drv_ts_usec        driver time in usec
+ * @param fw_ts_usec         firmware time in usec
+ * @param data               frame data
+ * @param len                frame data len
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_packet_fate_vendor_event(moal_private *priv,
+			      packet_fate_packet_type pkt_type,
+			      t_u8 fate, frame_type payload_type,
+			      t_u32 drv_ts_usec, t_u32 fw_ts_usec,
+			      t_u8 *data, t_u32 len)
+{
+	struct wiphy *wiphy = NULL;
+	struct sk_buff *skb = NULL;
+	int event_id = 0;
+	int ret = 0;
+	PACKET_FATE_REPORT fate_report;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "priv is null\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	wiphy = priv->wdev->wiphy;
+
+	event_id = woal_get_event_id(event_packet_fate_monitor);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d\n", event_id);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+/**allocate skb*/
+#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE
+	skb = cfg80211_vendor_event_alloc(wiphy, priv->wdev,
+					  len + sizeof(PACKET_FATE_REPORT),
+					  event_id, GFP_ATOMIC);
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy,
+					  len + sizeof(PACKET_FATE_REPORT),
+					  event_id, GFP_ATOMIC);
+#endif
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	memset(&fate_report, 0, sizeof(PACKET_FATE_REPORT));
+	if (pkt_type == PACKET_TYPE_TX) {
+		fate_report.u.tx_report_i.fate = fate;
+		fate_report.u.tx_report_i.frame_inf.payload_type = payload_type;
+		fate_report.u.tx_report_i.frame_inf.driver_timestamp_usec =
+			drv_ts_usec;
+		fate_report.u.tx_report_i.frame_inf.firmware_timestamp_usec =
+			fw_ts_usec;
+		fate_report.u.tx_report_i.frame_inf.frame_len = len;
+		nla_put(skb, ATTR_PACKET_FATE_TX, sizeof(PACKET_FATE_REPORT),
+			&fate_report);
+	} else {
+		fate_report.u.rx_report_i.fate = fate;
+		fate_report.u.rx_report_i.frame_inf.payload_type = payload_type;
+		fate_report.u.rx_report_i.frame_inf.driver_timestamp_usec =
+			drv_ts_usec;
+		fate_report.u.rx_report_i.frame_inf.firmware_timestamp_usec =
+			fw_ts_usec;
+		fate_report.u.rx_report_i.frame_inf.frame_len = len;
+		nla_put(skb, ATTR_PACKET_FATE_RX, sizeof(PACKET_FATE_REPORT),
+			&fate_report);
+	}
+	DBG_HEXDUMP(MCMD_D, "fate_report", (t_u8 *)&fate_report,
+		    sizeof(PACKET_FATE_REPORT));
+
+	nla_put(skb, ATTR_PACKET_FATE_DATA, len, data);
+	DBG_HEXDUMP(MCMD_D, "packet_fate_data", data, len);
+
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+done:
+	PRINTM(MINFO, "packet fate vendor event ret %d\n", ret);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief log packet fate
+ *
+ * @param priv               A pointer to moal_private struct
+ * @param pkt_type           tx or rx
+ * @param fate               packet fate
+ * @param payload_type       type of payload
+ * @param drv_ts_usec        driver time in usec
+ * @param fw_ts_usec         firmware time in usec
+ * @param data               frame data
+ * @param len                frame data len
+ *
+ * @return      0: success  -1: fail
+ */
+int
+woal_packet_fate_monitor(moal_private *priv,
+			 packet_fate_packet_type pkt_type, t_u8 fate,
+			 frame_type payload_type, t_u32 drv_ts_usec,
+			 t_u32 fw_ts_usec, t_u8 *data, t_u32 len)
+{
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->pkt_fate_monitor_enable)
+		ret = woal_packet_fate_vendor_event(priv, pkt_type, fate,
+						    payload_type, drv_ts_usec,
+						    fw_ts_usec, data, len);
+
+	PRINTM(MINFO, "packet fate monitor ret %d\n", ret);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief init packet_filter in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_init_packet_filter(moal_private *priv)
+{
+	int ret = 0;
+	packet_filter *pkt_filter = NULL;
+
+	ENTER();
+
+	pkt_filter = vmalloc(sizeof(packet_filter));
+	if (!unlikely(pkt_filter)) {
+		PRINTM(MERROR, "WiFi Logger: packet_filter alloc failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	memset(pkt_filter, 0, sizeof(packet_filter));
+
+	spin_lock_init(&pkt_filter->lock);
+	pkt_filter->packet_filter_max_len = PACKET_FILTER_MAX_LEN;
+	pkt_filter->packet_filter_len = 0;
+	pkt_filter->packet_filter_version = APF_VERSION;
+	pkt_filter->state = PACKET_FILTER_STATE_STOP;
+
+	priv->packet_filter = pkt_filter;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief deinit packet_filter in moal_private
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_deinit_packet_filter(moal_private *priv)
+{
+	int ret = 0;
+	packet_filter *pkt_filter = NULL;
+	unsigned long flags;
+
+	ENTER();
+
+	pkt_filter = priv->packet_filter;
+
+	if (!unlikely(pkt_filter))
+		goto done;
+
+	spin_lock_irqsave(&pkt_filter->lock, flags);
+	pkt_filter->state = PACKET_FILTER_STATE_INIT;
+	spin_unlock_irqrestore(&pkt_filter->lock, flags);
+
+	vfree(pkt_filter);
+	priv->packet_filter = NULL;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to set packet filter
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_set_packet_filter(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       const void *data, int len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0, rem, type;
+	const struct nlattr *iter;
+	packet_filter *pkt_filter = NULL;
+	t_u32 packet_filter_len = 0;
+	unsigned long flags;
+
+	ENTER();
+	pkt_filter = priv->packet_filter;
+	if (!unlikely(pkt_filter) ||
+	    pkt_filter->state == PACKET_FILTER_STATE_INIT) {
+		PRINTM(MERROR, "packet_filter not init\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case ATTR_PACKET_FILTER_TOTAL_LENGTH:
+			packet_filter_len = nla_get_u32(iter);
+			if (packet_filter_len >
+			    pkt_filter->packet_filter_max_len) {
+				PRINTM(MERROR,
+				       "packet_filter_len exceed max\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			break;
+		case ATTR_PACKET_FILTER_PROGRAM:
+			spin_lock_irqsave(&pkt_filter->lock, flags);
+			strncpy(pkt_filter->packet_filter_program,
+				nla_data(iter),
+				MIN(packet_filter_len, nla_len(iter)));
+			pkt_filter->packet_filter_len =
+				MIN(packet_filter_len, nla_len(iter));
+			pkt_filter->state = PACKET_FILTER_STATE_START;
+			spin_unlock_irqrestore(&pkt_filter->lock, flags);
+			DBG_HEXDUMP(MDAT_D, "packet_filter_program",
+				    pkt_filter->packet_filter_program,
+				    pkt_filter->packet_filter_len);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to get packet filter capability
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_get_packet_filter_capability(struct wiphy *wiphy,
+						  struct wireless_dev *wdev,
+						  const void *data,
+						  int data_len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	t_u32 reply_len = 0;
+	int ret = 0;
+	packet_filter *pkt_filter;
+
+	ENTER();
+	pkt_filter = priv->packet_filter;
+	if (!unlikely(pkt_filter)) {
+		PRINTM(MERROR, "packet_filter not init\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	reply_len = sizeof(pkt_filter->packet_filter_version) +
+		sizeof(pkt_filter->packet_filter_max_len);
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (nla_put_u32(skb, ATTR_PACKET_FILTER_VERSION,
+			pkt_filter->packet_filter_version) ||
+	    nla_put_u32(skb, ATTR_PACKET_FILTER_MAX_LEN,
+			pkt_filter->packet_filter_max_len)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	if (ret)
+		PRINTM(MERROR, "Vendor command reply failed ret = %d\n", ret);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * Runs a packet filtering program over a packet.
+ *
+ * @param program the program bytecode.
+ * @param program_len the length of {@code apf_program} in bytes.
+ * @param packet the packet bytes, starting from the 802.3 header and not
+ *               including any CRC bytes at the end.
+ * @param packet_len the length of {@code packet} in bytes.
+ * @param filter_age the number of seconds since the filter was programmed.
+ *
+ * @return non-zero if packet should be passed to AP, zero if
+ *         packet should be dropped.
+ */
+int
+process_packet(const t_u8 *program, t_u32 program_len, const t_u8 *packet,
+	       t_u32 packet_len, t_u32 filter_age)
+{
+	/* Program counter */
+	t_u32 pc = 0;
+	/* Memory slot values. */
+	t_u32 mem[MEM_ITEMS] = { };
+	/* Register values. */
+	t_u32 reg[2] = { };
+	/* Number of instructions remaining to execute. This is done to make
+	 * sure there is upper bound on execution time. It should never be hit
+	 * and is only for safety. Initialize to the number of bytes in the
+	 * program which is an
+	 * upper bound on the number of instructions in the program.
+	 */
+	t_u32 instructions_left = program_len;
+
+	t_u8 bytecode;
+	t_u32 opcode;
+	t_u32 reg_num;
+	t_u32 len_field;
+	t_u32 imm_len;
+	t_u32 end_offs;
+	t_u32 val = 0;
+	t_u32 last_pkt_offs;
+	t_u32 imm = 0;
+	int32_t sign_imm = 0;
+	t_u32 offs = 0;
+	t_u32 i;
+	t_u32 load_size;
+
+/* Is offset within program bounds? */
+#define WITHIN_PROGRAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < program_len)
+/* Is offset within packet bounds? */
+#define WITHIN_PACKET_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < packet_len)
+/* Verify an internal condition and accept packet if it fails. */
+#define ASSERT_RETURN(c)						       \
+do {									       \
+	if (!(c))							       \
+		return PASS_PKT;					       \
+} while (0)
+/* If not within program bounds, Accept the packet */
+#define ASSERT_WITHIN_PROGRAM_BOUNDS(p) ASSERT_RETURN(WITHIN_PROGRAM_BOUNDS(p))
+/* If not within packet bounds, Accept the packet */
+#define ASSERT_WITHIN_PKT_BOUNDS(p) ASSERT_RETURN(WITHIN_PACKET_BOUNDS(p))
+/* If not within program or not ahead of program counter, Accept the packet */
+#define ASSERT_FORWARD_WITHIN_PROGRAM(p)                                       \
+	ASSERT_RETURN(WITHIN_PROGRAM_BOUNDS(p) && (p) >= pc)
+
+	/* Fill in pre-filled memory slot values. */
+	mem[MEM_OFFSET_PKT_SIZE] = packet_len;
+	mem[MEM_OFFSET_FILTER_AGE] = filter_age;
+	ASSERT_WITHIN_PKT_BOUNDS(APF_FRAME_HEADER_SIZE);
+
+	/* Only populate if IP version is IPv4. */
+	if ((packet[APF_FRAME_HEADER_SIZE] & 0xf0) == 0x40) {
+		mem[MEM_OFFSET_IPV4_HEADER_SIZE] =
+			(packet[APF_FRAME_HEADER_SIZE] & 15) * 4;
+	}
+
+	do {
+		if (pc == program_len)
+			return PASS_PKT;
+		else if (pc == (program_len + 1))
+			return DROP_PKT;
+		ASSERT_WITHIN_PROGRAM_BOUNDS(pc);
+		bytecode = program[pc++];
+		opcode = GET_OPCODE(bytecode);
+		reg_num = GET_REGISTER(bytecode);
+
+		/* All instructions have immediate fields, so load them now. */
+		len_field = GET_IMM_LENGTH(bytecode);
+		imm = 0;
+		sign_imm = 0;
+
+#define REG (reg[reg_num])
+#define OTHER_REG (reg[reg_num ^ 1])
+
+		if (len_field) {
+			imm_len = 1 << (len_field - 1);
+			ASSERT_FORWARD_WITHIN_PROGRAM(pc + imm_len - 1);
+			for (i = 0; i < imm_len; i++)
+				imm = (imm << 8) | program[pc++];
+			/* Sign extend imm into signed_imm. */
+			sign_imm = imm << ((4 - imm_len) * 8);
+			sign_imm >>= (4 - imm_len) * 8;
+		}
+		switch (opcode) {
+		case NXP_LDB_OPCODE:
+		case NXP_LDH_OPCODE:
+		case NXP_LDW_OPCODE:
+		case NXP_LDBX_OPCODE:
+		case NXP_LDHX_OPCODE:
+		case NXP_LDWX_OPCODE:{
+				offs = imm;
+				if (opcode >= NXP_LDBX_OPCODE) {
+					/* Note: this can overflow and actually decrease
+					 * offs.
+					 */
+					offs += reg[1];
+				}
+				ASSERT_WITHIN_PKT_BOUNDS(offs);
+				switch (opcode) {
+				case NXP_LDB_OPCODE:
+				case NXP_LDBX_OPCODE:
+					load_size = 1;
+					break;
+				case NXP_LDH_OPCODE:
+				case NXP_LDHX_OPCODE:
+					load_size = 2;
+					break;
+				case NXP_LDW_OPCODE:
+				case NXP_LDWX_OPCODE:
+					load_size = 4;
+					break;
+					/* Immediately enclosing switch statement
+					 * guarantees
+					 * opcode cannot be any other value.
+					 */
+				}
+				end_offs = offs + (load_size - 1);
+				/* Catch overflow/wrap-around. */
+				ASSERT_RETURN(end_offs >= offs);
+				ASSERT_WITHIN_PKT_BOUNDS(end_offs);
+				val = 0;
+				while (load_size--)
+					val = (val << 8) | packet[offs++];
+				REG = val;
+				break;
+			}
+		case NXP_JMP_OPCODE:
+			/* This can jump backwards. Infinite looping prevented
+			 * by instructions_remaining.
+			 */
+			pc += imm;
+			break;
+		case NXP_JEQ_OPCODE:
+		case NXP_JNE_OPCODE:
+		case NXP_JGT_OPCODE:
+		case NXP_JLT_OPCODE:
+		case NXP_JSET_OPCODE:
+		case NXP_JNEBS_OPCODE:{
+				/* Load second immediate field. */
+				t_u32 cmp_imm = 0;
+
+				if (reg_num == 1) {
+					cmp_imm = reg[1];
+				} else if (len_field != 0) {
+					t_u32 cmp_imm_len =
+						1 << (len_field - 1);
+
+					ASSERT_FORWARD_WITHIN_PROGRAM(pc +
+								      cmp_imm_len
+								      - 1);
+					for (i = 0; i < cmp_imm_len; i++)
+						cmp_imm =
+							(cmp_imm << 8) |
+							program[pc++];
+				}
+				switch (opcode) {
+				case NXP_JEQ_OPCODE:
+					if (reg[0] == cmp_imm)
+						pc += imm;
+					break;
+				case NXP_JNE_OPCODE:
+					if (reg[0] != cmp_imm)
+						pc += imm;
+					break;
+				case NXP_JGT_OPCODE:
+					if (reg[0] > cmp_imm)
+						pc += imm;
+					break;
+				case NXP_JLT_OPCODE:
+					if (reg[0] < cmp_imm)
+						pc += imm;
+					break;
+				case NXP_JSET_OPCODE:
+					if (reg[0] & cmp_imm)
+						pc += imm;
+					break;
+				case NXP_JNEBS_OPCODE:{
+						/* cmp_imm is size in bytes of data to compare.
+						 * pc is offset of program bytes to compare.
+						 * imm is jump target offset.
+						 * REG is offset of packet bytes to compare.
+						 */
+						ASSERT_FORWARD_WITHIN_PROGRAM(pc
+									      +
+									      cmp_imm
+									      -
+									      1);
+						ASSERT_WITHIN_PKT_BOUNDS(REG);
+						last_pkt_offs =
+							REG + cmp_imm - 1;
+						ASSERT_RETURN(last_pkt_offs >=
+							      REG);
+						ASSERT_WITHIN_PKT_BOUNDS
+							(last_pkt_offs);
+						if (memcmp
+						    (program + pc, packet + REG,
+						     cmp_imm))
+							pc += imm;
+						/* skip past comparison bytes */
+						pc += cmp_imm;
+						break;
+					}
+				}
+				break;
+			}
+		case NXP_ADD_OPCODE:
+			reg[0] += reg_num ? reg[1] : imm;
+			break;
+		case NXP_MUL_OPCODE:
+			reg[0] *= reg_num ? reg[1] : imm;
+			break;
+		case NXP_DIV_OPCODE:{
+				const t_u32 div_operand =
+					reg_num ? reg[1] : imm;
+
+				ASSERT_RETURN(div_operand);
+				reg[0] /= div_operand;
+				break;
+			}
+		case NXP_AND_OPCODE:
+			reg[0] &= reg_num ? reg[1] : imm;
+			break;
+		case NXP_OR_OPCODE:
+			reg[0] |= reg_num ? reg[1] : imm;
+			break;
+		case NXP_SH_OPCODE:{
+				const int32_t shift_val =
+					reg_num ? (int32_t) reg[1] : sign_imm;
+				if (shift_val > 0)
+					reg[0] <<= shift_val;
+				else
+					reg[0] >>= -shift_val;
+				break;
+			}
+		case NXP_LI_OPCODE:
+			REG = sign_imm;
+			break;
+		case NXP_EXT_OPCODE:
+			if (
+/* If LDM_EXT_OPCODE is 0 and imm is compared with it, a compiler error will
+ * result,
+ * instead just enforce that imm is unsigned (so it's always greater or equal to
+ * 0).
+ */
+#if NXP_LDM_EXT_OPCODE == 0
+				   ENFORCE_UNSIGNED(imm) &&
+#else
+				   imm >= NXP_LDM_EXT_OPCODE &&
+#endif
+				   imm < (NXP_LDM_EXT_OPCODE + MEM_ITEMS)) {
+				REG = mem[imm - NXP_LDM_EXT_OPCODE];
+			} else if (imm >= NXP_STM_EXT_OPCODE &&
+				   imm < (NXP_STM_EXT_OPCODE + MEM_ITEMS)) {
+				mem[imm - NXP_STM_EXT_OPCODE] = REG;
+			} else
+				switch (imm) {
+				case NXP_NOT_EXT_OPCODE:
+					REG = ~REG;
+					break;
+				case NXP_NEG_EXT_OPCODE:
+					REG = -REG;
+					break;
+				case NXP_SWAP_EXT_OPCODE:{
+						t_u32 tmp = REG;
+
+						REG = OTHER_REG;
+						OTHER_REG = tmp;
+						break;
+					}
+				case NXP_MOV_EXT_OPCODE:
+					REG = OTHER_REG;
+					break;
+					/* Unknown extended opcode */
+				default:
+					/* Bail out */
+					return PASS_PKT;
+				}
+			break;
+			/* Unknown opcode */
+		default:
+			/* Bail out */
+			return PASS_PKT;
+		}
+	} while (instructions_left--);
+	return PASS_PKT;
+}
+
+/**
+ * @brief filter packet
+ *
+ * @param priv          A pointer to moal_private struct
+ * @param data          packet data
+ * @param len           packet len
+ * @param filter_age    filter age
+ * @return non-zero if packet should be passed to AP, zero if
+ *         packet should be dropped.
+ */
+int
+woal_filter_packet(moal_private *priv, t_u8 *data, t_u32 len, t_u32 filter_age)
+{
+	packet_filter *pkt_filter = NULL;
+	int ret = PASS_PKT;
+	unsigned long flags;
+
+	ENTER();
+	pkt_filter = priv->packet_filter;
+	if (!unlikely(pkt_filter)) {
+		PRINTM(MINFO, "packet_filter not init\n");
+		goto done;
+	}
+
+	if (pkt_filter->state != PACKET_FILTER_STATE_START)
+		goto done;
+
+	DBG_HEXDUMP(MDAT_D, "packet_filter_program",
+		    pkt_filter->packet_filter_program,
+		    pkt_filter->packet_filter_len);
+	DBG_HEXDUMP(MDAT_D, "packet_filter_data", data, len);
+	spin_lock_irqsave(&pkt_filter->lock, flags);
+	ret = process_packet(pkt_filter->packet_filter_program,
+			     pkt_filter->packet_filter_len, data, len,
+			     filter_age);
+	spin_unlock_irqrestore(&pkt_filter->lock, flags);
+
+done:
+	PRINTM(MINFO, "packet filter ret %d\n", ret);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief init wifi hal
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_init_wifi_hal(moal_private *priv)
+{
+	ENTER();
+	woal_init_ring_buffer(priv);
+	priv->pkt_fate_monitor_enable = MFALSE;
+	woal_init_packet_filter(priv);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief deinit wifi hal
+ *
+ * @param priv       A pointer to moal_private struct
+ *
+ * @return      0: success  1: fail
+ */
+int
+woal_deinit_wifi_hal(moal_private *priv)
+{
+	ENTER();
+	woal_deinit_ring_buffer(priv);
+	priv->pkt_fate_monitor_enable = MFALSE;
+	woal_deinit_packet_filter(priv);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief vendor command to get link layer statistic
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_cfg80211_subcmd_link_statistic_get(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	wifi_radio_stat *radio_stat = NULL;
+	wifi_radio_stat *radio_stat_tmp = NULL;
+	wifi_iface_stat *iface_stat = NULL;
+	t_u32 num_radio = 0, iface_stat_len = 0, radio_stat_len = 0;
+	int err = -1, length = 0, i;
+	char *ioctl_link_stats_buf = NULL;
+	t_u64 cur_time = 0;
+	t_u64 inter_msec = 0;
+	t_u64 max_msec = (t_u64)24 * (t_u64)24 * (t_u64)3600 * (t_u64)1000;
+	moal_handle *handle = priv->phandle;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) + BUF_MAXLEN);
+	if (req == NULL) {
+		PRINTM(MERROR, "Could not allocate mlan ioctl request!\n");
+		return -ENOMEM;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_LINK_STATS;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "get link layer statistic fail\n");
+		goto done;
+	}
+
+	ioctl_link_stats_buf = info->param.link_statistic;
+	num_radio = *((t_u32 *)info->param.link_statistic);
+
+	radio_stat = (wifi_radio_stat *) (info->param.link_statistic +
+					  sizeof(num_radio));
+	radio_stat_len = num_radio * sizeof(wifi_radio_stat);
+
+	/* Re-write on_time/tx_time/rx_time/on_time_scan from moal handle */
+	PRINTM(MINFO, "handle->on_time=%llu\n", handle->on_time);
+	if (handle->on_time) {
+		moal_get_boot_ktime(handle, &cur_time);
+		inter_msec = moal_do_div(cur_time - handle->on_time, 1000000);
+		PRINTM(MINFO, "cur_time=%llu inter_msec=%llu max_msec=%llu\n",
+		       cur_time, inter_msec, max_msec);
+		/* When we report the time up, u32 is not big enough(represent
+		 * max 49days) and might out of range, make the max value to
+		 * 24days.
+		 */
+		if (inter_msec > max_msec) {
+			PRINTM(MMSG,
+			       "Out of range, set inter_msec=%llu to max_msec=%llu\n",
+			       inter_msec, max_msec);
+			inter_msec = max_msec;
+		}
+	}
+	PRINTM(MINFO, "handle->tx_time=%llu\n", handle->tx_time);
+	PRINTM(MINFO, "handle->rx_time=%llu\n", handle->rx_time);
+	PRINTM(MINFO, "handle->scan_time=%llu\n", handle->scan_time);
+	radio_stat_tmp = radio_stat;
+	for (i = 0; i < num_radio; i++) {
+		radio_stat_tmp->on_time = (t_u32)inter_msec;
+		radio_stat_tmp->tx_time =
+			(t_u32)moal_do_div(handle->tx_time, 1000);
+		radio_stat_tmp->rx_time =
+			(t_u32)moal_do_div(handle->rx_time, 1000);
+		radio_stat_tmp->on_time_scan =
+			(t_u32)moal_do_div(handle->scan_time, 1000);
+		radio_stat_tmp++;
+	}
+
+	iface_stat = (wifi_iface_stat *) (info->param.link_statistic +
+					  sizeof(num_radio) + radio_stat_len);
+	iface_stat_len = sizeof(wifi_iface_stat);
+
+	/* could get peer info with separate cmd */
+	for (i = 0; i < iface_stat->num_peers; i++) {
+		/* no need copy, just increase iface_stat length */
+		iface_stat_len += sizeof(wifi_peer_info) +
+			sizeof(wifi_rate_stat) *
+			iface_stat->peer_info[i].num_rate;
+	}
+
+	/* Here the length doesn't contain addition 2 attribute header length */
+	length = NLA_HDRLEN * 2 + sizeof(num_radio) + radio_stat_len +
+		iface_stat_len;
+
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed\n");
+		goto done;
+	}
+
+	if (nla_put_u32(skb, ATTR_LL_STATS_NUM_RADIO, num_radio) ||
+	    nla_put(skb, ATTR_LL_STATS_RADIO, radio_stat_len, radio_stat) ||
+	    nla_put(skb, ATTR_LL_STATS_IFACE, iface_stat_len, iface_stat)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		goto done;
+	}
+
+	PRINTM(MDAT_D, "%s: <<< Start DUMP\n", __func__);
+	PRINTM(MDAT_D, "sizeof(wifi_radio_stat)=%zu\n",
+	       sizeof(wifi_radio_stat));
+	DBG_HEXDUMP(MDAT_D, "radio_stat", (t_u8 *)radio_stat, radio_stat_len);
+	PRINTM(MDAT_D, "sizeof(wifi_channel_stat)=%zu\n",
+	       sizeof(wifi_channel_stat));
+	DBG_HEXDUMP(MDAT_D, "iface_stat", (t_u8 *)iface_stat, iface_stat_len);
+	PRINTM(MDAT_D, "num_radio=%d\n", num_radio);
+	radio_stat_tmp = radio_stat;
+	for (i = 0; i < num_radio; i++) {
+		PRINTM(MDAT_D, "--radio_stat[%d]--\n", i);
+		PRINTM(MDAT_D, "radio=%d\n", radio_stat_tmp->radio);
+		PRINTM(MDAT_D, "on_time=%d\n", radio_stat_tmp->on_time);
+		PRINTM(MDAT_D, "tx_time=%d\n", radio_stat_tmp->tx_time);
+		PRINTM(MDAT_D, "reserved0=%d\n", radio_stat_tmp->reserved0);
+		PRINTM(MDAT_D, "rx_time=%d\n", radio_stat_tmp->rx_time);
+		PRINTM(MDAT_D, "on_time_scan=%d\n",
+		       radio_stat_tmp->on_time_scan);
+		PRINTM(MDAT_D, "on_time_nbd=%d\n", radio_stat_tmp->on_time_nbd);
+		PRINTM(MDAT_D, "on_time_gscan=%d\n",
+		       radio_stat_tmp->on_time_gscan);
+		PRINTM(MDAT_D, "on_time_roam_scan=%d\n",
+		       radio_stat_tmp->on_time_roam_scan);
+		PRINTM(MDAT_D, "on_time_pno_scan=%d\n",
+		       radio_stat_tmp->on_time_pno_scan);
+		PRINTM(MDAT_D, "on_time_hs20=%d\n",
+		       radio_stat_tmp->on_time_hs20);
+		PRINTM(MDAT_D, "num_channels=%d\n",
+		       radio_stat_tmp->num_channels);
+		radio_stat_tmp++;
+	}
+	PRINTM(MDAT_D, "%s: >>> End DUMP\n", __func__);
+
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err))
+		PRINTM(MERROR, "Vendor Command reply failed ret:%d\n", err);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	return err;
+}
+
+/**
+ * @brief API to trigger the link layer statistics collection.
+ *   Unless his API is invoked - link layer statistics will not be collected.
+ *   Radio statistics (once started) do not stop or get reset unless
+ *   wifi_clear_link_stats is invoked, Interface statistics (once started)
+ *   reset and start afresh after each connection.
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_cfg80211_subcmd_link_statistic_set(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(wdev->netdev);
+	struct nlattr *tb[ATTR_LL_STATS_MAX + 1];
+	wifi_link_layer_params ll_params;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int err = 0;
+
+	err = nla_parse(tb, ATTR_LL_STATS_MAX, data, len, NULL
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+			, NULL
+#endif
+		);
+	if (err)
+		return err;
+
+	if (!tb[ATTR_LL_STATS_MPDU_SIZE_THRESHOLD] ||
+	    !tb[ATTR_LL_STATS_AGGRESSIVE_STATS_GATHERING])
+		return -EINVAL;
+
+	ll_params.mpdu_size_threshold =
+		nla_get_u32(tb[ATTR_LL_STATS_MPDU_SIZE_THRESHOLD]);
+	ll_params.aggressive_statistics_gathering =
+		nla_get_u32(tb[ATTR_LL_STATS_AGGRESSIVE_STATS_GATHERING]);
+
+	PRINTM(MEVENT,
+	       "link layer params mpdu_size_threshold = 0x%x, aggressive_statistics_gathering = 0x%x\n",
+	       ll_params.mpdu_size_threshold,
+	       ll_params.aggressive_statistics_gathering);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
+					sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		PRINTM(MERROR, "Could not allocate mlan ioctl request!\n");
+		return -ENOMEM;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_LINK_STATS;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_SET;
+
+	/* Configure parameter to firmware */
+	moal_memcpy_ext(priv->phandle, info->param.link_statistic, &ll_params,
+			sizeof(ll_params),
+			sizeof(mlan_ds_get_info) - sizeof(t_u32));
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS)
+		PRINTM(MMSG, "enable link layer statistic successfully\n");
+
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	return 0;
+}
+
+/**
+ * @brief clear function should download command to fimrware,
+ *	  so that firmware could cleanup per peer statistic number
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_cfg80211_subcmd_link_statistic_clr(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(wdev->netdev);
+	struct nlattr *tb[ATTR_LL_STATS_MAX + 1];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	u32 stats_clear_req_mask = 0x0, stats_clear_rsp_mask = 0x0;
+	u8 stop_req = 0x0, stop_rsp = 0x0;
+	struct sk_buff *skb = NULL;
+	int err = 0, length = 0;
+
+	err = nla_parse(tb, ATTR_LL_STATS_MAX, data, len, NULL
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+			, NULL
+#endif
+		);
+	if (err)
+		return err;
+
+	if (!tb[ATTR_LL_STATS_CLEAR_REQ_MASK])
+		return -EINVAL;
+	else
+		stats_clear_req_mask =
+			nla_get_u32(tb[ATTR_LL_STATS_CLEAR_REQ_MASK]);
+
+	if (!tb[ATTR_LL_STATS_STOP_REQ])
+		return -EINVAL;
+	else
+		stop_req = nla_get_u8(tb[ATTR_LL_STATS_STOP_REQ]);
+
+	PRINTM(MEVENT,
+	       "link layer clear stats_clear_req_mask = 0x%x, stop_req = 0x%x\n",
+	       stats_clear_req_mask, stop_req);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
+					sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		PRINTM(MERROR, "Could not allocate mlan ioctl request!\n");
+		return -ENOMEM;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_LINK_STATS;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_CLEAR;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS)
+		PRINTM(MMSG, "disable link layer statistic successfully\n");
+
+	length = NLA_HDRLEN + sizeof(stats_clear_rsp_mask) + sizeof(stop_rsp);
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed\n");
+		err = -EINVAL;
+		goto exit;
+	}
+
+	/*  clear api to reset statistics, stats_clear_rsp_mask identifies what
+	 * stats have been cleared stop_req = 1 will imply whether to stop the
+	 * statistics collection. stop_rsp = 1 will imply that stop_req was
+	 * honored and statistics collection was stopped.
+	 */
+	stats_clear_rsp_mask = WIFI_STATS_RADIO | WIFI_STATS_IFACE;
+	stop_rsp = 1;
+	if (nla_put_u32(skb, ATTR_LL_STATS_CLEAR_RSP_MASK,
+			stats_clear_rsp_mask) ||
+	    nla_put_u8(skb, ATTR_LL_STATS_STOP_RSP, stop_rsp)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree_skb(skb);
+		err = -EINVAL;
+		goto exit;
+	}
+
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err)) {
+		PRINTM(MERROR, "Vendor Command reply failed ret:%d\n", err);
+		goto exit;
+		;
+	}
+
+exit:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	return err;
+}
+
+#ifdef STA_CFG80211
+#define RSSI_MONOTOR_START 1
+#define RSSI_MONOTOR_STOP 0
+
+/**
+ * @brief vendor command to control rssi monitor
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int
+woal_cfg80211_subcmd_rssi_monitor(struct wiphy *wiphy,
+				  struct wireless_dev *wdev,
+				  const void *data, int len)
+{
+	struct nlattr *tb[ATTR_RSSI_MONITOR_MAX + 1];
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(wdev->netdev);
+	u32 rssi_monitor_control = 0x0;
+	s8 rssi_min = 0, rssi_max = 0;
+	int err = 0;
+	t_u8 *pos = NULL;
+	struct sk_buff *skb = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv->media_connected) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = nla_parse(tb, ATTR_RSSI_MONITOR_MAX, data, len, NULL
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+			, NULL
+#endif
+		);
+	if (ret)
+		goto done;
+
+	if (!tb[ATTR_RSSI_MONITOR_CONTROL]) {
+		ret = -EINVAL;
+		goto done;
+	}
+	rssi_monitor_control = nla_get_u32(tb[ATTR_RSSI_MONITOR_CONTROL]);
+
+	if (rssi_monitor_control == RSSI_MONOTOR_START) {
+		if ((!tb[ATTR_RSSI_MONITOR_MIN_RSSI]) ||
+		    (!tb[ATTR_RSSI_MONITOR_MAX_RSSI])) {
+			ret = -EINVAL;
+			goto done;
+		}
+
+		rssi_min = nla_get_s8(tb[ATTR_RSSI_MONITOR_MIN_RSSI]);
+		rssi_max = nla_get_s8(tb[ATTR_RSSI_MONITOR_MAX_RSSI]);
+
+		PRINTM(MEVENT,
+		       "start rssi monitor rssi_min = %d, rssi_max= %d\n",
+		       rssi_min, rssi_max);
+
+		/* set rssi low/high threshold */
+		priv->cqm_rssi_high_thold = rssi_max;
+		priv->cqm_rssi_thold = rssi_min;
+		priv->cqm_rssi_hyst = 4;
+		woal_set_rssi_threshold(priv, 0, MOAL_IOCTL_WAIT);
+	} else if (rssi_monitor_control == RSSI_MONOTOR_STOP) {
+		/* stop rssi monitor */
+		PRINTM(MEVENT, "stop rssi monitor\n");
+		/* set both rssi_thold/hyst to 0, will trigger subscribe event
+		 * clear
+		 */
+		priv->cqm_rssi_high_thold = 0;
+		priv->cqm_rssi_thold = 0;
+		priv->cqm_rssi_hyst = 0;
+		woal_set_rssi_threshold(priv, 0, MOAL_IOCTL_WAIT);
+	} else {
+		PRINTM(MERROR, "invalid rssi_monitor control request\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Alloc the SKB for cmd reply */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	pos = skb_put(skb, len);
+	moal_memcpy_ext(priv->phandle, pos, data, len, len);
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err)) {
+		PRINTM(MERROR, "Vendor Command reply failed ret:%d\n", err);
+		ret = err;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send rssi event to kernel
+ *
+ * @param priv       A pointer to moal_private
+ * @param rssi       current rssi value
+ *
+ * @return      N/A
+ */
+void
+woal_cfg80211_rssi_monitor_event(moal_private *priv, t_s16 rssi)
+{
+	struct sk_buff *skb = NULL;
+	t_s8 rssi_value = 0;
+
+	ENTER();
+
+	skb = dev_alloc_skb(NLA_HDRLEN * 2 + ETH_ALEN + sizeof(t_s8));
+	if (!skb)
+		goto done;
+	/* convert t_s16 to t_s8 */
+	rssi_value = -abs(rssi);
+	if (nla_put(skb, ATTR_RSSI_MONITOR_CUR_BSSID, ETH_ALEN,
+		    priv->conn_bssid) ||
+	    nla_put_s8(skb, ATTR_RSSI_MONITOR_CUR_RSSI, rssi_value)) {
+		PRINTM(MERROR, "nla_put failed!\n");
+		kfree(skb);
+		goto done;
+	}
+	woal_cfg80211_vendor_event(priv, event_rssi_monitor, (t_u8 *)skb->data,
+				   skb->len);
+	kfree(skb);
+done:
+	LEAVE();
+}
+#endif
+
+/**
+ * @brief vendor command to get fw roaming capability
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  fail otherwise
+ */
+static int
+woal_cfg80211_subcmd_get_roaming_capability(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data, int len)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	wifi_roaming_capabilities capa;
+	struct sk_buff *skb = NULL;
+	int err = 0;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	capa.max_blacklist_size = MAX_AP_LIST;
+	capa.max_whitelist_size = MAX_SSID_NUM;
+
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+						  sizeof
+						  (wifi_roaming_capabilities) +
+						  50);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed\n");
+		goto done;
+	}
+
+	/* Push the data to the skb */
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CAPA,
+		sizeof(wifi_roaming_capabilities), (t_u8 *)&capa);
+
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err))
+		PRINTM(MERROR, "Vendor Command reply failed ret:%d\n", err);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to enable/disable fw roaming
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  fail otherwise
+ */
+static int
+woal_cfg80211_subcmd_fw_roaming_enable(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       const void *data, int len)
+{
+	moal_private *priv;
+	struct net_device *dev;
+	int ret = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	const struct nlattr *iter;
+	int type, rem, err;
+	t_u32 fw_roaming_enable = 0;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (!priv || !priv->phandle) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONTROL:
+			fw_roaming_enable = nla_get_u32(iter);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	PRINTM(MMSG, "FW roaming set enable=%d from wifi hal.\n",
+	       fw_roaming_enable);
+#if defined(STA_CFG80211)
+	if (fw_roaming_enable)
+		priv->roaming_enabled = MTRUE;
+	else
+		priv->roaming_enabled = MFALSE;
+#endif
+	/* Alloc the SKB for vendor_event */
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(t_u32) + 50);
+	if (unlikely(!skb)) {
+		PRINTM(MERROR, "skb alloc failed\n");
+		goto done;
+	}
+
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONTROL, sizeof(t_u32),
+		&fw_roaming_enable);
+	err = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(err))
+		PRINTM(MERROR, "Vendor Command reply failed ret:%d\n", err);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to config blacklist and whitelist for fw roaming
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  fail otherwise
+ */
+static int
+woal_cfg80211_subcmd_fw_roaming_config(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       const void *data, int len)
+{
+	moal_private *priv;
+	struct net_device *dev;
+	int ret = MLAN_STATUS_SUCCESS;
+	const struct nlattr *iter;
+	int type, rem;
+	wifi_bssid_params blacklist;
+	wifi_ssid_params whitelist;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (!priv || !priv->phandle) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	memset((char *)&blacklist, 0, sizeof(wifi_bssid_params));
+	memset((char *)&whitelist, 0, sizeof(wifi_ssid_params));
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_BSSID:
+			moal_memcpy_ext(priv->phandle, (t_u8 *)&blacklist,
+					nla_data(iter), nla_len(iter),
+					sizeof(wifi_bssid_params));
+			break;
+		case MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_SSID:
+			moal_memcpy_ext(priv->phandle, (t_u8 *)&whitelist,
+					nla_data(iter), nla_len(iter),
+					sizeof(wifi_ssid_params));
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to enable/disable 11k
+ *
+ * @param wiphy         A pointer to wiphy struct
+ * @param wdev          A pointer to wireless_dev struct
+ * @param data           a pointer to data
+ * @param data_len     data length
+ *
+ * @return      0: success  <0: fail
+ */
+static int
+woal_cfg80211_subcmd_11k_cfg(struct wiphy *wiphy,
+			     struct wireless_dev *wdev,
+			     const void *data, int data_len)
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	struct nlattr *tb_vendor[ATTR_ND_OFFLOAD_MAX + 1];
+	int ret = 0;
+	int status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	nla_parse(tb_vendor, ATTR_ND_OFFLOAD_MAX, (struct nlattr *)data,
+		  data_len, NULL
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+		  , NULL
+#endif
+		);
+	if (!tb_vendor[ATTR_ND_OFFLOAD_CONTROL]) {
+		PRINTM(MINFO, "%s: ATTR_ND_OFFLOAD not found\n", __func__);
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to set scan mac oui
+ *
+ * @param wiphy         A pointer to wiphy struct
+ * @param wdev          A pointer to wireless_dev struct
+ * @param data           a pointer to data
+ * @param data_len     data length
+ *
+ * @return      0: success  <0: fail
+ */
+static int
+woal_cfg80211_subcmd_set_scan_mac_oui(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      const void *data, int data_len)
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = NULL;
+	struct nlattr *tb_vendor[ATTR_WIFI_MAX + 1];
+	t_u8 mac_oui[3];
+	int ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	nla_parse(tb_vendor, ATTR_WIFI_MAX, (struct nlattr *)data, data_len,
+		  NULL
+#if KERNEL_VERSION(4, 12, 0) <= CFG80211_VERSION_CODE
+		  , NULL
+#endif
+		);
+	if (!tb_vendor[ATTR_SCAN_MAC_OUI_SET]) {
+		PRINTM(MINFO, "%s: ATTR_SCAN_MAC_OUI_SET not found\n",
+		       __func__);
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, mac_oui,
+			nla_data(tb_vendor[ATTR_SCAN_MAC_OUI_SET]), 3, 3);
+	moal_memcpy_ext(priv->phandle, priv->random_mac, priv->current_addr,
+			ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
+	moal_memcpy_ext(priv->phandle, priv->random_mac, mac_oui, 3,
+			MLAN_MAC_ADDR_LENGTH);
+	PRINTM(MCMND, "random_mac is " FULL_MACSTR "\n",
+	       FULL_MAC2STR(priv->random_mac));
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to start keep alive
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  fail otherwise
+ */
+static int
+woal_cfg80211_subcmd_start_keep_alive(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      const void *data, int len)
+{
+	moal_private *priv;
+	struct net_device *dev;
+	int ret = MLAN_STATUS_SUCCESS;
+	int type, rem;
+	t_u8 mkeep_alive_id = 0;
+	t_u16 ether_type = 0;
+	t_u8 *ip_pkt = NULL;
+	t_u16 ip_pkt_len = 0;
+	t_u8 src_mac[ETH_ALEN];
+	t_u8 dst_mac[ETH_ALEN];
+	t_u32 period_msec = 0;
+	t_u32 retry_interval = 0;
+	t_u8 retry_cnt = 0;
+	const struct nlattr *iter;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case MKEEP_ALIVE_ATTRIBUTE_ID:
+			mkeep_alive_id = nla_get_u8(iter);
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE:
+			ether_type = nla_get_u16(iter);
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN:
+			ip_pkt_len = nla_get_u16(iter);
+			if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) {
+				ret = -EINVAL;
+				goto exit;
+			}
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_IP_PKT:
+			if (ip_pkt_len) {
+				ip_pkt = (u8 *)kzalloc(ip_pkt_len, GFP_ATOMIC);
+				if (ip_pkt == NULL) {
+					ret = -ENOMEM;
+					PRINTM(MERROR,
+					       "Failed to allocate mem for ip packet\n");
+					goto exit;
+				}
+				moal_memcpy_ext(priv->phandle, ip_pkt,
+						(u8 *)nla_data(iter),
+						nla_len(iter), ip_pkt_len);
+			}
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR:
+			moal_memcpy_ext(priv->phandle, src_mac, nla_data(iter),
+					nla_len(iter), ETH_ALEN);
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR:
+			moal_memcpy_ext(priv->phandle, dst_mac, nla_data(iter),
+					nla_len(iter), ETH_ALEN);
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC:
+			period_msec = nla_get_u32(iter);
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_RETRY_INTERVAL:
+			retry_interval = nla_get_u32(iter);
+			break;
+		case MKEEP_ALIVE_ATTRIBUTE_RETRY_CNT:
+			retry_cnt = nla_get_u8(iter);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			goto exit;
+		}
+	}
+
+	ret = woal_priv_save_cloud_keep_alive_params(priv, mkeep_alive_id, true,
+						     ether_type, ip_pkt,
+						     ip_pkt_len, src_mac,
+						     dst_mac, period_msec,
+						     retry_interval, retry_cnt);
+	if (ret < 0)
+		PRINTM(MERROR, "start_mkeep_alive is failed ret: %d\n", ret);
+
+exit:
+	if (ip_pkt)
+		kfree(ip_pkt);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to stop keep alive
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  fail otherwise
+ */
+static int
+woal_cfg80211_subcmd_stop_keep_alive(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int len)
+{
+	moal_private *priv;
+	struct net_device *dev;
+	int ret = MLAN_STATUS_SUCCESS;
+	int type, rem;
+	t_u8 mkeep_alive_id = 0;
+	const struct nlattr *iter;
+
+	ENTER();
+
+	if (!wdev || !wdev->netdev) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	dev = wdev->netdev;
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	nla_for_each_attr(iter, data, len, rem) {
+		type = nla_type(iter);
+		switch (type) {
+		case MKEEP_ALIVE_ATTRIBUTE_ID:
+			mkeep_alive_id = nla_get_u8(iter);
+			break;
+		default:
+			PRINTM(MERROR, "Unknown type: %d\n", type);
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	ret = woal_stop_mkeep_alive(priv, mkeep_alive_id, 0, NULL, NULL);
+	if (ret < 0)
+		PRINTM(MERROR, "stop_mkeep_alive is failed ret: %d\n", ret);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Upload last keep alive packet to Host through vendor
+ event
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param mkeep_alive   Pointer to mlan_ds_misc_keep_alive structure
+
+ * @return      0: success  fail otherwise
+ */
+int
+woal_mkeep_alive_vendor_event(moal_private *priv,
+			      mlan_ds_misc_keep_alive * mkeep_alive)
+{
+	struct wiphy *wiphy = priv->wdev->wiphy;
+	struct sk_buff *skb = NULL;
+	int ret = MLAN_STATUS_SUCCESS;
+	int event_id = 0;
+	t_u16 len = 0;
+
+	ENTER();
+
+	event_id = woal_get_event_id(event_cloud_keep_alive);
+	if (event_max == event_id) {
+		PRINTM(MERROR, "Not find this event %d\n", event_id);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (!mkeep_alive) {
+		PRINTM(MERROR, "Parameter is NULL\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	len = mkeep_alive->pkt_len;
+
+	/**allocate skb*/
+#if KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE
+	skb = cfg80211_vendor_event_alloc(wiphy, priv->wdev, len + 50,
+#else
+	skb = cfg80211_vendor_event_alloc(wiphy, len + 50,
+#endif
+					  event_id, GFP_ATOMIC);
+
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor event\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	nla_put(skb, MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, sizeof(t_u16), &len);
+	nla_put(skb, MKEEP_ALIVE_ATTRIBUTE_IP_PKT, len, mkeep_alive->packet);
+
+	/**send event*/
+	cfg80211_vendor_event(skb, GFP_ATOMIC);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief vendor command to set enable/disable dfs offload
+ *
+ * @param wiphy       A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  1: fail
+ */
+static int
+woal_cfg80211_subcmd_set_dfs_offload(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     const void *data, int data_len)
+{
+	struct sk_buff *skb = NULL;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	int dfs_offload;
+	int ret = 1;
+
+	ENTER();
+	dfs_offload = moal_extflg_isset(handle, EXT_DFS_OFFLOAD);
+
+	/** Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(dfs_offload));
+	if (!skb) {
+		PRINTM(MERROR, "allocate memory fail for vendor cmd\n");
+		ret = 1;
+		LEAVE();
+		return ret;
+	}
+	nla_put(skb, MRVL_WLAN_VENDOR_ATTR_DFS, sizeof(t_u32), &dfs_offload);
+	ret = cfg80211_vendor_cmd_reply(skb);
+
+	LEAVE();
+	return ret;
+}
+
+// clang-format off
+static const struct wiphy_vendor_command vendor_commands[] = {
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_set_drvdbg,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_set_drvdbg,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_valid_channels,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_valid_channels,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_attr_policy,
+	 .maxattr = ATTR_WIFI_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_set_scan_mac_oui,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_set_scan_mac_oui,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_attr_policy,
+	 .maxattr = ATTR_WIFI_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_link_statistic_set,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_link_statistic_set,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_ll_stat_policy,
+	 .maxattr = ATTR_LL_STATS_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_link_statistic_get,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_link_statistic_get,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_link_statistic_clr,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_link_statistic_clr,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_ll_stat_policy,
+	 .maxattr = ATTR_LL_STATS_MAX,
+#endif
+	 },
+#ifdef STA_CFG80211
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_rssi_monitor,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_rssi_monitor,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_rssi_monitor_policy,
+	 .maxattr = ATTR_RSSI_MONITOR_MAX,
+#endif
+	 },
+#endif
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_roaming_capability,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_roaming_capability,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_fw_roaming_enable,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_fw_roaming_enable,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_fw_roaming_policy,
+	 .maxattr = MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_fw_roaming_config,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_fw_roaming_config,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_fw_roaming_policy,
+	 .maxattr = MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_start_keep_alive,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_start_keep_alive,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_keep_alive_policy,
+	 .maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_stop_keep_alive,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_stop_keep_alive,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_dfs_capability,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_set_dfs_offload,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_nd_offload},
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_11k_cfg,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_nd_offload_policy,
+	 .maxattr = ATTR_ND_OFFLOAD_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_drv_version,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_drv_version,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_fw_version,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_fw_version,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_wifi_supp_feature_set,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_supp_feature_set,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_set_country_code,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_set_country_code,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_wifi_logger_supp_feature_set,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	 .doit = woal_cfg80211_subcmd_get_wifi_logger_supp_feature_set,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_logger_policy,
+	 .maxattr = ATTR_WIFI_LOGGER_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_ring_buff_status,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_get_ring_buff_status,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_logger_policy,
+	 .maxattr = ATTR_WIFI_LOGGER_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_start_logging,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_start_logging,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_logger_policy,
+	 .maxattr = ATTR_WIFI_LOGGER_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_ring_buff_data,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_get_ring_data,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_logger_policy,
+	 .maxattr = ATTR_WIFI_LOGGER_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_start_packet_fate_monitor,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_start_packet_fate_monitor,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_fw_mem_dump,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_get_fw_dump,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_drv_mem_dump,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_get_drv_dump,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_set_packet_filter,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_set_packet_filter,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = woal_packet_filter_policy,
+	 .maxattr = ATTR_PACKET_FILTER_MAX,
+#endif
+	 },
+	{
+	 .info = {
+		  .vendor_id = MRVL_VENDOR_ID,
+		  .subcmd = sub_cmd_get_packet_filter_capability,
+		  },
+	 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+	 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
+	 .doit = woal_cfg80211_subcmd_get_packet_filter_capability,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	 .policy = VENDOR_CMD_RAW_DATA,
+#endif
+	 },
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+	{
+	.info = {
+		.vendor_id = MRVL_VENDOR_ID,
+		.subcmd = sub_cmd_set_latency_mode,
+	},
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+	.doit = woal_cfg80211_subcmd_set_wifi_latency_mode,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+	.policy = woal_attr_policy,
+	.maxattr = ATTR_WIFI_MAX,
+#endif
+	},
+#endif
+};
+
+// clang-format on
+
+/**
+ * @brief register vendor commands and events
+ *
+ * @param wiphy       A pointer to wiphy struct
+ *
+ * @return
+ */
+void
+woal_register_cfg80211_vendor_command(struct wiphy *wiphy)
+{
+	ENTER();
+	wiphy->vendor_commands = vendor_commands;
+	wiphy->n_vendor_commands = ARRAY_SIZE(vendor_commands);
+	wiphy->vendor_events = vendor_events;
+	wiphy->n_vendor_events = ARRAY_SIZE(vendor_events);
+	LEAVE();
+}
+#endif
diff --git a/wlan_sd8987/mlinux/moal_cfg80211_util.h b/wlan_sd8987/mlinux/moal_cfg80211_util.h
new file mode 100755
index 0000000..f681482
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_cfg80211_util.h
@@ -0,0 +1,789 @@
+/** @file moal_cfg80211_util.h
+ *
+ * @brief This file contains the CFG80211 vendor specific defines.
+ *
+ *
+ * Copyright 2015-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#ifndef _MOAL_CFGVENDOR_H_
+#define _MOAL_CFGVENDOR_H_
+
+#include "moal_main.h"
+
+#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
+#define RING_NAME_MAX 32
+typedef int wifi_ring_buffer_id;
+
+#define VALID_RING(id) (id >= 0 && id < RING_ID_MAX)
+
+/** WiFi ring control structure */
+typedef struct _wifi_ring_ctrl {
+	/** Written bytes */
+	t_u32 written_bytes;
+	/** Read Bytes */
+	t_u32 read_bytes;
+	/** Written records */
+	t_u32 written_records;
+} ring_buffer_ctrl;
+
+enum ring_state {
+	/** ring is not initialized*/
+	RING_STOP = 0,
+	/** ring is live and logging*/
+	RING_ACTIVE,
+	/** ring is initialized but not logging*/
+	RING_SUSPEND,
+};
+
+/** WiFi ring buffer sttructure */
+typedef struct _wifi_ring_buffer {
+	/** Ring ID */
+	wifi_ring_buffer_id ring_id;
+	/** Ring name */
+	t_u8 name[RING_NAME_MAX];
+	/** Ring size */
+	t_u32 ring_size;
+	/** Write pointer */
+	t_u32 wp;
+	/** Read pointer */
+	t_u32 rp;
+	/** Log level */
+	t_u32 log_level;
+	/** Threshold */
+	t_u32 threshold;
+	/** Ring buffer */
+	void *ring_buf;
+	/** Lock */
+	spinlock_t lock;
+	/** Buffer control */
+	ring_buffer_ctrl ctrl;
+	/** Ring state */
+	enum ring_state state;
+	/** Delayed work */
+	struct delayed_work work;
+	/** Interval */
+	unsigned long interval;
+	/** Moal priv */
+	moal_private *priv;
+} wifi_ring_buffer;
+
+#define VERBOSE_RING_NAME "verbose"
+#define EVENT_RING_NAME "event"
+
+#define DEFAULT_RING_BUFFER_SIZE 1024
+
+#define TLV_LOG_HEADER_LEN 4
+
+#define WIFI_LOGGER_MEMORY_DUMP_SUPPORTED MBIT(0)	/* Memory dump of Fw */
+#define WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORT MBIT(1)	/*PKT status */
+#define WIFI_LOGGER_CONNECT_EVENT_SUPPORTED MBIT(2)	/* connectivity event */
+#define WIFI_LOGGER_POWER_EVENT_SUPPORTED MBIT(3)	/* Power of driver */
+#define WIFI_LOGGER_WAKE_LOCK_SUPPORTED MBIT(4)	/* Wake lock of driver */
+#define WIFI_LOGGER_VERBOSE_SUPPORTED MBIT(5)	/*verbose log of Fw */
+#define WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED                                   \
+	MBIT(6)			/*monitor the health of Fw */
+
+/**
+ * Parameters of wifi logger events are TLVs
+ * Event parameters tags are defined as:
+ */
+#define WIFI_TAG_VENDOR_SPECIFIC 0	// take a byte stream as parameter
+#define WIFI_TAG_BSSID 1	// takes a 6 bytes MAC address as parameter
+#define WIFI_TAG_ADDR 2		// takes a 6 bytes MAC address as parameter
+#define WIFI_TAG_SSID 3		// takes a 32 bytes SSID address as parameter
+#define WIFI_TAG_STATUS 4	// takes an integer as parameter
+#define WIFI_TAG_REASON_CODE 14	// take a reason code as per 802.11 as parameter
+#define WIFI_TAG_RSSI 21	// take an integer as parameter
+#define WIFI_TAG_CHANNEL 22	// take an integer as parameter
+
+#define RING_ENTRY_SIZE (sizeof(wifi_ring_buffer_entry))
+#define ENTRY_LENGTH(hdr) (hdr->entry_size + RING_ENTRY_SIZE)
+#define READ_AVAIL_SPACE(ring)                                                 \
+	(ring->ctrl.written_bytes - ring->ctrl.read_bytes)
+
+enum logger_attributes {
+	ATTR_WIFI_LOGGER_INVALID = 0,
+	ATTR_WIFI_LOGGER_RING_ID,
+	ATTR_WIFI_LOGGER_FLAGS,
+	ATTR_WIFI_LOGGER_VERBOSE_LEVEL,
+	ATTR_WIFI_LOGGER_MIN_DATA_SIZE,
+	ATTR_RING_BUFFER_STATUS,
+	ATTR_NUM_RINGS,
+	ATTR_WIFI_LOGGER_FEATURE_SET,
+	ATTR_WIFI_LOGGER_MAX_INTERVAL_SEC,
+	ATTR_RING_BUFFER,
+	ATTR_NAME,
+	ATTR_MEM_DUMP,
+	ATTR_ERR_CODE,
+	ATTR_RING_DATA,
+	ATTR_WAKE_REASON_STAT,
+	ATTR_PACKET_FATE_TX,
+	ATTR_PACKET_FATE_RX,
+	ATTR_PACKET_FATE_DATA,
+	ATTR_FW_DUMP_PATH = 20,
+	ATTR_DRV_DUMP_PATH = 21,
+	ATTR_WIFI_LOGGER_AFTER_LAST,
+	ATTR_WIFI_LOGGER_MAX = ATTR_WIFI_LOGGER_AFTER_LAST - 1
+};
+
+/* Below events refer to the wifi_connectivity_event ring and shall be supported
+ */
+enum {
+	WIFI_EVENT_ASSOCIATION_REQUESTED = 0,
+	WIFI_EVENT_AUTH_COMPLETE,
+	WIFI_EVENT_ASSOC_COMPLETE,
+};
+
+enum {
+	/* set for binary entries */
+	RING_BUFFER_ENTRY_FLAGS_HAS_BINARY = (1 << (0)),
+	/* set if 64 bits timestamp is present */
+	RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1))
+};
+
+enum {
+	ENTRY_TYPE_CONNECT_EVENT = 1,
+	ENTRY_TYPE_PKT,
+	ENTRY_TYPE_WAKE_LOCK,
+	ENTRY_TYPE_POWER_EVENT,
+	ENTRY_TYPE_DATA
+};
+
+/** WiFi ring buffer entry structure */
+typedef struct {
+	/** size of payload excluding the header */
+	t_u16 entry_size;
+	/** Flags */
+	t_u8 flags;
+	/** entry type */
+	t_u8 type;
+	/** present if has_timestamp bit is set. */
+	t_u64 timestamp;
+} __attribute__ ((packed)) wifi_ring_buffer_entry;
+
+/** WiFi ring buffer status structure*/
+typedef struct _wifi_ring_buffer_status {
+	/** Ring name */
+	t_u8 name[RING_NAME_MAX];
+	/** Flag */
+	t_u32 flag;
+	/** Ring ID */
+	wifi_ring_buffer_id ring_id;
+	/** Buffer size */
+	t_u32 ring_buffer_byte_size;
+	/** Verbose Level */
+	t_u32 verbose_level;
+	/** Written bytes */
+	t_u32 written_bytes;
+	/** Read bytes */
+	t_u32 read_bytes;
+	/** Written records */
+	t_u32 written_records;
+} wifi_ring_buffer_status;
+
+/** TLV log structure */
+typedef struct {
+	/** Tag */
+	u16 tag;
+	/** Length of value*/
+	u16 length;
+	/** Value */
+	u8 value[];
+} __attribute__ ((packed)) tlv_log;
+
+/** WiFi ring buffer driver structure */
+typedef struct {
+	/** event */
+	u16 event;
+	/** TLV log structure array */
+	tlv_log tlvs[];
+	/** separate parameter structure per event to be provided and optional
+	 * data the event_data is expected to include an official android part,
+	 * with some parameter as transmit rate, num retries, num scan result
+	 * found etc... as well, event_data can include a vendor proprietary
+	 * part which is understood by the developer only
+	 */
+} __attribute__ ((packed)) wifi_ring_buffer_driver_connectivity_event;
+
+/** Assoc logger data structure */
+typedef struct _assoc_logger {
+	/** vendor specific */
+	t_u8 oui[3];
+	/** BSSID */
+	t_u8 bssid[MLAN_MAC_ADDR_LENGTH];
+	/** SSID */
+	t_u8 ssid[MLAN_MAX_SSID_LENGTH];
+	/** RSSI */
+	t_s32 rssi;
+	/** Channel */
+	t_u32 channel;
+} assoc_logger_data;
+
+int woal_ring_event_logger(moal_private *priv, int ring_id,
+			   pmlan_event pmevent);
+
+int woal_wake_reason_logger(moal_private *priv,
+			    mlan_ds_hs_wakeup_reason wake_reason);
+
+#define MD5_PREFIX_LEN 4
+#define MAX_FATE_LOG_LEN 32
+#define MAX_FRAME_LEN_ETHERNET 1518
+#define MAX_FRAME_LEN_80211_MGMT 2352
+
+/** packet_fate_packet_type */
+typedef enum {
+	PACKET_TYPE_TX,
+	PACKET_TYPE_RX,
+} packet_fate_packet_type;
+
+/** packet fate frame_type */
+typedef enum {
+	FRAME_TYPE_UNKNOWN,
+	FRAME_TYPE_ETHERNET_II,
+	FRAME_TYPE_80211_MGMT,
+} frame_type;
+
+/** wifi_tx_packet_fate */
+typedef enum {
+	/** Sent over air and ACKed. */
+	TX_PKT_FATE_ACKED,
+
+	/** Sent over air but not ACKed. (Normal for broadcast/multicast.) */
+	TX_PKT_FATE_SENT,
+
+	/** Queued within firmware, but not yet sent over air. */
+	TX_PKT_FATE_FW_QUEUED,
+
+	/** Dropped by firmware as invalid. E.g. bad source address, bad
+	 *  checksum, or invalid for current state.
+	 */
+	TX_PKT_FATE_FW_DROP_INVALID,
+
+	/** Dropped by firmware due to lack of buffer space. */
+	TX_PKT_FATE_FW_DROP_NOBUFS,
+
+	/** Dropped by firmware for any other reason. Includes frames that were
+	 *  sent by driver to firmware, but unaccounted for by firmware.
+	 */
+	TX_PKT_FATE_FW_DROP_OTHER,
+
+	/** Queued within driver, not yet sent to firmware. */
+	TX_PKT_FATE_DRV_QUEUED,
+
+	/** Dropped by driver as invalid. E.g. bad source address, or invalid
+	 *  for current state.
+	 */
+	TX_PKT_FATE_DRV_DROP_INVALID,
+
+	/** Dropped by driver due to lack of buffer space. */
+	TX_PKT_FATE_DRV_DROP_NOBUFS,
+
+	/** Dropped by driver for any other reason. */
+	TX_PKT_FATE_DRV_DROP_OTHER,
+} wifi_tx_packet_fate;
+
+/** wifi_rx_packet_fate */
+typedef enum {
+	/** Valid and delivered to network stack (e.g., netif_rx()). */
+	RX_PKT_FATE_SUCCESS,
+
+	/** Queued within firmware, but not yet sent to driver. */
+	RX_PKT_FATE_FW_QUEUED,
+
+	/** Dropped by firmware due to host-programmable filters. */
+	RX_PKT_FATE_FW_DROP_FILTER,
+
+	/** Dropped by firmware as invalid. E.g. bad checksum, decrypt failed,
+	 *  or invalid for current state.
+	 */
+	RX_PKT_FATE_FW_DROP_INVALID,
+
+	/** Dropped by firmware due to lack of buffer space. */
+	RX_PKT_FATE_FW_DROP_NOBUFS,
+
+	/** Dropped by firmware for any other reason. */
+	RX_PKT_FATE_FW_DROP_OTHER,
+
+	/** Queued within driver, not yet delivered to network stack. */
+	RX_PKT_FATE_DRV_QUEUED,
+
+	/** Dropped by driver due to filter rules. */
+	RX_PKT_FATE_DRV_DROP_FILTER,
+
+	/** Dropped by driver as invalid. E.g. not permitted in current state.
+	 */
+	RX_PKT_FATE_DRV_DROP_INVALID,
+
+	/** Dropped by driver due to lack of buffer space. */
+	RX_PKT_FATE_DRV_DROP_NOBUFS,
+
+	/** Dropped by driver for any other reason. */
+	RX_PKT_FATE_DRV_DROP_OTHER,
+} wifi_rx_packet_fate;
+
+/** frame_info_i */
+typedef struct {
+	/** Payload Type */
+	frame_type payload_type;
+	/** Driver timestamp in uS */
+	u32 driver_timestamp_usec;
+	/** FW timestamp in uS */
+	u32 firmware_timestamp_usec;
+	/** Frame Length */
+	u32 frame_len;
+} frame_info_i;
+
+/** wifi_tx_report_i */
+typedef struct {
+	/** MD5 prefix */
+	char md5_prefix[MD5_PREFIX_LEN];
+	/** TX packet fate */
+	wifi_tx_packet_fate fate;
+	/** frame information */
+	frame_info_i frame_inf;
+} wifi_tx_report_i;
+
+/** wifi_rx_report_i */
+typedef struct {
+	/** MD5 prefix */
+	char md5_prefix[MD5_PREFIX_LEN];
+	/** TX packet fate */
+	wifi_rx_packet_fate fate;
+	/** frame information */
+	frame_info_i frame_inf;
+} wifi_rx_report_i;
+
+/** packet_fate_report_t */
+typedef struct packet_fate_report_t {
+	union {
+		wifi_tx_report_i tx_report_i;
+		wifi_rx_report_i rx_report_i;
+	} u;
+} PACKET_FATE_REPORT;
+
+int woal_packet_fate_monitor(moal_private *priv,
+			     packet_fate_packet_type pkt_type, t_u8 fate,
+			     frame_type payload_type,
+			     t_u32 driver_timestamp_usec,
+			     t_u32 firmware_timestamp_usec, t_u8 *data,
+			     t_u32 len);
+
+/** =========== Define Copied from apf.h START =========== */
+/* Number of memory slots, see ldm/stm instructions. */
+#define MEM_ITEMS 16
+/* Upon program execution starting some memory slots are prefilled: */
+/* 4*([APF_FRAME_HEADER_SIZE]&15) */
+#define MEM_OFFSET_IPV4_HEADER_SIZE 13
+/* Size of packet in bytes. */
+#define MEM_OFFSET_PKT_SIZE 14
+/* Age since filter installed in seconds. */
+#define MEM_OFFSET_FILTER_AGE 15
+
+/* Leave 0 opcode unused as it's a good indicator of accidental incorrect
+ * execution (e.g. data).
+ */
+/* Load 1 byte from immediate offset, e.g. "ldb R0, [5]" */
+#define NXP_LDB_OPCODE 1
+/* Load 2 bytes from immediate offset, e.g. "ldh R0, [5]" */
+#define NXP_LDH_OPCODE 2
+/* Load 4 bytes from immediate offset, e.g. "ldw R0, [5]" */
+#define NXP_LDW_OPCODE 3
+/* Load 1 byte from immediate offset plus register, e.g. "ldbx R0, [5]R0" */
+#define NXP_LDBX_OPCODE 4
+/* Load 2 byte from immediate offset plus register, e.g. "ldhx R0, [5]R0" */
+#define NXP_LDHX_OPCODE 5
+/* Load 4 byte from immediate offset plus register, e.g. "ldwx R0, [5]R0" */
+#define NXP_LDWX_OPCODE 6
+/* Add, e.g. "add R0,5" */
+#define NXP_ADD_OPCODE 7
+/* Multiply, e.g. "mul R0,5" */
+#define NXP_MUL_OPCODE 8
+/* Divide, e.g. "div R0,5" */
+#define NXP_DIV_OPCODE 9
+/* And, e.g. "and R0,5" */
+#define NXP_AND_OPCODE 10
+/* Or, e.g. "or R0,5" */
+#define NXP_OR_OPCODE 11
+/* Left shift, e.g, "sh R0, 5" or "sh R0, -5" (shifts right) */
+#define NXP_SH_OPCODE 12
+/* Load immediate, e.g. "li R0,5" (immediate encoded as signed value) */
+#define NXP_LI_OPCODE 13
+/* Unconditional jump, e.g. "jmp label" */
+#define NXP_JMP_OPCODE 14
+/* Compare equal and branch, e.g. "jeq R0,5,label" */
+#define NXP_JEQ_OPCODE 15
+/* Compare not equal and branch, e.g. "jne R0,5,label" */
+#define NXP_JNE_OPCODE 16
+/* Compare greater than and branch, e.g. "jgt R0,5,label" */
+#define NXP_JGT_OPCODE 17
+/* Compare less than and branch, e.g. "jlt R0,5,label" */
+#define NXP_JLT_OPCODE 18
+/* Compare any bits set and branch, e.g. "jset R0,5,label" */
+#define NXP_JSET_OPCODE 19
+/* Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455" */
+#define NXP_JNEBS_OPCODE 20
+/* Immediate value is one of *_EXT_OPCODE
+ * Extended opcodes. These all have an opcode of EXT_OPCODE
+ * and specify the actual opcode in the immediate field.
+ */
+#define NXP_EXT_OPCODE 21
+/* Load from memory, e.g. "ldm R0,5"
+ * Values 0-15 represent loading the different memory slots.
+ */
+#define NXP_LDM_EXT_OPCODE 0
+/* Store to memory, e.g. "stm R0,5" *
+ * Values 16-31 represent storing to the different memory slots.
+ */
+#define NXP_STM_EXT_OPCODE 16
+/* Not, e.g. "not R0" */
+#define NXP_NOT_EXT_OPCODE 32
+/* Negate, e.g. "neg R0" */
+#define NXP_NEG_EXT_OPCODE 33
+/* Swap, e.g. "swap R0,R1" */
+#define NXP_SWAP_EXT_OPCODE 34
+/* Move, e.g. "move R0,R1" */
+#define NXP_MOV_EXT_OPCODE 35
+
+#define GET_OPCODE(i) (((i) >> 3) & 31)
+#define GET_REGISTER(i) ((i)&1)
+#define GET_IMM_LENGTH(i) (((i) >> 1) & 3)
+/** =========== Define Copied from apf.h END =========== */
+
+/** =========== Define Copied from apf_interpreter.h START =========== */
+/**
+ * Version of APF instruction set processed by accept_packet().
+ * Should be returned by wifi_get_packet_filter_info.
+ */
+#define APF_VERSION 2
+/** =========== Define Copied from apf_interpreter.h END =========== */
+
+/** =========== Define Copied from apf_interpreter.c START =========== */
+/* Return code indicating "packet" should accepted. */
+#define PASS_PKT 1
+/* Return code indicating "packet" should be dropped. */
+#define DROP_PKT 0
+/* If "c" is of an unsigned type, generate a compile warning that gets promoted
+ * to an error. This makes bounds checking simpler because ">= 0" can be
+ * avoided. Otherwise adding superfluous ">= 0" with unsigned expressions
+ * generates compile warnings.
+ */
+#define ENFORCE_UNSIGNED(c) ((c) == (uint32_t)(c))
+/** =========== Define Copied from apf_interpreter.c END =========== */
+
+/** depend on the format of skb->data */
+#define APF_FRAME_HEADER_SIZE 14
+#define PACKET_FILTER_MAX_LEN 1024
+
+enum {
+	PACKET_FILTER_STATE_INIT = 0,
+	PACKET_FILTER_STATE_STOP,
+	PACKET_FILTER_STATE_START,
+};
+
+enum wifi_attr_packet_filter {
+	ATTR_PACKET_FILTER_INVALID = 0,
+	ATTR_PACKET_FILTER_TOTAL_LENGTH,
+	ATTR_PACKET_FILTER_PROGRAM,
+	ATTR_PACKET_FILTER_VERSION,
+	ATTR_PACKET_FILTER_MAX_LEN,
+	ATTR_PACKET_FILTER_AFTER_LAST,
+	ATTR_PACKET_FILTER_MAX = ATTR_PACKET_FILTER_AFTER_LAST - 1
+};
+
+/** Packet filter structure */
+typedef struct _packet_filter {
+	spinlock_t lock;
+	t_u8 state;
+	t_u8 packet_filter_program[PACKET_FILTER_MAX_LEN];
+	t_u8 packet_filter_len;
+	t_u32 packet_filter_version;
+	t_u32 packet_filter_max_len;
+} packet_filter;
+
+int woal_filter_packet(moal_private *priv, t_u8 *data, t_u32 len,
+		       t_u32 filter_age);
+
+int woal_init_wifi_hal(moal_private *priv);
+int woal_deinit_wifi_hal(moal_private *priv);
+
+#define ATTRIBUTE_U32_LEN (nla_total_size(NLA_HDRLEN + 4))
+#define VENDOR_ID_OVERHEAD ATTRIBUTE_U32_LEN
+#define VENDOR_SUBCMD_OVERHEAD ATTRIBUTE_U32_LEN
+#define VENDOR_DATA_OVERHEAD (nla_total_size(NLA_HDRLEN))
+
+#define VENDOR_REPLY_OVERHEAD                                                  \
+	(VENDOR_ID_OVERHEAD + VENDOR_SUBCMD_OVERHEAD + VENDOR_DATA_OVERHEAD)
+
+/* Features Enums*/
+#define WLAN_FEATURE_INFRA 0x0001	// Basic infrastructure mode support
+#define WLAN_FEATURE_INFRA_5G 0x0002	// 5 GHz Band support
+#define WLAN_FEATURE_HOTSPOT 0x0004	// GAS/ANQP support
+#define WLAN_FEATURE_P2P 0x0008	// Wifi-Direct/P2P
+#define WLAN_FEATURE_SOFT_AP 0x0010	// Soft AP support
+#define WLAN_FEATURE_GSCAN 0x0020	// Google-Scan APIsi support
+#define WLAN_FEATURE_NAN 0x0040	// Neighbor Awareness Networking (NAN)
+#define WLAN_FEATURE_D2D_RTT 0x0080	// Device-to-device RTT support
+#define WLAN_FEATURE_D2AP_RTT 0x0100	// Device-to-AP RTT support
+#define WLAN_FEATURE_BATCH_SCAN 0x0200	// Batched Scan (legacy) support
+#define WLAN_FEATURE_PNO 0x0400	// Preferred network offload support
+#define WLAN_FEATURE_ADDITIONAL_STA 0x0800	// Two STAs support
+#define WLAN_FEATURE_TDLS 0x1000	// Tunnel directed link setup (TDLS)
+#define WLAN_FEATURE_TDLS_OFFCHANNEL 0x2000	// TDLS off channel support
+#define WLAN_FEATURE_EPR 0x4000	// Enhanced power reporting support
+#define WLAN_FEATURE_AP_STA 0x8000	// AP STA Concurrency support
+#define WLAN_FEATURE_LINK_LAYER_STATS                                          \
+	0x10000			// Link layer stats collection support
+#define WLAN_FEATURE_LOGGER 0x20000	// WiFi Logger support
+#define WLAN_FEATURE_HAL_EPNO 0x40000	// WiFi enhanced PNO support
+#define WLAN_FEATURE_RSSI_MONITOR 0x80000	// RSSI Monitor support
+#define WLAN_FEATURE_MKEEP_ALIVE 0x100000	// WiFi mkeep_alive support
+#define WLAN_FEATURE_CONFIG_NDO 0x200000	// ND offload configure support
+#define WLAN_FEATURE_TX_TRANSMIT_POWER                                         \
+	0x400000		// Capture Tx transmit power levels
+#define WLAN_FEATURE_CONTROL_ROAMING 0x800000	// Enable/Disable firmware roaming
+#define WLAN_FEATURE_IE_WHITELIST 0x1000000	// Probe IE white listing support
+#define WLAN_FEATURE_SCAN_RAND                                                 \
+	0x2000000		// MAC & Probe Sequence Number randomization Support
+#define WLAN_FEATURE_SET_LATENCY_MODE 0x40000000 // Support Latency mode setting
+// Add more features here
+
+#define MAX_CHANNEL_NUM 200
+
+/** Wifi Band */
+typedef enum {
+	WIFI_BAND_UNSPECIFIED,
+	/** 2.4 GHz */
+	WIFI_BAND_BG = 1,
+	/** 5 GHz without DFS */
+	WIFI_BAND_A = 2,
+	/** 5 GHz DFS only */
+	WIFI_BAND_A_DFS = 4,
+	/** 5 GHz with DFS */
+	WIFI_BAND_A_WITH_DFS = 6,
+	/** 2.4 GHz + 5 GHz; no DFS */
+	WIFI_BAND_ABG = 3,
+	/** 2.4 GHz + 5 GHz with DFS */
+	WIFI_BAND_ABG_WITH_DFS = 7,
+
+	/** Keep it last */
+	WIFI_BAND_LAST,
+	WIFI_BAND_MAX = WIFI_BAND_LAST - 1,
+} wifi_band;
+
+typedef enum wifi_attr {
+	ATTR_FEATURE_SET_INVALID = 0,
+	ATTR_SCAN_MAC_OUI_SET = 1,
+	ATTR_FEATURE_SET = 2,
+	ATTR_NODFS_VALUE = 3,
+	ATTR_COUNTRY_CODE = 4,
+	ATTR_CHANNELS_BAND = 5,
+	ATTR_NUM_CHANNELS = 6,
+	ATTR_CHANNEL_LIST = 7,
+	ATTR_GET_CONCURRENCY_MATRIX_SET_SIZE_MAX = 8,
+	ATTR_GET_CONCURRENCY_MATRIX_SET_SIZE = 9,
+	ATTR_GET_CONCURRENCY_MATRIX_SET = 10,
+	ATTR_WIFI_LATENCY_MODE = 11,
+	ATTR_WIFI_AFTER_LAST,
+	ATTR_WIFI_MAX = ATTR_WIFI_AFTER_LAST - 1
+} wifi_attr_t;
+
+enum mrvl_wlan_vendor_attr_wifi_logger {
+	MRVL_WLAN_VENDOR_ATTR_NAME = 10,
+};
+
+/**vendor event*/
+enum vendor_event {
+	event_hang = 0,
+	event_fw_dump_done = 1,
+	event_rssi_monitor = 0x1501,
+	event_cloud_keep_alive = 0x10003,
+	event_dfs_radar_detected = 0x10004,
+	event_dfs_cac_started = 0x10005,
+	event_dfs_cac_finished = 0x10006,
+	event_dfs_cac_aborted = 0x10007,
+	event_dfs_nop_finished = 0x10008,
+	event_wifi_logger_ring_buffer_data = 0x1000b,
+	event_wifi_logger_alert,
+	event_packet_fate_monitor,
+	event_wake_reason_report,
+	event_max,
+};
+
+/** struct dfs_event */
+typedef struct _dfs_event {
+	/** Frequency */
+	int freq;
+	/** HT enable */
+	int ht_enabled;
+	/** Channel Offset */
+	int chan_offset;
+	/** Channel width */
+	enum nl80211_chan_width chan_width;
+	/** Center Frequency 1 */
+	int cf1;
+	/** Center Frequency 2 */
+	int cf2;
+} dfs_event;
+
+void woal_cfg80211_dfs_vendor_event(moal_private *priv, int event,
+				    struct cfg80211_chan_def *chandef);
+
+enum ATTR_LINK_LAYER_STAT {
+	ATTR_LL_STATS_INVALID,
+	ATTR_LL_STATS_MPDU_SIZE_THRESHOLD,
+	ATTR_LL_STATS_AGGRESSIVE_STATS_GATHERING,
+	ATTR_LL_STATS_IFACE,
+	ATTR_LL_STATS_NUM_RADIO,
+	ATTR_LL_STATS_RADIO,
+	ATTR_LL_STATS_CLEAR_REQ_MASK,
+	ATTR_LL_STATS_STOP_REQ,
+	ATTR_LL_STATS_CLEAR_RSP_MASK,
+	ATTR_LL_STATS_STOP_RSP,
+	ATTR_LL_STATS_AFTER_LAST,
+	ATTR_LL_STATS_MAX = ATTR_LL_STATS_AFTER_LAST - 1,
+};
+
+enum ATTR_RSSI_MONITOR {
+	ATTR_RSSI_MONITOR_INVALID,
+	ATTR_RSSI_MONITOR_CONTROL,
+	ATTR_RSSI_MONITOR_MIN_RSSI,
+	ATTR_RSSI_MONITOR_MAX_RSSI,
+	ATTR_RSSI_MONITOR_CUR_BSSID,
+	ATTR_RSSI_MONITOR_CUR_RSSI,
+	ATTR_RSSI_MONITOR_AFTER_LAST,
+	ATTR_RSSI_MONITOR_MAX = ATTR_RSSI_MONITOR_AFTER_LAST - 1,
+};
+void woal_cfg80211_rssi_monitor_event(moal_private *priv, t_s16 rssi);
+
+/**vendor sub command*/
+enum vendor_sub_command {
+	sub_cmd_set_drvdbg = 0,
+	sub_cmd_start_keep_alive = 0x0003,
+	sub_cmd_stop_keep_alive = 0x0004,
+	sub_cmd_dfs_capability = 0x0005,
+	sub_cmd_set_scan_mac_oui = 0x0007,
+	sub_cmd_set_packet_filter = 0x0011,
+	sub_cmd_get_packet_filter_capability,
+	sub_cmd_nd_offload = 0x0100,
+	sub_cmd_link_statistic_set = 0x1200,
+	sub_cmd_link_statistic_get = 0x1201,
+	sub_cmd_link_statistic_clr = 0x1202,
+	sub_cmd_get_valid_channels = 0x1009,
+	sub_cmd_get_wifi_supp_feature_set = 0x100a,
+	sub_cmd_set_country_code = 0x100d,
+	sub_cmd_set_latency_mode = 0x1015,
+	sub_cmd_get_fw_version = 0x1404,
+	sub_cmd_get_drv_version = 0x1406,
+	sub_cmd_start_logging = 0x1400,
+	sub_cmd_get_wifi_logger_supp_feature_set,
+	sub_cmd_get_ring_buff_data,
+	sub_cmd_get_ring_buff_status,
+	sub_cmd_get_fw_mem_dump = 0x1405,
+	sub_cmd_get_drv_mem_dump = 0x1407,
+	sub_cmd_start_packet_fate_monitor = 0x1408,
+	sub_cmd_rssi_monitor = 0x1500,
+	/*Sub-command for wifi hal */
+	sub_cmd_get_roaming_capability = 0x1700,
+	sub_cmd_fw_roaming_enable = 0x1701,
+	sub_cmd_fw_roaming_config = 0x1702,
+	sub_cmd_max,
+};
+
+void woal_register_cfg80211_vendor_command(struct wiphy *wiphy);
+int woal_cfg80211_vendor_event(moal_private *priv, int event,
+			       t_u8 *data, int len);
+
+enum mrvl_wlan_vendor_attr {
+	MRVL_WLAN_VENDOR_ATTR_INVALID = 0,
+	/* Used by MRVL_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */
+	MRVL_WLAN_VENDOR_ATTR_DFS = 1,
+	MRVL_WLAN_VENDOR_ATTR_AFTER_LAST,
+
+	MRVL_WLAN_VENDOR_ATTR_MAX = MRVL_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
+};
+
+typedef enum {
+	ATTR_ND_OFFLOAD_INVALID = 0,
+	ATTR_ND_OFFLOAD_CONTROL,
+	ATTR_ND_OFFLOAD_AFTER_LAST,
+	ATTR_ND_OFFLOAD_MAX = ATTR_ND_OFFLOAD_AFTER_LAST - 1,
+} ND_OFFLOAD_ATTR;
+
+#define MKEEP_ALIVE_IP_PKT_MAX 256
+enum mkeep_alive_attributes {
+	MKEEP_ALIVE_ATTRIBUTE_INVALID = 0,
+	MKEEP_ALIVE_ATTRIBUTE_ID,
+	MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE,
+	MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
+	MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
+	MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
+	MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
+	MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
+	MKEEP_ALIVE_ATTRIBUTE_RETRY_INTERVAL,
+	MKEEP_ALIVE_ATTRIBUTE_RETRY_CNT,
+	MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST,
+	MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1
+};
+
+/** WiFi roaming capabilities structure */
+typedef struct {
+	/** max blacklist size */
+	u32 max_blacklist_size;
+	/** max whitelist size */
+	u32 max_whitelist_size;
+} wifi_roaming_capabilities;
+
+/** WiFi BSSID params structure */
+typedef struct {
+	/** Num of BSSID */
+	u32 num_bssid;
+	/** List of AP mac address */
+	t_u8 mac_addr[MAX_AP_LIST][MLAN_MAC_ADDR_LENGTH];
+} wifi_bssid_params;
+
+/** SSID structure */
+typedef struct {
+	/** Length */
+	u32 length;
+	/** SSID */
+	char ssid[MLAN_MAX_SSID_LENGTH];
+} ssid_t;
+
+/** WiFi SSID params structure */
+typedef struct {
+	/** No of SSID */
+	u32 num_ssid;
+	/** Whitelist SSID */
+	ssid_t whitelist_ssid[MAX_SSID_NUM];
+} wifi_ssid_params;
+
+/*Attribute for wifi hal*/
+enum mrvl_wlan_vendor_attr_fw_roaming {
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_INVALID = 0,
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CAPA,
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONTROL,
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_BSSID,
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_CONFIG_SSID,
+	/* keep last */
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_AFTER_LAST,
+	MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_MAX =
+		MRVL_WLAN_VENDOR_ATTR_FW_ROAMING_AFTER_LAST - 1
+};
+
+#endif
+#endif /* _MOAL_CFGVENDOR_H_ */
diff --git a/wlan_sd8987/mlinux/moal_debug.c b/wlan_sd8987/mlinux/moal_debug.c
new file mode 100755
index 0000000..baa7fa6
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_debug.c
@@ -0,0 +1,1488 @@
+/** @file moal_debug.c
+ *
+ * @brief This file contains functions for debug proc file.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    11/03/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#ifdef USB
+#include "moal_usb.h"
+#endif
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+
+/** Get info item size */
+#define item_size(n) (sizeof(((mlan_debug_info *)0)->n))
+/** Get info item address */
+#define item_addr(n) ((t_ptr) & (((mlan_debug_info *)0)->n))
+
+/** Get moal_private member size */
+#define item_priv_size(n) (sizeof(((moal_private *)0)->n))
+/** Get moal_private member address */
+#define item_priv_addr(n) ((t_ptr) & (((moal_private *)0)->n))
+
+/** Get moal_handle member size */
+#define item_handle_size(n) (sizeof(((moal_handle *)0)->n))
+/** Get moal_handle member address */
+#define item_handle_addr(n) ((t_ptr) & (((moal_handle *)0)->n))
+
+#ifdef USB
+/** Get moal card member size */
+#define item_card_size(n) (sizeof(((struct usb_card_rec *)0)->n))
+/** Get moal card member address */
+#define item_card_addr(n) ((t_ptr) & (((struct usb_card_rec *)0)->n))
+#endif
+
+#ifdef STA_SUPPORT
+static struct debug_data items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg, 0},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing), INFO_ADDR},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt), INFO_ADDR},
+	{"main_lock_flag", item_size(main_lock_flag), item_addr(main_lock_flag),
+	 INFO_ADDR},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag), INFO_ADDR},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing), INFO_ADDR},
+	{"rx_pkts_queued", item_size(rx_pkts_queued), item_addr(rx_pkts_queued),
+	 INFO_ADDR},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo), INFO_ADDR},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi), INFO_ADDR},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be), INFO_ADDR},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk), INFO_ADDR},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size), INFO_ADDR},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size),
+	 INFO_ADDR},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size), INFO_ADDR},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode), INFO_ADDR},
+	{"ps_state", item_size(ps_state), item_addr(ps_state), INFO_ADDR},
+	{"is_deep_sleep", item_size(is_deep_sleep), item_addr(is_deep_sleep),
+	 INFO_ADDR},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req), INFO_ADDR},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try), INFO_ADDR},
+	{"wakeup_timeout", item_size(pm_wakeup_timeout),
+	 item_addr(pm_wakeup_timeout), INFO_ADDR},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured), INFO_ADDR},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated),
+	 INFO_ADDR},
+	{"rx_pkts_queued", item_size(rx_pkts_queued), item_addr(rx_pkts_queued),
+	 INFO_ADDR},
+	{"tx_pkts_queued", item_size(tx_pkts_queued), item_addr(tx_pkts_queued),
+	 INFO_ADDR},
+	{"pps_uapsd_mode", item_size(pps_uapsd_mode), item_addr(pps_uapsd_mode),
+	 INFO_ADDR},
+	{"sleep_pd", item_size(sleep_pd), item_addr(sleep_pd), INFO_ADDR},
+	{"qos_cfg", item_size(qos_cfg), item_addr(qos_cfg), INFO_ADDR},
+	{"tx_lock_flag", item_size(tx_lock_flag), item_addr(tx_lock_flag),
+	 INFO_ADDR},
+	{"port_open", item_size(port_open), item_addr(port_open), INFO_ADDR},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count), INFO_ADDR},
+	{"scan_processing", item_size(scan_processing),
+	 item_addr(scan_processing), INFO_ADDR},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout), INFO_ADDR},
+	{"timeout_cmd_id", item_size(timeout_cmd_id), item_addr(timeout_cmd_id),
+	 INFO_ADDR},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act), INFO_ADDR},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id),
+	 INFO_ADDR},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act),
+	 INFO_ADDR},
+	{"last_cmd_index", item_size(last_cmd_index), item_addr(last_cmd_index),
+	 INFO_ADDR},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id), INFO_ADDR},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index), INFO_ADDR},
+	{"last_event", item_size(last_event), item_addr(last_event), INFO_ADDR},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index), INFO_ADDR},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node), INFO_ADDR},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure), INFO_ADDR},
+	{"num_cmd_sleep_cfm_fail",
+	 item_size(num_cmd_sleep_cfm_host_to_card_failure),
+	 item_addr(num_cmd_sleep_cfm_host_to_card_failure), INFO_ADDR},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure), INFO_ADDR},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure), INFO_ADDR},
+#ifdef SDIO
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure),
+	 INFO_ADDR | (INTF_SD << 8)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure), INFO_ADDR | (INTF_SD << 8)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure), INFO_ADDR | (INTF_SD << 8)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status), INFO_ADDR | (INTF_SD << 8)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq),
+	 INFO_ADDR | (INTF_SD << 8)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update), INFO_ADDR | (INTF_SD << 8)},
+	{"sdio_rx_aggr", item_size(sdio_rx_aggr), item_addr(sdio_rx_aggr),
+	 INFO_ADDR | (INTF_SD << 8)},
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt), INFO_ADDR | (INTF_SD << 8)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports), INFO_ADDR | (INTF_SD << 8)},
+#endif
+	{"num_evt_deauth", item_size(num_event_deauth),
+	 item_addr(num_event_deauth), INFO_ADDR},
+	{"num_evt_disassoc", item_size(num_event_disassoc),
+	 item_addr(num_event_disassoc), INFO_ADDR},
+	{"num_evt_link_lost", item_size(num_event_link_lost),
+	 item_addr(num_event_link_lost), INFO_ADDR},
+	{"num_cmd_deauth", item_size(num_cmd_deauth), item_addr(num_cmd_deauth),
+	 INFO_ADDR},
+	{"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
+	 item_addr(num_cmd_assoc_success), INFO_ADDR},
+	{"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
+	 item_addr(num_cmd_assoc_failure), INFO_ADDR},
+	{"num_cons_assoc_failure", item_size(num_cons_assoc_failure),
+	 item_addr(num_cons_assoc_failure), INFO_ADDR},
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent), INFO_ADDR},
+	{"data_sent", item_size(data_sent), item_addr(data_sent), INFO_ADDR},
+	{"data_sent_cnt", item_size(data_sent_cnt), item_addr(data_sent_cnt),
+	 INFO_ADDR},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap),
+	 INFO_ADDR},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port),
+	 INFO_ADDR},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap),
+	 INFO_ADDR},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port),
+	 INFO_ADDR},
+#ifdef PCIE
+	{"txbd_rdptr", item_size(txbd_rdptr), item_addr(txbd_rdptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"txbd_wrptr", item_size(txbd_wrptr), item_addr(txbd_wrptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"rxbd_rdptr", item_size(rxbd_rdptr), item_addr(rxbd_rdptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"rxbd_wrptr", item_size(rxbd_wrptr), item_addr(rxbd_wrptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"eventbd_rdptr", item_size(eventbd_rdptr), item_addr(eventbd_rdptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"eventbd_wrptr", item_size(eventbd_wrptr), item_addr(eventbd_wrptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+#endif
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received), INFO_ADDR},
+	{"event_received", item_size(event_received), item_addr(event_received),
+	 INFO_ADDR},
+
+#ifdef USB
+	{"tx_cmd_urb_pending", item_card_size(tx_cmd_urb_pending),
+	 item_card_addr(tx_cmd_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+	{"tx_data_urb_pending", item_card_size(tx_data_urb_pending),
+	 item_card_addr(tx_data_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+#ifdef USB_CMD_DATA_EP
+	{"rx_cmd_urb_pending", item_card_size(rx_cmd_urb_pending),
+	 item_card_addr(rx_cmd_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+#endif
+	{"rx_data_urb_pending", item_card_size(rx_data_urb_pending),
+	 item_card_addr(rx_data_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+#endif /* USB */
+	{"num_tx_timeout", item_priv_size(num_tx_timeout),
+	 item_priv_addr(num_tx_timeout), PRIV_ADDR},
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending), HANDLE_ADDR},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending), HANDLE_ADDR},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending), HANDLE_ADDR},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count), HANDLE_ADDR},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count), HANDLE_ADDR},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count), HANDLE_ADDR},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count), HANDLE_ADDR},
+#ifdef PCIE
+	{"malloc_cons_count", item_handle_size(malloc_cons_count),
+	 item_handle_addr(malloc_cons_count), HANDLE_ADDR},
+#endif
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state), HANDLE_ADDR},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state), HANDLE_ADDR},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w),
+	 HANDLE_ADDR},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r),
+	 HANDLE_ADDR},
+#endif
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count), HANDLE_ADDR},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count), HANDLE_ADDR},
+#ifdef STA_CFG80211
+    {"scan_timeout", item_handle_size(scan_timeout),
+	 item_handle_addr(scan_timeout), HANDLE_ADDR},
+#endif
+};
+
+#endif
+
+#ifdef UAP_SUPPORT
+static struct debug_data uap_items[] = {
+#ifdef DEBUG_LEVEL1
+	{"drvdbg", sizeof(drvdbg), (t_ptr)&drvdbg, 0},
+#endif
+	{"mlan_processing", item_size(mlan_processing),
+	 item_addr(mlan_processing), INFO_ADDR},
+	{"main_process_cnt", item_size(main_process_cnt),
+	 item_addr(main_process_cnt), INFO_ADDR},
+	{"main_lock_flag", item_size(main_lock_flag), item_addr(main_lock_flag),
+	 INFO_ADDR},
+	{"delay_task_flag", item_size(delay_task_flag),
+	 item_addr(delay_task_flag), INFO_ADDR},
+	{"mlan_rx_processing", item_size(mlan_rx_processing),
+	 item_addr(mlan_rx_processing), INFO_ADDR},
+	{"rx_pkts_queued", item_size(rx_pkts_queued), item_addr(rx_pkts_queued),
+	 INFO_ADDR},
+	{"wmm_ac_vo", item_size(wmm_ac_vo), item_addr(wmm_ac_vo), INFO_ADDR},
+	{"wmm_ac_vi", item_size(wmm_ac_vi), item_addr(wmm_ac_vi), INFO_ADDR},
+	{"wmm_ac_be", item_size(wmm_ac_be), item_addr(wmm_ac_be), INFO_ADDR},
+	{"wmm_ac_bk", item_size(wmm_ac_bk), item_addr(wmm_ac_bk), INFO_ADDR},
+	{"max_tx_buf_size", item_size(max_tx_buf_size),
+	 item_addr(max_tx_buf_size), INFO_ADDR},
+	{"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size),
+	 INFO_ADDR},
+	{"curr_tx_buf_size", item_size(curr_tx_buf_size),
+	 item_addr(curr_tx_buf_size), INFO_ADDR},
+	{"ps_mode", item_size(ps_mode), item_addr(ps_mode), INFO_ADDR},
+	{"ps_state", item_size(ps_state), item_addr(ps_state), INFO_ADDR},
+	{"wakeup_dev_req", item_size(pm_wakeup_card_req),
+	 item_addr(pm_wakeup_card_req), INFO_ADDR},
+	{"wakeup_tries", item_size(pm_wakeup_fw_try),
+	 item_addr(pm_wakeup_fw_try), INFO_ADDR},
+	{"wakeup_timeout", item_size(pm_wakeup_timeout),
+	 item_addr(pm_wakeup_timeout), INFO_ADDR},
+	{"hs_configured", item_size(is_hs_configured),
+	 item_addr(is_hs_configured), INFO_ADDR},
+	{"hs_activated", item_size(hs_activated), item_addr(hs_activated),
+	 INFO_ADDR},
+	{"rx_pkts_queued", item_size(rx_pkts_queued), item_addr(rx_pkts_queued),
+	 INFO_ADDR},
+	{"tx_pkts_queued", item_size(tx_pkts_queued), item_addr(tx_pkts_queued),
+	 INFO_ADDR},
+	{"bypass_pkt_count", item_size(bypass_pkt_count),
+	 item_addr(bypass_pkt_count), INFO_ADDR},
+	{"num_bridge_pkts", item_size(num_bridge_pkts),
+	 item_addr(num_bridge_pkts), INFO_ADDR},
+	{"num_drop_pkts", item_size(num_drop_pkts), item_addr(num_drop_pkts),
+	 INFO_ADDR},
+	{"num_cmd_timeout", item_size(num_cmd_timeout),
+	 item_addr(num_cmd_timeout), INFO_ADDR},
+	{"timeout_cmd_id", item_size(timeout_cmd_id), item_addr(timeout_cmd_id),
+	 INFO_ADDR},
+	{"timeout_cmd_act", item_size(timeout_cmd_act),
+	 item_addr(timeout_cmd_act), INFO_ADDR},
+	{"last_cmd_id", item_size(last_cmd_id), item_addr(last_cmd_id),
+	 INFO_ADDR},
+	{"last_cmd_act", item_size(last_cmd_act), item_addr(last_cmd_act),
+	 INFO_ADDR},
+	{"last_cmd_index", item_size(last_cmd_index), item_addr(last_cmd_index),
+	 INFO_ADDR},
+	{"last_cmd_resp_id", item_size(last_cmd_resp_id),
+	 item_addr(last_cmd_resp_id), INFO_ADDR},
+	{"last_cmd_resp_index", item_size(last_cmd_resp_index),
+	 item_addr(last_cmd_resp_index), INFO_ADDR},
+	{"last_event", item_size(last_event), item_addr(last_event), INFO_ADDR},
+	{"last_event_index", item_size(last_event_index),
+	 item_addr(last_event_index), INFO_ADDR},
+	{"num_no_cmd_node", item_size(num_no_cmd_node),
+	 item_addr(num_no_cmd_node), INFO_ADDR},
+	{"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
+	 item_addr(num_cmd_host_to_card_failure), INFO_ADDR},
+	{"num_cmd_sleep_cfm_fail",
+	 item_size(num_cmd_sleep_cfm_host_to_card_failure),
+	 item_addr(num_cmd_sleep_cfm_host_to_card_failure), INFO_ADDR},
+	{"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
+	 item_addr(num_tx_host_to_card_failure), INFO_ADDR},
+	{"num_alloc_buffer_failure", item_size(num_alloc_buffer_failure),
+	 item_addr(num_alloc_buffer_failure), INFO_ADDR},
+#ifdef SDIO
+	{"num_cmdevt_c2h_fail", item_size(num_cmdevt_card_to_host_failure),
+	 item_addr(num_cmdevt_card_to_host_failure),
+	 INFO_ADDR | (INTF_SD << 8)},
+	{"num_rx_c2h_fail", item_size(num_rx_card_to_host_failure),
+	 item_addr(num_rx_card_to_host_failure), INFO_ADDR | (INTF_SD << 8)},
+	{"num_int_read_fail", item_size(num_int_read_failure),
+	 item_addr(num_int_read_failure), INFO_ADDR | (INTF_SD << 8)},
+	{"last_int_status", item_size(last_int_status),
+	 item_addr(last_int_status), INFO_ADDR | (INTF_SD << 8)},
+	{"num_of_irq", item_size(num_of_irq), item_addr(num_of_irq),
+	 INFO_ADDR | (INTF_SD << 8)},
+	{"mp_invalid_update", item_size(mp_invalid_update),
+	 item_addr(mp_invalid_update), INFO_ADDR | (INTF_SD << 8)},
+	{"sdio_rx_aggr", item_size(sdio_rx_aggr), item_addr(sdio_rx_aggr),
+	 INFO_ADDR | (INTF_SD << 8)},
+	{"mpa_sent_last_pkt", item_size(mpa_sent_last_pkt),
+	 item_addr(mpa_sent_last_pkt), INFO_ADDR | (INTF_SD << 8)},
+	{"mpa_sent_no_ports", item_size(mpa_sent_no_ports),
+	 item_addr(mpa_sent_no_ports), INFO_ADDR | (INTF_SD << 8)},
+#endif
+	{"cmd_sent", item_size(cmd_sent), item_addr(cmd_sent), INFO_ADDR},
+	{"data_sent", item_size(data_sent), item_addr(data_sent), INFO_ADDR},
+	{"data_sent_cnt", item_size(data_sent_cnt), item_addr(data_sent_cnt),
+	 INFO_ADDR},
+	{"mp_rd_bitmap", item_size(mp_rd_bitmap), item_addr(mp_rd_bitmap),
+	 INFO_ADDR},
+	{"curr_rd_port", item_size(curr_rd_port), item_addr(curr_rd_port),
+	 INFO_ADDR},
+	{"mp_wr_bitmap", item_size(mp_wr_bitmap), item_addr(mp_wr_bitmap),
+	 INFO_ADDR},
+	{"curr_wr_port", item_size(curr_wr_port), item_addr(curr_wr_port),
+	 INFO_ADDR},
+#ifdef PCIE
+	{"txbd_rdptr", item_size(txbd_rdptr), item_addr(txbd_rdptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"txbd_wrptr", item_size(txbd_wrptr), item_addr(txbd_wrptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"rxbd_rdptr", item_size(rxbd_rdptr), item_addr(rxbd_rdptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"rxbd_wrptr", item_size(rxbd_wrptr), item_addr(rxbd_wrptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"eventbd_rdptr", item_size(eventbd_rdptr), item_addr(eventbd_rdptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+	{"eventbd_wrptr", item_size(eventbd_wrptr), item_addr(eventbd_wrptr),
+	 INFO_ADDR | (INTF_PCIE << 8)},
+#endif
+	{"cmd_resp_received", item_size(cmd_resp_received),
+	 item_addr(cmd_resp_received), INFO_ADDR},
+	{"event_received", item_size(event_received), item_addr(event_received),
+	 INFO_ADDR},
+
+#ifdef USB
+	{"tx_cmd_urb_pending", item_card_size(tx_cmd_urb_pending),
+	 item_card_addr(tx_cmd_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+	{"tx_data_urb_pending", item_card_size(tx_data_urb_pending),
+	 item_card_addr(tx_data_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+#ifdef USB_CMD_DATA_EP
+	{"rx_cmd_urb_pending", item_card_size(rx_cmd_urb_pending),
+	 item_card_addr(rx_cmd_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+#endif
+	{"rx_data_urb_pending", item_card_size(rx_data_urb_pending),
+	 item_card_addr(rx_data_urb_pending), CARD_ADDR | (INTF_USB << 8)},
+#endif /* USB */
+	{"num_tx_timeout", item_priv_size(num_tx_timeout),
+	 item_priv_addr(num_tx_timeout), PRIV_ADDR},
+	{"ioctl_pending", item_handle_size(ioctl_pending),
+	 item_handle_addr(ioctl_pending), HANDLE_ADDR},
+	{"tx_pending", item_handle_size(tx_pending),
+	 item_handle_addr(tx_pending), HANDLE_ADDR},
+	{"rx_pending", item_handle_size(rx_pending),
+	 item_handle_addr(rx_pending), HANDLE_ADDR},
+	{"lock_count", item_handle_size(lock_count),
+	 item_handle_addr(lock_count), HANDLE_ADDR},
+	{"malloc_count", item_handle_size(malloc_count),
+	 item_handle_addr(malloc_count), HANDLE_ADDR},
+	{"vmalloc_count", item_handle_size(vmalloc_count),
+	 item_handle_addr(vmalloc_count), HANDLE_ADDR},
+	{"mbufalloc_count", item_handle_size(mbufalloc_count),
+	 item_handle_addr(mbufalloc_count), HANDLE_ADDR},
+#ifdef PCIE
+	{"malloc_cons_count", item_handle_size(malloc_cons_count),
+	 item_handle_addr(malloc_cons_count), HANDLE_ADDR | (INTF_PCIE << 8)},
+#endif
+	{"main_state", item_handle_size(main_state),
+	 item_handle_addr(main_state), HANDLE_ADDR},
+	{"driver_state", item_handle_size(driver_state),
+	 item_handle_addr(driver_state), HANDLE_ADDR},
+#ifdef SDIO_MMC_DEBUG
+	{"sdiocmd53w", item_handle_size(cmd53w), item_handle_addr(cmd53w),
+	 HANDLE_ADDR | (INTF_SD << 8)},
+	{"sdiocmd53r", item_handle_size(cmd53r), item_handle_addr(cmd53r),
+	 HANDLE_ADDR | (INTF_SD << 8)},
+#endif
+	{"hs_skip_count", item_handle_size(hs_skip_count),
+	 item_handle_addr(hs_skip_count), HANDLE_ADDR},
+	{"hs_force_count", item_handle_size(hs_force_count),
+	 item_handle_addr(hs_force_count), HANDLE_ADDR},
+};
+#endif /* UAP_SUPPORT */
+
+/**
+ *  @brief This function reset histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *
+ *  @return   N/A
+ */
+void
+woal_hist_do_reset(moal_private *priv, void *data)
+{
+	hgm_data *phist_data = (hgm_data *)data;
+	int ix;
+	t_u16 rx_rate_max_size = priv->phandle->card_info->rx_rate_max;
+
+	if (!phist_data)
+		return;
+	atomic_set(&(phist_data->num_samples), 0);
+	for (ix = 0; ix < rx_rate_max_size; ix++)
+		atomic_set(&(phist_data->rx_rate[ix]), 0);
+	for (ix = 0; ix < SNR_MAX; ix++)
+		atomic_set(&(phist_data->snr[ix]), 0);
+	for (ix = 0; ix < NOISE_FLR_MAX; ix++)
+		atomic_set(&(phist_data->noise_flr[ix]), 0);
+	for (ix = 0; ix < SIG_STRENGTH_MAX; ix++)
+		atomic_set(&(phist_data->sig_str[ix]), 0);
+}
+
+/**
+ *  @brief This function reset all histogram data
+ *
+ *  @param priv                A pointer to moal_private
+ *
+ *  @return   N/A
+ */
+void
+woal_hist_data_reset(moal_private *priv)
+{
+	int i = 0;
+	for (i = 0; i < priv->phandle->card_info->histogram_table_num; i++)
+		woal_hist_do_reset(priv, priv->hist_data[i]);
+}
+
+/**
+ *  @brief This function reset histogram data according to antenna
+ *
+ *  @param priv                A pointer to moal_private
+ *
+ *  @return   N/A
+ */
+void
+woal_hist_reset_table(moal_private *priv, t_u8 antenna)
+{
+	hgm_data *phist_data = priv->hist_data[antenna];
+
+	woal_hist_do_reset(priv, phist_data);
+}
+
+/** NF calculation */
+#define CAL_NF(NF) ((t_s8)(-(t_s8)(NF)))
+/** RSSI calculation */
+#define CAL_RSSI(SNR, NF) ((t_s8)((t_s8)(SNR) + CAL_NF(NF)))
+
+/**
+ *  @brief This function set histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate      rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *
+ *  @return   N/A
+ */
+static void
+woal_hist_data_set(moal_private *priv, t_u16 rx_rate, t_s8 snr,
+		   t_s8 nflr, t_u8 antenna)
+{
+	hgm_data *phist_data = priv->hist_data[antenna];
+	t_s8 nf = CAL_NF(nflr);
+	t_s8 rssi = CAL_RSSI(snr, nflr);
+
+	atomic_inc(&(phist_data->num_samples));
+	if (rx_rate < priv->phandle->card_info->rx_rate_max)
+		atomic_inc(&(phist_data->rx_rate[rx_rate]));
+	atomic_inc(&(phist_data->snr[snr + 128]));
+	atomic_inc(&(phist_data->noise_flr[nf + 128]));
+	atomic_inc(&(phist_data->sig_str[rssi + 128]));
+}
+
+/**
+ *  @brief This function add histogram data
+ *
+ *  @param priv 		A pointer to moal_private
+ *  @param rx_rate      rx rate
+ *  @param snr			snr
+ *  @param nflr			NF
+ *
+ *  @return   N/A
+ */
+void
+woal_hist_data_add(moal_private *priv, t_u16 rx_rate, t_s8 snr, t_s8 nflr,
+		   t_u8 antenna)
+{
+	hgm_data *phist_data = NULL;
+	unsigned long curr_size;
+
+	if ((antenna + 1) > priv->phandle->card_info->histogram_table_num)
+		antenna = 0;
+	phist_data = priv->hist_data[antenna];
+	curr_size = atomic_read(&(phist_data->num_samples));
+	if (curr_size > HIST_MAX_SAMPLES)
+		woal_hist_reset_table(priv, antenna);
+	woal_hist_data_set(priv, rx_rate, snr, nflr, antenna);
+}
+
+#define MAX_MCS_NUM_SUPP 16
+#define MAX_MCS_NUM_AC 10
+#define MAX_MCS_NUM_AX 12
+/**
+ *  @brief histogram info in proc
+ *
+ *  @param sfp     pointer to seq_file structure
+ *  @param data
+ *
+ *  @return        Number of output data or MLAN_STATUS_FAILURE
+ */
+static int
+woal_histogram_info(struct seq_file *sfp, void *data)
+{
+	hgm_data *phist_data = (hgm_data *)data;
+	int i = 0;
+	int value = 0;
+	t_bool sgi_enable = 0;
+	t_u8 bw = 0;
+	t_u8 mcs_index = 0;
+	t_u8 nss = 0;
+	t_u8 gi = 0;
+	wlan_hist_proc_data *hist_data = (wlan_hist_proc_data *) sfp->private;
+	moal_private *priv = (moal_private *)hist_data->priv;
+	t_u16 rx_rate_max_size = priv->phandle->card_info->rx_rate_max;
+
+	ENTER();
+	if (MODULE_GET == 0) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	seq_printf(sfp, "total samples = %d \n",
+		   atomic_read(&(phist_data->num_samples)));
+	seq_printf(sfp, "rx rates (in Mbps):\n");
+	seq_printf(sfp, "\t0-3:     B-MCS  0-3\n");
+	seq_printf(sfp, "\t4-11:    G-MCS  0-7\n");
+	seq_printf(sfp,
+		   "\t12-27:   N-MCS  0-15(BW20)             28-43:   N-MCS  0-15(BW40)\n");
+	seq_printf(sfp,
+		   "\t44-59:   N-MCS  0-15(BW20:SGI)         60-75:   N-MCS  0-15(BW40:SGI)\n");
+	seq_printf(sfp,
+		   "\t76-85:   AC-MCS 0-9(VHT:BW20:NSS1)     86-95:   AC-MCS 0-9(VHT:BW20:NSS2)\n");
+	seq_printf(sfp,
+		   "\t96-105:  AC-MCS 0-9(VHT:BW40:NSS1)     106-115: AC-MCS 0-9(VHT:BW40:NSS2)\n");
+	seq_printf(sfp,
+		   "\t116-125: AC-MCS 0-9(VHT:BW80:NSS1)     126-135: AC-MCS 0-9(VHT:BW80:NSS2)\n");
+	seq_printf(sfp,
+		   "\t136-145: AC-MCS 0-9(VHT:BW20:NSS1:SGI) 146-155: AC-MCS 0-9(VHT:BW20:NSS2:SGI)\n");
+	seq_printf(sfp,
+		   "\t156-165: AC-MCS 0-9(VHT:BW40:NSS1:SGI) 166-175: AC-MCS 0-9(VHT:BW40:NSS2:SGI)\n");
+	seq_printf(sfp,
+		   "\t176-185: AC-MCS 0-9(VHT:BW80:NSS1:SGI) 186-195: AC-MCS 0-9(VHT:BW80:NSS2:SGI)\n\n");
+	seq_printf(sfp,
+		   "\t196-207: AX-MCS 0-11(BW20:NSS1)        208-219: AX-MCS 0-11(BW20:NSS2)\n");
+	seq_printf(sfp,
+		   "\t220-231: AX-MCS 0-11(BW40:NSS1)        232-243: AX-MCS 0-11(BW40:NSS2)\n");
+	seq_printf(sfp,
+		   "\t244-255: AX-MCS 0-11(BW80:NSS1)        256-267: AX-MCS 0-11(BW80:NSS2)\n");
+	seq_printf(sfp,
+		   "\t268-279: AX-MCS 0-11(BW20:NSS1:GI1)    280-291: AX-MCS 0-11(BW20:NSS2:GI1)\n");
+	seq_printf(sfp,
+		   "\t292-303: AX-MCS 0-11(BW40:NSS1:GI1)    304-315: AX-MCS 0-11(BW40:NSS2:GI1)\n");
+	seq_printf(sfp,
+		   "\t316-327: AX-MCS 0-11(BW80:NSS1:GI1)    328-339: AX-MCS 0-11(BW80:NSS2:GI1)\n");
+	seq_printf(sfp,
+		   "\t340-351: AX-MCS 0-11(BW20:NSS1:GI2)    352-363: AX-MCS 0-11(BW20:NSS2:GI2)\n");
+	seq_printf(sfp,
+		   "\t364-375: AX-MCS 0-11(BW40:NSS1:GI2)    376-387: AX-MCS 0-11(BW40:NSS2:GI2)\n");
+	seq_printf(sfp,
+		   "\t388-399: AX-MCS 0-11(BW80:NSS1:GI2)    400-411: AX-MCS 0-11(BW80:NSS2:GI2)\n");
+
+	for (i = 0; i < rx_rate_max_size; i++) {
+		value = atomic_read(&(phist_data->rx_rate[i]));
+		if (value) {
+			if (i <= 11)
+				seq_printf(sfp, "rx_rate[%03d] = %d\n", i,
+					   value);
+			else if (i <= 75) {
+				sgi_enable = (i - 12) / (MAX_MCS_NUM_SUPP * 2);	// 0:LGI,
+				// 1:SGI
+				bw = ((i - 12) % (MAX_MCS_NUM_SUPP * 2)) / MAX_MCS_NUM_SUPP;	// 0:20MHz, 1:40MHz
+				mcs_index = (i - 12) % MAX_MCS_NUM_SUPP;
+				seq_printf(sfp,
+					   "rx_rate[%03d] = %d (MCS:%d HT BW:%dMHz%s)\n",
+					   i, value, mcs_index, (1 << bw) * 20,
+					   sgi_enable ? " SGI" : "");
+			} else if (i <= 195) {
+				sgi_enable = (i - 76) / (MAX_MCS_NUM_AC * 6);	// 0:LGI,
+				// 1:SGI
+				bw = ((i - 76) % (MAX_MCS_NUM_AC * 6)) / (MAX_MCS_NUM_AC * 2);	// 0:20MHz, 1:40MHz,
+				// 2:80MHz
+				nss = (((i - 76) % (MAX_MCS_NUM_AC * 6)) % (MAX_MCS_NUM_AC * 2)) / MAX_MCS_NUM_AC;	// 0:NSS1, 1:NSS2
+				mcs_index = (i - 76) % MAX_MCS_NUM_AC;
+
+				seq_printf(sfp,
+					   "rx_rate[%03d] = %d (MCS:%d VHT BW:%dMHz NSS:%d%s)\n",
+					   i, value, mcs_index, (1 << bw) * 20,
+					   nss + 1, sgi_enable ? " SGI" : "");
+			} else if (i <= 411) {
+				gi = (i - 196) / (MAX_MCS_NUM_AX * 6);	// 0,1,2
+				bw = ((i - 196) % (MAX_MCS_NUM_AX * 6)) / (MAX_MCS_NUM_AX * 2);	// 0:20MHz, 1:40MHz,
+				// 2:80MHz
+				nss = (((i - 196) % (MAX_MCS_NUM_AX * 6)) % (MAX_MCS_NUM_AX * 2)) / MAX_MCS_NUM_AX;	// 0:NSS1, 1:NSS2
+				mcs_index = (i - 196) % MAX_MCS_NUM_AX;
+
+				seq_printf(sfp,
+					   "rx_rate[%03d] = %d (MCS:%d AX BW:%dMHz NSS:%d GI:%d)\n",
+					   i, value, mcs_index, (1 << bw) * 20,
+					   nss + 1, gi);
+			}
+		}
+	}
+	for (i = 0; i < SNR_MAX; i++) {
+		value = atomic_read(&(phist_data->snr[i]));
+		if (value)
+			seq_printf(sfp, "snr[%02ddB] = %d\n", (int)(i - 128),
+				   value);
+	}
+	for (i = 0; i < NOISE_FLR_MAX; i++) {
+		value = atomic_read(&(phist_data->noise_flr[i]));
+		if (value)
+			seq_printf(sfp, "noise_flr[%02ddBm] = %d\n",
+				   (int)(i - 128), value);
+	}
+	for (i = 0; i < SIG_STRENGTH_MAX; i++) {
+		value = atomic_read(&(phist_data->sig_str[i]));
+		if (value)
+			seq_printf(sfp, "sig_strength[%02ddBm] = %d\n",
+				   (int)(i - 128), value);
+	}
+
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc read function for histogram
+ *
+ *  @param sfp     pointer to seq_file structure
+ *  @param data
+ *
+ *  @return        Number of output data or MLAN_STATUS_FAILURE
+ */
+static int
+woal_histogram_read(struct seq_file *sfp, void *data)
+{
+	wlan_hist_proc_data *hist_data = (wlan_hist_proc_data *) sfp->private;
+	moal_private *priv = (moal_private *)hist_data->priv;
+
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (hist_data->ant_idx < priv->phandle->card_info->histogram_table_num)
+		woal_histogram_info(sfp, priv->hist_data[hist_data->ant_idx]);
+
+	LEAVE();
+	return 0;
+}
+
+static int
+woal_histogram_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_histogram_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_histogram_read, PDE(inode)->data);
+#endif
+}
+
+/**
+ *  @brief Proc write function for histogram
+ *
+ *  @param f       file pointer
+ *  @param buf     pointer to data buffer
+ *  @param count   data number to write
+ *  @param off     Offset
+ *
+ *  @return        number of data
+ */
+static ssize_t
+woal_histogram_write(struct file *f, const char __user * buf,
+		     size_t count, loff_t * off)
+{
+	struct seq_file *sfp = f->private_data;
+	wlan_hist_proc_data *hist_data = (wlan_hist_proc_data *) sfp->private;
+	moal_private *priv = (moal_private *)hist_data->priv;
+	woal_hist_reset_table(priv, hist_data->ant_idx);
+	return count;
+}
+
+/**
+ *  @brief Proc read function for log
+ *
+ *  @param sfp     pointer to seq_file structure
+ *  @param data
+ *
+ *  @return        Number of output data or MLAN_STATUS_FAILURE
+ */
+static int
+woal_log_read(struct seq_file *sfp, void *data)
+{
+	moal_private *priv = (moal_private *)sfp->private;
+	mlan_ds_get_stats stats;
+	int i = 0;
+	ENTER();
+	if (!priv) {
+		LEAVE();
+		return -EFAULT;
+	}
+	if (MODULE_GET == 0) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	memset(&stats, 0x00, sizeof(stats));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, &stats)) {
+		PRINTM(MERROR,
+		       "woal_log_read: Get log: Failed to get stats info!");
+		MODULE_PUT;
+		LEAVE();
+		return -EFAULT;
+	}
+
+	seq_printf(sfp, "dot11GroupTransmittedFrameCount = %d\n",
+		   stats.mcast_tx_frame);
+	seq_printf(sfp, "dot11FailedCount = %d\n", stats.failed);
+	seq_printf(sfp, "dot11RetryCount = %d\n", stats.retry);
+	seq_printf(sfp, "dot11MultipleRetryCount = %d\n", stats.multi_retry);
+	seq_printf(sfp, "dot11FrameDuplicateCount = %d\n", stats.frame_dup);
+	seq_printf(sfp, "dot11RTSSuccessCount = %d\n", stats.rts_success);
+	seq_printf(sfp, "dot11RTSFailureCount = %d\n", stats.rts_failure);
+	seq_printf(sfp, "dot11ACKFailureCount = %d\n", stats.ack_failure);
+	seq_printf(sfp, "dot11ReceivedFragmentCount = %d\n", stats.rx_frag);
+	seq_printf(sfp, "dot11GroupReceivedFrameCount = %d\n",
+		   stats.mcast_rx_frame);
+	seq_printf(sfp, "dot11FCSErrorCount = %d\n", stats.fcs_error);
+	seq_printf(sfp, "dot11TransmittedFrameCount = %d\n", stats.tx_frame);
+	seq_printf(sfp, "wepicverrcnt-1 = %d\n", stats.wep_icv_error[0]);
+	seq_printf(sfp, "wepicverrcnt-2 = %d\n", stats.wep_icv_error[1]);
+	seq_printf(sfp, "wepicverrcnt-3 = %d\n", stats.wep_icv_error[2]);
+	seq_printf(sfp, "wepicverrcnt-4 = %d\n", stats.wep_icv_error[3]);
+	seq_printf(sfp, "beaconReceivedCount = %d\n", stats.bcn_rcv_cnt);
+	seq_printf(sfp, "beaconMissedCount = %d\n", stats.bcn_miss_cnt);
+	if (stats.amsdu_rx_cnt)
+		seq_printf(sfp, "ReceivedMSDUinPerAMSDU = %d\n",
+			   stats.msdu_in_rx_amsdu_cnt / stats.amsdu_rx_cnt);
+	seq_printf(sfp, "ReceivedMSDUinAMSDUCount = %d\n",
+		   stats.msdu_in_rx_amsdu_cnt);
+	if (stats.amsdu_tx_cnt)
+		seq_printf(sfp, "TransmitMSDUinPerAMSDU = %d\n",
+			   stats.msdu_in_tx_amsdu_cnt / stats.amsdu_tx_cnt);
+	seq_printf(sfp, "TransmitMSDUinAMSDUCount = %d\n",
+		   stats.msdu_in_tx_amsdu_cnt);
+	if (priv->phandle->fw_getlog_enable) {
+		seq_printf(sfp, "dot11TransmittedFragmentCount = %u\n",
+			   stats.tx_frag_cnt);
+		seq_printf(sfp, "dot11QosTransmittedFragmentCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_tx_frag_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosFailedCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_failed_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosRetryCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_retry_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosMultipleRetryCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_multi_retry_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosFrameDuplicateCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_frm_dup_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosRTSSuccessCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_rts_suc_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosRTSFailureCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_rts_failure_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosACKFailureCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_ack_failure_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosReceivedFragmentCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_rx_frag_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosTransmittedFrameCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_tx_frm_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosDiscardedFrameCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_discarded_frm_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosMPDUsReceivedCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_mpdus_rx_cnt[i]);
+		}
+		seq_printf(sfp, "\ndot11QosRetriesReceivedCount = ");
+		for (i = 0; i < 8; i++) {
+			seq_printf(sfp, "%u ", stats.qos_retries_rx_cnt[i]);
+		}
+		seq_printf(sfp,
+			   "\ndot11RSNAStatsCMACICVErrors = %u\n"
+			   "dot11RSNAStatsCMACReplays = %u\n"
+			   "dot11RSNAStatsRobustMgmtCCMPReplays = %u\n"
+			   "dot11RSNAStatsTKIPICVErrors = %u\n"
+			   "dot11RSNAStatsTKIPReplays = %u\n"
+			   "dot11RSNAStatsCCMPDecryptErrors = %u\n"
+			   "dot11RSNAstatsCCMPReplays = %u\n"
+			   "dot11TransmittedAMSDUCount = %u\n"
+			   "dot11FailedAMSDUCount = %u\n"
+			   "dot11RetryAMSDUCount = %u\n"
+			   "dot11MultipleRetryAMSDUCount = %u\n"
+			   "dot11TransmittedOctetsInAMSDUCount = %llu\n"
+			   "dot11AMSDUAckFailureCount = %u\n"
+			   "dot11ReceivedAMSDUCount = %u\n"
+			   "dot11ReceivedOctetsInAMSDUCount = %llu\n"
+			   "dot11TransmittedAMPDUCount = %u\n"
+			   "dot11TransmittedMPDUsInAMPDUCount = %u\n"
+			   "dot11TransmittedOctetsInAMPDUCount = %llu\n"
+			   "dot11AMPDUReceivedCount = %u\n"
+			   "dot11MPDUInReceivedAMPDUCount = %u\n"
+			   "dot11ReceivedOctetsInAMPDUCount = %llu\n"
+			   "dot11AMPDUDelimiterCRCErrorCount = %u\n",
+			   stats.cmacicv_errors, stats.cmac_replays,
+			   stats.mgmt_ccmp_replays, stats.tkipicv_errors,
+			   stats.tkip_replays, stats.ccmp_decrypt_errors,
+			   stats.ccmp_replays, stats.tx_amsdu_cnt,
+			   stats.failed_amsdu_cnt, stats.retry_amsdu_cnt,
+			   stats.multi_retry_amsdu_cnt,
+			   stats.tx_octets_in_amsdu_cnt,
+			   stats.amsdu_ack_failure_cnt, stats.rx_amsdu_cnt,
+			   stats.rx_octets_in_amsdu_cnt, stats.tx_ampdu_cnt,
+			   stats.tx_mpdus_in_ampdu_cnt,
+			   stats.tx_octets_in_ampdu_cnt, stats.ampdu_rx_cnt,
+			   stats.mpdu_in_rx_ampdu_cnt,
+			   stats.rx_octets_in_ampdu_cnt,
+			   stats.ampdu_delimiter_crc_error_cnt);
+	}
+
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc read function for log
+ *
+ *  @param inode     pointer to inode
+ *  @param file       file pointer
+ *
+ *  @return        number of data
+ */
+static int
+woal_log_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_log_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_log_read, PDE(inode)->data);
+#endif
+}
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief Proc read function
+ *
+ *  @param sfp     pointer to seq_file structure
+ *  @param data
+ *
+ *  @return        Number of output data or MLAN_STATUS_FAILURE
+ */
+static int
+woal_debug_read(struct seq_file *sfp, void *data)
+{
+	int val = 0;
+	unsigned int i;
+
+	struct debug_data_priv *items_priv =
+		(struct debug_data_priv *)sfp->private;
+	struct debug_data *d = items_priv->items;
+	moal_private *priv = items_priv->priv;
+	mlan_debug_info *info = NULL;
+	t_u32 intf_mask = INTF_MASK << 8;
+	unsigned int j;
+#ifdef SDIO
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	info = &(priv->phandle->debug_info);
+
+	if (MODULE_GET == 0) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	priv->phandle->driver_state = woal_check_driver_status(priv->phandle);
+	/* Get debug information */
+	if (woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info))
+		goto exit;
+
+	for (i = 0; i < (unsigned int)items_priv->num_of_items; i++) {
+		/* If this item is interface specific but card interface is NOT
+		 * correspond type, we will not count it. */
+		if ((d[i].attr & intf_mask) &&
+		    !((d[i].attr & intf_mask) &
+		      (priv->phandle->card_type & intf_mask)))
+			continue;
+
+		if (d[i].size == 1)
+			val = *((t_u8 *)d[i].addr);
+		else if (d[i].size == 2)
+			val = *((t_u16 *)d[i].addr);
+		else if (d[i].size == 4)
+			val = *((t_u32 *)d[i].addr);
+		else {
+			seq_printf(sfp, "%s=", d[i].name);
+			for (j = 0; j < d[i].size; j += 2) {
+				val = *(t_u16 *)(d[i].addr + j);
+				seq_printf(sfp, "0x%x ", val);
+			}
+			seq_printf(sfp, "\n");
+			continue;
+		}
+		if (strstr(d[i].name, "id") || strstr(d[i].name, "bitmap")
+#ifdef PCIE
+		    || strstr(d[i].name, "ptr")
+#endif
+			)
+			seq_printf(sfp, "%s=0x%x\n", d[i].name, val);
+		else
+			seq_printf(sfp, "%s=%d\n", d[i].name, val);
+	}
+#ifdef SDIO
+	if (IS_SD(priv->phandle->card_type)) {
+		mp_aggr_pkt_limit = info->mp_aggr_pkt_limit;
+		seq_printf(sfp, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
+			   info->last_recv_wr_bitmap, info->last_mp_index);
+		seq_printf(sfp,
+			   "last_recv_rd_bitmap=0x%x mp_data_port_mask=0x%x\n",
+			   info->last_recv_rd_bitmap, info->mp_data_port_mask);
+		for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
+			seq_printf(sfp,
+				   "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n",
+				   info->last_mp_wr_bitmap[i],
+				   info->last_mp_wr_ports[i],
+				   info->last_mp_wr_len[i],
+				   info->last_curr_wr_port[i]);
+			for (j = 0; j < mp_aggr_pkt_limit; j++) {
+				seq_printf(sfp, "0x%02x ",
+					   info->last_mp_wr_info
+					   [i * mp_aggr_pkt_limit + j]);
+			}
+			seq_printf(sfp, "\n");
+		}
+		seq_printf(sfp, "SDIO MPA Tx: ");
+		for (i = 0; i < mp_aggr_pkt_limit; i++)
+			seq_printf(sfp, "%d ", info->mpa_tx_count[i]);
+		seq_printf(sfp, "\n");
+		seq_printf(sfp, "SDIO MPA Rx: ");
+		for (i = 0; i < mp_aggr_pkt_limit; i++)
+			seq_printf(sfp, "%d ", info->mpa_rx_count[i]);
+		seq_printf(sfp, "\n");
+		seq_printf(sfp, "SDIO MP Update: ");
+		for (i = 0; i < (mp_aggr_pkt_limit * 2); i++)
+			seq_printf(sfp, "%d ", info->mp_update[i]);
+		seq_printf(sfp, "\n");
+	}
+#endif
+#ifdef PCIE
+	if (IS_PCIE(priv->phandle->card_type)) {
+		seq_printf(sfp, "txbd_rdptr=0x%x txbd_wrptr=0x%x\n",
+			   info->txbd_rdptr, info->txbd_wrptr);
+		seq_printf(sfp, "rxbd_rdptr=0x%x rxbd_wrptr=0x%x\n",
+			   info->rxbd_rdptr, info->rxbd_wrptr);
+		seq_printf(sfp, "eventbd_rdptr=0x%x event_wrptr=0x%x\n",
+			   info->eventbd_rdptr, info->eventbd_wrptr);
+		seq_printf(sfp, "last_wr_index:%d\n",
+			   info->txbd_wrptr & (info->txrx_bd_size - 1));
+		seq_printf(sfp, "txrx bd size:%d\n", info->txrx_bd_size);
+	}
+#endif
+	seq_printf(sfp, "tcp_ack_drop_cnt=%d\n", priv->tcp_ack_drop_cnt);
+	seq_printf(sfp, "tcp_ack_cnt=%d\n", priv->tcp_ack_cnt);
+	seq_printf(sfp, "tcp_ack_payload=%d\n", priv->tcp_ack_payload);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	for (i = 0; i < 4; i++)
+		seq_printf(sfp, "wmm_tx_pending[%d]:%d\n", i,
+			   atomic_read(&priv->wmm_tx_pending[i]));
+#endif
+	if (info->tx_tbl_num) {
+		seq_printf(sfp, "Tx BA stream table:\n");
+		for (i = 0; i < info->tx_tbl_num; i++) {
+			seq_printf(sfp,
+				   "tid = %d, ra = %02x:%02x:%02x:%02x:%02x:%02x amsdu=%d\n",
+				   (int)info->tx_tbl[i].tid,
+				   info->tx_tbl[i].ra[0], info->tx_tbl[i].ra[1],
+				   info->tx_tbl[i].ra[2], info->tx_tbl[i].ra[3],
+				   info->tx_tbl[i].ra[4], info->tx_tbl[i].ra[5],
+				   (int)info->tx_tbl[i].amsdu);
+		}
+	}
+	if (info->rx_tbl_num) {
+		seq_printf(sfp, "Rx reorder table:\n");
+		for (i = 0; i < info->rx_tbl_num; i++) {
+			seq_printf(sfp,
+				   "tid = %d, ta =  %02x:%02x:%02x:%02x:%02x:%02x, start_win = %d, "
+				   "win_size = %d, amsdu=%d",
+				   (int)info->rx_tbl[i].tid,
+				   info->rx_tbl[i].ta[0], info->rx_tbl[i].ta[1],
+				   info->rx_tbl[i].ta[2], info->rx_tbl[i].ta[3],
+				   info->rx_tbl[i].ta[4], info->rx_tbl[i].ta[5],
+				   (int)info->rx_tbl[i].start_win,
+				   (int)info->rx_tbl[i].win_size,
+				   (int)info->rx_tbl[i].amsdu);
+			seq_printf(sfp, "\n");
+
+			seq_printf(sfp, "buffer: ");
+			for (j = 0; j < info->rx_tbl[i].win_size; j++) {
+				if (info->rx_tbl[i].buffer[j] == MTRUE)
+					seq_printf(sfp, "1 ");
+				else
+					seq_printf(sfp, "0 ");
+			}
+			seq_printf(sfp, "\n");
+		}
+	}
+	for (i = 0; i < info->ralist_num; i++) {
+		seq_printf(sfp,
+			   "ralist ra: %02x:%02x:%02x:%02x:%02x:%02x tid=%d pkts=%d pause=%d\n",
+			   info->ralist[i].ra[0], info->ralist[i].ra[1],
+			   info->ralist[i].ra[2], info->ralist[i].ra[3],
+			   info->ralist[i].ra[4], info->ralist[i].ra[5],
+			   info->ralist[i].tid, info->ralist[i].total_pkts,
+			   info->ralist[i].tx_pause);
+	}
+
+	for (i = 0; i < info->tdls_peer_num; i++) {
+		seq_printf(sfp,
+			   "tdls peer: %02x:%02x:%02x:%02x:%02x:%02x snr=%d nf=%d\n",
+			   info->tdls_peer_list[i].mac_addr[0],
+			   info->tdls_peer_list[i].mac_addr[1],
+			   info->tdls_peer_list[i].mac_addr[2],
+			   info->tdls_peer_list[i].mac_addr[3],
+			   info->tdls_peer_list[i].mac_addr[4],
+			   info->tdls_peer_list[i].mac_addr[5],
+			   info->tdls_peer_list[i].snr,
+			   -info->tdls_peer_list[i].nf);
+		seq_printf(sfp, "htcap: ");
+		for (j = 0; j < sizeof(IEEEtypes_HTCap_t); j++)
+			seq_printf(sfp, "%02x ",
+				   info->tdls_peer_list[i].ht_cap[j]);
+		seq_printf(sfp, "\nExtcap: ");
+		for (j = 0; j < sizeof(IEEEtypes_ExtCap_t); j++)
+			seq_printf(sfp, "%02x ",
+				   info->tdls_peer_list[i].ext_cap[j]);
+		seq_printf(sfp, "\n");
+		seq_printf(sfp, "vhtcap: ");
+		for (j = 0; j < sizeof(IEEEtypes_VHTCap_t); j++)
+			seq_printf(sfp, "%02x ",
+				   info->tdls_peer_list[i].vht_cap[j]);
+		seq_printf(sfp, "\n");
+	}
+exit:
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Proc write function
+ *
+ *  @param f       file pointer
+ *  @param buf     pointer to data buffer
+ *  @param count   data number to write
+ *  @param off     Offset
+ *
+ *  @return        number of data
+ */
+static ssize_t
+woal_debug_write(struct file *f, const char __user * buf,
+		 size_t count, loff_t * off)
+{
+	int r, i;
+	char *pdata;
+	char *p;
+	char *p0;
+	char *p1;
+	char *p2;
+	struct seq_file *sfp = f->private_data;
+	struct debug_data_priv *items_priv =
+		(struct debug_data_priv *)sfp->private;
+	struct debug_data *d = items_priv->items;
+	moal_private *priv = items_priv->priv;
+	mlan_debug_info *info = &(priv->phandle->debug_info);
+#ifdef DEBUG_LEVEL1
+	t_u32 last_drvdbg = drvdbg;
+#endif
+	gfp_t flag;
+
+	ENTER();
+
+	if (MODULE_GET == 0) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	pdata = kzalloc(count + 1, flag);
+	if (pdata == NULL) {
+		MODULE_PUT;
+		LEAVE();
+		return 0;
+	}
+
+	if (copy_from_user(pdata, buf, count)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		kfree(pdata);
+		MODULE_PUT;
+		LEAVE();
+		return 0;
+	}
+	pdata[count] = '\0';
+
+	if (woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info)) {
+		kfree(pdata);
+		MODULE_PUT;
+		LEAVE();
+		return 0;
+	}
+
+	p0 = pdata;
+	for (i = 0; i < items_priv->num_of_items; i++) {
+		do {
+			p = strstr(p0, d[i].name);
+			if (p == NULL)
+				break;
+			p1 = strchr(p, '\n');
+			if (p1 == NULL)
+				break;
+			p0 = p1++;
+			p2 = strchr(p, '=');
+			if (!p2)
+				break;
+			p2++;
+			r = woal_string_to_number(p2);
+			if (d[i].size == 1)
+				*((t_u8 *)d[i].addr) = (t_u8)r;
+			else if (d[i].size == 2)
+				*((t_u16 *)d[i].addr) = (t_u16)r;
+			else if (d[i].size == 4)
+				*((t_u32 *)d[i].addr) = (t_u32)r;
+			break;
+		} while (MTRUE);
+	}
+	kfree(pdata);
+
+#ifdef DEBUG_LEVEL1
+	if (last_drvdbg != drvdbg)
+		woal_set_drvdbg(priv, drvdbg);
+#endif
+
+	MODULE_PUT;
+	LEAVE();
+	return count;
+}
+
+static int
+woal_debug_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_debug_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_debug_read, PDE(inode)->data);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops debug_proc_fops = {
+	.proc_open = woal_debug_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+	.proc_write = woal_debug_write,
+};
+#else
+static const struct file_operations debug_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_debug_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = woal_debug_write,
+};
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops histogram_proc_fops = {
+	.proc_open = woal_histogram_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+	.proc_write = woal_histogram_write,
+};
+#else
+static const struct file_operations histogram_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_histogram_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = woal_histogram_write,
+};
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops log_proc_fops = {
+	.proc_open = woal_log_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+#else
+static const struct file_operations log_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_log_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Create debug proc file
+ *
+ *  @param priv    A pointer to a moal_private structure
+ *
+ *  @return        N/A
+ */
+void
+woal_debug_entry(moal_private *priv)
+{
+	struct proc_dir_entry *r;
+	int i;
+	char hist_entry[50];
+	struct debug_data *d = NULL;
+
+	ENTER();
+
+	if (priv->proc_entry == NULL) {
+		LEAVE();
+		return;
+	}
+#ifdef STA_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		priv->items_priv.items = kmalloc(sizeof(items), GFP_KERNEL);
+		if (!priv->items_priv.items) {
+			PRINTM(MERROR,
+			       "Failed to allocate memory for debug data\n");
+			LEAVE();
+			return;
+		}
+		moal_memcpy_ext(priv->phandle, priv->items_priv.items, items,
+				sizeof(items), sizeof(items));
+		priv->items_priv.num_of_items = ARRAY_SIZE(items);
+	}
+#endif
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		priv->items_priv.items = kmalloc(sizeof(uap_items), GFP_KERNEL);
+		if (!priv->items_priv.items) {
+			PRINTM(MERROR,
+			       "Failed to allocate memory for debug data\n");
+			LEAVE();
+			return;
+		}
+		moal_memcpy_ext(priv->phandle, priv->items_priv.items,
+				uap_items, sizeof(uap_items),
+				sizeof(uap_items));
+		priv->items_priv.num_of_items = ARRAY_SIZE(uap_items);
+	}
+#endif
+
+	priv->items_priv.priv = priv;
+
+	d = priv->items_priv.items;
+	for (i = 0; i < priv->items_priv.num_of_items; i++) {
+		if (IS_INFO_ADDR(d[i].attr))
+			d[i].addr += (t_ptr)&(priv->phandle->debug_info);
+		else if (IS_HANDLE_ADDR(d[i].attr))
+			d[i].addr += (t_ptr)(priv->phandle);
+		else if (IS_PRIV_ADDR(d[i].attr))
+			d[i].addr += (t_ptr)(priv);
+		else if (IS_CARD_ADDR(d[i].attr))
+			d[i].addr += (t_ptr)(priv->phandle->card);
+	}
+
+	/* Create proc entry */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	r = proc_create_data("debug", 0644, priv->proc_entry, &debug_proc_fops,
+			     &priv->items_priv);
+	if (r == NULL)
+#else
+	r = create_proc_entry("debug", 0644, priv->proc_entry);
+	if (r) {
+		r->data = &priv->items_priv;
+		r->proc_fops = &debug_proc_fops;
+	} else
+#endif
+	{
+		PRINTM(MMSG, "Fail to create proc debug entry\n");
+		LEAVE();
+		return;
+	}
+	if (priv->bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->hist_entry = proc_mkdir("histogram", priv->proc_entry);
+		if (!priv->hist_entry) {
+			PRINTM(MERROR, "Fail to mkdir histogram!\n");
+			LEAVE();
+			return;
+		}
+		for (i = 0; i < priv->phandle->card_info->histogram_table_num;
+		     i++) {
+			priv->hist_proc[i].ant_idx = i;
+			priv->hist_proc[i].priv = priv;
+			snprintf(hist_entry, sizeof(hist_entry), "wlan-ant%d",
+				 i);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			r = proc_create_data(hist_entry, 0644, priv->hist_entry,
+					     &histogram_proc_fops,
+					     &priv->hist_proc[i]);
+			if (r == NULL)
+#else
+			r = create_proc_entry("histogram", 0644,
+					      priv->hist_entry);
+			if (r) {
+				r->data = &priv->hist_proc[i];
+				r->proc_fops = &histogram_proc_fops;
+			} else
+#endif
+			{
+				PRINTM(MMSG,
+				       "Fail to create proc histogram entry %s\n",
+				       hist_entry);
+				LEAVE();
+				return;
+			}
+		}
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	r = proc_create_data("log", 0644, priv->proc_entry, &log_proc_fops,
+			     priv);
+	if (r == NULL)
+#else
+	r = create_proc_entry("log", 0644, priv->proc_entry);
+	if (r) {
+		r->data = priv;
+		r->proc_fops = &log_proc_fops;
+	} else
+#endif
+	{
+		PRINTM(MMSG, "Fail to create proc log entry\n");
+		LEAVE();
+		return;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Remove proc file
+ *
+ *  @param priv  A pointer to a moal_private structure
+ *
+ *  @return      N/A
+ */
+void
+woal_debug_remove(moal_private *priv)
+{
+	char hist_entry[50];
+	int i;
+	ENTER();
+
+	kfree(priv->items_priv.items);
+	/* Remove proc entry */
+	remove_proc_entry("debug", priv->proc_entry);
+	if (priv->bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		for (i = 0; i < priv->phandle->card_info->histogram_table_num;
+		     i++) {
+			snprintf(hist_entry, sizeof(hist_entry), "wlan-ant%d",
+				 i);
+			remove_proc_entry(hist_entry, priv->hist_entry);
+		}
+		remove_proc_entry("histogram", priv->proc_entry);
+	}
+	remove_proc_entry("log", priv->proc_entry);
+
+	LEAVE();
+}
+#endif
diff --git a/wlan_sd8987/mlinux/moal_eth_ioctl.c b/wlan_sd8987/mlinux/moal_eth_ioctl.c
new file mode 100755
index 0000000..58e4aa7
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_eth_ioctl.c
@@ -0,0 +1,17674 @@
+
+/** @file  moal_eth_ioctl.c
+  *
+  * @brief This file contains private ioctl functions
+
+  *
+  * Copyright 2014-2021 NXP
+  *
+  * This software file (the File) is distributed by NXP
+  * under the terms of the GNU General Public License Version 2, June 1991
+  * (the License).  You may use, redistribute and/or modify the File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/************************************************************************
+Change log:
+    01/05/2012: initial version
+************************************************************************/
+
+#include "moal_main.h"
+#include "moal_eth_ioctl.h"
+#include "mlan_ioctl.h"
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+#include "moal_priv.h"
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#endif
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+#ifdef USB
+#include "moal_usb.h"
+#endif
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif
+#ifdef PCIE
+#include "moal_pcie.h"
+#endif
+#ifdef STA_CFG80211
+#include "moal_sta_cfg80211.h"
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#include "moal_cfg80211_util.h"
+#endif
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/** Bands supported in Infra mode */
+static t_u16 SupportedInfraBand[] = {
+	BAND_B,
+	BAND_B | BAND_G,
+	BAND_G,
+	BAND_GN,
+	BAND_B | BAND_G | BAND_GN,
+	BAND_G | BAND_GN,
+	BAND_A,
+	BAND_B | BAND_A,
+	BAND_B | BAND_G | BAND_A,
+	BAND_G | BAND_A,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN,
+	BAND_A | BAND_G | BAND_AN | BAND_GN,
+	BAND_A | BAND_AN,
+	BAND_GN | BAND_GAC,
+	BAND_B | BAND_G | BAND_GN | BAND_GAC,
+	BAND_G | BAND_GN | BAND_GAC,
+	BAND_GN | BAND_GAC | BAND_GAX,
+	BAND_B | BAND_G | BAND_GN | BAND_GAC | BAND_GAX,
+	BAND_G | BAND_GN | BAND_GAC | BAND_GAX,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_GAC,
+	BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
+	BAND_A | BAND_AN | BAND_AAC,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_GAC |
+		BAND_AAX,
+	BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX,
+	BAND_A | BAND_AN | BAND_AAC | BAND_AAX,
+};
+
+/** Bands supported in Ad-Hoc mode */
+static t_u8 SupportedAdhocBand[] = {
+	BAND_B,
+	BAND_B | BAND_G,
+	BAND_G,
+	BAND_A,
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#ifdef UAP_SUPPORT
+/** Network device handlers for uAP */
+extern const struct net_device_ops woal_uap_netdev_ops;
+#endif
+#ifdef STA_SUPPORT
+/** Network device handlers for STA */
+extern const struct net_device_ops woal_netdev_ops;
+#endif
+#endif
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ * @brief Parse a string to extract numerical arguments
+ *
+ * @param pos           Pointer to the arguments string
+ * @param data          Pointer to the arguments buffer
+ * @param datalen       Length of the arguments buffer
+ * @param user_data_len Pointer to the number of arguments extracted
+ *
+ * @return              MLAN_STATUS_SUCCESS
+ */
+static mlan_status
+parse_arguments(t_u8 *pos, int *data, int datalen, int *user_data_len)
+{
+	int i, j, k;
+	char cdata[10];
+	int is_hex = 0;
+
+	if (strlen(pos) == 0) {
+		*user_data_len = 0;
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	memset(cdata, 0, sizeof(cdata));
+	for (i = 0, j = 0, k = 0; i <= (int)strlen(pos); i++) {
+		if ((k == 0) && (i <= (int)(strlen(pos) - 2))) {
+			if ((pos[i] == '0') && (pos[i + 1] == 'x')) {
+				is_hex = 1;
+				i = i + 2;
+			}
+		}
+		if (pos[i] == '\0' || pos[i] == ' ') {
+			if (j >= datalen) {
+				j++;
+				break;
+			}
+			if (is_hex) {
+				data[j] = woal_atox(cdata);
+				is_hex = 0;
+			} else {
+				woal_atoi(&data[j], cdata);
+			}
+			j++;
+			k = 0;
+			memset(cdata, 0, sizeof(cdata));
+			if (pos[i] == '\0')
+				break;
+		} else {
+			if (k >= (int)sizeof(cdata)) {
+				PRINTM(MERROR, "Invalid numerical arguments\n");
+				break;
+			}
+			cdata[k] = pos[i];
+			k++;
+		}
+	}
+
+	*user_data_len = j;
+	return MLAN_STATUS_SUCCESS;
+}
+
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+/**
+ *  @brief Set wps & p2p ie in AP mode
+ *
+ *  @param priv         Pointer to priv stucture
+ *  @param ie           Pointer to ies data
+ *  @param len          Length of data
+ *
+ *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_ap_wps_p2p_ie(moal_private *priv, t_u8 *ie, size_t len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *pos = ie;
+	int ie_len;
+
+	ENTER();
+
+	ie_len = len - 2;
+	if (ie_len <= 0) {
+		PRINTM(MERROR, "IE len error: %d\n", ie_len);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Android cmd format:
+	 * "SET_AP_WPS_P2P_IE 1"  -- beacon IE
+	 * "SET_AP_WPS_P2P_IE 2"  -- proberesp IE
+	 * "SET_AP_WPS_P2P_IE 4"  -- assocresp IE
+	 */
+	if (*pos == '1') {
+		/* set the beacon wps/p2p ies */
+		pos += 2;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_mgmt_frame_ie(priv, pos, ie_len, NULL, 0,
+						NULL, 0, NULL, 0,
+						MGMT_MASK_BEACON_WPS_P2P,
+						MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (*pos == '2') {
+		/* set the probe resp ies */
+		pos += 2;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, pos, ie_len,
+						NULL, 0, NULL, 0,
+						MGMT_MASK_PROBE_RESP,
+						MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Failed to set probe resp ie\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (*pos == '4') {
+		/* set the assoc resp ies */
+		pos += 2;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, pos,
+						ie_len, NULL, 0,
+						MGMT_MASK_ASSOC_RESP,
+						MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Failed to set assoc resp ie\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/**
+ *  @brief Set miracast mode
+ *
+ *  @param priv         Pointer to priv stucture
+ *  @param pdata        Pointer to cmd buffer
+ *  @param len          Length of data
+ *
+ *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+static mlan_status
+woal_set_miracast_mode(moal_private *priv, t_u8 *pdata, size_t len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *pos = pdata;
+
+	ENTER();
+	if (!pos || (len == 0)) {
+		PRINTM(MERROR, "%s: Null buf!\n", __func__);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	while (!isdigit(*pos) && --len > 0)
+		pos++;
+	switch (*pos) {
+	case '0':
+		/* disable miracast mode */
+		priv->phandle->miracast_mode = 0;
+		break;
+	case '1':
+		/* Source */
+		priv->phandle->miracast_mode = 1;
+		break;
+	case '2':
+		/* Sink */
+		priv->phandle->miracast_mode = 2;
+		break;
+	default:
+		PRINTM(MERROR, "%s: Unknown miracast mode (%c)\n",
+		       priv->netdev->name, *pos);
+		ret = MLAN_STATUS_FAILURE;
+		break;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ *  @brief Get Driver Version
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_get_priv_driver_version(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	int len = 0, ret = -1;
+	char buf[MLAN_MAX_VER_STR_LEN];
+
+	ENTER();
+
+	if (!respbuf) {
+		LEAVE();
+		return 0;
+	}
+
+	memset(buf, 0, sizeof(buf));
+
+	/* Get version string to local buffer */
+	woal_get_version(priv->phandle, buf, sizeof(buf) - 1);
+	len = strlen(buf);
+
+	if (len) {
+		/* Copy back the retrieved version string */
+		PRINTM(MINFO, "MOAL VERSION: %s\n", buf);
+		ret = MIN(len, (int)(respbuflen - 1));
+		moal_memcpy_ext(priv->phandle, respbuf, buf, ret,
+				respbuflen - 1);
+	} else {
+		ret = -1;
+		PRINTM(MERROR, "Get version failed!\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Hostcmd interface from application
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *  @param wait_option  Wait option
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+int
+woal_priv_hostcmd(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen,
+		  t_u8 wait_option)
+{
+	int ret = 0;
+	t_u8 *data_ptr;
+	t_u32 buf_len = 0;
+	HostCmd_Header cmd_header;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_HOSTCMD));
+	buf_len = *((t_u32 *)data_ptr);
+	moal_memcpy_ext(priv->phandle, &cmd_header, data_ptr + sizeof(buf_len),
+			sizeof(HostCmd_Header), sizeof(HostCmd_Header));
+
+	PRINTM(MINFO, "Host command len = %d\n",
+	       woal_le16_to_cpu(cmd_header.size));
+	if (woal_le16_to_cpu(cmd_header.size) > MRVDRV_SIZE_OF_CMD_BUFFER) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_HOST_CMD;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	misc_cfg->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
+	/* get the whole command */
+	moal_memcpy_ext(priv->phandle, misc_cfg->param.hostcmd.cmd,
+			data_ptr + sizeof(buf_len), misc_cfg->param.hostcmd.len,
+			MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto error;
+	}
+	ret = misc_cfg->param.hostcmd.len + sizeof(buf_len) + strlen(CMD_NXP) +
+		strlen(PRIV_CMD_HOSTCMD);
+	if (ret > (int)respbuflen) {
+		ret = -EFAULT;
+		goto error;
+	}
+	moal_memcpy_ext(priv->phandle, data_ptr + sizeof(buf_len),
+			misc_cfg->param.hostcmd.cmd,
+			misc_cfg->param.hostcmd.len,
+			respbuflen - (strlen(CMD_NXP) +
+				      strlen(PRIV_CMD_HOSTCMD) +
+				      sizeof(buf_len)));
+	moal_memcpy_ext(priv->phandle, data_ptr,
+			(t_u8 *)&misc_cfg->param.hostcmd.len, sizeof(t_u32),
+			sizeof(t_u32));
+
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               configure 11ax HE capability or HE operation
+ *
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param len          length used
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_setget_priv_11axcmdcfg(moal_private *priv, t_u8 *respbuf,
+			    t_u32 respbuflen, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ax_cmd_cfg *cfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int header_len = 0, user_data_len = 0;
+	int data[3] = { 0 };
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ax_cmd_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_11AX_CFG;
+	req->action = MLAN_ACT_SET;
+
+	cfg = (mlan_ds_11ax_cmd_cfg *) req->pbuf;
+	cfg->sub_command = MLAN_OID_11AX_CMD_CFG;
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	PRINTM(MINFO, "data_len=%d,data=%d,%d,%d\n", user_data_len, data[0],
+	       data[1], data[2]);
+
+	if (user_data_len > 3 || user_data_len == 0) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EFAULT;
+		goto done;
+	} else if (user_data_len == 1) {
+		req->action = MLAN_ACT_GET;
+	}
+
+	switch (data[0]) {
+	case MLAN_11AXCMD_CFG_ID_SR_OBSS_PD_OFFSET:
+		cfg->sub_id = MLAN_11AXCMD_SR_SUBID;
+		cfg->param.sr_cfg.type = MRVL_DOT11AX_OBSS_PD_OFFSET_TLV_ID;
+		cfg->param.sr_cfg.len = sizeof(mlan_11axcmdcfg_obss_pd_offset);
+		cfg->param.sr_cfg.param.obss_pd_offset.offset[0] = data[1];
+		cfg->param.sr_cfg.param.obss_pd_offset.offset[1] = data[2];
+		break;
+	case MLAN_11AXCMD_CFG_ID_SR_ENABLE:
+		cfg->sub_id = MLAN_11AXCMD_SR_SUBID;
+		cfg->param.sr_cfg.type = MRVL_DOT11AX_ENABLE_SR_TLV_ID;
+		cfg->param.sr_cfg.len = sizeof(mlan_11axcmdcfg_sr_control);
+		cfg->param.sr_cfg.param.sr_control.control = data[1];
+		break;
+	case MLAN_11AXCMD_CFG_ID_BEAM_CHANGE:
+		cfg->sub_id = MLAN_11AXCMD_BEAM_SUBID;
+		cfg->param.beam_cfg.value = data[1];
+		break;
+	case MLAN_11AXCMD_CFG_ID_HTC_ENABLE:
+		cfg->sub_id = MLAN_11AXCMD_HTC_SUBID;
+		cfg->param.htc_cfg.value = data[1];
+		break;
+	case MLAN_11AXCMD_CFG_ID_TXOP_RTS:
+		cfg->sub_id = MLAN_11AXCMD_TXOPRTS_SUBID;
+		cfg->param.txop_cfg.rts_thres = data[1];
+		break;
+	case MLAN_11AXCMD_CFG_ID_TX_OMI:
+		cfg->sub_id = MLAN_11AXCMD_TXOMI_SUBID;
+		cfg->param.txomi_cfg.omi = data[1];
+		break;
+	case MLAN_11AXCMD_CFG_ID_OBSSNBRU_TOLTIME:
+		cfg->sub_id = MLAN_11AXCMD_OBSS_TOLTIME_SUBID;
+		cfg->param.toltime_cfg.tol_time = data[1];
+		break;
+	default:
+		PRINTM(MERROR, "unknown 11axcmd\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, &req->action,
+			sizeof(req->action), sizeof(req->action));
+	respbuf += sizeof(req->action);
+
+	cfg = (mlan_ds_11ax_cmd_cfg *) respbuf;
+	moal_memcpy_ext(priv->phandle, cfg, req->pbuf,
+			sizeof(mlan_ds_11ax_cmd_cfg), respbuflen);
+
+	ret = sizeof(req->action) + sizeof(mlan_ds_11ax_cmd_cfg);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief             Set/get range ext mode
+ *
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param len          length used
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_setget_priv_range_ext(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[1];
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RANGE_EXT);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_RANGE_EXT;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid Parameter\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[0] < 0 || data[0] > 2) {
+			PRINTM(MERROR,
+			       "Invalid Parameter: range_ext mode 0-2\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		misc->param.range_ext_mode = (t_u8)data[0];
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.range_ext_mode;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u32 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Custom IE setting
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_customie(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	t_u8 *data_ptr;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_custom_ie *pcustom_ie = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_CUSTOMIE));
+
+	pcustom_ie = (mlan_ds_misc_custom_ie *)data_ptr;
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((pcustom_ie->len == 0) ||
+	    (pcustom_ie->len == sizeof(pcustom_ie->ie_data_list[0].ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, &misc->param.cust_ie, pcustom_ie,
+			sizeof(mlan_ds_misc_custom_ie),
+			sizeof(mlan_ds_misc_custom_ie));
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	pcustom_ie = (mlan_ds_misc_custom_ie *)data_ptr;
+	moal_memcpy_ext(priv->phandle, pcustom_ie, &misc->param.cust_ie,
+			sizeof(mlan_ds_misc_custom_ie),
+			respbuflen -
+			(strlen(CMD_NXP) + strlen(PRIV_CMD_CUSTOMIE)));
+	ret = sizeof(mlan_ds_misc_custom_ie);
+	if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) {
+		/* send a separate error code to indicate error from driver */
+		ret = EFAULT;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Band and Adhoc-band setting
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_bandcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	unsigned int i;
+	int data[3];
+	int user_data_len = 0;
+	t_u32 infra_band = 0;
+	t_u32 adhoc_band = 0;
+	t_u32 adhoc_channel = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+	mlan_ds_band_cfg *band_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_BANDCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_BANDCFG),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	if (user_data_len > 0) {
+		if (priv->media_connected == MTRUE) {
+			LEAVE();
+			return -EOPNOTSUPP;
+		}
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+
+	if (user_data_len == 0) {
+		/* Get config_bands, adhoc_start_band and adhoc_channel values
+		 * from MLAN
+		 */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* To support only <b/bg/bgn/n/aac/gac> */
+		infra_band = data[0];
+		for (i = 0; i < (sizeof(SupportedInfraBand) /
+				 sizeof(SupportedInfraBand[0])); i++)
+			if (infra_band == SupportedInfraBand[i])
+				break;
+		if (i == sizeof(SupportedInfraBand)) {
+			ret = -EINVAL;
+			goto error;
+		}
+
+		/* Set Adhoc band */
+		if (user_data_len >= 2) {
+			adhoc_band = data[1];
+			for (i = 0; i < sizeof(SupportedAdhocBand); i++)
+				if (adhoc_band == SupportedAdhocBand[i])
+					break;
+			if (i == sizeof(SupportedAdhocBand)) {
+				ret = -EINVAL;
+				goto error;
+			}
+		}
+
+		/* Set Adhoc channel */
+		if (user_data_len >= 3) {
+			adhoc_channel = data[2];
+			if (adhoc_channel == 0) {
+				/* Check if specified adhoc channel is non-zero
+				 */
+				ret = -EINVAL;
+				goto error;
+			}
+		}
+		/* Set config_bands and adhoc_start_band values to MLAN */
+		req->action = MLAN_ACT_SET;
+		radio_cfg->param.band_cfg.config_bands = infra_band;
+		radio_cfg->param.band_cfg.adhoc_start_band = adhoc_band;
+		radio_cfg->param.band_cfg.adhoc_channel = adhoc_channel;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	band_cfg = (mlan_ds_band_cfg *)respbuf;
+
+	moal_memcpy_ext(priv->phandle, band_cfg, &radio_cfg->param.band_cfg,
+			sizeof(mlan_ds_band_cfg), respbuflen);
+
+	ret = sizeof(mlan_ds_band_cfg);
+
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11n configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_httxcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[2];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_HTTXCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_HTTXCFG),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (user_data_len == 0) {
+		/* Get 11n tx parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
+	} else {
+		cfg_11n->param.tx_cfg.httxcap = data[0];
+		PRINTM(MINFO, "SET: httxcap:0x%x\n", data[0]);
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BOTH;
+		if (user_data_len == 2) {
+			if (data[1] != BAND_SELECT_BG &&
+			    data[1] != BAND_SELECT_A &&
+			    data[1] != BAND_SELECT_BOTH) {
+				PRINTM(MERROR, "Invalid band selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			cfg_11n->param.tx_cfg.misc_cfg = data[1];
+			PRINTM(MINFO, "SET: httxcap band:0x%x\n", data[1]);
+		}
+		/* Update 11n tx parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data[0] = cfg_11n->param.tx_cfg.httxcap;
+	PRINTM(MINFO, "GET: httxcap:0x%x\n", data[0]);
+
+	if (req->action == MLAN_ACT_GET) {
+		cfg_11n->param.tx_cfg.httxcap = 0;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		data[1] = cfg_11n->param.tx_cfg.httxcap;
+		PRINTM(MINFO, "GET: httxcap for 5GHz:0x%x\n", data[1]);
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, data, sizeof(data), respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11n capability information
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_htcapinfo(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[2];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	woal_ht_cap_info *ht_cap = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_HTCAPINFO))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_HTCAPINFO),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (user_data_len == 0) {
+		/* Get 11n tx parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BG;
+	} else {
+		cfg_11n->param.htcap_cfg.htcap = data[0];
+		PRINTM(MINFO, "SET: htcapinfo:0x%x\n", data[0]);
+		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BOTH;
+		if (user_data_len == 2) {
+			if (data[1] != BAND_SELECT_BG &&
+			    data[1] != BAND_SELECT_A &&
+			    data[1] != BAND_SELECT_BOTH) {
+				PRINTM(MERROR, "Invalid band selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			cfg_11n->param.htcap_cfg.misc_cfg = data[1];
+			PRINTM(MINFO, "SET: htcapinfo band:0x%x\n", data[1]);
+		}
+		/* Update 11n tx parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data[0] = cfg_11n->param.htcap_cfg.htcap;
+	PRINTM(MINFO, "GET: htcapinfo for 2.4GHz:0x%x\n", data[0]);
+
+	if (req->action == MLAN_ACT_GET) {
+		cfg_11n->param.htcap_cfg.htcap = 0;
+		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		data[1] = cfg_11n->param.htcap_cfg.htcap;
+		PRINTM(MINFO, "GET: htcapinfo for 5GHz:0x%x\n", data[1]);
+	}
+
+	ht_cap = (woal_ht_cap_info *)respbuf;
+	ht_cap->ht_cap_info_bg = data[0];
+	ht_cap->ht_cap_info_a = data[1];
+	ret = sizeof(woal_ht_cap_info);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get add BA parameters
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_addbapara(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[5];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	woal_addba *addba = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_ADDBAPARA))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_ADDBAPARA),
+				data, ARRAY_SIZE(data), &user_data_len);
+
+		if (user_data_len != ARRAY_SIZE(data)) {
+			PRINTM(MERROR, "Invalid number of arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] < 0 || data[0] > MLAN_DEFAULT_BLOCK_ACK_TIMEOUT) {
+			PRINTM(MERROR, "Incorrect addba timeout value.\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[1] <= 0 || data[1] > MLAN_AMPDU_MAX_TXWINSIZE ||
+		    data[2] <= 0 || data[2] > MLAN_AMPDU_MAX_RXWINSIZE) {
+			PRINTM(MERROR, "Incorrect Tx/Rx window size.\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[3] < 0 || data[3] > 1 || data[4] < 0 || data[4] > 1) {
+			PRINTM(MERROR, "Incorrect Tx/Rx amsdu.\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (user_data_len == 0) {
+		/* Get add BA parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+	} else {
+		cfg_11n->param.addba_param.timeout = data[0];
+		cfg_11n->param.addba_param.txwinsize = data[1];
+		cfg_11n->param.addba_param.rxwinsize = data[2];
+		cfg_11n->param.addba_param.txamsdu = data[3];
+		cfg_11n->param.addba_param.rxamsdu = data[4];
+		PRINTM(MINFO,
+		       "SET: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d rxamsdu=%d\n",
+		       data[0], data[1], data[2], data[3], data[4]);
+		/* Update add BA parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	addba = (woal_addba *)respbuf;
+
+	addba->time_out = cfg_11n->param.addba_param.timeout;
+	addba->tx_win_size = cfg_11n->param.addba_param.txwinsize;
+	addba->rx_win_size = cfg_11n->param.addba_param.rxwinsize;
+	addba->tx_amsdu = cfg_11n->param.addba_param.txamsdu;
+	addba->rx_amsdu = cfg_11n->param.addba_param.rxamsdu;
+	PRINTM(MINFO,
+	       "GET: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d, rxamsdu=%d\n",
+	       addba->time_out, addba->tx_win_size, addba->rx_win_size,
+	       addba->tx_amsdu, addba->rx_amsdu);
+
+	ret = sizeof(woal_addba);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Delete selective BA based on parameters
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_delba(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[2] = { 0xFF, 0xFF };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_ds_11n_delba *del_ba = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	int header_len = 0;
+	t_u8 *mac_pos = NULL;
+	t_u8 peer_mac[ETH_ALEN] = { 0 };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DELBA);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* Incorrect number of arguments */
+		PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mac_pos = strstr(respbuf + header_len, " ");
+	if (mac_pos)
+		mac_pos = strstr(mac_pos + 1, " ");
+	if (mac_pos) {
+#define MAC_STRING_LENGTH 17
+		if (strlen(mac_pos + 1) != MAC_STRING_LENGTH) {
+			PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+			ret = -EINVAL;
+			goto done;
+		}
+		woal_mac2u8(peer_mac, mac_pos + 1);
+		*mac_pos = '\0';
+	}
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (mac_pos)
+		user_data_len++;
+
+	if (user_data_len > 3 || (!(data[0] & (DELBA_TX | DELBA_RX))) ||
+	    (data[1] != DELBA_ALL_TIDS && !(data[1] <= 7))) {
+		/* Incorrect number of arguments */
+		PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_DELBA;
+
+	del_ba = &cfg_11n->param.del_ba;
+	memset(del_ba, 0, sizeof(mlan_ds_11n_delba));
+	del_ba->direction = (t_u8)data[0];
+	del_ba->tid = DELBA_ALL_TIDS;
+	if (user_data_len > 1)
+		del_ba->tid = (t_u8)data[1];
+	if (user_data_len > 2)
+		moal_memcpy_ext(priv->phandle, del_ba->peer_mac_addr, peer_mac,
+				ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = sprintf(respbuf, "OK. BA deleted successfully.\n") + 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the reject addba requst conditions
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_rejectaddbareq(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[1];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_NXP) + strlen(PRIV_CMD_REJECTADDBAREQ))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_REJECTADDBAREQ),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_REJECT_ADDBA_REQ;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (user_data_len == 0) {
+		/* Get the reject addba req conditions */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* Set the reject addba req conditions */
+		cfg_11n->param.reject_addba_req.conditions = data[0];
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (req->action == MLAN_ACT_GET) {
+		sprintf(respbuf, "0x%x",
+			cfg_11n->param.reject_addba_req.conditions);
+		ret = strlen(respbuf) + 1;
+	} else {
+		ret = sprintf(respbuf, "OK\n") + 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get the addba reject setting
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action set or get
+ *  @param addba_reject A pointer to addba_reject array.
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_ioctl_addba_reject(moal_private *priv, t_u32 action, t_u8 *addba_reject)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	req->action = action;
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, cfg_11n->param.addba_reject,
+				addba_reject,
+				sizeof(cfg_11n->param.addba_reject),
+				sizeof(cfg_11n->param.addba_reject));
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, addba_reject,
+				cfg_11n->param.addba_reject,
+				sizeof(cfg_11n->param.addba_reject),
+				MAX_NUM_TID);
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get addba prio_tbl
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action set or get
+ *  @param aggr_prio_tbl  A pointer to mlan_ds_11n_aggr_prio_tbl.
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_ioctl_aggr_prio_tbl(moal_private *priv, t_u32 action,
+			 mlan_ds_11n_aggr_prio_tbl *aggr_prio_tbl)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	req->action = action;
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &cfg_11n->param.aggr_prio_tbl,
+				aggr_prio_tbl,
+				sizeof(mlan_ds_11n_aggr_prio_tbl),
+				sizeof(mlan_ds_11n_aggr_prio_tbl));
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, aggr_prio_tbl,
+				&cfg_11n->param.aggr_prio_tbl,
+				sizeof(mlan_ds_11n_aggr_prio_tbl),
+				sizeof(mlan_ds_11n_aggr_prio_tbl));
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get addba_param
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action set or get
+ *  @param addba_param  A pointer to mlan_ds_11n_addba_param.
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_ioctl_addba_param(moal_private *priv, t_u32 action,
+		       mlan_ds_11n_addba_param *addba_param)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	req->action = action;
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &cfg_11n->param.addba_param,
+				addba_param, sizeof(mlan_ds_11n_addba_param),
+				sizeof(mlan_ds_11n_addba_param));
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, addba_param,
+				&cfg_11n->param.addba_param,
+				sizeof(mlan_ds_11n_addba_param),
+				sizeof(mlan_ds_11n_addba_param));
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *   @brief Configuring rx block-ack window size
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise failure
+ */
+static int
+woal_set_rx_ba_winsize(moal_private *priv, t_u8 *respbuf, int respbuflen)
+{
+	int data[2];
+	t_u8 addba_reject[MAX_NUM_TID];
+	mlan_ds_11n_addba_param addba_param;
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	memset((char *)data, 0, sizeof(data));
+	if (respbuf && strlen(respbuf) > 0)
+		parse_arguments(respbuf, data, ARRAY_SIZE(data),
+				&user_data_len);
+
+	if (user_data_len != 2) {
+		PRINTM(MERROR, "Invalid arguments for ba_winsize command\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data[0] > 7 || data[0] < 0) {
+		PRINTM(MERROR, "Invalid tid %d\n", data[0]);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data[1] < 0) {
+		PRINTM(MERROR, "Invalid winsize %d\n", data[1]);
+		ret = -EINVAL;
+		goto done;
+	}
+	memset(addba_reject, 0, sizeof(addba_reject));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_ioctl_addba_reject(priv, MLAN_ACT_GET, addba_reject)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	/* disable tx ba */
+	if (data[1] == 0) {
+		addba_reject[data[0]] = MTRUE;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_ioctl_addba_reject(priv, MLAN_ACT_SET, addba_reject))
+			ret = -EFAULT;
+	} else {
+		if (addba_reject[data[0]] == MTRUE) {
+			addba_reject[data[0]] = MFALSE;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_ioctl_addba_reject(priv, MLAN_ACT_SET,
+						    addba_reject)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+		memset(&addba_param, 0, sizeof(addba_param));
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_ioctl_addba_param(priv, MLAN_ACT_GET, &addba_param)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[1] != (int)addba_param.rxwinsize) {
+			addba_param.rxwinsize = data[1];
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_ioctl_addba_param(priv, MLAN_ACT_SET,
+						   &addba_param))
+				 ret = -EFAULT;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *   @brief Configuring trx block-ack window size
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise failure
+ */
+static int
+woal_set_tx_ba_winsize(moal_private *priv, t_u8 *respbuf, int respbuflen)
+{
+	int data[2];
+	mlan_ds_11n_aggr_prio_tbl aggr_prio_tbl;
+	mlan_ds_11n_addba_param addba_param;
+	t_u8 tos_to_tid_inv[] = { 0x02, 0x00, 0x01, 0x03,
+		0x04, 0x05, 0x06, 0x07
+	};
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	memset((char *)data, 0, sizeof(data));
+	if (respbuf && strlen(respbuf) > 0)
+		parse_arguments(respbuf, data, ARRAY_SIZE(data),
+				&user_data_len);
+
+	if (user_data_len != 2) {
+		PRINTM(MERROR, "Invalid arguments for ba_winsize command\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data[0] > 7 || data[0] < 0) {
+		PRINTM(MERROR, "Invalid tid %d\n", data[0]);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data[1] < 0) {
+		PRINTM(MERROR, "Invalid winsize %d\n", data[1]);
+		ret = -EINVAL;
+		goto done;
+	}
+	memset(&aggr_prio_tbl, 0, sizeof(aggr_prio_tbl));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_ioctl_aggr_prio_tbl(priv, MLAN_ACT_GET, &aggr_prio_tbl)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	/* disable tx ba */
+	if (data[1] == 0) {
+		if (aggr_prio_tbl.ampdu[data[0]] != 0xff) {
+			aggr_prio_tbl.ampdu[data[0]] = 0xff;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_ioctl_aggr_prio_tbl(priv, MLAN_ACT_SET,
+						     &aggr_prio_tbl))
+				 ret = -EFAULT;
+		}
+	} else {
+		if (aggr_prio_tbl.ampdu[data[0]] == 0xff) {
+			aggr_prio_tbl.ampdu[data[0]] = tos_to_tid_inv[data[0]];
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_ioctl_aggr_prio_tbl(priv, MLAN_ACT_SET,
+						     &aggr_prio_tbl)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+		memset(&addba_param, 0, sizeof(addba_param));
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_ioctl_addba_param(priv, MLAN_ACT_GET, &addba_param)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[1] != (int)addba_param.txwinsize) {
+			addba_param.txwinsize = data[1];
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_ioctl_addba_param(priv, MLAN_ACT_SET,
+						   &addba_param))
+				 ret = -EFAULT;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get aggregation priority table configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_aggrpriotbl(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	int data[MAX_NUM_TID * 2], i, j;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_AGGRPRIOTBL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_AGGRPRIOTBL),
+				data, ARRAY_SIZE(data), &user_data_len);
+
+		if (user_data_len != ARRAY_SIZE(data)) {
+			PRINTM(MERROR, "Invalid number of arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		for (i = 0, j = 0; i < user_data_len; i = i + 2, ++j) {
+			if ((data[i] > 7 && data[i] != 0xff) ||
+			    (data[i + 1] > 7 && data[i + 1] != 0xff)) {
+				PRINTM(MERROR,
+				       "Invalid priority, valid value 0-7 or 0xff.\n");
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (user_data_len == 0) {
+		/* Get aggr priority table from MLAN */
+		req->action = MLAN_ACT_GET;
+	} else {
+		for (i = 0, j = 0; i < user_data_len; i = i + 2, ++j) {
+			cfg_11n->param.aggr_prio_tbl.ampdu[j] = data[i];
+			cfg_11n->param.aggr_prio_tbl.amsdu[j] = data[i + 1];
+		}
+		/* Update aggr priority table in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	for (i = 0, j = 0; i < (MAX_NUM_TID * 2); i = i + 2, ++j) {
+		respbuf[i] = cfg_11n->param.aggr_prio_tbl.ampdu[j];
+		respbuf[i + 1] = cfg_11n->param.aggr_prio_tbl.amsdu[j];
+	}
+
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Add BA reject configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_addbareject(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	int data[MAX_NUM_TID], i;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_ADDBAREJECT))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_ADDBAREJECT),
+				data, ARRAY_SIZE(data), &user_data_len);
+
+		if (user_data_len != ARRAY_SIZE(data)) {
+			PRINTM(MERROR, "Invalid number of arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		for (i = 0; i < user_data_len; i++) {
+			if (data[i] != 0 && data[i] != 1) {
+				PRINTM(MERROR,
+				       "addba reject only takes argument as 0 or 1\n");
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (user_data_len == 0) {
+		/* Get add BA reject configuration from MLAN */
+		req->action = MLAN_ACT_GET;
+	} else {
+		for (i = 0; i < user_data_len; i++)
+			cfg_11n->param.addba_reject[i] = data[i];
+		/* Update add BA reject configuration in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	for (i = 0; i < MAX_NUM_TID; i++)
+		respbuf[i] = cfg_11n->param.addba_reject[i];
+
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11AC configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_vhtcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[6];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ac_cfg *cfg_11ac = NULL;
+	mlan_ds_11ac_vht_cfg *vhtcfg = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_VHTCFG))) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	memset((char *)data, 0, sizeof(data));
+	parse_arguments(respbuf + strlen(CMD_NXP) + strlen(PRIV_CMD_VHTCFG),
+			data, ARRAY_SIZE(data), &user_data_len);
+
+	if ((user_data_len > 6) || (user_data_len < 2)) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
+	cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
+	req->req_id = MLAN_IOCTL_11AC_CFG;
+
+	/* Band */
+	if ((data[0] < 0) || (data[0] > 2)) {
+		PRINTM(MERROR, "Invalid band selection\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		if (data[0] == BAND_SELECT_BOTH) {
+			cfg_11ac->param.vht_cfg.band =
+				(BAND_SELECT_BG | BAND_SELECT_A);
+		} else {
+			cfg_11ac->param.vht_cfg.band = data[0];
+		}
+		PRINTM(MINFO, "GET/SET: vhtcfg band: 0x%x\n", data[0]);
+	}
+
+	/* Tx/Rx */
+	if ((data[1] <= 0) || (data[1] > 3)) {
+		PRINTM(MERROR, "Invalid Tx/Rx selection\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		cfg_11ac->param.vht_cfg.txrx = data[1];
+		PRINTM(MINFO, "GET/SET: vhtcfg txrx: 0x%x\n", data[1]);
+	}
+
+	if (user_data_len == 2) {
+		/* GET operation */
+		if (data[0] == BAND_SELECT_BOTH) {
+			/* if get both bands, get BG first */
+			cfg_11ac->param.vht_cfg.band = BAND_SELECT_BG;
+		}
+		if (priv->bss_role == MLAN_BSS_ROLE_UAP)
+			cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_RX;
+
+		req->action = MLAN_ACT_GET;
+	} else {
+		if (user_data_len == 3) {
+			PRINTM(MERROR, "Invalid number of arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (user_data_len >= 4) {
+			/* BW cfg */
+			if ((data[2] < 0) || (data[2] > 1) ||
+			    ((data[2] == 1) && (data[0] & BAND_SELECT_BG))) {
+				PRINTM(MERROR, "Invalid BW cfg selection\n");
+				ret = -EINVAL;
+				goto done;
+			} else {
+				cfg_11ac->param.vht_cfg.bwcfg = data[2];
+				PRINTM(MINFO, "SET: vhtcfg bw cfg:0x%x\n",
+				       data[2]);
+			}
+
+			cfg_11ac->param.vht_cfg.vht_cap_info = data[3];
+			PRINTM(MINFO, "SET: vhtcfg vht_cap_info:0x%x\n",
+			       data[3]);
+		}
+		if (user_data_len == 4) {
+			data[4] = 0xffffffff;
+			data[5] = 0xffffffff;
+		}
+		if (user_data_len == 5) {
+			PRINTM(MERROR, "Invalid number of arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (user_data_len >= 4) {
+			cfg_11ac->param.vht_cfg.vht_tx_mcs = data[4];
+			cfg_11ac->param.vht_cfg.vht_rx_mcs = data[5];
+		}
+		/* Update 11AC parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* number of vhtcfg entries */
+	*respbuf = 1;
+	vhtcfg = (mlan_ds_11ac_vht_cfg *)(respbuf + 1);
+	moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
+			sizeof(mlan_ds_11ac_vht_cfg), respbuflen - 1);
+	ret = 1 + sizeof(mlan_ds_11ac_vht_cfg);
+
+	if ((req->action == MLAN_ACT_GET) && (data[0] == BAND_SELECT_BOTH)) {
+		cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* number of vhtcfg entries */
+		*respbuf = 2;
+		vhtcfg++;
+		moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
+				sizeof(mlan_ds_11ac_vht_cfg),
+				respbuflen - 1 - sizeof(mlan_ds_11ac_vht_cfg));
+		ret += sizeof(mlan_ds_11ac_vht_cfg);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11AC Operating Mode Notification configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_opermodecfg(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	int data[2];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ac_cfg *cfg_11ac = NULL;
+	mlan_ds_11ac_opermode_cfg *opermodecfg = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset((char *)data, 0, sizeof(data));
+	parse_arguments(respbuf + strlen(CMD_NXP) +
+			strlen(PRIV_CMD_OPERMODECFG),
+			data, ARRAY_SIZE(data), &user_data_len);
+
+	if ((user_data_len != 0) && (user_data_len != 2)) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (user_data_len == 2) {
+		/* Channel width */
+		if ((data[0] < 1) || (data[0] > 4)) {
+			PRINTM(MERROR, "Invalid channel width: 0x%x\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		/* nss */
+		if ((data[1] < 1) || (data[1] > 8)) {
+			PRINTM(MERROR, "Invalid nss: 0x%x\n", data[1]);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
+	cfg_11ac->sub_command = MLAN_OID_11AC_OPERMODE_CFG;
+	req->req_id = MLAN_IOCTL_11AC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		cfg_11ac->param.opermode_cfg.bw = data[0];
+		cfg_11ac->param.opermode_cfg.nss = data[1];
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	opermodecfg = (mlan_ds_11ac_opermode_cfg *) respbuf;
+	moal_memcpy_ext(priv->phandle, opermodecfg,
+			&(cfg_11ac->param.opermode_cfg), sizeof(*opermodecfg),
+			respbuflen);
+	ret = sizeof(*opermodecfg);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11AC configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_get_priv_datarate(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_rate *rate = NULL;
+	mlan_data_rate *data_rate = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->sub_command = MLAN_OID_GET_DATA_RATE;
+	req->req_id = MLAN_IOCTL_RATE;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data_rate = (mlan_data_rate *)respbuf;
+
+	moal_memcpy_ext(priv->phandle, data_rate, &rate->param.data_rate,
+			sizeof(mlan_data_rate), respbuflen);
+
+	ret = sizeof(mlan_data_rate);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get tx rate configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[4];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_rate *rate = NULL;
+	woal_tx_rate_cfg *ratecfg = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	txrate_setting *rate_setting = NULL;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_TXRATECFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_TXRATECFG),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 4) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_RATE;
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->sub_command = MLAN_OID_RATE_CFG;
+	rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
+
+	if (user_data_len == 0) {
+		/* Get operation */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* Set operation */
+		req->action = MLAN_ACT_SET;
+		/* format */
+		if ((data[0] != AUTO_RATE) && (data[0] >= 4)) {
+			PRINTM(MERROR, "Invalid format selection\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == AUTO_RATE) {
+			/* auto */
+			rate->param.rate_cfg.is_rate_auto = 1;
+		} else {
+			/* fixed rate */
+			PRINTM(MINFO, "SET: txratefg format: 0x%x\n", data[0]);
+			if ((data[0] != AUTO_RATE) &&
+			    (data[0] > MLAN_RATE_FORMAT_HE)
+				) {
+				PRINTM(MERROR, "Invalid format selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			rate->param.rate_cfg.rate_format = data[0];
+
+			if (user_data_len >= 2) {
+				PRINTM(MINFO, "SET: txratefg index: 0x%x\n",
+				       data[1]);
+				/* sanity check */
+				if (((data[0] == MLAN_RATE_FORMAT_LG) &&
+				     (data[1] > MLAN_RATE_INDEX_OFDM7)) ||
+				    ((data[0] == MLAN_RATE_FORMAT_HT) &&
+				     (data[1] != 32) && (data[1] > 15)
+				    )
+				    || ((data[0] == MLAN_RATE_FORMAT_VHT) &&
+					(data[1] > MLAN_RATE_INDEX_MCS9))
+				    || ((data[0] == MLAN_RATE_FORMAT_HE) &&
+					(data[1] > MLAN_RATE_INDEX_MCS11))
+					) {
+					PRINTM(MERROR,
+					       "Invalid index selection\n");
+					ret = -EINVAL;
+					goto done;
+				}
+
+				PRINTM(MINFO, "SET: txratefg index: 0x%x\n",
+				       data[1]);
+				rate->param.rate_cfg.rate = data[1];
+			}
+
+			if (data[0] == 2 || data[0] == 3) {
+				PRINTM(MINFO, "SET: txratefg nss: 0x%x\n",
+				       data[2]);
+				/* NSS is supported up to 2 */
+				if ((data[2] <= 0) || (data[2] >= 3)) {
+					PRINTM(MERROR,
+					       "Invalid nss selection\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				rate->param.rate_cfg.nss = data[2];
+			}
+			if (user_data_len == 4) {
+				rate->param.rate_cfg.rate_setting =
+					data[3] & ~0x0C00;
+				PRINTM(MIOCTL,
+				       "SET: txratefg HE Rate Setting: 0x%x\n",
+				       data[3]);
+
+/* HE Preamble type */
+//#define HE_SU_PREAMBLE 0
+#define HE_ER_PREAMBLE 1
+
+/* HE ER SU Type */
+#define HE_ER_SU_BANDWIDTH_TONE242 0
+#define HE_ER_SU_BANDWIDTH_TONE106 1
+
+				rate_setting = (txrate_setting *) & data[3];
+
+				if (data[0] == MLAN_RATE_FORMAT_HE) {
+					if (rate_setting->preamble ==
+					    HE_ER_PREAMBLE) {
+						if (rate_setting->bandwidth ==
+						    HE_ER_SU_BANDWIDTH_TONE242)
+						{
+							if ((data[1] >
+							     MLAN_RATE_INDEX_MCS2)
+							    || data[2] >
+							    MLAN_RATE_NSS1) {
+								PRINTM(MERROR,
+								       "Invalid rate and MCS or NSS configuration for 242 tone\n");
+								ret = -EINVAL;
+								goto done;
+							}
+						} else if (rate_setting->
+							   bandwidth ==
+							   HE_ER_SU_BANDWIDTH_TONE106)
+						{
+							if ((data[1] !=
+							     MLAN_RATE_INDEX_MCS0)
+							    || data[2] !=
+							    MLAN_RATE_NSS1) {
+								PRINTM(MERROR,
+								       "Invalid rate and MCS or NSS configuration\n for 106 tone");
+								ret = -EINVAL;
+								goto done;
+							}
+						} else {
+							PRINTM(MERROR,
+							       "Invalid Bandwidth for HE ER Preamble\n");
+							ret = -EINVAL;
+							goto done;
+						}
+					}
+					if ((rate_setting->dcm) &&
+					    (rate_setting->stbc == 0)) {
+						if ((data[1] ==
+						     MLAN_RATE_INDEX_MCS2) ||
+						    (data[1] >
+						     MLAN_RATE_INDEX_MCS4)) {
+							PRINTM(MERROR,
+							       "Invalid MCS configuration if DCM is supported\n");
+							ret = -EINVAL;
+							goto done;
+						}
+					}
+				}
+			} else {
+				rate->param.rate_cfg.rate_setting = 0xffff;
+			}
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ratecfg = (woal_tx_rate_cfg *)respbuf;
+	if (rate->param.rate_cfg.is_rate_auto == MTRUE) {
+		ratecfg->rate_format = 0xFF;
+	} else {
+		/* fixed rate */
+		ratecfg->rate_format = rate->param.rate_cfg.rate_format;
+		ratecfg->rate_index = rate->param.rate_cfg.rate;
+		if (rate->param.rate_cfg.rate_format == MLAN_RATE_FORMAT_VHT
+		    || rate->param.rate_cfg.rate_format == MLAN_RATE_FORMAT_HE)
+			ratecfg->nss = rate->param.rate_cfg.nss;
+		ratecfg->rate_setting = rate->param.rate_cfg.rate_setting;
+	}
+
+	ret = sizeof(woal_tx_rate_cfg);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+/**
+ *  @brief Get statistics information
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *  @param stats        A pointer to mlan_ds_get_stats structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_get_stats_info(moal_private *priv, t_u8 wait_option,
+		    mlan_ds_get_stats *stats)
+{
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+		info->sub_command = MLAN_OID_GET_STATS;
+	else if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+		info->sub_command = MLAN_OID_GET_UAP_STATS_LOG;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (stats)
+			moal_memcpy_ext(priv->phandle, stats,
+					&info->param.stats,
+					sizeof(mlan_ds_get_stats),
+					sizeof(mlan_ds_get_stats));
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+		priv->w_stats.discard.fragment = info->param.stats.fcs_error;
+		priv->w_stats.discard.retries = info->param.stats.retry;
+		priv->w_stats.discard.misc = info->param.stats.ack_failure;
+#endif
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get wireless stats information
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_get_priv_getlog(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_get_stats *stats;
+	ENTER();
+
+	if (respbuflen < sizeof(*stats)) {
+		PRINTM(MERROR, "Get log: respbuflen (%d) too small!",
+		       (int)respbuflen);
+		ret = -EFAULT;
+		goto done;
+	}
+	stats = (mlan_ds_get_stats *)respbuf;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, stats)) {
+		PRINTM(MERROR, "Get log: Failed to get stats info!");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (priv->phandle->fw_getlog_enable)
+		ret = sizeof(mlan_ds_get_stats);
+	else
+		ret = sizeof(mlan_ds_get_stats_org);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/Get esupplicant mode configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_esuppmode(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[3];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	woal_esuppmode_cfg *esupp_mode = NULL;
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->phandle->card_info->embedded_supp) {
+		PRINTM(MERROR, "Not supported cmd on this card\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_ESUPPMODE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_ESUPPMODE),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len >= 4 || user_data_len == 1 || user_data_len == 2) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ESUPP_MODE;
+
+	if (user_data_len == 0) {
+		/* Get operation */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* Set operation */
+		req->action = MLAN_ACT_SET;
+		/* RSN mode */
+		sec->param.esupp_mode.rsn_mode = data[0];
+		/* Pairwise cipher */
+		sec->param.esupp_mode.act_paircipher = (data[1] & 0xFF);
+		/* Group cipher */
+		sec->param.esupp_mode.act_groupcipher = (data[2] & 0xFF);
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	esupp_mode = (woal_esuppmode_cfg *)respbuf;
+	esupp_mode->rsn_mode =
+		(t_u16)((sec->param.esupp_mode.rsn_mode) & 0xFFFF);
+	esupp_mode->pairwise_cipher =
+		(t_u8)((sec->param.esupp_mode.act_paircipher) & 0xFF);
+	esupp_mode->group_cipher =
+		(t_u8)((sec->param.esupp_mode.act_groupcipher) & 0xFF);
+
+	ret = sizeof(woal_esuppmode_cfg);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get esupplicant passphrase configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_setget_priv_passphrase(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	int ret = 0, action = -1, i = 0;
+	char *begin, *end, *opt;
+	t_u16 len = 0;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u8 *mac = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->phandle->card_info->embedded_supp) {
+		PRINTM(MERROR, "Not supported cmd on this card\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_PASSPHRASE))) {
+		PRINTM(MERROR, "No arguments provided\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Parse the buf to get the cmd_action */
+	begin = respbuf + strlen(CMD_NXP) + strlen(PRIV_CMD_PASSPHRASE);
+	end = woal_strsep(&begin, ';', '/');
+	if (end)
+		action = woal_atox(end);
+	if (action < 0 || action > 2 || end[1] != '\0') {
+		PRINTM(MERROR, "Invalid action argument %s\n", end);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
+	if (action == 0)
+		req->action = MLAN_ACT_GET;
+	else
+		req->action = MLAN_ACT_SET;
+
+	while (begin) {
+		end = woal_strsep(&begin, ';', '/');
+		opt = woal_strsep(&end, '=', '/');
+		if (!opt || !end || !end[0]) {
+			PRINTM(MERROR, "Invalid option\n");
+			ret = -EINVAL;
+			break;
+		} else if (!strnicmp(opt, "ssid", strlen(opt))) {
+			if (strlen(end) > MLAN_MAX_SSID_LENGTH) {
+				PRINTM(MERROR,
+				       "SSID length exceeds max length\n");
+				ret = -EFAULT;
+				break;
+			}
+			sec->param.passphrase.ssid.ssid_len = strlen(end);
+			moal_memcpy_ext(priv->phandle,
+					sec->param.passphrase.ssid.ssid, end,
+					strlen(end), MLAN_MAX_SSID_LENGTH);
+			PRINTM(MINFO, "ssid=%s, len=%d\n",
+			       sec->param.passphrase.ssid.ssid,
+			       (int)sec->param.passphrase.ssid.ssid_len);
+		} else if (!strnicmp(opt, "bssid", strlen(opt))) {
+			woal_mac2u8((t_u8 *)&sec->param.passphrase.bssid, end);
+		} else if (!strnicmp(opt, "psk", strlen(opt)) &&
+			   req->action == MLAN_ACT_SET) {
+			if (strlen(end) != MLAN_PMK_HEXSTR_LENGTH) {
+				PRINTM(MERROR, "Invalid PMK length\n");
+				ret = -EINVAL;
+				break;
+			}
+			woal_ascii2hex((t_u8 *)(sec->param.passphrase.psk.pmk.
+						pmk), end,
+				       MLAN_PMK_HEXSTR_LENGTH / 2);
+			sec->param.passphrase.psk_type = MLAN_PSK_PMK;
+		} else if (!strnicmp(opt, "passphrase", strlen(opt)) &&
+			   req->action == MLAN_ACT_SET) {
+			if (strlen(end) < MLAN_MIN_PASSPHRASE_LENGTH ||
+			    strlen(end) > MLAN_MAX_PASSPHRASE_LENGTH) {
+				PRINTM(MERROR,
+				       "Invalid length for passphrase\n");
+				ret = -EINVAL;
+				break;
+			}
+			sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE;
+			moal_memcpy_ext(priv->phandle,
+					sec->param.passphrase.psk.passphrase.
+					passphrase, end,
+					sizeof(sec->param.passphrase.psk.
+					       passphrase.passphrase),
+					sizeof(sec->param.passphrase.psk.
+					       passphrase.passphrase));
+			sec->param.passphrase.psk.passphrase.passphrase_len =
+				strlen(end);
+			PRINTM(MINFO, "passphrase=%s, len=%d\n",
+			       sec->param.passphrase.psk.passphrase.passphrase,
+			       (int)sec->param.passphrase.psk.passphrase.
+			       passphrase_len);
+		} else if (!strnicmp(opt, "sae_password", strlen(opt)) &&
+			   req->action == MLAN_ACT_SET) {
+			if (strlen(end) < MLAN_MIN_SAE_PASSWORD_LENGTH ||
+			    strlen(end) > MLAN_MAX_SAE_PASSWORD_LENGTH) {
+				PRINTM(MERROR,
+				       "Invalid length for sae password\n");
+				ret = -EINVAL;
+				break;
+			}
+			sec->param.passphrase.psk_type = MLAN_PSK_SAE_PASSWORD;
+			moal_memcpy_ext(priv->phandle,
+					sec->param.passphrase.psk.sae_password.
+					sae_password, end,
+					sizeof(sec->param.passphrase.psk.
+					       sae_password.sae_password),
+					sizeof(sec->param.passphrase.psk.
+					       sae_password.sae_password));
+			sec->param.passphrase.psk.sae_password.
+				sae_password_len = strlen(end);
+			PRINTM(MINFO, "sae_password=%s, len=%d\n",
+			       sec->param.passphrase.psk.sae_password.
+			       sae_password,
+			       (int)sec->param.passphrase.psk.sae_password.
+			       sae_password_len);
+		} else {
+			PRINTM(MERROR, "Invalid option %s\n", opt);
+			ret = -EINVAL;
+			break;
+		}
+	}
+	if (ret)
+		goto done;
+
+	if (action == 2)
+		sec->param.passphrase.psk_type = MLAN_PSK_CLEAR;
+	else if (action == 0)
+		sec->param.passphrase.psk_type = MLAN_PSK_QUERY;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(respbuf, 0, respbuflen);
+	if (sec->param.passphrase.ssid.ssid_len) {
+		len += sprintf(respbuf + len, "ssid:");
+		moal_memcpy_ext(priv->phandle, respbuf + len,
+				sec->param.passphrase.ssid.ssid,
+				sec->param.passphrase.ssid.ssid_len,
+				respbuflen - len);
+		len += sec->param.passphrase.ssid.ssid_len;
+		len += sprintf(respbuf + len, " ");
+	}
+	if (memcmp(&sec->param.passphrase.bssid, zero_mac, sizeof(zero_mac))) {
+		mac = (t_u8 *)&sec->param.passphrase.bssid;
+		len += sprintf(respbuf + len, "bssid:");
+		for (i = 0; i < ETH_ALEN - 1; ++i)
+			len += sprintf(respbuf + len, "%02x:", mac[i]);
+		len += sprintf(respbuf + len, "%02x ", mac[i]);
+	}
+	if (sec->param.passphrase.psk_type == MLAN_PSK_PMK) {
+		len += sprintf(respbuf + len, "psk:");
+		for (i = 0; i < MLAN_MAX_KEY_LENGTH; ++i)
+			len += sprintf(respbuf + len, "%02x",
+				       sec->param.passphrase.psk.pmk.pmk[i]);
+		len += sprintf(respbuf + len, "\n");
+	}
+	if (sec->param.passphrase.psk_type == MLAN_PSK_PASSPHRASE)
+		len += sprintf(respbuf + len, "passphrase:%s\n",
+			       sec->param.passphrase.psk.passphrase.passphrase);
+	if (sec->param.passphrase.psk_type == MLAN_PSK_SAE_PASSWORD)
+		len += sprintf(respbuf + len, "sae_password:%s\n",
+			       sec->param.passphrase.psk.sae_password.
+			       sae_password);
+
+	ret = len;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Deauthenticate
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_deauth(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	t_u8 mac[ETH_ALEN];
+
+	ENTER();
+
+	if (strlen(respbuf) > (strlen(CMD_NXP) + strlen(PRIV_CMD_DEAUTH))) {
+		/* Deauth mentioned BSSID */
+		woal_mac2u8(mac, respbuf + strlen(CMD_NXP) +
+			    strlen(PRIV_CMD_DEAUTH));
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_disconnect(priv, MOAL_IOCTL_WAIT, mac,
+				    DEF_DEAUTH_REASON_CODE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
+				    DEF_DEAUTH_REASON_CODE))
+			ret = -EFAULT;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief uap station deauth ioctl handler
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_ap_deauth(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u8 *data_ptr;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_deauth_param deauth_param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_AP_DEAUTH));
+	memset(&deauth_param, 0, sizeof(mlan_deauth_param));
+	moal_memcpy_ext(priv->phandle, &deauth_param, data_ptr,
+			sizeof(mlan_deauth_param), sizeof(mlan_deauth_param));
+
+	PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n",
+	       MAC2STR(deauth_param.mac_addr), deauth_param.reason_code);
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)ioctl_req->pbuf;
+
+	bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
+	ioctl_req->req_id = MLAN_IOCTL_BSS;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.deauth_param, &deauth_param,
+			sizeof(mlan_deauth_param), sizeof(mlan_deauth_param));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, data_ptr, &ioctl_req->status_code,
+			sizeof(t_u32),
+			respbuflen - (strlen(CMD_NXP) +
+				      strlen(PRIV_CMD_AP_DEAUTH)));
+	ret = sizeof(t_u32);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap get station list handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_get_sta_list(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_get_info *info = NULL;
+	mlan_ds_sta_list *sta_list = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	info = (mlan_ds_get_info *)ioctl_req->pbuf;
+	info->sub_command = MLAN_OID_UAP_STA_LIST;
+	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	sta_list = (mlan_ds_sta_list *)(respbuf + strlen(CMD_NXP) +
+					strlen(PRIV_CMD_GET_STA_LIST));
+	moal_memcpy_ext(priv->phandle, sta_list, &info->param.sta_list,
+			ioctl_req->data_read_written,
+			respbuflen - (strlen(CMD_NXP) +
+				      strlen(PRIV_CMD_GET_STA_LIST)));
+	ret = ioctl_req->data_read_written + strlen(CMD_NXP) +
+		strlen(PRIV_CMD_GET_STA_LIST);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap bss_config handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_bss_config(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	t_u32 action = 0;
+	int offset = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	offset = strlen(CMD_NXP) + strlen(PRIV_CMD_BSS_CONFIG);
+	moal_memcpy_ext(priv->phandle, (u8 *)&action, respbuf + offset,
+			sizeof(action), sizeof(action));
+	offset += sizeof(action);
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)ioctl_req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
+	ioctl_req->req_id = MLAN_IOCTL_BSS;
+	if (action == 1) {
+		ioctl_req->action = MLAN_ACT_SET;
+		/* Get the BSS config from user */
+		moal_memcpy_ext(priv->phandle, &bss->param.bss_config,
+				respbuf + offset, sizeof(mlan_uap_bss_param),
+				sizeof(mlan_uap_bss_param));
+	} else {
+		ioctl_req->action = MLAN_ACT_GET;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		moal_memcpy_ext(priv->phandle, respbuf + offset,
+				&bss->param.bss_config,
+				sizeof(mlan_uap_bss_param),
+				respbuflen - (t_u32)offset);
+	}
+	ret = sizeof(mlan_uap_bss_param);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/**
+ *  @brief Set/Get BSS role
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_bssrole(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[1];
+	int ret = 0;
+	int user_data_len = 0;
+	t_u8 action = MLAN_ACT_GET;
+
+	ENTER();
+
+	memset((char *)data, 0, sizeof(data));
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_BSSROLE))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_BSSROLE),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len >= 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (user_data_len == 0) {
+		action = MLAN_ACT_GET;
+	} else {
+		if ((data[0] != MLAN_BSS_ROLE_STA &&
+		     data[0] != MLAN_BSS_ROLE_UAP) ||
+		    priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) {
+			PRINTM(MWARN, "Invalid BSS role\n");
+			ret = -EINVAL;
+			goto error;
+		}
+		if (data[0] == GET_BSS_ROLE(priv)) {
+			PRINTM(MWARN, "Already BSS is in desired role\n");
+			goto done;
+		}
+		action = MLAN_ACT_SET;
+		/* Reset interface */
+		woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE);
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_role_cfg(priv, action, MOAL_IOCTL_WAIT, (t_u8 *)data)) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	if (user_data_len) {
+		/* Initialize private structures */
+		woal_init_priv(priv, MOAL_IOCTL_WAIT);
+		/* Enable interfaces */
+		netif_device_attach(priv->netdev);
+		woal_start_queue(priv->netdev);
+	}
+
+done:
+	memset(respbuf, 0, respbuflen);
+	respbuf[0] = (t_u8)data[0];
+	ret = 1;
+
+error:
+	LEAVE();
+	return ret;
+}
+#endif /* STA_SUPPORT && UAP_SUPPORT */
+#endif /* WIFI_DIRECT_SUPPORT */
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Set user scan
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_setuserscan(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	wlan_user_scan_cfg scan_cfg;
+	int ret = 0;
+
+	ENTER();
+
+	/* Create the scan_cfg structure */
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+
+	/* We expect the scan_cfg structure to be passed in respbuf */
+	moal_memcpy_ext(priv->phandle, (char *)&scan_cfg,
+			respbuf + strlen(CMD_NXP) +
+			strlen(PRIV_CMD_SETUSERSCAN),
+			sizeof(wlan_user_scan_cfg), sizeof(wlan_user_scan_cfg));
+	moal_memcpy_ext(priv->phandle, scan_cfg.random_mac, priv->random_mac,
+			ETH_ALEN, MLAN_MAC_ADDR_LENGTH);
+	/* Call for scan */
+	if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
+		ret = -EFAULT;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get channel statistics
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_chanstats(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_scan_resp scan_resp;
+	chan_stats *stats = NULL;
+	int ret = 0;
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	memset(&scan_resp, 0, sizeof(scan_resp));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(respbuf, 0, respbuflen);
+	stats = (chan_stats *) respbuf;
+	stats->num_in_chan_stats = scan_resp.num_in_chan_stats;
+	ret = sizeof(ChanStatistics_t) * stats->num_in_chan_stats;
+	moal_memcpy_ext(priv->phandle, (t_u8 *)stats->stats,
+			(t_u8 *)scan_resp.pchan_stats, ret, respbuflen);
+	ret += sizeof(stats->num_in_chan_stats);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Retrieve the scan response/beacon table
+ *
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *  @param scan_resp    A pointer to mlan_scan_resp structure
+ *  @param scan_start   Argument
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+moal_ret_get_scan_table_ioctl(t_u8 *respbuf, t_u32 respbuflen,
+			      mlan_scan_resp *scan_resp, t_u32 scan_start)
+{
+	pBSSDescriptor_t pbss_desc, scan_table;
+	wlan_ioctl_get_scan_table_info *prsp_info;
+	int ret_code;
+	int ret_len;
+	int space_left;
+	t_u8 *pcurrent;
+	t_u8 *pbuffer_end;
+	t_u32 num_scans_done;
+
+	ENTER();
+
+	num_scans_done = 0;
+	ret_code = MLAN_STATUS_SUCCESS;
+
+	prsp_info = (wlan_ioctl_get_scan_table_info *)respbuf;
+	pcurrent = (t_u8 *)prsp_info->scan_table_entry_buf;
+
+	pbuffer_end = respbuf + respbuflen - 1;
+	space_left = pbuffer_end - pcurrent;
+	scan_table = (BSSDescriptor_t *)(scan_resp->pscan_table);
+
+	PRINTM(MINFO, "GetScanTable: scan_start req = %d\n", scan_start);
+	PRINTM(MINFO, "GetScanTable: length avail = %d\n", respbuflen);
+
+	if (!scan_start) {
+		PRINTM(MINFO, "GetScanTable: get current BSS Descriptor\n");
+
+		/* Use to get current association saved descriptor */
+		pbss_desc = scan_table;
+
+		ret_code = wlan_get_scan_table_ret_entry(pbss_desc, &pcurrent,
+							 &space_left);
+
+		if (ret_code == MLAN_STATUS_SUCCESS)
+			num_scans_done = 1;
+
+	} else {
+		scan_start--;
+
+		while (space_left &&
+		       (scan_start + num_scans_done <
+			scan_resp->num_in_scan_table) &&
+		       (ret_code == MLAN_STATUS_SUCCESS)) {
+			pbss_desc =
+				(scan_table + (scan_start + num_scans_done));
+
+			PRINTM(MINFO,
+			       "GetScanTable: get current BSS Descriptor [%d]\n",
+			       scan_start + num_scans_done);
+
+			ret_code =
+				wlan_get_scan_table_ret_entry(pbss_desc,
+							      &pcurrent,
+							      &space_left);
+
+			if (ret_code == MLAN_STATUS_SUCCESS)
+				num_scans_done++;
+		}
+	}
+
+	prsp_info->scan_number = num_scans_done;
+	ret_len = pcurrent - respbuf;
+
+	LEAVE();
+	return ret_len;
+}
+
+/**
+ *  @brief Get scan table
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_getscantable(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_scan *scan = NULL;
+	t_u32 scan_start;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+
+	ENTER();
+
+	/* First make sure scanning is not in progress */
+	if (handle->scan_pending_on_block == MTRUE) {
+		ret = -EAGAIN;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	scan = (mlan_ds_scan *)req->pbuf;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_GET;
+
+	/* Get the whole command from user */
+	moal_memcpy_ext(handle, &scan_start,
+			respbuf + strlen(CMD_NXP) +
+			strlen(PRIV_CMD_GETSCANTABLE),
+			sizeof(scan_start), sizeof(scan_start));
+	if (scan_start)
+		scan->sub_command = MLAN_OID_SCAN_NORMAL;
+	else
+		scan->sub_command = MLAN_OID_SCAN_GET_CURRENT_BSS;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		ret = moal_ret_get_scan_table_ioctl(respbuf, respbuflen,
+						    &scan->param.scan_resp,
+						    scan_start);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Extended capabilities configuration
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_extcapcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret, header;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	IEEEtypes_Header_t *ie;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		LEAVE();
+		return 0;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	header = strlen(CMD_NXP) + strlen(PRIV_CMD_EXTCAPCFG);
+	if ((int)strlen(respbuf) == header)
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+	else {
+		/* SET operation */
+		ie = (IEEEtypes_Header_t *)(respbuf + header);
+		if (ie->len > sizeof(ExtCap_t)) {
+			PRINTM(MERROR,
+			       "Extended Capability lenth is invalid\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		memset(&cfg->param.ext_cap, 0, sizeof(ExtCap_t));
+		moal_memcpy_ext(priv->phandle, &cfg->param.ext_cap, ie + 1,
+				ie->len, sizeof(ExtCap_t));
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(respbuf, 0, respbuflen);
+	ie = (IEEEtypes_Header_t *)respbuf;
+	ie->element_id = EXT_CAPABILITY;
+	ie->len = sizeof(ExtCap_t);
+	moal_memcpy_ext(priv->phandle, ie + 1, &cfg->param.ext_cap,
+			sizeof(ExtCap_t),
+			respbuflen - sizeof(IEEEtypes_Header_t));
+
+	ret = sizeof(IEEEtypes_Header_t) + ie->len;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/Get deep sleep mode configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_setgetdeepsleep(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[2];
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_DEEPSLEEP))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_DEEPSLEEP),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len >= 3) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len == 0) {
+		if (MLAN_STATUS_SUCCESS != woal_get_deep_sleep(priv, data)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		sprintf(respbuf, "%d %d", data[0], data[1]);
+		ret = strlen(respbuf) + 1;
+	} else {
+		if (data[0] == DEEP_SLEEP_OFF) {
+			PRINTM(MINFO, "Exit Deep Sleep Mode\n");
+			ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MFALSE,
+						  0);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				ret = -EINVAL;
+				goto done;
+			}
+		} else if (data[0] == DEEP_SLEEP_ON) {
+			PRINTM(MINFO, "Enter Deep Sleep Mode\n");
+			if (user_data_len != 2)
+				data[1] = 0;
+			ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MTRUE,
+						  data[1]);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				ret = -EINVAL;
+				goto done;
+			}
+		} else {
+			PRINTM(MERROR, "Unknown option = %u\n", data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		ret = sprintf(respbuf, "OK\n") + 1;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get IP address configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_setgetipaddr(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0, op_code = 0, data_length = 0, header = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (priv->bss_type != MLAN_BSS_TYPE_STA) {
+		PRINTM(MIOCTL, "Bss type[%d]: Not STA, ignore it\n",
+		       priv->bss_type);
+		ret = sprintf(respbuf, "OK\n") + 1;
+		goto done;
+	}
+
+	header = strlen(CMD_NXP) + strlen(PRIV_CMD_IPADDR);
+	data_length = strlen(respbuf) - header;
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+
+	if (data_length < 1) {	/* GET */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* Make sure we have the operation argument */
+		if (data_length > 2 && respbuf[header + 1] != ';') {
+			PRINTM(MERROR,
+			       "No operation argument. Separate with ';'\n");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			respbuf[header + 1] = '\0';
+		}
+		req->action = MLAN_ACT_SET;
+
+		/* Only one IP is supported in current firmware */
+		memset(misc->param.ipaddr_cfg.ip_addr[0], 0, IPADDR_LEN);
+		if (data_length > 2)
+			in4_pton(&respbuf[header + 2],
+				 MIN((IPADDR_MAX_BUF - 3), (data_length - 2)),
+				 misc->param.ipaddr_cfg.ip_addr[0], ' ', NULL);
+		misc->param.ipaddr_cfg.ip_addr_num = 1;
+		misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
+
+		if (woal_atoi(&op_code, &respbuf[header]) !=
+		    MLAN_STATUS_SUCCESS) {
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.ipaddr_cfg.op_code = (t_u32)op_code;
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->sub_command = MLAN_OID_MISC_IP_ADDR;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		snprintf(respbuf, IPADDR_MAX_BUF, "%d;%d.%d.%d.%d",
+			 misc->param.ipaddr_cfg.op_code,
+			 misc->param.ipaddr_cfg.ip_addr[0][0],
+			 misc->param.ipaddr_cfg.ip_addr[0][1],
+			 misc->param.ipaddr_cfg.ip_addr[0][2],
+			 misc->param.ipaddr_cfg.ip_addr[0][3]);
+		ret = IPADDR_MAX_BUF + 1;
+	} else {
+		ret = sprintf(respbuf, "OK\n") + 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get WPS session configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_setwpssession(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wps_cfg *pwps = NULL;
+	t_u32 data[1];
+	int ret = 0;
+	int user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset((char *)data, 0, sizeof(data));
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_WPSSESSION))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_WPSSESSION),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pwps = (mlan_ds_wps_cfg *)req->pbuf;
+
+	req->req_id = MLAN_IOCTL_WPS_CFG;
+	req->action = MLAN_ACT_SET;
+	pwps->sub_command = MLAN_OID_WPS_CFG_SESSION;
+
+	if (data[0] == 1)
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START;
+	else
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_END;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = sprintf(respbuf, "OK\n") + 1;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get OTP user data
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_otpuserdata(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[1];
+	int user_data_len = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_otp_user_data *otp = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_OTPUSERDATA))) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	memset((char *)data, 0, sizeof(data));
+	parse_arguments(respbuf + strlen(CMD_NXP) +
+			strlen(PRIV_CMD_OTPUSERDATA),
+			data, ARRAY_SIZE(data), &user_data_len);
+
+	if (user_data_len != 1) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	req->action = MLAN_ACT_GET;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_OTP_USER_DATA;
+	misc->param.otp_user_data.user_data_length = data[0];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	otp = (mlan_ds_misc_otp_user_data *)req->pbuf;
+
+	if (req->action == MLAN_ACT_GET) {
+		ret = MIN(otp->user_data_length, data[0]);
+		moal_memcpy_ext(priv->phandle, respbuf, otp->user_data, ret,
+				respbuflen);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set / Get country code
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_countrycode(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	int ret = 0;
+	/* char data[COUNTRY_CODE_LEN] = {0, 0, 0}; */
+	int header = 0, data_length = 0;	/* wrq->u.data.length; */
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	mlan_ds_misc_country_code *country_code = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header = strlen(CMD_NXP) + strlen(PRIV_CMD_COUNTRYCODE);
+	data_length = strlen(respbuf) - header;
+
+	if (data_length > COUNTRY_CODE_LEN) {
+		PRINTM(MERROR, "Invalid argument!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	country_code = &pcfg_misc->param.country_code;
+	pcfg_misc->sub_command = MLAN_OID_MISC_COUNTRY_CODE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (data_length <= 1) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		memset(country_code->country_code, 0, COUNTRY_CODE_LEN);
+		moal_memcpy_ext(priv->phandle, country_code->country_code,
+				respbuf + header, COUNTRY_CODE_LEN,
+				COUNTRY_CODE_LEN);
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		ret = data_length = COUNTRY_CODE_LEN;
+		memset(respbuf + header, 0, COUNTRY_CODE_LEN);
+		moal_memcpy_ext(priv->phandle, respbuf,
+				country_code->country_code, COUNTRY_CODE_LEN,
+				respbuflen);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get cfp information
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_cfpinfo(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfp_misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	cfp_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	cfp_misc->sub_command = MLAN_OID_MISC_CFP_INFO;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (respbuflen < req->data_read_written) {
+		PRINTM(MERROR, "response buffer length is too short!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)req->pbuf,
+			req->data_read_written, respbuflen);
+	ret = req->data_read_written;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get TCP Ack enhancement configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_setgettcpackenh(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u32 data[2] = { 0, 0 };
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_TCPACKENH))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_TCPACKENH),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len == 0) {
+		/* get operation */
+		data[0] = priv->enable_tcp_ack_enh;
+		data[1] = priv->tcp_ack_max_hold;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	} else {
+		/* set operation */
+		if (user_data_len >= 3) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] > 1 || data[1] > TCP_ACK_MAX_HOLD) {
+			PRINTM(MERROR, "Invalid argument\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == MTRUE) {
+			PRINTM(MINFO, "Enabling TCP Ack enhancement\n");
+			priv->enable_tcp_ack_enh = MTRUE;
+		} else if (data[0] == MFALSE) {
+			PRINTM(MINFO, "Disabling TCP Ack enhancement\n");
+			priv->enable_tcp_ack_enh = MFALSE;
+			/* release the tcp sessions if any */
+			woal_flush_tcp_sess_queue(priv);
+		}
+		if (user_data_len >= 2) {
+			PRINTM(MINFO, "TCP drop Ack configure: %d\n", data[1]);
+			priv->tcp_ack_max_hold = data[1];
+		}
+		data[0] = priv->enable_tcp_ack_enh;
+		data[1] = priv->tcp_ack_max_hold;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef REASSOCIATION
+/**
+ *  @brief Set Asynced ESSID
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *  @param bBSSID       A variable that bssid is set or not
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_assocessid(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen,
+		     t_u8 bBSSID)
+{
+	mlan_ssid_bssid ssid_bssid;
+	moal_handle *handle = priv->phandle;
+	int ret = 0;
+	int header_len = 0;
+	int copy_len = 0;
+	char buf[64];
+	t_u8 buflen = 0;
+	t_u8 i = 0;
+	t_u8 mac_idx = 0;
+
+	ENTER();
+
+	if (bBSSID)
+		header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_ASSOCBSSID);
+	else
+		header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_ASSOCESSID);
+
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "No argument, invalid operation!\n");
+		ret = -EINVAL;
+		LEAVE();
+		return ret;
+	}
+	copy_len = strlen(respbuf) - header_len;
+	buflen = MIN(copy_len, (int)(sizeof(buf) - 1));
+	memset(buf, 0, sizeof(buf));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	moal_memcpy_ext(handle, buf, respbuf + header_len, buflen, sizeof(buf));
+	priv->assoc_with_mac = MFALSE;
+
+	/* check if has parameter BSSID */
+	if (bBSSID) {
+		if (buflen < (3 * ETH_ALEN) + 2) {
+			PRINTM(MERROR,
+			       "Associate: Insufficient length in IOCTL input\n");
+			/* buffer should be at least 3 characters per BSSID
+			 *octet "00:"
+			 **   plus a space separater and at least 1 char in the
+			 *SSID
+			 */
+			ret = -EINVAL;
+			goto setessid_ret;
+		}
+		for (; (i < buflen) && (mac_idx < ETH_ALEN) && (buf[i] != ' ');
+		     i++) {
+			if (buf[i] == ':') {
+				mac_idx++;
+			} else {
+				ssid_bssid.bssid[mac_idx] =
+					(t_u8)woal_atox(buf + i);
+				while ((i < buflen) && isxdigit(buf[i + 1]))
+					/* Skip entire hex value */
+					i++;
+			}
+		}
+		/* Skip one space between the BSSID and start of the SSID */
+		i++;
+		PRINTM(MMSG, "Trying to associate AP BSSID = [" MACSTR "]\n",
+		       MAC2STR(ssid_bssid.bssid));
+		priv->assoc_with_mac = MTRUE;
+	}
+
+	ssid_bssid.ssid.ssid_len = buflen - i;
+	/* Check the size of the ssid_len */
+	if (ssid_bssid.ssid.ssid_len > MLAN_MAX_SSID_LENGTH + 1) {
+		PRINTM(MERROR, "ssid_bssid.ssid.ssid_len = %d\n",
+		       ssid_bssid.ssid.ssid_len);
+		ret = -E2BIG;
+		goto setessid_ret;
+	}
+
+	/* Copy the SSID */
+	moal_memcpy_ext(handle, ssid_bssid.ssid.ssid, buf + i,
+			ssid_bssid.ssid.ssid_len, MLAN_MAX_SSID_LENGTH);
+
+	if (!ssid_bssid.ssid.ssid_len ||
+	    (MFALSE == woal_ssid_valid(&ssid_bssid.ssid))) {
+		PRINTM(MERROR, "Invalid SSID - aborting set_essid\n");
+		ret = -EINVAL;
+		goto setessid_ret;
+	}
+
+	PRINTM(MMSG, "Trying to associate AP SSID = %s\n",
+	       (char *)ssid_bssid.ssid.ssid);
+
+	/* Cancel re-association */
+	priv->reassoc_required = MFALSE;
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_set_essid\n");
+		ret = -EBUSY;
+		LEAVE();
+		return ret;
+	}
+
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
+
+	if (MTRUE == woal_is_connected(priv, &ssid_bssid)) {
+		PRINTM(MIOCTL, "Already connect to the network\n");
+		ret = sprintf(respbuf,
+			      "Has already connected to this ESSID!\n") + 1;
+		goto setessid_ret;
+	}
+	moal_memcpy_ext(handle, &priv->prev_ssid_bssid, &ssid_bssid,
+			sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
+	/* disconnect before driver assoc */
+	woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL, DEF_DEAUTH_REASON_CODE);
+	priv->set_asynced_essid_flag = MTRUE;
+	priv->reassoc_required = MTRUE;
+	priv->phandle->is_reassoc_timer_set = MTRUE;
+	woal_mod_timer(&priv->phandle->reassoc_timer, 0);
+	ret = sprintf(respbuf, "%s\n", buf) + 1;
+
+setessid_ret:
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Get wakeup reason
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_getwakeupreason(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	t_u32 data;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_NXP) + strlen(PRIV_CMD_WAKEUPREASON))) {
+		/* GET operation */
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+		if (req == NULL) {
+			LEAVE();
+			return -ENOMEM;
+		}
+
+		pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+		pm_cfg->sub_command = MLAN_OID_PM_HS_WAKEUP_REASON;
+		req->req_id = MLAN_IOCTL_PM_CFG;
+		req->action = MLAN_ACT_GET;
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		} else {
+			data = pm_cfg->param.wakeup_reason.hs_wakeup_reason;
+			sprintf(respbuf, " %d", data);
+			ret = strlen(respbuf) + 1;
+			kfree(req);
+		}
+	} else {
+		PRINTM(MERROR, "Not need argument, invalid operation!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Set / Get listen interval
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_listeninterval(moal_private *priv, t_u8 *respbuf,
+				 t_u32 respbuflen)
+{
+	int data[1];
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *pcfg_bss = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (strlen(respbuf) ==
+	    (strlen(CMD_NXP) + strlen(PRIV_CMD_LISTENINTERVAL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_LISTENINTERVAL),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_bss = (mlan_ds_bss *)req->pbuf;
+	pcfg_bss->sub_command = MLAN_OID_BSS_LISTEN_INTERVAL;
+	req->req_id = MLAN_IOCTL_BSS;
+
+	if (user_data_len) {
+		pcfg_bss->param.listen_interval = (t_u16)data[0];
+		req->action = MLAN_ACT_SET;
+	} else {
+		req->action = MLAN_ACT_GET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (req->action == MLAN_ACT_GET) {
+		sprintf(respbuf, "%d", pcfg_bss->param.listen_interval);
+		ret = strlen(respbuf) + 1;
+	} else {
+		ret = sprintf(respbuf, "OK\n") + 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef DEBUG_LEVEL1
+/**
+ *  @brief Set / Get driver debug level
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_drvdbg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[4];
+	int user_data_len = 0;
+	int ret = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_DRVDBG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_DRVDBG),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len) {
+		/* Get the driver debug bit masks from user */
+		drvdbg = data[0];
+		/* Set the driver debug bit masks into mlan */
+		if (woal_set_drvdbg(priv, drvdbg)) {
+			PRINTM(MERROR, "Set drvdbg failed!\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	ret = sizeof(drvdbg);
+
+	moal_memcpy_ext(priv->phandle, respbuf, &drvdbg, sizeof(drvdbg),
+			respbuflen);
+
+	printk(KERN_ALERT "drvdbg = 0x%08x\n", drvdbg);
+#ifdef DEBUG_LEVEL2
+	printk(KERN_ALERT "MINFO  (%08x) %s\n", MINFO,
+	       (drvdbg & MINFO) ? "X" : "");
+	printk(KERN_ALERT "MWARN  (%08x) %s\n", MWARN,
+	       (drvdbg & MWARN) ? "X" : "");
+	printk(KERN_ALERT "MENTRY (%08x) %s\n", MENTRY,
+	       (drvdbg & MENTRY) ? "X" : "");
+#endif
+	printk(KERN_ALERT "MMPA_D (%08x) %s\n", MMPA_D,
+	       (drvdbg & MMPA_D) ? "X" : "");
+	printk(KERN_ALERT "MIF_D  (%08x) %s\n", MIF_D,
+	       (drvdbg & MIF_D) ? "X" : "");
+	printk(KERN_ALERT "MFW_D  (%08x) %s\n", MFW_D,
+	       (drvdbg & MFW_D) ? "X" : "");
+	printk(KERN_ALERT "MEVT_D (%08x) %s\n", MEVT_D,
+	       (drvdbg & MEVT_D) ? "X" : "");
+	printk(KERN_ALERT "MCMD_D (%08x) %s\n", MCMD_D,
+	       (drvdbg & MCMD_D) ? "X" : "");
+	printk(KERN_ALERT "MDAT_D (%08x) %s\n", MDAT_D,
+	       (drvdbg & MDAT_D) ? "X" : "");
+	printk(KERN_ALERT "MREG_D (%08x) %s\n", MREG_D,
+	       (drvdbg & MREG_D) ? "X" : "");
+	printk(KERN_ALERT "MIOCTL (%08x) %s\n", MIOCTL,
+	       (drvdbg & MIOCTL) ? "X" : "");
+	printk(KERN_ALERT "MINTR  (%08x) %s\n", MINTR,
+	       (drvdbg & MINTR) ? "X" : "");
+	printk(KERN_ALERT "MEVENT (%08x) %s\n", MEVENT,
+	       (drvdbg & MEVENT) ? "X" : "");
+	printk(KERN_ALERT "MCMND  (%08x) %s\n", MCMND,
+	       (drvdbg & MCMND) ? "X" : "");
+	printk(KERN_ALERT "MDATA  (%08x) %s\n", MDATA,
+	       (drvdbg & MDATA) ? "X" : "");
+	printk(KERN_ALERT "MERROR (%08x) %s\n", MERROR,
+	       (drvdbg & MERROR) ? "X" : "");
+	printk(KERN_ALERT "MFATAL (%08x) %s\n", MFATAL,
+	       (drvdbg & MFATAL) ? "X" : "");
+	printk(KERN_ALERT "MMSG   (%08x) %s\n", MMSG,
+	       (drvdbg & MMSG) ? "X" : "");
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#endif
+
+/**
+ *  @brief management frame filter wakeup config
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param respbuf          A pointer to response buffer
+ *  @param respbuflen       Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_mgmt_filter(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int header_len = 0, data_len = 0;
+	int ret = 0;
+	t_u16 action;
+	t_u8 *argument;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_MGMT_FILTER;
+	ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
+
+	header_len = strlen(PRIV_CMD_MGMT_FILTER) + strlen(CMD_NXP);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		argument = (t_u8 *)(respbuf + header_len);
+		data_len = respbuflen - header_len;
+		if (data_len >
+		    (int)(MAX_MGMT_FRAME_FILTER *
+			  sizeof(mlan_mgmt_frame_wakeup))) {
+			PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__);
+			ret = -EINVAL;
+			goto done;
+		}
+		moal_memcpy_ext(priv->phandle,
+				(t_u8 *)pm_cfg->param.mgmt_filter, argument,
+				data_len, sizeof(pm_cfg->param.mgmt_filter));
+		action = MLAN_ACT_SET;
+	}
+
+	ioctl_req->action = action;
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+#define PARAMETER_GPIO_INDICATION 1
+#define PARAMETER_EXTEND_HSCFG 2
+#define PARAMETER_HS_WAKEUP_INTERVAL 3
+/**
+ *  @brief Set/Get Host Sleep configuration
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param respbuf          A pointer to response buffer
+ *  @param respbuflen       Available length of response buffer
+ *  @param invoke_hostcmd   MTRUE --invoke HostCmd, otherwise MFALSE
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_hscfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen,
+		BOOLEAN invoke_hostcmd)
+{
+	int data[13] = { 0 };
+	int *temp_data, type;
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ds_hs_cfg hscfg, hscfg_temp;
+	t_u16 action;
+	mlan_bss_info bss_info;
+	int is_negative = MFALSE;
+	t_u8 *arguments = NULL;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
+	memset(&hscfg_temp, 0, sizeof(mlan_ds_hs_cfg));
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_HSCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		arguments = respbuf + strlen(CMD_NXP) + strlen(PRIV_CMD_HSCFG);
+		if (*arguments == '-') {
+			is_negative = MTRUE;
+			arguments += 1;
+		}
+		parse_arguments(arguments, data, ARRAY_SIZE(data),
+				&user_data_len);
+
+		if (is_negative == MTRUE) {
+			if (data[0] == 1) {
+				data[0] = -1;
+			} else {
+				PRINTM(MERROR, "Invalid arguments\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	if (user_data_len == 0) {
+		action = MLAN_ACT_GET;
+	} else {
+		if (user_data_len >= 1 && user_data_len <= 13) {
+			action = MLAN_ACT_SET;
+		} else {
+			PRINTM(MERROR, "Invalid arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* HS config is blocked if HS is already activated */
+	if (user_data_len &&
+	    (data[0] != (int)HOST_SLEEP_CFG_CANCEL ||
+	     invoke_hostcmd == MFALSE)) {
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		if (bss_info.is_hs_configured) {
+			PRINTM(MERROR, "HS already configured\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	/* Do a GET first if some arguments are not provided */
+	if (user_data_len >= 1 && user_data_len < 11) {
+		woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
+				       &hscfg_temp);
+	}
+	hscfg.conditions = hscfg_temp.conditions;
+	hscfg.gpio = hscfg_temp.gpio;
+	hscfg.gap = hscfg_temp.gap;
+
+	if (user_data_len)
+		hscfg.conditions = data[0];
+	if (user_data_len >= 2)
+		hscfg.gpio = data[1];
+	if (user_data_len >= 3)
+		hscfg.gap = data[2];
+	user_data_len = user_data_len - 3;
+	if (user_data_len > 0) {
+		temp_data = data + 3;
+		while ((user_data_len > 0) && temp_data) {
+			type = *temp_data;
+			switch (type) {
+			case PARAMETER_GPIO_INDICATION:
+				if (user_data_len >= 2)
+					hscfg.ind_gpio = *(++temp_data);
+				else {
+					PRINTM(MERROR,
+					       "Invaild number of parameters\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				if (user_data_len >= 3) {
+					hscfg.level = *(++temp_data);
+					if (hscfg.level != 0 &&
+					    hscfg.level != 1) {
+						PRINTM(MERROR,
+						       "Invalid indication gpio arguments\n");
+						ret = -EINVAL;
+						goto done;
+					}
+				}
+				hscfg.param_type_ind = type;
+				user_data_len = user_data_len - 3;
+				temp_data++;
+				break;
+			case PARAMETER_EXTEND_HSCFG:
+				if (user_data_len >= 4) {
+					hscfg.event_force_ignore =
+						*(++temp_data);
+					hscfg.event_use_ext_gap =
+						*(++temp_data);
+					hscfg.ext_gap = *(++temp_data);
+					hscfg.gpio_wave = *(++temp_data);
+				} else {
+					PRINTM(MERROR,
+					       "Invaild number of parameters\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				/* Force_ignore_gpio and ext_gap_gpio should not
+				 * set the same bit(s)*/
+				if ((hscfg.event_force_ignore &
+				     hscfg.event_use_ext_gap) ||
+				    (hscfg.gpio_wave != 1 &&
+				     hscfg.gpio_wave != 0)) {
+					PRINTM(MERROR,
+					       "Invalid arguments for extend hscfg\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				hscfg.param_type_ext = type;
+				user_data_len = user_data_len - 5;
+				temp_data++;
+				break;
+			case PARAMETER_HS_WAKEUP_INTERVAL:
+				if (user_data_len >= 2)
+					hscfg.hs_wake_interval = *(++temp_data);
+				else {
+					PRINTM(MERROR,
+					       "Invaild number of parameters\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				user_data_len = user_data_len - 2;
+				temp_data++;
+				break;
+			default:
+				PRINTM(MERROR, "Unsupported type\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+	}
+
+	if ((invoke_hostcmd == MTRUE) && (action == MLAN_ACT_SET)) {
+		/* Need to issue an extra IOCTL first to set up parameters */
+		hscfg.is_invoke_hostcmd = MFALSE;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					   &hscfg)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	hscfg.is_invoke_hostcmd = invoke_hostcmd;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_GET) {
+		/* Return the current driver host sleep configurations */
+		moal_memcpy_ext(priv->phandle, respbuf, &hscfg,
+				sizeof(mlan_ds_hs_cfg), respbuflen);
+		ret = sizeof(mlan_ds_hs_cfg);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Host Sleep parameters
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_hssetpara(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[13] = { 0 };
+	int user_data_len = 0;
+	int ret = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_HSSETPARA))) {
+		PRINTM(MERROR, "Invalid arguments\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_HSSETPARA),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	if (user_data_len >= 1 && user_data_len <= 13) {
+		sprintf(respbuf, "%s%s%s", CMD_NXP, PRIV_CMD_HSCFG,
+			respbuf +
+			(strlen(CMD_NXP) + strlen(PRIV_CMD_HSSETPARA)));
+		respbuflen = strlen(respbuf);
+		ret = woal_priv_hscfg(priv, respbuf, respbuflen, MFALSE);
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get scan configuration parameters
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_set_get_scancfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0;
+	int data[9];
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_SCANCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_SCANCFG),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+
+	if (user_data_len) {
+		if ((data[0] < 0) || (data[0] > MLAN_SCAN_TYPE_PASSIVE)) {
+			PRINTM(MERROR, "Invalid argument for scan type\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[1] < 0) || (data[1] > MLAN_SCAN_MODE_ANY)) {
+			PRINTM(MERROR, "Invalid argument for scan mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[2] < 0) || (data[2] > MAX_PROBES)) {
+			PRINTM(MERROR, "Invalid argument for scan probes\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (((data[3] < 0) ||
+		     (data[3] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME)) ||
+		    ((data[4] < 0) ||
+		     (data[4] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME)) ||
+		    ((data[5] < 0) ||
+		     (data[5] > MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME))) {
+			PRINTM(MERROR, "Invalid argument for scan time\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[6] < 0) || (data[6] > MLAN_PASS_TO_ACT_SCAN_DIS)) {
+			PRINTM(MERROR,
+			       "Invalid argument for Passive to Active Scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[7] < 0) || (data[7] > 3)) {
+			PRINTM(MERROR, "Invalid argument for extended scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[8] < 0) || (data[8] > MRVDRV_MAX_SCAN_CHAN_GAP_TIME)) {
+			PRINTM(MERROR,
+			       "Invalid argument for scan channel gap\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, data,
+				sizeof(data), sizeof(scan->param.scan_cfg));
+	} else
+		req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, &scan->param.scan_cfg,
+			sizeof(mlan_scan_cfg), respbuflen);
+	ret = sizeof(mlan_scan_cfg);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Get Netlink Number
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_getnlnum(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int data = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null in %s\n", __FUNCTION__);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data = priv->phandle->netlink_num;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set / Get packet aggregation control
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_aggrctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[1];
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	moal_handle *handle = priv->phandle;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!handle || !handle->card) {
+		PRINTM(MERROR, "Handle or card is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset((char *)data, 0, sizeof(data));
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_AGGRCTRL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		if (woal_is_any_interface_active(priv->phandle)) {
+			PRINTM(MERROR,
+			       "aggrctrl are not allowed to change after BSS active!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_AGGRCTRL),
+				data, ARRAY_SIZE(data), &user_data_len);
+
+		if (sizeof(int) * user_data_len > sizeof(data)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg_misc->sub_command = MLAN_OID_MISC_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	/* Get the values first, then modify these values if user had modified
+	 * them */
+	if (user_data_len == 0)
+		req->action = MLAN_ACT_GET;
+	else {
+		req->action = MLAN_ACT_SET;
+		pcfg_misc->param.aggr_params.tx.enable = (t_u16)data[0];
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		/* MLAN will return CMD_INVALID if FW does not support this
+		 * feature */
+		if (MLAN_ERROR_CMD_INVALID == req->status_code)
+			ret = -EOPNOTSUPP;
+		else
+			ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(handle, respbuf, (t_u8 *)&pcfg_misc->param.aggr_params,
+			sizeof(mlan_ds_misc_aggr_ctrl), respbuflen);
+	ret = sizeof(mlan_ds_misc_aggr_ctrl);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef USB
+/**
+ *  @brief Set / Get USB packet aggregation control
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_usbaggrctrl(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	int data[8];
+	int user_data_len = 0;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	moal_handle *handle = priv->phandle;
+	struct usb_card_rec *cardp = NULL;
+	int i = 0, usb_resubmit_urbs = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!handle || !handle->card) {
+		PRINTM(MERROR, "Handle or card is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	cardp = (struct usb_card_rec *)handle->card;
+
+	memset((char *)data, 0, sizeof(data));
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_USBAGGRCTRL))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_USBAGGRCTRL),
+				data, ARRAY_SIZE(data), &user_data_len);
+
+		if (sizeof(int) * user_data_len > sizeof(data)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg_misc->sub_command = MLAN_OID_MISC_USB_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	/* Get the values first, then modify these values if user had modified
+	 * them */
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		/* MLAN will return CMD_INVALID if FW does not support this
+		 * feature */
+		if (MLAN_ERROR_CMD_INVALID == req->status_code)
+			ret = -EOPNOTSUPP;
+		else
+			ret = -EFAULT;
+		goto done;
+	}
+
+	if (user_data_len == 0) {
+		moal_memcpy_ext(handle, respbuf,
+				(t_u8 *)&pcfg_misc->param.usb_aggr_params,
+				sizeof(mlan_ds_misc_usb_aggr_ctrl), respbuflen);
+		ret = sizeof(mlan_ds_misc_usb_aggr_ctrl);
+		goto done;
+	}
+
+	switch (user_data_len) {
+	case 8:
+		if (data[7] < 0) {
+			PRINTM(MERROR, "Invalid Rx timeout value (%d)\n",
+			       data[7]);
+			ret = -EINVAL;
+			goto done;
+		}
+		pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.aggr_tmo =
+			(t_u16)data[7];
+		/* fall through */
+	case 7:
+		if (data[6] < 0 || (data[6] > 10000 &&
+				    data[6] != MLAN_USB_TX_AGGR_TIMEOUT_DYN)) {
+			PRINTM(MERROR, "Invalid Tx timeout value (%d)\n",
+			       data[6]);
+			ret = -EINVAL;
+			goto done;
+		}
+		pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl.aggr_tmo =
+			(t_u16)data[6];
+		/* fall through */
+	case 6:
+		if ((data[5] < 512) || ((data[5] % 512) != 0)) {
+			PRINTM(MERROR, "Invalid Rx alignment value (%d)\n",
+			       data[5]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (cardp->rx_deaggr_ctrl.enable &&
+		    pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.
+		    aggr_align != (t_u16)data[5])
+			usb_resubmit_urbs = 1;
+		pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.aggr_align =
+			(t_u16)data[5];
+		/* fall through */
+	case 5:
+		if ((data[4] < 2048) || ((data[4] % 2048) != 0)) {
+			PRINTM(MERROR, "Invalid Tx alignment value (%d)\n",
+			       data[4]);
+			ret = -EINVAL;
+			goto done;
+		}
+		pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl.aggr_align =
+			(t_u16)data[4];
+		/* fall through */
+	case 4:
+		if ((data[3] == 2) || (data[3] == 4) || (data[3] == 8) ||
+		    (data[3] == 16)) {
+			pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.
+				aggr_mode = MLAN_USB_AGGR_MODE_NUM;
+		} else if ((data[3] == 4096) || (data[3] == 8192) ||
+			   (data[3] == 16384) || (data[3] == 32768)) {
+			pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.
+				aggr_mode = MLAN_USB_AGGR_MODE_LEN;
+		} else {
+			PRINTM(MERROR, "Invalid Rx max size/num value (%d)\n",
+			       data[3]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (cardp->rx_deaggr_ctrl.enable &&
+		    pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.aggr_max !=
+		    (t_u16)data[3])
+			usb_resubmit_urbs = 1;
+		pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.aggr_max =
+			(t_u16)data[3];
+		/* fall through */
+	case 3:
+		if ((data[2] == 2) || (data[2] == 4) || (data[2] == 8) ||
+		    (data[2] == 16)) {
+			pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl.
+				aggr_mode = MLAN_USB_AGGR_MODE_NUM;
+		} else if ((data[2] == 4096) || (data[2] == 8192) ||
+			   (data[2] == 16384) || (data[2] == 32768)) {
+			pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl.
+				aggr_mode = MLAN_USB_AGGR_MODE_LEN;
+		} else {
+			PRINTM(MERROR, "Invalid Tx max size/num value (%d)\n",
+			       data[2]);
+			ret = -EINVAL;
+			goto done;
+		}
+		pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl.aggr_max =
+			(t_u16)data[2];
+		/* fall through */
+	case 2:
+		if ((data[1] != 0) && (data[1] != 1)) {
+			PRINTM(MERROR, "Invalid Rx enable value (%d)\n",
+			       data[1]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.enable !=
+		    (t_u16)data[1])
+			usb_resubmit_urbs = 1;
+		pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl.enable =
+			(t_u16)data[1];
+		/* fall through */
+	case 1:
+		if ((data[0] != 0) && (data[0] != 1)) {
+			PRINTM(MERROR, "Invalid Tx enable value (%d)\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl.enable =
+			(t_u16)data[0];
+	default:
+		break;
+	}
+
+	pcfg_misc->sub_command = MLAN_OID_MISC_USB_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(handle, respbuf,
+			(t_u8 *)&pcfg_misc->param.usb_aggr_params,
+			sizeof(mlan_ds_misc_usb_aggr_ctrl), respbuflen);
+	ret = sizeof(mlan_ds_misc_usb_aggr_ctrl);
+
+	/* Keep a copy of the latest Tx aggregation parameters in MOAL */
+	moal_memcpy_ext(handle, &cardp->tx_aggr_ctrl,
+			&pcfg_misc->param.usb_aggr_params.tx_aggr_ctrl,
+			sizeof(usb_aggr_ctrl_cfg), sizeof(usb_aggr_ctrl_cfg));
+
+	if (usb_resubmit_urbs) {
+		/* Indicate resubmition from here */
+		cardp->resubmit_urbs = 1;
+		/* Rx SG parameters has changed or disabled, kill the URBs, they
+		   will be resubmitted after saving the parameters to USB card
+		 */
+		if (atomic_read(&cardp->rx_data_urb_pending)) {
+			for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+				if (cardp->rx_data_list[i].urb) {
+					usb_kill_urb(cardp->rx_data_list[i].
+						     urb);
+					usb_init_urb(cardp->rx_data_list[i].
+						     urb);
+				}
+			}
+		}
+	}
+
+	/* Keep a copy of the latest Rx deaggregation parameters in MOAL */
+	moal_memcpy_ext(handle, &cardp->rx_deaggr_ctrl,
+			&pcfg_misc->param.usb_aggr_params.rx_deaggr_ctrl,
+			sizeof(usb_aggr_ctrl_cfg), sizeof(usb_aggr_ctrl_cfg));
+
+	if (usb_resubmit_urbs) {
+		/* Ensure the next data URBs will use the modified parameters */
+		if (!atomic_read(&cardp->rx_data_urb_pending)) {
+			/* Submit multiple Rx data URBs */
+			woal_usb_submit_rx_data_urbs(handle);
+		}
+		cardp->resubmit_urbs = 0;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Set AP settings
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful, otherwise fail
+ */
+static int
+woal_priv_set_ap(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	t_u8 *data_ptr;
+	const t_u8 bcast[MLAN_MAC_ADDR_LENGTH] =
+		{ 255, 255, 255, 255, 255, 255 };
+	const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 };
+	mlan_ssid_bssid ssid_bssid;
+	mlan_bss_info bss_info;
+	struct mwreq *mwr;
+	struct sockaddr *awrq;
+
+	ENTER();
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_SET_AP));
+
+	mwr = (struct mwreq *)data_ptr;
+
+	if (mwr->u.ap_addr.sa_family != ARPHRD_ETHER) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	awrq = (struct sockaddr *)&(mwr->u.ap_addr);
+
+	PRINTM(MINFO, "ASSOC: WAP: sa_data: " MACSTR "\n",
+	       MAC2STR((t_u8 *)awrq->sa_data));
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef REASSOCIATION
+	/* Cancel re-association */
+	priv->reassoc_required = MFALSE;
+#endif
+
+	/* zero_mac means disconnect */
+	if (!memcmp(zero_mac, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
+		woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
+				DEF_DEAUTH_REASON_CODE);
+		goto done;
+	}
+
+	/* Broadcast MAC means search for best network */
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+	if (memcmp(bcast, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
+		/* Check if we are already assoicated to the AP */
+		if (bss_info.media_connected == MTRUE) {
+			if (!memcmp(awrq->sa_data, &bss_info.bssid, ETH_ALEN))
+				goto done;
+		}
+		moal_memcpy_ext(priv->phandle, &ssid_bssid.bssid, awrq->sa_data,
+				ETH_ALEN, sizeof(mlan_802_11_mac_addr));
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		PRINTM(MERROR,
+		       "ASSOC: WAP: MAC address not found in BSSID List\n");
+		ret = -ENETUNREACH;
+		goto done;
+	}
+	/* Zero SSID implies use BSSID to connect */
+	memset(&ssid_bssid.ssid, 0, sizeof(mlan_802_11_ssid));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef REASSOCIATION
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
+			&bss_info.ssid, sizeof(mlan_802_11_ssid),
+			sizeof(mlan_802_11_ssid));
+	moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
+			&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
+			sizeof(mlan_802_11_mac_addr));
+#endif /* REASSOCIATION */
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Set BSS mode
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful, otherwise fail
+ */
+static int
+woal_priv_set_bss_mode(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+	t_u32 mode;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_SET_BSS_MODE));
+
+	mwr = (struct mwreq *)data_ptr;
+	mode = mwr->u.mode;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MODE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	switch (mode) {
+	case MW_MODE_INFRA:
+		bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
+		break;
+	case MW_MODE_ADHOC:
+		bss->param.bss_mode = MLAN_BSS_MODE_IBSS;
+		break;
+	case MW_MODE_AUTO:
+		bss->param.bss_mode = MLAN_BSS_MODE_AUTO;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret)
+		goto done;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ * @brief Set power management
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful, otherwise fail
+ */
+static int
+woal_priv_set_power(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+	int ret = 0, disabled;
+
+	ENTER();
+
+	if (moal_extflg_isset(priv->phandle, EXT_HW_TEST)) {
+		PRINTM(MIOCTL, "block set power in hw_test mode\n");
+		LEAVE();
+		return ret;
+	}
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_SET_POWER));
+
+	mwr = (struct mwreq *)data_ptr;
+	disabled = mwr->u.power.disabled;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_power_mgmt(priv, MLAN_ACT_SET, &disabled,
+				    mwr->u.power.flags, MOAL_IOCTL_WAIT)) {
+		return -EFAULT;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set essid
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful, otherwise fail
+ */
+static int
+woal_priv_set_essid(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_802_11_ssid req_ssid;
+	mlan_ssid_bssid ssid_bssid;
+#ifdef REASSOCIATION
+	moal_handle *handle = priv->phandle;
+	mlan_bss_info bss_info;
+#endif
+	int ret = 0;
+	t_u32 mode = 0;
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_SET_ESSID));
+
+	mwr = (struct mwreq *)data_ptr;
+
+#ifdef REASSOCIATION
+	/* Cancel re-association */
+	priv->reassoc_required = MFALSE;
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_set_essid\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#endif /* REASSOCIATION */
+
+	/* Check the size of the string */
+	if (mwr->u.essid.length > MW_ESSID_MAX_SIZE - 1) {
+		ret = -E2BIG;
+		goto setessid_ret;
+	}
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
+	memset(&req_ssid, 0, sizeof(mlan_802_11_ssid));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+	req_ssid.ssid_len = mwr->u.essid.length;
+
+	/* Check if we asked for 'any' or 'particular' */
+	if (!mwr->u.essid.flags) {
+#ifdef REASSOCIATION
+		if (!req_ssid.ssid_len) {
+			memset(&priv->prev_ssid_bssid.ssid, 0x00,
+			       sizeof(mlan_802_11_ssid));
+			memset(&priv->prev_ssid_bssid.bssid, 0x00,
+			       MLAN_MAC_ADDR_LENGTH);
+			goto setessid_ret;
+		}
+#endif
+		/* Do normal SSID scanning */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_request_scan(priv, MOAL_IOCTL_WAIT, NULL)) {
+			ret = -EFAULT;
+			goto setessid_ret;
+		}
+	} else {
+		/* Set the SSID */
+		moal_memcpy_ext(handle, req_ssid.ssid, mwr->u.essid.pointer,
+				req_ssid.ssid_len, MLAN_MAX_SSID_LENGTH);
+		if (!req_ssid.ssid_len ||
+		    (MFALSE == woal_ssid_valid(&req_ssid))) {
+			PRINTM(MERROR, "Invalid SSID - aborting set_essid\n");
+			ret = -EINVAL;
+			goto setessid_ret;
+		}
+
+		PRINTM(MINFO, "Requested new SSID = %s\n",
+		       (char *)req_ssid.ssid);
+		moal_memcpy_ext(handle, &ssid_bssid.ssid, &req_ssid,
+				sizeof(mlan_802_11_ssid),
+				sizeof(mlan_802_11_ssid));
+		if (MTRUE == woal_is_connected(priv, &ssid_bssid)) {
+			PRINTM(MIOCTL, "Already connect to the network\n");
+			goto setessid_ret;
+		}
+
+		if (mwr->u.essid.flags != 0xFFFF) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_find_essid(priv, &ssid_bssid,
+					    MOAL_IOCTL_WAIT)) {
+				/* Do specific SSID scanning */
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_request_scan(priv, MOAL_IOCTL_WAIT,
+						      &req_ssid)) {
+					ret = -EFAULT;
+					goto setessid_ret;
+				}
+			}
+		}
+	}
+
+	mode = woal_get_mode(priv, MOAL_IOCTL_WAIT);
+
+	if (mode != MW_MODE_ADHOC) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_find_best_network(priv, MOAL_IOCTL_WAIT,
+					   &ssid_bssid)) {
+			ret = -EFAULT;
+			goto setessid_ret;
+		}
+	}
+#ifdef UAP_SUPPORT
+	else if (MLAN_STATUS_SUCCESS !=
+		 woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid))
+		/* Adhoc start, Check the channel command */
+		woal_11h_channel_check_ioctl(priv, MOAL_IOCTL_WAIT);
+#endif
+
+	/* Connect to BSS by ESSID */
+	memset(&ssid_bssid.bssid, 0, MLAN_MAC_ADDR_LENGTH);
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		ret = -EFAULT;
+		goto setessid_ret;
+	}
+#ifdef REASSOCIATION
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto setessid_ret;
+	}
+	moal_memcpy_ext(handle, &priv->prev_ssid_bssid.ssid, &bss_info.ssid,
+			sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
+	moal_memcpy_ext(handle, &priv->prev_ssid_bssid.bssid, &bss_info.bssid,
+			MLAN_MAC_ADDR_LENGTH, sizeof(mlan_802_11_mac_addr));
+#endif /* REASSOCIATION */
+
+setessid_ret:
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set authentication mode parameters
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful, otherwise fail
+ */
+static int
+woal_priv_set_auth(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+	int ret = 0;
+	t_u32 auth_mode = 0;
+	t_u32 encrypt_mode = 0;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_SET_AUTH));
+
+	mwr = (struct mwreq *)data_ptr;
+
+	switch (mwr->u.param.flags & MW_AUTH_INDEX) {
+	case MW_AUTH_CIPHER_PAIRWISE:
+	case MW_AUTH_CIPHER_GROUP:
+		if (mwr->u.param.value & MW_AUTH_CIPHER_NONE)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_NONE;
+		else if (mwr->u.param.value & MW_AUTH_CIPHER_WEP40)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_WEP40;
+		else if (mwr->u.param.value & MW_AUTH_CIPHER_WEP104)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_WEP104;
+		else if (mwr->u.param.value & MW_AUTH_CIPHER_TKIP)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_TKIP;
+		else if (mwr->u.param.value & MW_AUTH_CIPHER_CCMP)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_CCMP;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_encrypt_mode(priv, MOAL_IOCTL_WAIT, encrypt_mode))
+			ret = -EFAULT;
+		break;
+	case MW_AUTH_80211_AUTH_ALG:
+		switch (mwr->u.param.value) {
+		case MW_AUTH_ALG_SHARED_KEY:
+			PRINTM(MINFO, "Auth mode shared key!\n");
+			auth_mode = MLAN_AUTH_MODE_SHARED;
+			break;
+		case MW_AUTH_ALG_LEAP:
+			PRINTM(MINFO, "Auth mode LEAP!\n");
+			auth_mode = MLAN_AUTH_MODE_NETWORKEAP;
+			break;
+		case MW_AUTH_ALG_OPEN_SYSTEM:
+			PRINTM(MINFO, "Auth mode open!\n");
+			auth_mode = MLAN_AUTH_MODE_OPEN;
+			break;
+		case MW_AUTH_ALG_SHARED_KEY | MW_AUTH_ALG_OPEN_SYSTEM:
+		default:
+			PRINTM(MINFO, "Auth mode auto!\n");
+			auth_mode = MLAN_AUTH_MODE_AUTO;
+			break;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode))
+			ret = -EFAULT;
+		break;
+	case MW_AUTH_WPA_ENABLED:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wpa_enable(priv, MOAL_IOCTL_WAIT,
+					mwr->u.param.value))
+			ret = -EFAULT;
+		break;
+#define MW_AUTH_WAPI_ENABLED 0x20
+	case MW_AUTH_WAPI_ENABLED:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT,
+					 mwr->u.param.value))
+			ret = -EFAULT;
+		break;
+	case MW_AUTH_WPA_VERSION:
+		/* set WPA_VERSION_DISABLED/VERSION_WPA/VERSION_WP2 */
+		priv->wpa_version = mwr->u.param.value;
+		break;
+	case MW_AUTH_KEY_MGMT:
+		/* set KEY_MGMT_802_1X/KEY_MGMT_PSK */
+		priv->key_mgmt = mwr->u.param.value;
+		break;
+	case MW_AUTH_TKIP_COUNTERMEASURES:
+	case MW_AUTH_DROP_UNENCRYPTED:
+	case MW_AUTH_RX_UNENCRYPTED_EAPOL:
+	case MW_AUTH_ROAMING_CONTROL:
+	case MW_AUTH_PRIVACY_INVOKED:
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get current BSSID
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_get_ap(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+	int ret = 0;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_GET_AP));
+
+	mwr = (struct mwreq *)data_ptr;
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	ret = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (ret != MLAN_STATUS_SUCCESS)
+		return -EFAULT;
+
+	if (bss_info.media_connected == MTRUE) {
+		moal_memcpy_ext(priv->phandle, mwr->u.ap_addr.sa_data,
+				&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
+				sizeof(mwr->u.ap_addr.sa_data));
+	} else {
+		memset(mwr->u.ap_addr.sa_data, 0, MLAN_MAC_ADDR_LENGTH);
+	}
+	mwr->u.ap_addr.sa_family = ARPHRD_ETHER;
+	ret = strlen(CMD_NXP) + strlen(PRIV_CMD_GET_AP) + sizeof(struct mwreq);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Get power management
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_get_power(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	struct mwreq *mwr;
+	t_u8 *data_ptr;
+	int ret = 0, ps_mode;
+
+	ENTER();
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_GET_POWER));
+
+	mwr = (struct mwreq *)data_ptr;
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
+							   &ps_mode, 0,
+							   MOAL_IOCTL_WAIT)) {
+		return -EFAULT;
+	}
+
+	if (ps_mode)
+		mwr->u.power.disabled = 0;
+	else
+		mwr->u.power.disabled = 1;
+
+	mwr->u.power.value = 0;
+	ret = strlen(CMD_NXP) + strlen(PRIV_CMD_GET_POWER) +
+		sizeof(struct mwreq);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get power save mode
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_set_get_psmode(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	t_u32 action = MLAN_ACT_GET;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PSMODE);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		action = MLAN_ACT_SET;
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (data != 0 && data != 1) {
+		PRINTM(MERROR, "Invalid psmode=%d\n", data);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Flip the value */
+	data = !data;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_power_mgmt(priv, action, &data, 0, MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_SET)
+		data = !data;
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ * @brief Performs warm reset
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_warmreset(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	moal_handle *handle = priv->phandle;
+	moal_handle *ref_handle;
+	moal_private *ref_priv;
+	ENTER();
+	ret = woal_pre_warmreset(priv);
+	if (ret)
+		goto done;
+	ref_handle = (moal_handle *)handle->pref_mac;
+	if (ref_handle) {
+		ref_priv = woal_get_priv(ref_handle, MLAN_BSS_ROLE_ANY);
+		if (ref_priv) {
+			ret = woal_pre_warmreset(ref_priv);
+			if (ret)
+				goto done;
+			ret = woal_warmreset(ref_priv);
+			if (ret)
+				goto done;
+		}
+	}
+	ret = woal_warmreset(priv);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get TX power configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_txpowercfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[5];
+	int user_data_len;
+	int ret = 0;
+	mlan_bss_info bss_info;
+	mlan_ds_power_cfg *pcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 *arguments = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_TXPOWERCFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		arguments =
+			respbuf + strlen(CMD_NXP) + strlen(PRIV_CMD_TXPOWERCFG);
+		parse_arguments(arguments, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pcfg = (mlan_ds_power_cfg *)req->pbuf;
+	pcfg->sub_command = MLAN_OID_POWER_CFG_EXT;
+	req->req_id = MLAN_IOCTL_POWER_CFG;
+
+	if (!user_data_len)
+		req->action = MLAN_ACT_GET;
+	else {
+		/* SET operation */
+		req->action = MLAN_ACT_SET;
+		if (sizeof(int) * user_data_len > sizeof(data)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		switch (user_data_len) {
+		case 1:
+			if (data[0] == 0xFF)
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = TX_PWR_CFG_AUTO_CTRL_OFF;
+			else
+				ret = -EINVAL;
+			break;
+		case 3:
+		case 5:
+			switch (data[0]) {
+			case 0:	/* LG */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_LG;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW20;
+				break;
+			case 1:	/* 20 MHz HT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_HT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW20;
+				break;
+			case 2:	/* 40 MHz HT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_HT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW40;
+				break;
+			case 3:	/* 1 NSS 20 MHZ VHT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_VHT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW20;
+				pcfg->param.power_ext.power_group[0].nss = 1;
+				break;
+			case 4:	/* 2 NSS 20 MHZ VHT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_VHT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW20;
+				pcfg->param.power_ext.power_group[0].nss = 2;
+				break;
+			case 5:	/* 1 NSS 40 MHZ VHT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_VHT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW40;
+				pcfg->param.power_ext.power_group[0].nss = 1;
+				break;
+			case 6:	/* 2 NSS 40 MHZ VHT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_VHT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW40;
+				pcfg->param.power_ext.power_group[0].nss = 2;
+				break;
+			case 7:	/* 1 NSS 80 MHZ VHT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_VHT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_VHT_BW80;
+				pcfg->param.power_ext.power_group[0].nss = 1;
+				break;
+			case 8:	/* 2 NSS 80 MHZ VHT */
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_VHT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_VHT_BW80;
+				pcfg->param.power_ext.power_group[0].nss = 2;
+				break;
+			default:
+				ret = -EINVAL;
+				break;
+			}
+			pcfg->param.power_ext.power_group[0].first_rate_ind =
+				data[1];
+			pcfg->param.power_ext.power_group[0].last_rate_ind =
+				data[1];
+			if (data[2] < bss_info.min_power_level) {
+				PRINTM(MERROR,
+				       "The set powercfg rate value %d dBm is out of range (%d dBm-%d dBm)!\n",
+				       data[2], (int)bss_info.min_power_level,
+				       (int)bss_info.max_power_level);
+				ret = -EINVAL;
+				break;
+			}
+			if (data[2] > bss_info.max_power_level) {
+				PRINTM(MERROR,
+				       "The set powercfg rate value %d dBm is out of range (%d dBm-%d dBm)!\n",
+				       data[2], (int)bss_info.min_power_level,
+				       (int)bss_info.max_power_level);
+				ret = -EINVAL;
+				break;
+			}
+			pcfg->param.power_ext.power_group[0].power_min =
+				data[2];
+			pcfg->param.power_ext.power_group[0].power_max =
+				data[2];
+			pcfg->param.power_ext.power_group[0].power_step = 0;
+			pcfg->param.power_ext.num_pwr_grp = 1;
+
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		if (ret)
+			goto done;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!user_data_len) {
+		/* GET operation */
+		moal_memcpy_ext(priv->phandle, respbuf,
+				(t_u8 *)&pcfg->param.power_ext,
+				sizeof(pcfg->param.power_ext.num_pwr_grp) +
+				(MIN(pcfg->param.power_ext.num_pwr_grp,
+				     MAX_POWER_GROUP) *
+				 sizeof(mlan_power_group)), respbuflen);
+		ret = sizeof(pcfg->param.power_ext.num_pwr_grp) +
+			(MIN(pcfg->param.power_ext.num_pwr_grp, MAX_POWER_GROUP)
+			 * sizeof(mlan_power_group));
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get PS configuration parameters
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_pscfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[7] = { 0 }, ret = 0;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int allowed = 3;
+	int i = 3;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	allowed++;		/* For beacon missing timeout parameter */
+	allowed += 2;		/* For delay to PS and PS mode parameters */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PSCFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	if (user_data_len && user_data_len > allowed) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_CFG;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	if (user_data_len) {
+		if ((data[0] < PS_NULL_DISABLE)) {
+			PRINTM(MERROR,
+			       "Invalid argument for PS null interval\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[1] != MRVDRV_IGNORE_MULTIPLE_DTIM) &&
+		    (data[1] != MRVDRV_MATCH_CLOSEST_DTIM) &&
+		    ((data[1] < MRVDRV_MIN_MULTIPLE_DTIM) ||
+		     (data[1] > MRVDRV_MAX_MULTIPLE_DTIM))) {
+			PRINTM(MERROR, "Invalid argument for multiple DTIM\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		if ((data[2] < MRVDRV_MIN_LISTEN_INTERVAL) &&
+		    (data[2] != MRVDRV_LISTEN_INTERVAL_DISABLE)) {
+			PRINTM(MERROR,
+			       "Invalid argument for listen interval\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		if ((data[i] != DISABLE_BCN_MISS_TO) &&
+		    ((data[i] < MIN_BCN_MISS_TO) ||
+		     (data[i] > MAX_BCN_MISS_TO))) {
+			PRINTM(MERROR,
+			       "Invalid argument for beacon miss timeout\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		if (user_data_len < allowed - 1)
+			data[i] = DELAY_TO_PS_UNCHANGED;
+		else if ((data[i] < MIN_DELAY_TO_PS) ||
+			 (data[i] > MAX_DELAY_TO_PS)) {
+			PRINTM(MERROR, "Invalid argument for delay to PS\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		if ((data[i] != PS_MODE_UNCHANGED) &&
+		    (data[i] != PS_MODE_AUTO) && (data[i] != PS_MODE_POLL) &&
+		    (data[i] != PS_MODE_NULL)) {
+			PRINTM(MERROR, "Invalid argument for PS mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		req->action = MLAN_ACT_SET;
+		moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_cfg, data,
+				sizeof(data), sizeof(pm_cfg->param.ps_cfg));
+	} else
+		req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, data, &pm_cfg->param.ps_cfg,
+			MIN((sizeof(int) * allowed),
+			    sizeof(pm_cfg->param.ps_cfg)), sizeof(data));
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+			sizeof(int) * allowed, respbuflen);
+	ret = sizeof(int) * allowed;
+	if (req->action == MLAN_ACT_SET) {
+		pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+		pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
+		pm_cfg->param.ps_mode = 1;
+		req->req_id = MLAN_IOCTL_PM_CFG;
+		req->action = MLAN_ACT_SET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get PS configuration parameters
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_bcntimeoutcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[4] = { 0 }, ret = 0;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int allowed = 4;
+	int i = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_BCNTIMEOUTCFG);
+
+	memset((char *)data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if (user_data_len != allowed) {
+		PRINTM(MERROR, "Invalid args num: input=%d allowed=%d\n",
+		       user_data_len, allowed);
+		ret = -EINVAL;
+		goto done;
+	}
+	for (i = 0; i < allowed; i++) {
+		if (data[i] <= 0) {
+			PRINTM(MERROR, "Invalid data[%d]=%d\n", i, data[i]);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_BCN_TIMEOUT;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	req->action = MLAN_ACT_SET;
+	pm_cfg->param.bcn_timeout.bcn_miss_tmo_window = (t_u16)data[0];
+	pm_cfg->param.bcn_timeout.bcn_miss_tmo_period = (t_u16)data[1];
+	pm_cfg->param.bcn_timeout.bcn_rq_tmo_window = (t_u16)data[2];
+	pm_cfg->param.bcn_timeout.bcn_rq_tmo_period = (t_u16)data[3];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get sleep period
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_sleeppd(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SLEEPPD);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len) {
+		if ((data <= MAX_SLEEP_PERIOD && data >= MIN_SLEEP_PERIOD) ||
+		    (data == 0)
+		    || (data == SLEEP_PERIOD_RESERVED_FF)
+			) {
+			req->action = MLAN_ACT_SET;
+			pm_cfg->param.sleep_period = data;
+		} else {
+			ret = -EINVAL;
+			goto done;
+		}
+	} else
+		req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!user_data_len) {
+		data = pm_cfg->param.sleep_period;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get Tx control flag
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_txcontrol(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_TXCONTROL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TXCONTROL);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len) {
+		req->action = MLAN_ACT_SET;
+		misc_cfg->param.tx_control = (t_u32)data;
+	} else {
+		req->action = MLAN_ACT_GET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!user_data_len) {
+		data = misc_cfg->param.tx_control;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Read/Write adapter registers value
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_regrdwr(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[3];
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg_mem = NULL;
+	int user_data_len = 0, header_len = 0;
+	t_u8 *arguments = NULL, *space_ind = NULL;
+	t_u32 is_negative_val = MFALSE;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	gfp_t flag;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg_mem = (mlan_ds_reg_mem *)req->pbuf;
+	reg_mem->sub_command = MLAN_OID_REG_RW;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_REGRDWR);
+
+	if ((int)strlen(respbuf) == header_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	/* SET operation */
+	memset((char *)data, 0, sizeof(data));
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	arguments = kzalloc(strlen(respbuf) * sizeof(char), flag);
+	if (arguments == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	strcpy(arguments, respbuf + header_len);
+	space_ind = strstr((char *)arguments, " ");
+	if (space_ind)
+		space_ind = strstr(space_ind + 1, " ");
+	if (space_ind) {
+		if (*(char *)(space_ind + 1) == '-') {
+			is_negative_val = MTRUE;
+			arguments[space_ind + 1 - arguments] = '\0';
+			strcat(arguments, space_ind + 2);
+		}
+	}
+	parse_arguments(arguments, data, ARRAY_SIZE(data), &user_data_len);
+	if (is_negative_val == MTRUE)
+		data[2] *= -1;
+
+	if (user_data_len == 2) {
+		req->action = MLAN_ACT_GET;
+	} else if (user_data_len == 3) {
+		req->action = MLAN_ACT_SET;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	reg_mem->param.reg_rw.type = (t_u32)data[0];
+	reg_mem->param.reg_rw.offset = (t_u32)data[1];
+	if (user_data_len == 3)
+		reg_mem->param.reg_rw.value = (t_u32)data[2];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		moal_memcpy_ext(priv->phandle, respbuf, &reg_mem->param.reg_rw,
+				sizeof(reg_mem->param.reg_rw), respbuflen);
+		ret = sizeof(reg_mem->param.reg_rw);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	kfree(arguments);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Read the EEPROM contents of the card
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_rdeeprom(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[2];
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg_mem = NULL;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg_mem = (mlan_ds_reg_mem *)req->pbuf;
+	reg_mem->sub_command = MLAN_OID_EEPROM_RD;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RDEEPROM);
+
+	if ((int)strlen(respbuf) == header_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	/* SET operation */
+	memset((char *)data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len == 2) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	reg_mem->param.rd_eeprom.offset = (t_u16)data[0];
+	reg_mem->param.rd_eeprom.byte_count = (t_u16)data[1];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		moal_memcpy_ext(priv->phandle, respbuf,
+				&reg_mem->param.rd_eeprom,
+				sizeof(reg_mem->param.rd_eeprom), respbuflen);
+		ret = sizeof(reg_mem->param.rd_eeprom);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Read/Write device memory value
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_memrdwr(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[2];
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg_mem = NULL;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg_mem = (mlan_ds_reg_mem *)req->pbuf;
+	reg_mem->sub_command = MLAN_OID_MEM_RW;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MEMRDWR);
+
+	if ((int)strlen(respbuf) == header_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	/* SET operation */
+	memset((char *)data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len == 1) {
+		PRINTM(MINFO, "MEM_RW: GET\n");
+		req->action = MLAN_ACT_GET;
+	} else if (user_data_len == 2) {
+		PRINTM(MINFO, "MEM_RW: SET\n");
+		req->action = MLAN_ACT_SET;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	reg_mem->param.mem_rw.addr = (t_u32)data[0];
+	if (user_data_len == 2)
+		reg_mem->param.mem_rw.value = (t_u32)data[1];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		moal_memcpy_ext(priv->phandle, respbuf, &reg_mem->param.mem_rw,
+				sizeof(reg_mem->param.mem_rw), respbuflen);
+		ret = sizeof(reg_mem->param.mem_rw);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO
+/**
+ *  @brief Cmd52 read/write register
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_priv_sdcmd52rw(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u8 rw = 0, func, data = 0;
+	int buf[3], reg, ret = MLAN_STATUS_SUCCESS;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SDCMD52RW);
+	memset((t_u8 *)buf, 0, sizeof(buf));
+
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	parse_arguments(respbuf + header_len, buf, ARRAY_SIZE(buf),
+			&user_data_len);
+
+	if (user_data_len < 2 || user_data_len > 3) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	func = (t_u8)buf[0];
+	if (func > 7) {
+		PRINTM(MERROR, "Invalid function number!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	reg = (t_u32)buf[1];
+	if (user_data_len == 2) {
+		rw = 0;		/* CMD52 read */
+		PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
+	}
+	if (user_data_len == 3) {
+		rw = 1;		/* CMD52 write */
+		data = (t_u8)buf[2];
+		PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
+		       func, reg, data);
+	}
+
+	if (!rw) {
+#ifdef SDIO_MMC
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (func)
+			data = sdio_readb(((struct sdio_mmc_card *)priv->
+					   phandle->card)
+					  ->func, reg, &ret);
+		else
+			data = sdio_f0_readb(((struct sdio_mmc_card *)priv->
+					      phandle->card)
+					     ->func, reg, &ret);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		if (ret) {
+			PRINTM(MERROR,
+			       "sdio_readb: reading register 0x%X failed\n",
+			       reg);
+			goto done;
+		}
+#else
+		if (sdio_read_ioreg(priv->phandle->card, func, reg, &data) < 0) {
+			PRINTM(MERROR,
+			       "sdio_read_ioreg: reading register 0x%X failed\n",
+			       reg);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#endif /* SDIO_MMC */
+	} else {
+#ifdef SDIO_MMC
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (func)
+			sdio_writeb(((struct sdio_mmc_card *)priv->phandle->
+				     card)
+				    ->func, data, reg, &ret);
+		else
+			sdio_f0_writeb(((struct sdio_mmc_card *)priv->phandle->
+					card)
+				       ->func, data, reg, &ret);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		if (ret) {
+			PRINTM(MERROR,
+			       "sdio_writeb: writing register 0x%X failed\n",
+			       reg);
+			goto done;
+		}
+#else
+		if (sdio_write_ioreg(priv->phandle->card, func, reg, data) < 0) {
+			PRINTM(MERROR,
+			       "sdio_write_ioreg: writing register 0x%X failed\n",
+			       reg);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#endif /* SDIO_MMC */
+	}
+
+	/* Action = GET */
+	buf[0] = data;
+
+	moal_memcpy_ext(priv->phandle, respbuf, &buf, sizeof(int), respbuflen);
+	ret = sizeof(int);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO */
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief arpfilter ioctl function
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return		0 --success, otherwise fail
+ */
+static int
+woal_priv_arpfilter(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 *data_ptr = NULL;
+	t_u32 buf_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GEN_IE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	misc->param.gen_ie.type = MLAN_IE_TYPE_ARP_FILTER;
+
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_ARPFILTER));
+	buf_len = *((t_u16 *)data_ptr);
+	misc->param.gen_ie.len = buf_len;
+	moal_memcpy_ext(priv->phandle, (void *)(misc->param.gen_ie.ie_data),
+			data_ptr + sizeof(buf_len), buf_len, MAX_IE_SIZE);
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief Set / Get Auto ARP Response configuration
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_auto_arp(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[4];
+	int user_data_len = 0;
+	int ret = 0;
+	moal_handle *handle = NULL;
+
+	ENTER();
+
+	if (priv == NULL) {
+		PRINTM(MERROR, "Invalid priv\n");
+		goto done;
+	}
+	handle = priv->phandle;
+
+	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_AUTO_ARP))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_AUTO_ARP),
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len) {
+		/* Get the enable/disable value from user */
+		handle->hs_auto_arp = data[0];
+		PRINTM(MIOCTL, "Auto ARP : %s\n",
+		       handle->hs_auto_arp ? "enable" : "disable");
+	}
+
+	moal_memcpy_ext(handle, respbuf, &handle->hs_auto_arp,
+			sizeof(handle->hs_auto_arp), respbuflen);
+	ret = sizeof(handle->hs_auto_arp);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set deauth control
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_deauth_ctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ds_snmp_mib *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0, header_len = 0, data = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_snmp_mib *)req->pbuf;
+	cfg->sub_command = MLAN_OID_SNMP_MIB_CTRL_DEAUTH;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DEAUTH_CTRL);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		cfg->param.deauthctrl = (t_u8)data;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data = (int)cfg->param.deauthctrl;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#define MRVL_TLV_HEADER_SIZE 4
+/**
+ *  @brief              Get/Set per packet Txctl and Rxinfo configuration
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_per_pkt_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	t_u8 *pos = NULL;
+	int left_len, header_len = 0;
+	mlan_per_pkt_cfg *perpkt = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PER_PKT_CFG);
+	pos = respbuf + header_len;
+	left_len = respbuflen - header_len;
+
+	if (priv->phandle->card_info->per_pkt_cfg_support == 0) {
+		PRINTM(MERROR, "Device not support per packet configuration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_PER_PKT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (*pos == 0) {
+		/* GET operation */
+		pos++;
+		if (priv->tx_protocols.protocol_num) {
+			perpkt = (mlan_per_pkt_cfg *) pos;
+			perpkt->type = TLV_TYPE_PER_PKT_CFG;
+			perpkt->tx_rx_control = TX_PKT_CTRL;
+			perpkt->proto_type_num =
+				priv->tx_protocols.protocol_num;
+			moal_memcpy_ext(priv->phandle, perpkt->ether_type,
+					priv->tx_protocols.protocols,
+					perpkt->proto_type_num * sizeof(t_u16),
+					MAX_NUM_ETHER_TYPE * sizeof(t_u16));
+			perpkt->len =
+				(perpkt->proto_type_num + 1) * sizeof(t_u16);
+			pos += perpkt->len + MRVL_TLV_HEADER_SIZE;
+		}
+		if (priv->rx_protocols.protocol_num) {
+			perpkt = (mlan_per_pkt_cfg *) pos;
+			perpkt->type = TLV_TYPE_PER_PKT_CFG;
+			perpkt->tx_rx_control = RX_PKT_INFO;
+			perpkt->proto_type_num =
+				priv->rx_protocols.protocol_num;
+			moal_memcpy_ext(priv->phandle, perpkt->ether_type,
+					priv->rx_protocols.protocols,
+					perpkt->proto_type_num * sizeof(t_u16),
+					MAX_NUM_ETHER_TYPE * sizeof(t_u16));
+			perpkt->len =
+				(perpkt->proto_type_num + 1) * sizeof(t_u16);
+			pos += perpkt->len + MRVL_TLV_HEADER_SIZE;
+		}
+		ret = pos - respbuf;
+		goto done;
+	} else if (*pos == 1) {
+		/* SET operation */
+		req->action = MLAN_ACT_SET;
+		pos++;
+		left_len--;
+		while (*pos == TLV_TYPE_PER_PKT_CFG && (left_len > 2)) {
+			perpkt = (mlan_per_pkt_cfg *) pos;
+			if (perpkt->tx_rx_control & TX_PKT_CTRL) {
+				priv->tx_protocols.protocol_num =
+					perpkt->proto_type_num;
+				if (perpkt->proto_type_num <=
+				    MAX_NUM_ETHER_TYPE)
+					moal_memcpy_ext(priv->phandle,
+							priv->tx_protocols.
+							protocols,
+							perpkt->ether_type,
+							perpkt->proto_type_num *
+							sizeof(t_u16),
+							MAX_NUM_ETHER_TYPE *
+							sizeof(t_u16));
+			}
+			if (perpkt->tx_rx_control & RX_PKT_INFO) {
+				priv->rx_protocols.protocol_num =
+					perpkt->proto_type_num;
+				if (perpkt->proto_type_num <=
+				    MAX_NUM_ETHER_TYPE)
+					moal_memcpy_ext(priv->phandle,
+							priv->rx_protocols.
+							protocols,
+							perpkt->ether_type,
+							perpkt->proto_type_num *
+							sizeof(t_u16),
+							MAX_NUM_ETHER_TYPE *
+							sizeof(t_u16));
+			}
+			if (!perpkt->tx_rx_control) {
+				memset(&priv->tx_protocols, 0,
+				       sizeof(dot11_protocol));
+				memset(&priv->rx_protocols, 0,
+				       sizeof(dot11_protocol));
+			}
+			pos += perpkt->len + MRVL_TLV_HEADER_SIZE;
+			left_len -= (perpkt->len + MRVL_TLV_HEADER_SIZE);
+		}
+	} else
+		goto done;
+
+	if (perpkt != NULL)
+		misc->param.txrx_pkt_ctrl = perpkt->tx_rx_control;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief              Get Region Channel Power
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_chnrgpwr(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int header_len = 0;
+	t_u8 *pos = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	header_len = strlen(PRIV_CMD_GET_CHNRGPWR);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GET_REGIONPWR_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	ret = header_len + sizeof(t_u16) + misc->param.rgchnpwr_cfg.length;
+	pos = respbuf + header_len;
+	moal_memcpy_ext(priv->phandle, pos, &misc->param.rgchnpwr_cfg,
+			sizeof(t_u16) + misc->param.rgchnpwr_cfg.length,
+			respbuflen - header_len);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief              Get TX/RX histogram statistic
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_txpwrlimit(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_chan_trpc_cfg *trpc_cfg = NULL;
+	int header_len = 0;
+	t_u8 *pos = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	header_len = strlen(PRIV_CMD_GET_TXPWR_LIMIT);
+	trpc_cfg = (mlan_ds_misc_chan_trpc_cfg *) (respbuf + header_len);
+	if ((trpc_cfg->sub_band != 0) && (trpc_cfg->sub_band != 0x10) &&
+	    (trpc_cfg->sub_band != 0x11) && (trpc_cfg->sub_band != 0x12) &&
+	    (trpc_cfg->sub_band != 0x13)) {
+		PRINTM(MERROR, "Invalid subband=0x%x\n", trpc_cfg->sub_band);
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GET_CHAN_TRPC_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	misc->param.trpc_cfg.sub_band = trpc_cfg->sub_band;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	ret = header_len + sizeof(t_u16) + sizeof(t_u16) +
+		misc->param.trpc_cfg.length;
+	pos = respbuf + header_len;
+	moal_memcpy_ext(priv->phandle, pos, &misc->param.trpc_cfg,
+			sizeof(t_u16) + sizeof(t_u16) +
+			misc->param.trpc_cfg.length, respbuflen - header_len);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/**
+ *  @brief              Get TX/RX histogram statistic
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_getcfgchanlist(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int num_chan = 0;
+	wlan_ieee80211_chan_list *plist = NULL;
+	struct ieee80211_supported_band *sband;
+	struct wiphy *wiphy = NULL;
+	int i;
+
+	ENTER();
+	if (priv && priv->wdev)
+		wiphy = priv->wdev->wiphy;
+	if (!wiphy) {
+		PRINTM(MERROR, "wiphy is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	plist = (wlan_ieee80211_chan_list *) respbuf;
+	sband = wiphy->bands[NL80211_BAND_2GHZ];
+	if (sband) {
+		num_chan += sband->n_channels;
+		for (i = 0; i < sband->n_channels; i++) {
+			plist->chan_list[i].center_freq =
+				sband->channels[i].center_freq;
+			plist->chan_list[i].hw_value =
+				sband->channels[i].hw_value;
+			plist->chan_list[i].flags = sband->channels[i].flags;
+			plist->chan_list[i].max_power =
+				sband->channels[i].max_power;
+		}
+	}
+	sband = wiphy->bands[NL80211_BAND_5GHZ];
+	if (sband) {
+		for (i = 0; i < sband->n_channels; i++) {
+			plist->chan_list[i + num_chan].center_freq =
+				sband->channels[i].center_freq;
+			plist->chan_list[i + num_chan].hw_value =
+				sband->channels[i].hw_value;
+			plist->chan_list[i + num_chan].flags =
+				sband->channels[i].flags;
+			plist->chan_list[i + num_chan].max_power =
+				sband->channels[i].max_power;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 8, 13)
+			plist->chan_list[i + num_chan].dfs_state =
+				sband->channels[i].dfs_state;
+#endif
+		}
+		num_chan += sband->n_channels;
+	}
+	plist->num_chan = num_chan;
+	ret = sizeof(wlan_ieee80211_chan_list) +
+		sizeof(wlan_ieee80211_chan) * num_chan;
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief              Get TX/RX histogram statistic
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_rx_tx_histogram(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	tx_rx_histogram *tx_rx_info = NULL;
+	int header_len = 0;
+	t_u8 *pos = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	header_len = strlen(PRIV_CMD_TX_RX_HISTOGRAM);
+	tx_rx_info = (tx_rx_histogram *) (respbuf + header_len);
+	if (tx_rx_info->enable > 2 ||
+	    (tx_rx_info->enable == GET_TX_RX_HISTOGRAM &&
+	     (tx_rx_info->action > 3 || tx_rx_info->action <= 0))) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GET_TX_RX_HISTOGRAM;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if (tx_rx_info->enable == GET_TX_RX_HISTOGRAM) {
+		misc->param.tx_rx_histogram.enable = ENABLE_TX_RX_HISTOGRAM;
+		misc->param.tx_rx_histogram.action = (t_u16)tx_rx_info->action;
+	} else {
+		misc->param.tx_rx_histogram.enable = tx_rx_info->enable;
+		misc->param.tx_rx_histogram.action |=
+			FLAG_TX_HISTOGRAM | FLAG_RX_HISTOGRAM;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = header_len + 2 * sizeof(t_u8);
+	if (tx_rx_info->enable & GET_TX_RX_HISTOGRAM) {
+		pos = respbuf + header_len + 2 * sizeof(t_u8);
+		/* Save tx/rx histogram size */
+		moal_memcpy_ext(priv->phandle, pos,
+				&misc->param.tx_rx_histogram.size,
+				sizeof(misc->param.tx_rx_histogram.size),
+				respbuflen - (header_len + 2 * sizeof(t_u8)));
+		ret += sizeof(misc->param.tx_rx_histogram.size);
+		pos += sizeof(misc->param.tx_rx_histogram.size);
+		moal_memcpy_ext(priv->phandle, pos,
+				&misc->param.tx_rx_histogram.value,
+				misc->param.tx_rx_histogram.size,
+				respbuflen - (header_len + 2 * sizeof(t_u8)) -
+				sizeof(misc->param.tx_rx_histogram.size));
+		ret += misc->param.tx_rx_histogram.size;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get hotspot mode configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_hotspotcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_HOTSPOTCFG);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+	}
+	if (user_data_len >= 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+		if (req == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+
+		cfg = (mlan_ds_misc_cfg *)req->pbuf;
+		if (user_data_len == 0) {
+			req->action = MLAN_ACT_GET;
+		} else {
+			cfg->param.hotspot_cfg = data;
+			req->action = MLAN_ACT_SET;
+		}
+	}
+	cfg->sub_command = MLAN_OID_MISC_HOTSPOT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data = cfg->param.hotspot_cfg;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Mgmt Frame passthru mask
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_mgmt_frame_passthru_ctrl(moal_private *priv, t_u8 *respbuf,
+				   t_u32 respbuflen)
+{
+	int ret = 0;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *mgmt_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MGMT_FRAME_CTRL);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+	}
+
+	if (user_data_len >= 2) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+		if (req == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		mgmt_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		mgmt_cfg->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
+
+		if (user_data_len == 0) {	/* Get */
+			req->action = MLAN_ACT_GET;
+		} else {	/* Set */
+			mgmt_cfg->param.mgmt_subtype_mask = data;
+			req->action = MLAN_ACT_SET;
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data = mgmt_cfg->param.mgmt_subtype_mask;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to send an ADDTS TSPEC
+ *
+ *  Receive a ADDTS command from the application.  The command structure
+ *    contains a TSPEC and timeout in milliseconds.  The timeout is performed
+ *    in the firmware after the ADDTS command frame is sent.
+ *
+ *  The TSPEC is received in the API as an opaque block. The firmware will
+ *    send the entire data block, including the bytes after the TSPEC.  This
+ *    is done to allow extra IEs to be packaged with the TSPEC in the ADDTS
+ *    action frame.
+ *
+ *  The IOCTL structure contains two return fields:
+ *    - The firmware command result, which indicates failure and timeouts
+ *    - The IEEE Status code which contains the corresponding value from
+ *      any ADDTS response frame received.
+ *
+ *  In addition, the opaque TSPEC data block passed in is replaced with the
+ *    TSPEC received in the ADDTS response frame.  In case of failure, the
+ *    AP may modify the TSPEC on return and in the case of success, the
+ *    medium time is returned as calculated by the AP.  Along with the TSPEC,
+ *    any IEs that are sent in the ADDTS response are also returned and can be
+ *    parsed using the IOCTL length as an indicator of extra elements.
+ *
+ *  The return value to the application layer indicates a driver execution
+ *    success or failure.  A successful return could still indicate a firmware
+ *    failure or AP negotiation failure via the commandResult field copied
+ *    back to the application.
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_wmm_addts_req_ioctl(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *cfg = NULL;
+	wlan_ioctl_wmm_addts_req_t addts_ioctl;
+	int ret = 0, header_len = 0, copy_len = sizeof(addts_ioctl);
+	t_u8 *data_ptr;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_ADDTS);
+	data_ptr = respbuf + header_len;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_WMM_CFG_ADDTS;
+
+	memset(&addts_ioctl, 0x00, sizeof(addts_ioctl));
+
+	moal_memcpy_ext(priv->phandle, (t_u8 *)&addts_ioctl, data_ptr,
+			sizeof(addts_ioctl), sizeof(addts_ioctl));
+
+	cfg->param.addts.timeout = addts_ioctl.timeout_ms;
+	cfg->param.addts.ie_data_len = addts_ioctl.ie_data_len;
+
+	moal_memcpy_ext(priv->phandle, cfg->param.addts.ie_data,
+			addts_ioctl.ie_data, cfg->param.addts.ie_data_len,
+			MLAN_WMM_TSPEC_SIZE + MLAN_WMM_ADDTS_EXTRA_IE_BYTES);
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	addts_ioctl.cmd_result = cfg->param.addts.result;
+	addts_ioctl.ieee_status_code = (t_u8)cfg->param.addts.status_code;
+	addts_ioctl.ie_data_len = cfg->param.addts.ie_data_len;
+
+	moal_memcpy_ext(priv->phandle, addts_ioctl.ie_data,
+			cfg->param.addts.ie_data, cfg->param.addts.ie_data_len,
+			MLAN_WMM_TSPEC_SIZE + MLAN_WMM_ADDTS_EXTRA_IE_BYTES);
+
+	copy_len = (sizeof(addts_ioctl) - sizeof(addts_ioctl.ie_data) +
+		    cfg->param.addts.ie_data_len);
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&addts_ioctl, copy_len,
+			respbuflen);
+	ret = copy_len;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to send a DELTS TSPEC
+ *
+ *  Receive a DELTS command from the application.  The command structure
+ *    contains a TSPEC and reason code along with space for a command result
+ *    to be returned.  The information is packaged is sent to the wlan_cmd.c
+ *    firmware command prep and send routines for execution in the firmware.
+ *
+ *  The reason code is not used for WMM implementations but is indicated in
+ *    the 802.11e specification.
+ *
+ *  The return value to the application layer indicates a driver execution
+ *    success or failure.  A successful return could still indicate a firmware
+ *    failure via the cmd_result field copied back to the application.
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_wmm_delts_req_ioctl(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *cfg = NULL;
+	wlan_ioctl_wmm_delts_req_t delts_ioctl;
+	int ret = 0, header_len = 0, copy_len = 0;
+	t_u8 *data_ptr;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DELTS);
+	data_ptr = respbuf + header_len;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_WMM_CFG_DELTS;
+
+	memset(&delts_ioctl, 0x00, sizeof(delts_ioctl));
+
+	if ((int)strlen(respbuf) > header_len) {
+		copy_len = MIN(strlen(data_ptr), sizeof(delts_ioctl));
+		moal_memcpy_ext(priv->phandle, (t_u8 *)&delts_ioctl, data_ptr,
+				copy_len, sizeof(delts_ioctl));
+
+		cfg->param.delts.status_code =
+			(t_u32)delts_ioctl.ieee_reason_code;
+		cfg->param.delts.ie_data_len = (t_u8)delts_ioctl.ie_data_len;
+
+		moal_memcpy_ext(priv->phandle, cfg->param.delts.ie_data,
+				delts_ioctl.ie_data,
+				cfg->param.delts.ie_data_len,
+				MLAN_WMM_TSPEC_SIZE);
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		/* Return the firmware command result back to the application
+		 * layer */
+		delts_ioctl.cmd_result = cfg->param.delts.result;
+		copy_len = sizeof(delts_ioctl);
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&delts_ioctl,
+				copy_len, respbuflen);
+		ret = copy_len;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get/set a specified AC Queue's parameters
+ *
+ *  Receive a AC Queue configuration command which is used to get, set, or
+ *    default the parameters associated with a specific WMM AC Queue.
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_priv_qconfig(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	mlan_ds_wmm_queue_config *pqcfg = NULL;
+	wlan_ioctl_wmm_queue_config_t qcfg_ioctl;
+	t_u8 *data_ptr;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_CONFIG;
+
+	memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl));
+	pqcfg = (mlan_ds_wmm_queue_config *)&pwmm->param.q_cfg;
+	data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_QCONFIG));
+
+	moal_memcpy_ext(priv->phandle, (t_u8 *)&qcfg_ioctl, data_ptr,
+			sizeof(qcfg_ioctl), sizeof(qcfg_ioctl));
+	pqcfg->action = qcfg_ioctl.action;
+	pqcfg->access_category = qcfg_ioctl.access_category;
+	pqcfg->msdu_lifetime_expiry = qcfg_ioctl.msdu_lifetime_expiry;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl));
+	qcfg_ioctl.action = pqcfg->action;
+	qcfg_ioctl.access_category = pqcfg->access_category;
+	qcfg_ioctl.msdu_lifetime_expiry = pqcfg->msdu_lifetime_expiry;
+	moal_memcpy_ext(priv->phandle, data_ptr, (t_u8 *)&qcfg_ioctl,
+			sizeof(qcfg_ioctl),
+			respbuflen -
+			(strlen(CMD_NXP) + strlen(PRIV_CMD_QCONFIG)));
+	ret = strlen(CMD_NXP) + strlen(PRIV_CMD_QCONFIG) + sizeof(qcfg_ioctl);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get the status of the WMM queues
+ *
+ *  Return the following information for each WMM AC:
+ *        - WMM IE Acm Required
+ *        - Firmware Flow Required
+ *        - Firmware Flow Established
+ *        - Firmware Queue Enabled
+ *        - Firmware Delivery Enabled
+ *        - Firmware Trigger Enabled
+ *
+ *  @param priv    Pointer to the moal_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_wmm_queue_status_ioctl(moal_private *priv, t_u8 *respbuf,
+				 t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	wlan_ioctl_wmm_queue_status_t qstatus_ioctl;
+	int ret = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_QSTATUS);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_STATUS;
+
+	if ((int)strlen(respbuf) == header_len) {
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memset(&qstatus_ioctl, 0x00, sizeof(qstatus_ioctl));
+		moal_memcpy_ext(priv->phandle, (void *)&qstatus_ioctl,
+				(void *)&pwmm->param.q_status,
+				sizeof(qstatus_ioctl), sizeof(qstatus_ioctl));
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&qstatus_ioctl,
+				sizeof(qstatus_ioctl), respbuflen);
+		ret = sizeof(qstatus_ioctl);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get the status of the WMM Traffic Streams
+ *
+ *  @param priv    Pointer to the moal_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_wmm_ts_status_ioctl(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	wlan_ioctl_wmm_ts_status_t ts_status_ioctl;
+	int ret = 0, header_len = 0;
+	t_u8 *data_ptr;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TS_STATUS);
+	data_ptr = respbuf + header_len;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_TS_STATUS;
+
+	memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl));
+
+	moal_memcpy_ext(priv->phandle, (t_u8 *)&ts_status_ioctl, data_ptr,
+			sizeof(ts_status_ioctl), sizeof(ts_status_ioctl));
+
+	memset(&pwmm->param.ts_status, 0x00, sizeof(ts_status_ioctl));
+	pwmm->param.ts_status.tid = ts_status_ioctl.tid;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl));
+	moal_memcpy_ext(priv->phandle, (void *)&ts_status_ioctl,
+			(void *)&pwmm->param.ts_status, sizeof(ts_status_ioctl),
+			sizeof(ts_status_ioctl));
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&ts_status_ioctl,
+			sizeof(ts_status_ioctl), respbuflen);
+	ret = sizeof(ts_status_ioctl);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get MAC control
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_macctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MAC_CTRL);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_MAC_CONTROL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0)
+		req->action = MLAN_ACT_GET;
+	else {
+		cfg->param.mac_ctrl = (t_u32)data;
+		req->action = MLAN_ACT_SET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&cfg->param.mac_ctrl,
+			sizeof(data), respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get connection status
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_getwap(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+#ifdef STA_SUPPORT
+	mlan_bss_info bss_info;
+#endif
+
+	ENTER();
+
+#ifdef STA_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		memset(&bss_info, 0, sizeof(bss_info));
+
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+		if (bss_info.media_connected == MTRUE) {
+			moal_memcpy_ext(priv->phandle, respbuf,
+					(t_u8 *)&bss_info.bssid,
+					MLAN_MAC_ADDR_LENGTH, respbuflen);
+		} else {
+			memset(respbuf, 0, MLAN_MAC_ADDR_LENGTH);
+		}
+	}
+#endif
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		if (priv->bss_started) {
+			moal_memcpy_ext(priv->phandle, respbuf,
+					priv->current_addr,
+					MLAN_MAC_ADDR_LENGTH, respbuflen);
+		} else {
+			memset(respbuf, 0, MLAN_MAC_ADDR_LENGTH);
+		}
+	}
+#endif
+	ret = MLAN_MAC_ADDR_LENGTH;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Region Code
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_region_code(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_REGION_CODE);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_REGION;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0)
+		req->action = MLAN_ACT_GET;
+	else {
+		cfg->param.region_code = (t_u32)data;
+		req->action = MLAN_ACT_SET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&cfg->param.region_code,
+			sizeof(data), respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef RX_PACKET_COALESCE
+/**
+ *  @brief Set/Get RX packet coalesceing setting
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_rx_pkt_coalesce_cfg(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	int ret = 0;
+	t_u32 data[2];
+	int user_data_len = 0, header_len = 0;
+	mlan_ds_misc_cfg *cfg = NULL;
+	t_u8 *data_ptr;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = respbuf + strlen(CMD_NXP) + strlen(PRIV_CMD_RX_COAL_CFG);
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RX_COAL_CFG);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if ((user_data_len != 0) && (user_data_len != 2)) {
+		PRINTM(MERROR, "Invalid arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_RX_PACKET_COALESCE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		cfg->param.rx_coalesce.packet_threshold = data[0];
+		cfg->param.rx_coalesce.delay = data[1];
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf,
+			(mlan_ds_misc_rx_packet_coalesce *)&cfg->param.
+			rx_coalesce, req->buf_len, respbuflen);
+	ret = req->buf_len;
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+/**
+ *  @brief Set/Get FW side mac address
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_fwmacaddr(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	t_u8 data[ETH_ALEN];
+	int ret = 0;
+	int header_len = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_FWMACADDR);
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MAC_ADDR;
+	req->req_id = MLAN_IOCTL_BSS;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		req->action = MLAN_ACT_SET;
+		memset(data, 0, sizeof(data));
+		woal_mac2u8(data, respbuf + header_len);
+		moal_memcpy_ext(priv->phandle, bss->param.mac_addr, data,
+				ETH_ALEN, sizeof(mlan_802_11_mac_addr));
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, bss->param.mac_addr,
+			sizeof(data), respbuflen);
+	ret = sizeof(data);
+	HEXDUMP("FW MAC Addr:", respbuf, ETH_ALEN);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+/**
+ *  @brief Set offchannel
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_offchannel(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[4];
+	int ret = 0;
+	t_u8 status = 1;
+	t_u8 chan_type = CHAN_NO_HT;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_OFFCHANNEL);
+
+	if (header_len == (int)strlen(respbuf)) {
+		/* Query current remain on channel status */
+		if (priv->phandle->remain_on_channel)
+			ret = sprintf(respbuf,
+				      "There is pending remain on channel from bss %d\n",
+				      priv->phandle->remain_bss_index) + 1;
+		else
+			ret = sprintf(respbuf,
+				      "There is no pending remain on channel\n")
+				+ 1;
+		goto done;
+	} else
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (user_data_len >= 1) {
+		if ((data[0] != 0) && (data[0] != 1)) {
+			PRINTM(MERROR, "action (%d) must be either 0 or 1\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	if (user_data_len == 2) {
+		if (data[0] == 1) {
+			PRINTM(MERROR,
+			       "channel and duration must both the mentioned\n");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			PRINTM(MWARN,
+			       "extra arguments are ignored since action is 'cancel'\n");
+		}
+	}
+	if (user_data_len >= 3) {
+		if (data[0] == 1) {
+			if (data[1] < 0) {
+				PRINTM(MERROR, "channel cannot be negative\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (data[2] < 0) {
+				PRINTM(MERROR, "duration cannot be negative\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (user_data_len == 4) {
+				if (data[3] &&
+				    (data[3] != CHANNEL_BW_40MHZ_ABOVE) &&
+				    (data[3] != CHANNEL_BW_40MHZ_BELOW)
+				    && (data[3] != CHANNEL_BW_80MHZ)
+					) {
+					PRINTM(MERROR, "invalid bandwidth");
+					ret = -EINVAL;
+					goto done;
+				}
+				switch (data[3]) {
+				case CHANNEL_BW_40MHZ_ABOVE:
+					chan_type = CHAN_HT40PLUS;
+					break;
+				case CHANNEL_BW_40MHZ_BELOW:
+					chan_type = CHAN_HT40MINUS;
+					break;
+				case CHANNEL_BW_80MHZ:
+					chan_type = CHAN_VHT80;
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	if (data[0] == 0) {
+		if (!priv->phandle->remain_on_channel) {
+			ret = sprintf(respbuf,
+				      "There is no pending remain on channel to be canceled\n")
+				+ 1;
+			goto done;
+		}
+		if (woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT,
+							MTRUE, &status, NULL, 0,
+							0)) {
+			PRINTM(MERROR, "remain_on_channel: Failed to cancel\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (status == MLAN_STATUS_SUCCESS)
+			priv->phandle->remain_on_channel = MFALSE;
+	} else if (data[0] == 1) {
+		if (woal_cfg80211_remain_on_channel_cfg
+		    (priv, MOAL_IOCTL_WAIT, MFALSE, &status,
+		     ieee80211_get_channel(priv->wdev->wiphy,
+					   ieee80211_channel_to_frequency(data
+									  [1]
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+									  ,
+									  (data
+									   [1]
+									   <=
+									   14 ?
+									   IEEE80211_BAND_2GHZ
+									   :
+									   IEEE80211_BAND_5GHZ)
+#endif
+					   )), chan_type, (t_u32)data[2])) {
+			PRINTM(MERROR, "remain_on_channel: Failed to start\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (status == MLAN_STATUS_SUCCESS) {
+			priv->phandle->remain_on_channel = MTRUE;
+			priv->phandle->remain_bss_index = priv->bss_index;
+		}
+	}
+
+	if (status != MLAN_STATUS_SUCCESS)
+		ret = -EFAULT;
+	else
+		ret = sprintf(respbuf, "OK\n") + 1;
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ *  @brief Set/Get dscp map
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_set_get_dscp_map(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 *pos = NULL;
+	int copy_size = 0, header_len = 0;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DSCP_MAP);
+	if ((int)strlen(respbuf) != header_len) {
+		/* SET operation */
+		pos = respbuf + header_len;
+		moal_memcpy_ext(priv->phandle, priv->dscp_map, pos,
+				sizeof(priv->dscp_map), sizeof(priv->dscp_map));
+	}
+
+	copy_size = MIN(sizeof(priv->dscp_map), respbuflen);
+	moal_memcpy_ext(priv->phandle, respbuf, priv->dscp_map, copy_size,
+			respbuflen);
+	ret = copy_size;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get extended driver version
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_driver_verext(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int copy_size = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_VER_EXT;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_VEREXT);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	info->param.ver_ext.version_str_sel = data;
+	if (((t_s32)(info->param.ver_ext.version_str_sel)) < 0) {
+		PRINTM(MERROR, "Invalid arguments!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/*
+	 * Set the amount to copy back to the application as the minimum of the
+	 *   available assoc resp data or the buffer provided by the application
+	 */
+	copy_size = MIN(strlen(info->param.ver_ext.version_str), respbuflen);
+	moal_memcpy_ext(priv->phandle, respbuf, info->param.ver_ext.version_str,
+			copy_size, respbuflen);
+	ret = copy_size;
+	PRINTM(MINFO, "MOAL EXTENDED VERSION: %s\n",
+	       info->param.ver_ext.version_str);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef USB
+#ifdef CONFIG_USB_SUSPEND
+/**
+ *  @brief This function makes USB device to suspend.
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_enter_usb_suspend(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+
+	ENTER();
+	ret = woal_enter_usb_suspend(priv->phandle);
+	moal_memcpy_ext(priv->phandle, respbuf, &ret, sizeof(int), respbuflen);
+	ret = sizeof(int);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function makes USB device to resume.
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_exit_usb_suspend(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+
+	ENTER();
+	ret = woal_exit_usb_suspend(priv->phandle);
+	moal_memcpy_ext(priv->phandle, respbuf, &ret, sizeof(int), respbuflen);
+	ret = sizeof(int);
+
+	LEAVE();
+	return ret;
+}
+#endif /* CONFIG_USB_SUSPEND */
+#endif
+
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+/**
+ *  @brief SET/Get radio
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_radio_ctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0, option = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RADIO_CTRL);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &option, 1,
+				&user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (user_data_len == 1) {
+		/* Set radio */
+		if (option < 0 || option > 1) {
+			PRINTM(MERROR, "Invalid arguments!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS != woal_set_radio(priv, (t_u8)option))
+			ret = -EFAULT;
+		goto done;
+	} else {
+		/* Get radio status */
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		moal_memcpy_ext(priv->phandle, respbuf, &bss_info.radio_on,
+				sizeof(bss_info.radio_on), respbuflen);
+		ret = sizeof(bss_info.radio_on);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Implement WMM enable command
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_wmm_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_wmm_cfg *wmm = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	wmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	wmm->sub_command = MLAN_OID_WMM_CFG_ENABLE;
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_WMM_CFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			/* Set wmm */
+			if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			req->action = MLAN_ACT_SET;
+			if (data == CMD_DISABLED)
+				wmm->param.wmm_enable = MFALSE;
+			else
+				wmm->param.wmm_enable = MTRUE;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, &wmm->param.wmm_enable,
+			sizeof(wmm->param.wmm_enable), respbuflen);
+	ret = sizeof(wmm->param.wmm_enable);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Implement Mininum BA Threshold cfg command
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_min_ba_threshold_cfg(moal_private *priv, t_u8 *respbuf,
+			       t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_MIN_BA_THRESHOLD;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MIN_BA_THRESH_CFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			/* Set minimum BA Threshold */
+			if ((data < 0) || (data > 16)) {
+				PRINTM(MERROR,
+				       "Error: Valid minimum BA threshold range (0-16)!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			req->action = MLAN_ACT_SET;
+			cfg_11n->param.min_ba_threshold = data;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf,
+			&cfg_11n->param.min_ba_threshold,
+			sizeof(cfg_11n->param.min_ba_threshold), respbuflen);
+	ret = sizeof(cfg_11n->param.min_ba_threshold);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_SUPPORT)
+/**
+ *  @brief Implement 802.11D enable command
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_11d_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_11d_cfg *pcfg_11d = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	pcfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
+	pcfg_11d->sub_command = MLAN_OID_11D_CFG_ENABLE;
+	req->req_id = MLAN_IOCTL_11D_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_11D_CFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			req->action = MLAN_ACT_SET;
+			if (data == CMD_DISABLED)
+				pcfg_11d->param.enable_11d = MFALSE;
+			else
+				pcfg_11d->param.enable_11d = MTRUE;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, &pcfg_11d->param.enable_11d,
+			sizeof(pcfg_11d->param.enable_11d), respbuflen);
+	ret = sizeof(pcfg_11d->param.enable_11d);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Implement 802.11D clear chan table command
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_priv_11d_clr_chan_tbl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ds_11d_cfg *pcfg_11d = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_11D_CLR_TBL);
+
+	if ((int)strlen(respbuf) != header_len) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	pcfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
+	pcfg_11d->sub_command = MLAN_OID_11D_CLR_CHAN_TABLE;
+	req->req_id = MLAN_IOCTL_11D_CFG;
+	req->action = MLAN_ACT_SET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifndef OPCHAN
+/**
+ *  @brief Set/Get WWS mode
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_wws_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_misc_cfg *wws = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	wws = (mlan_ds_misc_cfg *)req->pbuf;
+	wws->sub_command = MLAN_OID_MISC_WWS;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_WWS_CFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
+				PRINTM(MERROR,
+				       "Invalid arguments, WWS config not changed!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			req->action = MLAN_ACT_SET;
+			wws->param.wws_cfg = (t_u16)data;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, &wws->param.wws_cfg,
+			sizeof(wws->param.wws_cfg), respbuflen);
+	ret = sizeof(wws->param.wws_cfg);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if defined(REASSOCIATION)
+/**
+ *  @brief Set/Get reassociation settings
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_reassoc(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	moal_handle *handle = priv->phandle;
+	int data = 0;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_REASSOCTRL);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		data = (int)(priv->reassoc_on);
+		moal_memcpy_ext(handle, respbuf, &data, sizeof(data),
+				respbuflen);
+		ret = sizeof(data);
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			if (data == 0) {
+				handle->reassoc_on &= ~MBIT(priv->bss_index);
+				priv->reassoc_on = MFALSE;
+				priv->reassoc_required = MFALSE;
+				if (!handle->reassoc_on &&
+				    handle->is_reassoc_timer_set == MTRUE) {
+					woal_cancel_timer(&handle->
+							  reassoc_timer);
+					handle->is_reassoc_timer_set = MFALSE;
+				}
+			} else if (data == 1) {
+				handle->reassoc_on |= MBIT(priv->bss_index);
+				priv->reassoc_on = MTRUE;
+			} else {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+			}
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif /* REASSOCIATION */
+
+/**
+ *  @brief Get Transmit buffer size
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_txbuf_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int buf_size = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TXBUF_CFG);
+
+	if ((int)strlen(respbuf) != header_len) {
+		PRINTM(MERROR,
+		       "Don't support set Tx buffer size after driver loaded!\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		/* Get Tx buffer size from MLAN */
+		req->action = MLAN_ACT_GET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	buf_size = cfg_11n->param.tx_buf_size;
+	moal_memcpy_ext(priv->phandle, respbuf, &buf_size, sizeof(buf_size),
+			respbuflen);
+	ret = sizeof(buf_size);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Set/Get auth type
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_auth_type(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int auth_type = 0;
+	t_u32 auth_mode;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_AUTH_TYPE);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		user_data_len = 0;
+		auth_type = auth_mode;
+		moal_memcpy_ext(priv->phandle, respbuf, &auth_type,
+				sizeof(auth_type), respbuflen);
+		ret = sizeof(auth_type);
+		goto done;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &auth_type, 1,
+				&user_data_len);
+		if (user_data_len == 1) {
+			PRINTM(MINFO, "SET: auth_type %d\n", auth_type);
+			if (((auth_type < MLAN_AUTH_MODE_OPEN) ||
+			     (auth_type > MLAN_AUTH_MODE_SAE))
+			    && (auth_type != MLAN_AUTH_MODE_AUTO)
+				) {
+				ret = -EINVAL;
+				goto done;
+			}
+			auth_mode = auth_type;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT,
+					       auth_mode)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set/get user provisioned local power constraint
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_11h_local_pwr_constraint(moal_private *priv, t_u8 *respbuf,
+				   t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+	ds_11hcfg->sub_command = MLAN_OID_11H_LOCAL_POWER_CONSTRAINT;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_POWER_CONS);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			req->action = MLAN_ACT_SET;
+			ds_11hcfg->param.usr_local_power_constraint =
+				(t_s8)data;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		data = (int)ds_11hcfg->param.usr_local_power_constraint;
+		moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+				respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get HT stream configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_ht_stream_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_11n_cfg *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_11N_CFG_STREAM_CFG;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_HT_STREAM_CFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			if (data != HT_STREAM_MODE_1X1 &&
+			    data != HT_STREAM_MODE_2X2) {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			req->action = MLAN_ACT_SET;
+			cfg->param.stream_cfg = data;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data = ((mlan_ds_11n_cfg *)req->pbuf)->param.stream_cfg;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set mimo switch configurations
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_mimo_switch(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[2] = { 0 };
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_MIMO_SWITCH;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MIMO_SWITCH);
+
+	if ((int)strlen(respbuf) > header_len) {
+		/* SET operation */
+		req->action = MLAN_ACT_SET;
+		parse_arguments(respbuf + header_len, data, 2, &user_data_len);
+		if (user_data_len == 2) {
+			radio->param.mimo_switch_cfg.txpath_antmode = data[0];
+			radio->param.mimo_switch_cfg.rxpath_antmode = data[1];
+		} else {
+			PRINTM(MERROR, "Invalid arguments!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid arguments!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get thermal reading
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_thermal(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0, header_len = 0, data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_THERMAL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_THERMAL);
+
+	if ((int)strlen(respbuf) != header_len) {
+		PRINTM(MERROR, "Set is not supported for this command\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data = (int)cfg->param.thermal;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get beacon interval
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_beacon_interval(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = ENOMEM;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_IBSS_BCN_INTERVAL;
+	req->req_id = MLAN_IOCTL_BSS;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_BCN_INTERVAL);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+		if (user_data_len == 1) {
+			if ((data < MLAN_MIN_BEACON_INTERVAL) ||
+			    (data > MLAN_MAX_BEACON_INTERVAL)) {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			req->action = MLAN_ACT_SET;
+			bss->param.bcn_interval = data;
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data = ((mlan_ds_bss *)req->pbuf)->param.bcn_interval;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Get signal
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_signal(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+/** Input data size */
+#define IN_DATA_SIZE 2
+/** Output data size */
+#define OUT_DATA_SIZE 12
+	int ret = 0;
+	int in_data[IN_DATA_SIZE];
+	int out_data[OUT_DATA_SIZE];
+	mlan_ds_get_signal signal;
+	int data_length = 0;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	memset(in_data, 0, sizeof(in_data));
+	memset(out_data, 0, sizeof(out_data));
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_GET_SIGNAL);
+
+	if ((int)strlen(respbuf) != header_len)
+		parse_arguments(respbuf + header_len, in_data, IN_DATA_SIZE,
+				&user_data_len);
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can not get RSSI in disconnected state\n");
+		ret = -ENOTSUPP;
+		goto done;
+	}
+
+	if (user_data_len) {
+		if (user_data_len > IN_DATA_SIZE) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	switch (user_data_len) {
+	case 0:		/* No checking, get everything */
+		break;
+	case 2:		/* Check subtype range */
+		if (in_data[1] < 1 || in_data[1] > 4) {
+			ret = -EINVAL;
+			goto done;
+		}
+		/* Fall through */
+	case 1:		/* Check type range */
+		if (in_data[0] < 1 || in_data[0] > 3) {
+			ret = -EINVAL;
+			goto done;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		goto done;
+	}
+
+	memset(&signal, 0, sizeof(mlan_ds_get_signal));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_signal_info(priv, MOAL_IOCTL_WAIT, &signal)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MINFO, "RSSI Beacon Last   : %d\n", (int)signal.bcn_rssi_last);
+	PRINTM(MINFO, "RSSI Beacon Average: %d\n", (int)signal.bcn_rssi_avg);
+	PRINTM(MINFO, "RSSI Data Last     : %d\n", (int)signal.data_rssi_last);
+	PRINTM(MINFO, "RSSI Data Average  : %d\n", (int)signal.data_rssi_avg);
+	PRINTM(MINFO, "SNR Beacon Last    : %d\n", (int)signal.bcn_snr_last);
+	PRINTM(MINFO, "SNR Beacon Average : %d\n", (int)signal.bcn_snr_avg);
+	PRINTM(MINFO, "SNR Data Last      : %d\n", (int)signal.data_snr_last);
+	PRINTM(MINFO, "SNR Data Average   : %d\n", (int)signal.data_snr_avg);
+	PRINTM(MINFO, "NF Beacon Last     : %d\n", (int)signal.bcn_nf_last);
+	PRINTM(MINFO, "NF Beacon Average  : %d\n", (int)signal.bcn_nf_avg);
+	PRINTM(MINFO, "NF Data Last       : %d\n", (int)signal.data_nf_last);
+	PRINTM(MINFO, "NF Data Average    : %d\n", (int)signal.data_nf_avg);
+
+	/* Check type */
+	switch (in_data[0]) {
+	case 0:		/* Send everything */
+		out_data[data_length++] = signal.bcn_rssi_last;
+		out_data[data_length++] = signal.bcn_rssi_avg;
+		out_data[data_length++] = signal.data_rssi_last;
+		out_data[data_length++] = signal.data_rssi_avg;
+		out_data[data_length++] = signal.bcn_snr_last;
+		out_data[data_length++] = signal.bcn_snr_avg;
+		out_data[data_length++] = signal.data_snr_last;
+		out_data[data_length++] = signal.data_snr_avg;
+		out_data[data_length++] = signal.bcn_nf_last;
+		out_data[data_length++] = signal.bcn_nf_avg;
+		out_data[data_length++] = signal.data_nf_last;
+		out_data[data_length++] = signal.data_nf_avg;
+		break;
+	case 1:		/* RSSI */
+		/* Check subtype */
+		switch (in_data[1]) {
+		case 0:	/* Everything */
+			out_data[data_length++] = signal.bcn_rssi_last;
+			out_data[data_length++] = signal.bcn_rssi_avg;
+			out_data[data_length++] = signal.data_rssi_last;
+			out_data[data_length++] = signal.data_rssi_avg;
+			break;
+		case 1:	/* bcn last */
+			out_data[data_length++] = signal.bcn_rssi_last;
+			break;
+		case 2:	/* bcn avg */
+			out_data[data_length++] = signal.bcn_rssi_avg;
+			break;
+		case 3:	/* data last */
+			out_data[data_length++] = signal.data_rssi_last;
+			break;
+		case 4:	/* data avg */
+			out_data[data_length++] = signal.data_rssi_avg;
+			break;
+		default:
+			break;
+		}
+		break;
+	case 2:		/* SNR */
+		/* Check subtype */
+		switch (in_data[1]) {
+		case 0:	/* Everything */
+			out_data[data_length++] = signal.bcn_snr_last;
+			out_data[data_length++] = signal.bcn_snr_avg;
+			out_data[data_length++] = signal.data_snr_last;
+			out_data[data_length++] = signal.data_snr_avg;
+			break;
+		case 1:	/* bcn last */
+			out_data[data_length++] = signal.bcn_snr_last;
+			break;
+		case 2:	/* bcn avg */
+			out_data[data_length++] = signal.bcn_snr_avg;
+			break;
+		case 3:	/* data last */
+			out_data[data_length++] = signal.data_snr_last;
+			break;
+		case 4:	/* data avg */
+			out_data[data_length++] = signal.data_snr_avg;
+			break;
+		default:
+			break;
+		}
+		break;
+	case 3:		/* NF */
+		/* Check subtype */
+		switch (in_data[1]) {
+		case 0:	/* Everything */
+			out_data[data_length++] = signal.bcn_nf_last;
+			out_data[data_length++] = signal.bcn_nf_avg;
+			out_data[data_length++] = signal.data_nf_last;
+			out_data[data_length++] = signal.data_nf_avg;
+			break;
+		case 1:	/* bcn last */
+			out_data[data_length++] = signal.bcn_nf_last;
+			break;
+		case 2:	/* bcn avg */
+			out_data[data_length++] = signal.bcn_nf_avg;
+			break;
+		case 3:	/* data last */
+			out_data[data_length++] = signal.data_nf_last;
+			break;
+		case 4:	/* data avg */
+			out_data[data_length++] = signal.data_nf_avg;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, out_data,
+			(data_length * sizeof(int)), respbuflen);
+	ret = data_length * sizeof(int);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+static int
+woal_signal_ext_enable(moal_private *priv, t_u8 enable)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_snmp_mib *snmp = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	snmp = (mlan_ds_snmp_mib *)req->pbuf;
+	snmp->sub_command = MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+	req->action = MLAN_ACT_SET;
+	snmp->param.signalext_enable = enable;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get signal
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_signal_ext(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+#define PATH_SIZE 13
+	int ret = 0;
+	int data = 0, path = 0, data_len = 0;
+	int user_data_len = 0, header_len = 0;
+	int out_data[PATH_SIZE * MAX_PATH_NUM] = { 0 };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_ds_get_signal signal_get[MAX_PATH_NUM];
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int path_num;
+	t_u8 enable = 1;
+
+	ENTER();
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can not get RSSI in disconnected state\n");
+		ret = -ENOTSUPP;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_GET_SIGNAL_EXT);
+
+	if ((int)strlen(respbuf) != header_len) {
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data < PATH_ALL || data > PATH_AB) {
+		PRINTM(MERROR, "Wrong arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/** Enable signalext feature in firmware */
+	if (MLAN_STATUS_SUCCESS != woal_signal_ext_enable(priv, enable)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	woal_sched_timeout(1000);
+	enable = 0;
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_SIGNAL_EXT;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+	info->param.path_id = (t_u16)data;
+
+	/* Send IOCTL request to MLAN */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) {
+		woal_signal_ext_enable(priv, enable);
+		ret = -EFAULT;
+		goto done;
+	}
+	if (MLAN_STATUS_SUCCESS != woal_signal_ext_enable(priv, enable)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	path_num = 1;
+	if (data == PATH_ALL) {
+		moal_memcpy_ext(priv->phandle, signal_get,
+				info->param.signal_ext, sizeof(signal_get),
+				sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		moal_memcpy_ext(priv->phandle, signal_get,
+				info->param.signal_ext,
+				sizeof(mlan_ds_get_signal), sizeof(signal_get));
+
+	for (path = 0; path < path_num; path++) {
+		if (signal_get[path].selector == PATH_AB)
+			PRINTM(MINFO, "PATH A+B:\n");
+		else if (signal_get[path].selector == PATH_A)
+			PRINTM(MINFO, "PATH A:\n");
+		else if (signal_get[path].selector == PATH_B)
+			PRINTM(MINFO, "PATH B:\n");
+		PRINTM(MINFO, "RSSI Beacon Last   : %d\n",
+		       (int)signal_get[path].bcn_rssi_last);
+		PRINTM(MINFO, "RSSI Beacon Average: %d\n",
+		       (int)signal_get[path].bcn_rssi_avg);
+		PRINTM(MINFO, "RSSI Data Last     : %d\n",
+		       (int)signal_get[path].data_rssi_last);
+		PRINTM(MINFO, "RSSI Data Average  : %d\n",
+		       (int)signal_get[path].data_rssi_avg);
+		PRINTM(MINFO, "SNR Beacon Last    : %d\n",
+		       (int)signal_get[path].bcn_snr_last);
+		PRINTM(MINFO, "SNR Beacon Average : %d\n",
+		       (int)signal_get[path].bcn_snr_avg);
+		PRINTM(MINFO, "SNR Data Last      : %d\n",
+		       (int)signal_get[path].data_snr_last);
+		PRINTM(MINFO, "SNR Data Average   : %d\n",
+		       (int)signal_get[path].data_snr_avg);
+		PRINTM(MINFO, "NF Beacon Last     : %d\n",
+		       (int)signal_get[path].bcn_nf_last);
+		PRINTM(MINFO, "NF Beacon Average  : %d\n",
+		       (int)signal_get[path].bcn_nf_avg);
+		PRINTM(MINFO, "NF Data Last       : %d\n",
+		       (int)signal_get[path].data_nf_last);
+		PRINTM(MINFO, "NF Data Average    : %d\n",
+		       (int)signal_get[path].data_nf_avg);
+		out_data[data_len++] = (int)signal_get[path].selector;
+		out_data[data_len++] = (int)signal_get[path].bcn_rssi_last;
+		out_data[data_len++] = (int)signal_get[path].bcn_rssi_avg;
+		out_data[data_len++] = (int)signal_get[path].data_rssi_last;
+		out_data[data_len++] = (int)signal_get[path].data_rssi_avg;
+		out_data[data_len++] = (int)signal_get[path].bcn_snr_last;
+		out_data[data_len++] = (int)signal_get[path].bcn_snr_avg;
+		out_data[data_len++] = (int)signal_get[path].data_snr_last;
+		out_data[data_len++] = (int)signal_get[path].data_snr_avg;
+		out_data[data_len++] = (int)signal_get[path].bcn_nf_last;
+		out_data[data_len++] = (int)signal_get[path].bcn_nf_avg;
+		out_data[data_len++] = (int)signal_get[path].data_nf_last;
+		out_data[data_len++] = (int)signal_get[path].data_nf_avg;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, out_data,
+			(MIN((PATH_SIZE * MAX_PATH_NUM), data_len) *
+			 sizeof(int)), respbuflen);
+	ret = data_len * sizeof(int);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get signalext v2
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_signal_ext_v2(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+#define PATH_SIZE 13
+	int ret = 0;
+	int data = 0, path = 0, data_len = 0;
+	int user_data_len = 0, header_len = 0;
+	int out_data[PATH_SIZE * MAX_PATH_NUM] = { 0 };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_ds_get_signal signal_get[MAX_PATH_NUM];
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int path_num;
+
+	ENTER();
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can not get RSSI in disconnected state\n");
+		ret = -ENOTSUPP;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_GET_SIGNAL_EXT_V2);
+	if ((int)strlen(respbuf) != header_len) {
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+	}
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data < PATH_ALL || data > PATH_AB) {
+		PRINTM(MERROR, "Wrong arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_SIGNAL_EXT;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+	info->param.path_id = (t_u16)data;
+
+	/* Send IOCTL request to MLAN */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) {
+		PRINTM(MERROR,
+		       "Enable signalextcfg: mlanutl mlanX signalextcfg 1"
+		       " before issuing this command\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	path_num = 1;
+
+	if (data == PATH_ALL) {
+		moal_memcpy_ext(priv->phandle, signal_get,
+				info->param.signal_ext, sizeof(signal_get),
+				sizeof(signal_get));
+		path_num = MAX_PATH_NUM;
+	} else
+		moal_memcpy_ext(priv->phandle, signal_get,
+				info->param.signal_ext,
+				sizeof(mlan_ds_get_signal), sizeof(signal_get));
+
+	PRINTM(MMSG, "data=%d path_num=%d\n", data, path_num);
+
+	for (path = 0; path < path_num; path++) {
+		if (signal_get[path].selector == PATH_AB)
+			PRINTM(MINFO, "PATH A+B:\n");
+		else if (signal_get[path].selector == PATH_A)
+			PRINTM(MINFO, "PATH A:\n");
+		else if (signal_get[path].selector == PATH_B)
+			PRINTM(MINFO, "PATH B:\n");
+		PRINTM(MINFO, "RSSI Beacon Last   : %d\n",
+		       (int)signal_get[path].bcn_rssi_last);
+		PRINTM(MINFO, "RSSI Beacon Average: %d\n",
+		       (int)signal_get[path].bcn_rssi_avg);
+		PRINTM(MINFO, "RSSI Data Last     : %d\n",
+		       (int)signal_get[path].data_rssi_last);
+		PRINTM(MINFO, "RSSI Data Average  : %d\n",
+		       (int)signal_get[path].data_rssi_avg);
+		PRINTM(MINFO, "SNR Beacon Last    : %d\n",
+		       (int)signal_get[path].bcn_snr_last);
+		PRINTM(MINFO, "SNR Beacon Average : %d\n",
+		       (int)signal_get[path].bcn_snr_avg);
+		PRINTM(MINFO, "SNR Data Last      : %d\n",
+		       (int)signal_get[path].data_snr_last);
+		PRINTM(MINFO, "SNR Data Average   : %d\n",
+		       (int)signal_get[path].data_snr_avg);
+		PRINTM(MINFO, "NF Beacon Last     : %d\n",
+		       (int)signal_get[path].bcn_nf_last);
+		PRINTM(MINFO, "NF Beacon Average  : %d\n",
+		       (int)signal_get[path].bcn_nf_avg);
+		PRINTM(MINFO, "NF Data Last       : %d\n",
+		       (int)signal_get[path].data_nf_last);
+		PRINTM(MINFO, "NF Data Average    : %d\n",
+		       (int)signal_get[path].data_nf_avg);
+		out_data[data_len++] = (int)signal_get[path].selector;
+		out_data[data_len++] = (int)signal_get[path].bcn_rssi_last;
+		out_data[data_len++] = (int)signal_get[path].bcn_rssi_avg;
+		out_data[data_len++] = (int)signal_get[path].data_rssi_last;
+		out_data[data_len++] = (int)signal_get[path].data_rssi_avg;
+		out_data[data_len++] = (int)signal_get[path].bcn_snr_last;
+		out_data[data_len++] = (int)signal_get[path].bcn_snr_avg;
+		out_data[data_len++] = (int)signal_get[path].data_snr_last;
+		out_data[data_len++] = (int)signal_get[path].data_snr_avg;
+		out_data[data_len++] = (int)signal_get[path].bcn_nf_last;
+		out_data[data_len++] = (int)signal_get[path].bcn_nf_avg;
+		out_data[data_len++] = (int)signal_get[path].data_nf_last;
+		out_data[data_len++] = (int)signal_get[path].data_nf_avg;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, out_data,
+			(MIN((PATH_SIZE * MAX_PATH_NUM), data_len) *
+			 sizeof(int)), respbuflen);
+	ret = data_len * sizeof(int);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set signalext cfg
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             The result of this processing.
+ */
+static int
+woal_priv_signalext_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int enable = 0;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	ENTER();
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SIGNALEXT_CFG);
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "Invalid arguments!\n");
+		ret = -EINVAL;
+		goto done;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &enable, 1,
+				&user_data_len);
+		if (user_data_len == 1) {
+			if (enable != 0x0 && enable != 0x1) {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			ret = woal_signal_ext_enable(priv, enable);
+		} else {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* #ifdef STA_SUPPORT */
+
+#if defined(STA_SUPPORT)
+/**
+ * @brief               Make PMF bit required/optional
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              0 -- success, otherwise fail
+ */
+static int
+woal_priv_set_get_pmfcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[2] = { 0, 0 };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ds_misc_pmfcfg *pmfcfg;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->phandle->card_info->embedded_supp) {
+		PRINTM(MERROR, "Not supported cmd on this card\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PMFCFG);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	if (user_data_len > 2) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	pmfcfg = (mlan_ds_misc_pmfcfg *)&cfg->param.pmfcfg;
+	cfg->sub_command = MLAN_OID_MISC_PMFCFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len == 0)
+		req->action = MLAN_ACT_GET;
+	else {
+		pmfcfg->mfpc = (t_u8)data[0];
+		pmfcfg->mfpr = (t_u8)data[1];
+		req->action = MLAN_ACT_SET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&cfg->param.pmfcfg,
+			sizeof(mlan_ds_misc_pmfcfg), respbuflen);
+	ret = sizeof(mlan_ds_misc_pmfcfg);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief               Get/Set inactivity timeout extend
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_inactivity_timeout_ext(moal_private *priv, t_u8 *respbuf,
+				 t_u32 respbuflen)
+{
+	int data[4];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pmcfg = NULL;
+	pmlan_ds_inactivity_to inac_to = NULL;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_INACTIVITYTO);
+	memset(data, 0, sizeof(data));
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	if (user_data_len != 0 && user_data_len != 3 && user_data_len != 4) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
+	inac_to = &pmcfg->param.inactivity_to;
+	pmcfg->sub_command = MLAN_OID_PM_CFG_INACTIVITY_TO;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (user_data_len) {
+		inac_to->timeout_unit = data[0];
+		inac_to->unicast_timeout = data[1];
+		inac_to->mcast_timeout = data[2];
+		if (user_data_len == 4)
+			inac_to->ps_entry_timeout = data[3];
+		req->action = MLAN_ACT_SET;
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		data[0] = inac_to->timeout_unit;
+		data[1] = inac_to->unicast_timeout;
+		data[2] = inac_to->mcast_timeout;
+		data[3] = inac_to->ps_entry_timeout;
+
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Enable/Disable amsdu_aggr_ctrl
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_11n_amsdu_aggr_ctrl(moal_private *priv, t_u8 *respbuf,
+			      t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0, data[2] = { 0 };
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_AMSDU_AGGR_CTRL);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, 1, &user_data_len);
+
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		cfg_11n->param.amsdu_aggr_ctrl.enable = data[0];
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = cfg_11n->param.amsdu_aggr_ctrl.enable;
+	data[1] = cfg_11n->param.amsdu_aggr_ctrl.curr_buf_size;
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get Transmit beamforming capabilities
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_tx_bf_cap_ioctl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *bf_cfg = NULL;
+	int ret = 0, bf_cap = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TX_BF_CAP);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
+	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &bf_cap, 1,
+				&user_data_len);
+
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		bf_cfg->param.tx_bf_cap = bf_cap;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	bf_cap = bf_cfg->param.tx_bf_cap;
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&bf_cap, sizeof(bf_cap),
+			respbuflen);
+	ret = sizeof(bf_cap);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO
+/**
+ * @brief               Turn on/off the sdio clock
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_sdio_clock_ioctl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int data = 2;
+	int user_data_len = 0, header_len = 0;
+	/* Initialize the clock state as on */
+	static int clock_state = 1;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SDIO_CLOCK);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&clock_state,
+				sizeof(clock_state), respbuflen);
+		ret = sizeof(clock_state);
+		goto done;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data, 1, &user_data_len);
+
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	switch (data) {
+	case CMD_DISABLED:
+		PRINTM(MINFO, "SDIO clock is turned off\n");
+		ret = woal_sdio_set_bus_clock(priv->phandle, MFALSE);
+		clock_state = data;
+		break;
+	case CMD_ENABLED:
+		PRINTM(MINFO, "SDIO clock is turned on\n");
+		ret = woal_sdio_set_bus_clock(priv->phandle, MTRUE);
+		clock_state = data;
+		break;
+	default:
+		ret = -EINVAL;
+		PRINTM(MINFO, "sdioclock: wrong parameter\n");
+		break;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef SDIO
+/**
+ * @brief               Set SDIO Multi-point aggregation control parameters
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_sdio_mpa_ctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0, data[6];
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MPA_CTRL);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+
+		if (user_data_len > 6) {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_SDIO_MPA_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	/* Get the values first, then modify these values if
+	 * user had modified them */
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "woal_request_ioctl returned %d\n", ret);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (user_data_len == 0) {
+		data[0] = misc->param.mpa_ctrl.tx_enable;
+		data[1] = misc->param.mpa_ctrl.rx_enable;
+		data[2] = misc->param.mpa_ctrl.tx_buf_size;
+		data[3] = misc->param.mpa_ctrl.rx_buf_size;
+		data[4] = misc->param.mpa_ctrl.tx_max_ports;
+		data[5] = misc->param.mpa_ctrl.rx_max_ports;
+
+		PRINTM(MINFO, "Get Param: %d %d %d %d %d %d\n", data[0],
+		       data[1], data[2], data[3], data[4], data[5]);
+
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+		goto done;
+	}
+
+	switch (user_data_len) {
+	case 6:
+		misc->param.mpa_ctrl.rx_max_ports = data[5];
+		/* fall through */
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+		/* fall through */
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+		/* fall through */
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+		/* fall through */
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+		/* fall through */
+	case 1:
+		/* Set cmd */
+		req->action = MLAN_ACT_SET;
+
+		PRINTM(MINFO, "Set Param: %d %d %d %d %d %d\n", data[0],
+		       data[1], data[2], data[3], data[4], data[5]);
+
+		misc->param.mpa_ctrl.tx_enable = data[0];
+		break;
+	default:
+		PRINTM(MERROR, "Default case error\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief               Configure sleep parameters
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_sleep_params_ioctl(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pm = NULL;
+	mlan_ds_sleep_params *psleep_params = NULL;
+	int data[6] = { 0 }, i;
+	int user_data_len = 0, header_len = 0;
+#ifdef DEBUG_LEVEL1
+	char err_str[][36] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"control periodic calibration(0-2)"},
+	{"control of external sleepClock(0-2)"},
+	{"value of reserved for debug"}
+	};
+#endif
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm = (mlan_ds_pm_cfg *)req->pbuf;
+	pm->sub_command = MLAN_OID_PM_CFG_SLEEP_PARAMS;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	psleep_params = (pmlan_ds_sleep_params)&pm->param.sleep_params;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SLEEP_PARAMS);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len != 6) {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+#define MIN_VAL 0x0000
+#define MAX_VAL 0xFFFF
+		for (i = 0; i < 6; i++) {
+			if ((i == 3) || (i == 4)) {
+				/* These two cases are handled below the loop */
+				continue;
+			}
+			if (data[i] < MIN_VAL || data[i] > MAX_VAL) {
+				PRINTM(MERROR, "Invalid %s (0-65535)!\n",
+				       err_str[i]);
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		if (data[3] < 0 || data[3] > 2) {
+			PRINTM(MERROR,
+			       "Invalid control periodic calibration (0-2)!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[4] < 0 || data[4] > 2) {
+			PRINTM(MERROR,
+			       "Invalid control of external sleep clock (0-2)!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		psleep_params->error = data[0];
+		psleep_params->offset = data[1];
+		psleep_params->stable_time = data[2];
+		psleep_params->cal_control = data[3];
+		psleep_params->ext_sleep_clk = data[4];
+		psleep_params->reserved = data[5];
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = psleep_params->error;
+	data[1] = psleep_params->offset;
+	data[2] = psleep_params->stable_time;
+	data[3] = psleep_params->cal_control;
+	data[4] = psleep_params->ext_sleep_clk;
+	data[5] = psleep_params->reserved;
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get DFS Testing settings
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_dfs_testing(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	int ret = 0;
+	int data[5] = { 0 };
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DFS_TESTING);
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+	ds_11hcfg->sub_command = MLAN_OID_11H_DFS_TESTING;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len != 5) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[0] > 1800) {
+			PRINTM(MERROR,
+			       "The maximum user CAC is 1800 seconds (30 mins).\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[1] > 0xFFFF) {
+			PRINTM(MERROR, "The maximum user NOP is 65535 sec.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[3] > 0xFF) {
+			PRINTM(MERROR,
+			       "The maximum user fixed channel is 255.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[4] != 0 && ((unsigned)data[4] != 1)) {
+			PRINTM(MERROR, "CAC restart should be 0/1\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		ds_11hcfg->param.dfs_testing.usr_cac_period_msec =
+			(t_u32)data[0] * 1000;
+		ds_11hcfg->param.dfs_testing.usr_nop_period_sec =
+			(t_u16)data[1];
+		ds_11hcfg->param.dfs_testing.usr_no_chan_change =
+			data[2] ? 1 : 0;
+		ds_11hcfg->param.dfs_testing.usr_fixed_new_chan = (t_u8)data[3];
+		ds_11hcfg->param.dfs_testing.usr_cac_restart = (t_u8)data[4];
+		priv->phandle->cac_restart = (t_u8)data[4];
+		priv->phandle->cac_period_jiffies = (t_u32)data[0] * HZ;
+		priv->phandle->usr_nop_period_sec = (t_u16)data[1];
+		req->action = MLAN_ACT_SET;
+#ifdef UAP_SUPPORT
+		priv->user_cac_period_msec =
+			ds_11hcfg->param.dfs_testing.usr_cac_period_msec;
+#endif
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		data[0] =
+			ds_11hcfg->param.dfs_testing.usr_cac_period_msec / 1000;
+		data[1] = ds_11hcfg->param.dfs_testing.usr_nop_period_sec;
+		data[2] = ds_11hcfg->param.dfs_testing.usr_no_chan_change;
+		data[3] = ds_11hcfg->param.dfs_testing.usr_fixed_new_chan;
+		data[4] = ds_11hcfg->param.dfs_testing.usr_cac_restart;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get DFS W53 settings
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_dfs53cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	int ret = 0;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DFS53_CFG);
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+	ds_11hcfg->sub_command = MLAN_OID_11H_DFS_W53_CFG;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args !\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data > DFS_W53_OLD) {
+			PRINTM(MERROR, "Invalid config !\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		ds_11hcfg->param.dfs_w53_cfg.dfs53cfg = (t_u8)data;
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		moal_memcpy_ext(priv->phandle, respbuf,
+				(t_u8 *)&ds_11hcfg->param.dfs_w53_cfg.dfs53cfg,
+				sizeof(ds_11hcfg->param.dfs_w53_cfg.dfs53cfg),
+				respbuflen);
+		ret = sizeof(t_u8);
+	}
+
+	PRINTM(MIOCTL, "dfs w53 cfg %d\n",
+	       ds_11hcfg->param.dfs_w53_cfg.dfs53cfg);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief determine the center frquency center index for bandwidth
+ *         of 80 MHz and 160 MHz
+ *
+ ** @param priv          Pointer to moal_private structure
+ *  @param band         band
+ *  @param pri_chan     primary channel
+ *  @param chan_bw      channel bandwidth
+ *
+ *  @return             channel center frequency center, if found; O, otherwise
+ */
+
+static t_u8
+woal_get_center_freq_idx(moal_private *priv, t_u8 band,
+			 t_u32 pri_chan, t_u8 chan_bw)
+{
+	t_u8 center_freq_idx = 0;
+
+	if (band & BAND_AAC) {
+		switch (pri_chan) {
+		case 36:
+		case 40:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 38;
+				break;
+			}
+			/* fall through */
+		case 44:
+		case 48:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 46;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 42;
+				break;
+			}
+			/* fall through */
+		case 52:
+		case 56:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 54;
+				break;
+			}
+			/* fall through */
+		case 60:
+		case 64:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 62;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 58;
+				break;
+			} else if (chan_bw == CHANNEL_BW_160MHZ) {
+				center_freq_idx = 50;
+				break;
+			}
+			/* fall through */
+		case 68:
+		case 72:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 70;
+				break;
+			}
+			/* fall through */
+		case 76:
+		case 80:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 78;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 74;
+				break;
+			}
+			/* fall through */
+		case 84:
+		case 88:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 86;
+				break;
+			}
+			/* fall through */
+		case 92:
+		case 96:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 94;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 90;
+				break;
+			}
+			/* fall through */
+		case 100:
+		case 104:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 102;
+				break;
+			}
+			/* fall through */
+		case 108:
+		case 112:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 110;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 106;
+				break;
+			}
+			/* fall through */
+		case 116:
+		case 120:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 118;
+				break;
+			}
+			/* fall through */
+		case 124:
+		case 128:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 126;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 122;
+			} else if (chan_bw == CHANNEL_BW_160MHZ) {
+				center_freq_idx = 114;
+			}
+			break;
+		case 132:
+		case 136:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 134;
+				break;
+			}
+			/* fall through */
+		case 140:
+		case 144:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 126;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 138;
+			}
+			break;
+		case 149:
+		case 153:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 151;
+				break;
+			}
+			/* fall through */
+		case 157:
+		case 161:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 159;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 155;
+				break;
+			}
+			/* fall through */
+		case 165:
+		case 169:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 167;
+				break;
+			}
+			/* fall through */
+		case 173:
+		case 177:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 175;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 171;
+				break;
+			}
+			/* fall through */
+		case 184:
+		case 188:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 186;
+				break;
+			}
+			/* fall through */
+		case 192:
+		case 196:
+			if (chan_bw == CHANNEL_BW_40MHZ_ABOVE ||
+			    chan_bw == CHANNEL_BW_40MHZ_BELOW) {
+				center_freq_idx = 194;
+				break;
+			} else if (chan_bw == CHANNEL_BW_80MHZ) {
+				center_freq_idx = 190;
+				break;
+			}
+			/* fall through */
+		default:	/* error. go to the default */
+			center_freq_idx = 42;
+		}
+	}
+	return center_freq_idx;
+}
+
+#if defined(UAP_SUPPORT)
+/**
+ *  @brief This function handles channel switch with CSA/ECSA IE.
+ *
+ ** @param priv          Pointer to moal_private structure
+ *  @param block_tx      0-no need block traffic 1- need block traffic
+ *  @param oper_class    oper_class
+ *  @param channel       channel
+ *  @param switch count  how many csa/ecsa beacon will send out
+ *  @param band_width    1-40Mhz above, 3-40Mhz below, 4-80Mhz, 5-160Mhz
+ *  @param ecsa          MTRUE/MFALSE;
+ *
+ *  @return             channel center frequency center, if found; O, otherwise
+ */
+static int
+woal_channel_switch(moal_private *priv, t_u8 block_tx, t_u8 oper_class,
+		    t_u8 channel, t_u8 switch_count, t_u8 band_width, t_u8 ecsa)
+{
+	IEEEtypes_ExtChanSwitchAnn_t *ext_chan_switch = NULL;
+	IEEEtypes_ChanSwitchAnn_t *chan_switch = NULL;
+	custom_ie *pcust_chansw_ie = NULL;
+	t_u8 center_freq_idx = 0;
+	IEEEtypes_Header_t *pChanSwWrap_ie = NULL;
+	IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = NULL;
+	IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u8 bw;
+	t_u8 new_oper_class = oper_class;
+	int ret = 0;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+	misc->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+	misc->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+	pcust_chansw_ie = (custom_ie *)&misc->param.cust_ie.ie_data_list[0];
+	pcust_chansw_ie->ie_index = 0xffff;	/*Auto index */
+	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	/*Add IE for
+											   BEACON/probe resp */
+	chan_switch = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
+	chan_switch->element_id = CHANNEL_SWITCH_ANN;
+	chan_switch->len = 3;
+	chan_switch->chan_switch_mode = block_tx;
+	chan_switch->new_channel_num = channel;
+	chan_switch->chan_switch_count = switch_count;
+	DBG_HEXDUMP(MCMD_D, "CSA IE", (t_u8 *)pcust_chansw_ie->ie_buffer,
+		    pcust_chansw_ie->ie_length);
+	switch (band_width) {
+	case CHANNEL_BW_40MHZ_ABOVE:
+	case CHANNEL_BW_40MHZ_BELOW:
+		bw = 40;
+		break;
+	case CHANNEL_BW_80MHZ:
+		bw = 80;
+		break;
+	case CHANNEL_BW_160MHZ:
+		bw = 160;
+		break;
+	default:
+		bw = 20;
+		break;
+	}
+	if (!new_oper_class && ecsa)
+		woal_priv_get_nonglobal_operclass_by_bw_channel(priv, bw,
+								channel,
+								&new_oper_class);
+	if (new_oper_class) {
+		pcust_chansw_ie->ie_length +=
+			sizeof(IEEEtypes_ExtChanSwitchAnn_t);
+		ext_chan_switch =
+			(IEEEtypes_ExtChanSwitchAnn_t *) (pcust_chansw_ie->
+							  ie_buffer +
+							  sizeof
+							  (IEEEtypes_ChanSwitchAnn_t));
+		ext_chan_switch->element_id = EXTEND_CHANNEL_SWITCH_ANN;
+		ext_chan_switch->len = 4;
+		ext_chan_switch->chan_switch_mode = block_tx;
+		ext_chan_switch->new_oper_class = new_oper_class;
+		ext_chan_switch->new_channel_num = channel;
+		ext_chan_switch->chan_switch_count = switch_count;
+		DBG_HEXDUMP(MCMD_D, "ECSA IE",
+			    (t_u8 *)(pcust_chansw_ie->ie_buffer +
+				     sizeof(IEEEtypes_ChanSwitchAnn_t)),
+			    pcust_chansw_ie->ie_length -
+			    sizeof(IEEEtypes_ChanSwitchAnn_t));
+	}
+	/* bandwidth 40/80/160 should set channel switch wrapper ie for 11ac 5G
+	 * channel*/
+	if (band_width && channel > 14) {
+		pChanSwWrap_ie =
+			(IEEEtypes_Header_t *)(pcust_chansw_ie->ie_buffer +
+					       pcust_chansw_ie->ie_length);
+		pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
+		pChanSwWrap_ie->len = sizeof(IEEEtypes_WideBWChanSwitch_t);
+
+		pbwchansw_ie = (IEEEtypes_WideBWChanSwitch_t
+				*)((t_u8 *)pChanSwWrap_ie +
+				   sizeof(IEEEtypes_Header_t));
+		pbwchansw_ie->ieee_hdr.element_id = BW_CHANNEL_SWITCH;
+		pbwchansw_ie->ieee_hdr.len =
+			sizeof(IEEEtypes_WideBWChanSwitch_t) -
+			sizeof(IEEEtypes_Header_t);
+
+		center_freq_idx = woal_get_center_freq_idx(priv, BAND_AAC,
+							   channel, band_width);
+		if (band_width == CHANNEL_BW_40MHZ_ABOVE ||
+		    band_width == CHANNEL_BW_40MHZ_BELOW) {
+			pbwchansw_ie->new_channel_width = 0;
+			pbwchansw_ie->new_channel_center_freq0 =
+				center_freq_idx;
+		} else if (band_width == CHANNEL_BW_80MHZ) {
+			pbwchansw_ie->new_channel_width = 1;
+			pbwchansw_ie->new_channel_center_freq0 =
+				center_freq_idx - 4;
+			pbwchansw_ie->new_channel_center_freq1 =
+				center_freq_idx + 4;
+		} else if (band_width == CHANNEL_BW_160MHZ) {
+			pbwchansw_ie->new_channel_width = 2;
+			pbwchansw_ie->new_channel_center_freq0 =
+				center_freq_idx - 8;
+			pbwchansw_ie->new_channel_center_freq1 =
+				center_freq_idx + 8;
+		} else
+			PRINTM(MERROR,
+			       "Invalid bandwidth.Support value 1/3/4/5 for 40+/40-/80/160MHZ\n");
+
+		/*prepare the VHT Transmit Power Envelope IE */
+		pvhttpcEnv_ie =
+			(IEEEtypes_VhtTpcEnvelope_t
+			 *)((t_u8 *)pChanSwWrap_ie +
+			    sizeof(IEEEtypes_Header_t) +
+			    sizeof(IEEEtypes_WideBWChanSwitch_t));
+		pvhttpcEnv_ie->ieee_hdr.element_id = VHT_TX_POWER_ENV;
+		pvhttpcEnv_ie->ieee_hdr.len =
+			sizeof(IEEEtypes_VhtTpcEnvelope_t) -
+			sizeof(IEEEtypes_Header_t);
+		/* Local Max TX Power Count= 3,
+		 * Local TX Power Unit Inter=EIP(0) */
+		pvhttpcEnv_ie->tpc_info = 3;
+		pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
+		pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
+		pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
+		pvhttpcEnv_ie->local_max_tp_160mhz_80_80mhz = 0xff;
+		pChanSwWrap_ie->len += sizeof(IEEEtypes_VhtTpcEnvelope_t);
+		pcust_chansw_ie->ie_length +=
+			pChanSwWrap_ie->len + sizeof(IEEEtypes_Header_t);
+		DBG_HEXDUMP(MCMD_D, "Channel switch wrapper IE",
+			    (t_u8 *)pChanSwWrap_ie,
+			    pChanSwWrap_ie->len + sizeof(IEEEtypes_Header_t));
+	}
+	if (block_tx) {
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		woal_stop_queue(priv->netdev);
+		priv->uap_tx_blocked = MTRUE;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to set ECSA IE\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	priv->phandle->chsw_wait_q_woken = MFALSE;
+	/* wait for channel switch to complete  */
+	wait_event_interruptible_timeout(priv->phandle->chsw_wait_q,
+					 priv->phandle->chsw_wait_q_woken,
+					 (u32)HZ * (switch_count +
+						    2) * 110 / 1000);
+
+	pcust_chansw_ie->ie_index = 0xffff;	/*Auto index */
+	pcust_chansw_ie->mgmt_subtype_mask = 0;
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to clear ECSA IE\n");
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+
+}
+#endif
+
+/**
+ * @brief               Set/Get CFP table codes
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cfp_code(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data[2] = { 0 };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_ds_misc_cfp_code *cfp_code = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFP_CODE);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfp_code = &misc_cfg->param.cfp_code;
+	misc_cfg->sub_command = MLAN_OID_MISC_CFP_CODE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 2) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		cfp_code->cfp_code_bg = data[0];
+		if (user_data_len == 2)
+			cfp_code->cfp_code_a = data[1];
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		data[0] = cfp_code->cfp_code_bg;
+		data[1] = cfp_code->cfp_code_a;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get Tx/Rx antenna
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_tx_rx_ant(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data[3] = { 0 };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_ANT_CFG);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 2) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+			radio->param.ant_cfg.tx_antenna = data[0];
+			radio->param.ant_cfg.rx_antenna = data[0];
+			if (user_data_len == 2)
+				radio->param.ant_cfg.rx_antenna = data[1];
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+			if (IS_CARD9098(priv->phandle->card_type) ||
+			    IS_CARD9097(priv->phandle->card_type)) {
+				woal_cfg80211_notify_antcfg(priv,
+							    priv->phandle->
+							    wiphy, radio);
+			}
+#endif
+		} else {
+			radio->param.ant_cfg_1x1.antenna = data[0];
+			if (user_data_len == 2)
+				radio->param.ant_cfg_1x1.evaluate_time =
+					data[1];
+		}
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!user_data_len) {
+		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+			data[0] = radio->param.ant_cfg.tx_antenna;
+			data[1] = radio->param.ant_cfg.rx_antenna;
+			if (data[0] && data[1])
+				ret = sizeof(int) * 2;
+			else
+				ret = sizeof(int) * 1;
+			moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+					sizeof(data), respbuflen);
+		} else {
+			data[0] = (int)radio->param.ant_cfg_1x1.antenna;
+			data[1] = (int)radio->param.ant_cfg_1x1.evaluate_time;
+			data[2] = (int)radio->param.ant_cfg_1x1.current_antenna;
+			moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+					sizeof(data), respbuflen);
+			ret = sizeof(data);
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/*
+ * @brief               Set/Get CWMode
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_cwmode(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_cw_mode_ctrl *cwmode;
+	int ret = 0;
+	int header_len = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CWMODE_CTRL;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CWMODE);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		ioctl_req->action = MLAN_ACT_SET;
+
+		cwmode = (mlan_ds_cw_mode_ctrl *) (respbuf + header_len +
+						   sizeof(t_u8));
+		misc->param.cwmode.mode = cwmode->mode;
+		misc->param.cwmode.txPower = cwmode->txPower;
+		misc->param.cwmode.rateInfo = cwmode->rateInfo;
+		misc->param.cwmode.channel = cwmode->channel;
+		misc->param.cwmode.chanInfo = cwmode->chanInfo;
+		misc->param.cwmode.pktLength = cwmode->pktLength;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&misc->param.cwmode,
+			sizeof(misc->param.cwmode), respbuflen);
+	ret = sizeof(misc->param.cwmode);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get out band independent reset
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_ind_rst_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data[2] = { 0 };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_IND_RST_CFG);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	memset(misc, 0, sizeof(mlan_ds_misc_cfg));
+	misc->sub_command = MLAN_OID_MISC_IND_RST_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 2) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		if ((user_data_len == 1) || (user_data_len == 2)) {
+			req->action = MLAN_ACT_SET;
+
+			/* ir_mode */
+			if (data[0] < 0 || data[0] > 2) {
+				PRINTM(MERROR, "Invalid ir mode parameter!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			misc->param.ind_rst_cfg.ir_mode = data[0];
+
+			/* gpio_pin */
+			if (user_data_len == 2) {
+				if ((data[1] != 0xFF) && (data[1] < 0)) {
+					PRINTM(MERROR,
+					       "Invalid gpio pin no!\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				misc->param.ind_rst_cfg.gpio_pin = data[1];
+			}
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = (int)misc->param.ind_rst_cfg.ir_mode;
+	data[1] = (int)misc->param.ind_rst_cfg.gpio_pin;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Get/Set system clock
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_sysclock(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int data[65];
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int ret = 0, i = 0;
+	int user_data_len = 0, header_len = 0;
+	int data_length = 0, length_index = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SYSCLOCK);
+	memset(data, 0, sizeof(data));
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+	}
+
+	if (user_data_len > MLAN_MAX_CLK_NUM) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_SYS_CLOCK;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len) {
+		/* SET operation */
+		req->action = MLAN_ACT_SET;
+
+		/* Set configurable clocks */
+		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_CONFIGURABLE;
+		cfg->param.sys_clock.sys_clk_num =
+			MIN(MLAN_MAX_CLK_NUM, user_data_len);
+		for (i = 0; i < cfg->param.sys_clock.sys_clk_num; i++)
+			cfg->param.sys_clock.sys_clk[i] = (t_u16)data[i];
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+
+		/* Get configurable clocks */
+		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_CONFIGURABLE;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		/* Current system clock */
+		data[1] = (int)cfg->param.sys_clock.cur_sys_clk;
+		data_length = 1;
+
+		length_index =
+			MIN(cfg->param.sys_clock.sys_clk_num, MLAN_MAX_CLK_NUM);
+
+		/* Configurable clocks */
+		for (i = 1; i <= length_index; i++)
+			data[i + data_length] =
+				(int)cfg->param.sys_clock.sys_clk[i - 1];
+
+		data_length += length_index;
+
+		/* Get supported clocks */
+		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_SUPPORTED;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		length_index =
+			MIN(cfg->param.sys_clock.sys_clk_num, MLAN_MAX_CLK_NUM);
+
+		/* Supported clocks */
+		for (i = 1; i <= length_index; i++)
+			data[i + data_length] =
+				(int)cfg->param.sys_clock.sys_clk[i - 1];
+
+		data_length += length_index;
+
+		/* Send length as first element */
+		data[0] = data_length;
+		data_length++;
+
+		moal_memcpy_ext(priv->phandle, respbuf, data,
+				sizeof(int) * data_length, respbuflen);
+		ret = data_length * sizeof(int);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Get GTK/PTK
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_key(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0, copy_len = 0;
+	int header_len = 0;
+	unsigned int i;
+	t_u8 key_ascii[256];
+	t_u8 *tmp;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_GET_KEY);
+	if ((int)strlen(respbuf) != header_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	memset(key_ascii, 0x00, sizeof(key_ascii));
+	tmp = key_ascii;
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can't get key in un-associated state\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Get Unicast Key */
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
+	sec->param.encrypt_key.key_index = 0;
+	sec->param.encrypt_key.key_flags = 0;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (sec->param.encrypt_key.key_len) {
+		sprintf((char *)tmp, "\n%s", "PTK: ");
+		tmp += 5;
+		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
+			tmp += sprintf((char *)tmp, "%02x",
+				       sec->param.encrypt_key.key_material[i]);
+	}
+
+	/* Get Multicase Key */
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
+	sec->param.encrypt_key.key_index = 0;
+	sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
+	memset(sec->param.encrypt_key.mac_addr, 0x0, MLAN_MAC_ADDR_LENGTH);
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (sec->param.encrypt_key.key_len) {
+		sprintf((char *)tmp, "\n%s", "GTK: ");
+		tmp += 5;
+		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
+			tmp += sprintf((char *)tmp, "%02x",
+				       sec->param.encrypt_key.key_material[i]);
+	}
+
+	/* Get IGTK Key */
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
+	sec->param.encrypt_key.key_index = 0;
+	sec->param.encrypt_key.key_flags = KEY_FLAG_AES_MCAST_IGTK;
+	memset(sec->param.encrypt_key.mac_addr, 0x0, MLAN_MAC_ADDR_LENGTH);
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (sec->param.encrypt_key.key_len) {
+		sprintf((char *)tmp, "\n%s", "IGTK: ");
+		tmp += 6;
+		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
+			tmp += sprintf((char *)tmp, "%02x",
+				       sec->param.encrypt_key.key_material[i]);
+	}
+
+	copy_len = tmp - key_ascii;
+	moal_memcpy_ext(priv->phandle, respbuf, &key_ascii, copy_len,
+			respbuflen);
+	ret = copy_len;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Associate to a specific indexed entry in the ScanTable
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_associate_ssid_bssid(moal_private *priv, t_u8 *respbuf,
+			       t_u32 respbuflen)
+{
+	int ret = 0, copy_len = 0;
+	int header_len = 0;
+	mlan_ssid_bssid ssid_bssid;
+#ifdef REASSOCIATION
+	mlan_bss_info bss_info;
+#endif
+	char buf[64];
+	t_u8 buflen;
+	t_u8 mac_idx;
+	t_u8 i;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_ASSOCIATE);
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	copy_len = strlen(respbuf) - header_len;
+	mac_idx = 0;
+	buflen = MIN(copy_len, (int)(sizeof(buf) - 1));
+	memset(buf, 0, sizeof(buf));
+	memset(&ssid_bssid, 0, sizeof(ssid_bssid));
+
+	if (buflen < (3 * ETH_ALEN) + 2) {
+		PRINTM(MERROR,
+		       "Associate: Insufficient length in IOCTL input\n");
+
+		/* buffer should be at least 3 characters per BSSID octet "00:"
+		 **   plus a space separater and at least 1 char in the SSID
+		 */
+		ret = -EINVAL;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, buf, respbuf + header_len, buflen,
+			sizeof(buf));
+
+	/* Skip white space */
+	for (i = 0; (i < buflen) && (buf[i] == ' '); i++) ;
+
+	/* Copy/Convert the BSSID */
+	for (; (i < buflen) && (mac_idx < ETH_ALEN) && (buf[i] != ' '); i++) {
+		if (buf[i] == ':') {
+			mac_idx++;
+		} else {
+			ssid_bssid.bssid[mac_idx] = (t_u8)woal_atox(buf + i);
+
+			while (((i < buflen) && isxdigit(buf[i + 1])))
+				/* Skip entire hex value */
+				i++;
+		}
+	}
+
+	/* Skip one space between the BSSID and start of the SSID */
+	i++;
+
+	/* Copy the SSID */
+	ssid_bssid.ssid.ssid_len = buflen - i;
+	moal_memcpy_ext(priv->phandle, ssid_bssid.ssid.ssid, buf + i,
+			sizeof(ssid_bssid.ssid.ssid),
+			sizeof(ssid_bssid.ssid.ssid));
+
+	PRINTM(MCMND, "iwpriv assoc: AP=[" MACSTR "], ssid(%d)=[%s]\n",
+	       MAC2STR(ssid_bssid.bssid), (int)ssid_bssid.ssid.ssid_len,
+	       ssid_bssid.ssid.ssid);
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef REASSOCIATION
+	memset(&bss_info, 0x00, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
+				&bss_info.ssid, sizeof(mlan_802_11_ssid),
+				sizeof(mlan_802_11_ssid));
+		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
+				&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
+				sizeof(mlan_802_11_mac_addr));
+	}
+#endif /* REASSOCIATION */
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/* Maximum input output characters in group WOAL_SET_GET_256_CHAR */
+#define MAX_IN_OUT_CHAR 256
+/** Tx BF Global conf argument index */
+#define BF_ENABLE_PARAM 1
+#define SOUND_ENABLE_PARAM 2
+#define FB_TYPE_PARAM 3
+#define SNR_THRESHOLD_PARAM 4
+#define SOUND_INTVL_PARAM 5
+#define BF_MODE_PARAM 6
+#define BF_CFG_ACT_GET 0
+#define BF_CFG_ACT_SET 1
+
+/**
+ * @brief               Set/Get Transmit beamforming configuration
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_tx_bf_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0;
+	int ret = 0, copy_len = 0;
+	int bf_action = 0, interval = 0;
+	int snr = 0, i, tmp_val = 0;
+	t_u8 buf[MAX_IN_OUT_CHAR], char_count = 0;
+	t_u8 *str, *token, *pos;
+	t_u16 action = 0;
+
+	mlan_ds_11n_tx_bf_cfg bf_cfg;
+	mlan_trigger_sound_args *bf_sound = NULL;
+	mlan_tx_bf_peer_args *tx_bf_peer = NULL;
+	mlan_snr_thr_args *bf_snr = NULL;
+	mlan_bf_periodicity_args *bf_periodicity = NULL;
+	mlan_bf_global_cfg_args *bf_global = NULL;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TX_BF_CFG);
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	memset(&bf_cfg, 0, sizeof(bf_cfg));
+	/* Pointer to corresponding buffer */
+	bf_sound = bf_cfg.body.bf_sound;
+	tx_bf_peer = bf_cfg.body.tx_bf_peer;
+	bf_snr = bf_cfg.body.bf_snr;
+	bf_periodicity = bf_cfg.body.bf_periodicity;
+	bf_global = &bf_cfg.body.bf_global_cfg;
+
+	/* Total characters in buffer */
+	char_count = strlen(respbuf) - header_len;
+	copy_len = char_count;
+	memset(buf, 0, sizeof(buf));
+	if (char_count) {
+		if (copy_len > (int)sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		moal_memcpy_ext(priv->phandle, buf, respbuf + header_len,
+				copy_len, sizeof(buf));
+
+		if (char_count > 1 && buf[1] != ';') {
+			PRINTM(MERROR,
+			       "No action argument. Separate with ';'\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		/* Replace ';' with NULL in the string to separate args */
+		for (i = 0; i < char_count; i++) {
+			if (buf[i] == ';')
+				buf[i] = '\0';
+		}
+		/* The first byte represents the beamforming action */
+		if (woal_atoi(&bf_action, &buf[0]) != MLAN_STATUS_SUCCESS) {
+			ret = -EINVAL;
+			goto done;
+		}
+		switch (bf_action) {
+		case BF_GLOBAL_CONFIGURATION:
+			if (char_count == 1) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+				/* Eliminate action field */
+				token = &buf[2];
+				for (i = 1, str = &buf[2]; token != NULL; i++) {
+					token = strstr(str, " ");
+					pos = str;
+					if (token != NULL) {
+						*token = '\0';
+						str = token + 1;
+					}
+					woal_atoi(&tmp_val, pos);
+					switch (i) {
+					case BF_ENABLE_PARAM:
+						bf_global->bf_enbl =
+							(t_u8)tmp_val;
+						break;
+					case SOUND_ENABLE_PARAM:
+						bf_global->sounding_enbl =
+							(t_u8)tmp_val;
+						break;
+					case FB_TYPE_PARAM:
+						bf_global->fb_type =
+							(t_u8)tmp_val;
+						break;
+					case SNR_THRESHOLD_PARAM:
+						bf_global->snr_threshold =
+							(t_u8)tmp_val;
+						break;
+					case SOUND_INTVL_PARAM:
+						bf_global->sounding_interval =
+							(t_u16)tmp_val;
+						break;
+					case BF_MODE_PARAM:
+						bf_global->bf_mode =
+							(t_u8)tmp_val;
+						break;
+					default:
+						PRINTM(MERROR,
+						       "Invalid Argument\n");
+						ret = -EINVAL;
+						goto done;
+					}
+				}
+			}
+			break;
+		case TRIGGER_SOUNDING_FOR_PEER:
+			/* First arg  = 2   BfAction
+			 * Second arg = 17  MAC "00:50:43:20:BF:64" */
+			if (char_count != 19) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			woal_mac2u8(bf_sound->peer_mac, &buf[2]);
+			action = MLAN_ACT_SET;
+			bf_cfg.action = BF_CFG_ACT_SET;
+			break;
+		case SET_GET_BF_PERIODICITY:
+			/* First arg  = 2   BfAction
+			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
+			 * Third arg =  1  (min char)  TX BF interval
+			 *              10 (max char)  u32 maximum value
+			 * 4294967295 */
+			if (char_count < 19 || char_count > 30) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+
+			woal_mac2u8(bf_periodicity->peer_mac, &buf[2]);
+			if (char_count == 19) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+				if (woal_atoi(&interval, &buf[20]) !=
+				    MLAN_STATUS_SUCCESS) {
+					ret = -EINVAL;
+					goto done;
+				}
+				bf_periodicity->interval = interval;
+			}
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			/* Handle only SET operation here
+			 * First arg  = 2   BfAction
+			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
+			 * Third arg  = 2   enable/disable bf
+			 * Fourth arg = 2   enable/disable sounding
+			 * Fifth arg  = 1   FB Type */
+			if (char_count != 25 && char_count != 1) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (char_count == 1) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				woal_mac2u8(tx_bf_peer->peer_mac, &buf[2]);
+				woal_atoi(&tmp_val, &buf[20]);
+				tx_bf_peer->bf_enbl = (t_u8)tmp_val;
+				woal_atoi(&tmp_val, &buf[22]);
+				tx_bf_peer->sounding_enbl = (t_u8)tmp_val;
+				woal_atoi(&tmp_val, &buf[24]);
+				tx_bf_peer->fb_type = (t_u8)tmp_val;
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			/* First arg  = 2   BfAction
+			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
+			 * Third arg  = 1/2 SNR u8 - can be 1/2 charerters */
+			if (char_count != 1 &&
+			    !(char_count == 21 || char_count == 22)) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (char_count == 1) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				woal_mac2u8(bf_snr->peer_mac, &buf[2]);
+				if (woal_atoi(&snr, &buf[20]) !=
+				    MLAN_STATUS_SUCCESS) {
+					ret = -EINVAL;
+					goto done;
+				}
+				bf_snr->snr = snr;
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+			}
+			break;
+		default:
+			ret = -EINVAL;
+			goto done;
+		}
+
+		/* Save the value */
+		bf_cfg.bf_action = bf_action;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	switch (bf_action) {
+	case BF_GLOBAL_CONFIGURATION:
+		moal_memcpy_ext(priv->phandle, respbuf, bf_global,
+				sizeof(mlan_bf_global_cfg_args), respbuflen);
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case TRIGGER_SOUNDING_FOR_PEER:
+		moal_memcpy_ext(priv->phandle, respbuf, bf_sound,
+				sizeof(mlan_bf_global_cfg_args), respbuflen);
+		ret = sizeof(mlan_bf_global_cfg_args);
+		break;
+	case SET_GET_BF_PERIODICITY:
+		moal_memcpy_ext(priv->phandle, respbuf, bf_periodicity,
+				sizeof(mlan_bf_periodicity_args), respbuflen);
+		ret = sizeof(mlan_bf_periodicity_args);
+		break;
+	case TX_BF_FOR_PEER_ENBL:
+		moal_memcpy_ext(priv->phandle, respbuf, tx_bf_peer,
+				sizeof(mlan_tx_bf_peer_args), respbuflen);
+		ret = sizeof(mlan_tx_bf_peer_args);
+		break;
+	case SET_SNR_THR_PEER:
+		moal_memcpy_ext(priv->phandle, respbuf, bf_snr,
+				sizeof(mlan_snr_thr_args), respbuflen);
+		ret = sizeof(mlan_snr_thr_args);
+		break;
+	default:
+		ret = 0;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO
+/**
+ * @brief               Cmd53 read/write register
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cmd53rdwr(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0;
+	int ret = 0;
+	t_u8 *buf = NULL;
+	t_u8 *data = NULL;
+	t_u8 rw, mode;
+	t_u16 blklen = 0, blknum = 0;
+	int reg = 0;
+	t_u32 pattern_len = 0, total_len = 0;
+	t_u16 cmd_len;
+	gfp_t flag;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SD_CMD53_RW);
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	data = kzalloc(WOAL_2K_BYTES, flag);
+	if (!data) {
+		PRINTM(MERROR, "Cannot allocate buffer for command!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, &cmd_len, respbuf + header_len,
+			sizeof(cmd_len), sizeof(cmd_len));
+	buf = respbuf + header_len + sizeof(cmd_len);
+
+	rw = buf[0];		/* read/write (0/1) */
+	reg = buf[5];		/* address */
+	reg = (reg << 8) | buf[4];
+	reg = (reg << 8) | buf[3];
+	reg = (reg << 8) | buf[2];
+	mode = buf[6];		/* byte mode/block mode (0/1) */
+	blklen = buf[8];	/* block size */
+	blklen = (blklen << 8) | buf[7];
+	blknum = buf[10];	/* block number or byte number */
+	blknum = (blknum << 8) | buf[9];
+
+	if (mode == BYTE_MODE)
+		blklen = 1;
+	else
+		mode = BLOCK_MODE;
+
+	total_len = (mode == BLOCK_MODE) ? blknum * blklen : blknum;
+	if (total_len > WOAL_2K_BYTES) {
+		PRINTM(MERROR, "Total data length is too large!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	PRINTM(MINFO,
+	       "CMD53 read/write, addr = %#x, mode = %d, "
+	       "block size = %d, block(byte) number = %d\n",
+	       reg, mode, blklen, blknum);
+
+	if (!rw) {
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (sdio_readsb
+		    (((struct sdio_mmc_card *)priv->phandle->card)->func,
+		     respbuf, reg, total_len)) {
+			PRINTM(MERROR,
+			       "sdio_readsb: reading memory 0x%x failed\n",
+			       reg);
+			goto done;
+		}
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		ret = total_len;
+	} else {
+		int pos = 0;
+		pattern_len = cmd_len - 11;
+		if (pattern_len > total_len)
+			pattern_len = total_len;
+
+		/* Copy/duplicate the pattern to data buffer */
+		for (pos = 0; pos < (int)total_len; pos++)
+			data[pos] = buf[11 + (pos % pattern_len)];
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (sdio_writesb
+		    (((struct sdio_mmc_card *)priv->phandle->card)->func, reg,
+		     data, total_len))
+			PRINTM(MERROR,
+			       "sdio_writesb: writing memory 0x%x failed\n",
+			       reg);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+	}
+
+done:
+	kfree(data);
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO */
+
+/**
+ * @brief               Set/Get Port Control mode
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_port_ctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	int ret = 0, data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PORT_CTRL);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len == 1) {
+			sec->param.port_ctrl_enabled = data;
+			req->action = MLAN_ACT_SET;
+		} else {
+			PRINTM(MERROR, "Invalid number of parameters\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		moal_memcpy_ext(priv->phandle, respbuf,
+				&sec->param.port_ctrl_enabled, sizeof(int),
+				respbuflen);
+		ret = sizeof(int);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Private IOCTL entry to get the By-passed TX packet from
+ * upper layer
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_bypassed_packet(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0;
+	int ret = 0;
+	struct sk_buff *skb = NULL;
+	struct ethhdr *eth;
+	t_u16 moreLen = 0, copyLen = 0;
+	ENTER();
+
+#define MLAN_BYPASS_PKT_EXTRA_OFFSET (4)
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PB_BYPASS);
+	copyLen = strlen(respbuf) - header_len;
+	moreLen = MLAN_MIN_DATA_HEADER_LEN + MLAN_BYPASS_PKT_EXTRA_OFFSET +
+		sizeof(mlan_buffer);
+
+	skb = alloc_skb(copyLen + moreLen, GFP_KERNEL);
+	if (skb == NULL) {
+		PRINTM(MERROR, "kmalloc no memory !!\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, moreLen);
+
+	moal_memcpy_ext(priv->phandle, skb_put(skb, copyLen),
+			respbuf + header_len, copyLen, copyLen);
+
+	eth = (struct ethhdr *)skb->data;
+	eth->h_proto = __constant_htons(eth->h_proto);
+	skb->dev = priv->netdev;
+
+	HEXDUMP("Bypass TX Data", skb->data, MIN(skb->len, 100));
+
+	woal_hard_start_xmit(skb, priv->netdev);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set Robustcoex gpiocfg
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_robustcoex(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[3] = { 0 };
+	mlan_ds_misc_cfg *robust_coex_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	robust_coex_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	while (respbuf[0] == ' ') {
+		/** skip space */
+		respbuf++;
+	}
+
+	if (strncmp(respbuf, "gpiocfg", strlen("gpiocfg")) == 0) {
+		header_len = strlen("gpiocfg") + 1;
+		parse_arguments(respbuf + header_len, data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len > 3) {
+			PRINTM(MERROR, "Invalid parameter number\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] != ROBUSTCOEX_GPIOCFG_ENABLE &&
+		    data[0] != ROBUSTCOEX_GPIOCFG_DISABLE) {
+			PRINTM(MERROR, "Invalid parameter number\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == ROBUSTCOEX_GPIOCFG_ENABLE) {
+			if (user_data_len != 3) {
+				PRINTM(MMSG,
+				       "Please provide gpio num and gpio polarity for ROBUSTCOEX_GPIOCFG_ENABLE\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			robust_coex_cfg->param.robustcoexparams.method =
+				ROBUSTCOEX_GPIO_CFG;
+			robust_coex_cfg->param.robustcoexparams.enable =
+				ROBUSTCOEX_GPIOCFG_ENABLE;
+			robust_coex_cfg->param.robustcoexparams.gpio_num =
+				data[1];
+			robust_coex_cfg->param.robustcoexparams.gpio_polarity =
+				data[2];
+		} else {
+			robust_coex_cfg->param.robustcoexparams.method =
+				ROBUSTCOEX_GPIO_CFG;
+			robust_coex_cfg->param.robustcoexparams.enable =
+				ROBUSTCOEX_GPIOCFG_DISABLE;
+			robust_coex_cfg->param.robustcoexparams.gpio_num = 0;
+			robust_coex_cfg->param.robustcoexparams.gpio_polarity =
+				0;
+		}
+		req->action = MLAN_ACT_SET;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		robust_coex_cfg->sub_command = MLAN_OID_MISC_ROBUSTCOEX;
+	} else {
+		PRINTM(MERROR, "Invalid parameter\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set DMCS mapping policy or get DMCS status
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_dmcs(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[2] = { 0 };
+	mlan_ds_misc_cfg *dmcs_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DMCS);
+	dmcs_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if (user_data_len > 2) {
+		PRINTM(MERROR, "Invalid number of args! %d\n", user_data_len);
+		ret = -EINVAL;
+		goto done;
+	}
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	dmcs_cfg->sub_command = MLAN_OID_MISC_DMCS_CONFIG;
+	dmcs_cfg->param.dmcs_policy.subcmd = data[0];
+	switch (data[0]) {
+	case 0:
+		if (user_data_len != 2) {
+			PRINTM(MERROR, "Please provide mapping policy\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		dmcs_cfg->param.dmcs_policy.mapping_policy = data[1];
+		break;
+	case 1:
+		req->action = MLAN_ACT_GET;
+		break;
+	default:
+		break;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (req->action == MLAN_ACT_GET) {
+		moal_memcpy_ext(priv->phandle, respbuf,
+				&dmcs_cfg->param.dmcs_status,
+				sizeof(mlan_ds_misc_dmcs_status), respbuflen);
+	}
+	ret = sizeof(mlan_ds_misc_dmcs_status);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set and get boot sleep configure
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_bootsleep(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int user_data_len = 0;
+	int header_len = 0;
+	int allowed = 1;
+	int data[1] = { 0 };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_BOOT_SLEEP;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_BOOTSLEEP);
+
+	if ((int)strlen(respbuf) == header_len) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len != allowed) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.boot_sleep = data[0] ? 1 : 0;
+		PRINTM(MIOCTL, "boot sleep cfg:%u\n", misc->param.boot_sleep);
+	}
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT_TIMEOUT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, &misc->param.boot_sleep,
+			sizeof(misc->param.boot_sleep), respbuflen);
+	ret = sizeof(misc->param.boot_sleep);
+
+	PRINTM(MIOCTL, "boot sleep cfg: %u\n", misc->param.boot_sleep);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(PCIE)
+/**
+ * @brief               Enable SSU support
+ * @param priv          Pointer to moal_private structure
+ * @param used_len 		used length
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_ssu_cmd(moal_private *priv, t_u8 used_len, t_u8 *respbuf,
+		  t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *ssu_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	ssu_params_cfg *ssu_params;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	ssu_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	memset(&ssu_cfg->param.ssu_params, 0, sizeof(mlan_ds_ssu_params));
+	if (!used_len) {
+		req->action = MLAN_ACT_SET;
+		ssu_cfg->param.ssu_params.nskip = 0;
+		ssu_cfg->param.ssu_params.nsel = 1;
+		ssu_cfg->param.ssu_params.adcdownsample = 3;
+		ssu_cfg->param.ssu_params.mask_adc_pkt = 0;
+		ssu_cfg->param.ssu_params.out_16bits = 1;
+	} else {
+		ssu_params = (ssu_params_cfg *) respbuf;
+		DBG_HEXDUMP(MCMD_D, "User SSU params:", respbuf,
+			    sizeof(mlan_ds_ssu_params));
+		if (ssu_params->ssu_mode == 2)
+			req->action = MLAN_ACT_DEFAULT;
+		else {
+			req->action = MLAN_ACT_SET;
+			ssu_cfg->param.ssu_params.nskip = ssu_params->nskip;
+			ssu_cfg->param.ssu_params.nsel = ssu_params->nsel;
+			ssu_cfg->param.ssu_params.adcdownsample =
+				ssu_params->adcdownsample;
+			ssu_cfg->param.ssu_params.mask_adc_pkt =
+				ssu_params->mask_adc_pkt;
+			ssu_cfg->param.ssu_params.out_16bits =
+				ssu_params->out_16bits;
+			ssu_cfg->param.ssu_params.spec_pwr_enable =
+				ssu_params->spec_pwr_enable;
+			ssu_cfg->param.ssu_params.rate_deduction =
+				ssu_params->rate_deduction;
+			ssu_cfg->param.ssu_params.n_pkt_avg =
+				ssu_params->n_pkt_avg;
+		}
+	}
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	ssu_cfg->sub_command = MLAN_OID_MISC_SSU;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief               Configure the hal/phy cfg params
+ *
+ *  The command structure contains the following parameters
+ *      dot11b_psd_mask: 1: enable, 0: disable
+ *      Reserved : reserved 7 params for future such use
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_hal_phy_cfg_cmd(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int ret = 0;
+	mlan_ds_hal_phy_cfg_params *data_ptr;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	data_ptr = (mlan_ds_hal_phy_cfg_params *) respbuf;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_HAL_PHY_CFG;
+
+	cfg->param.hal_phy_cfg_params.dot11b_psd_mask_cfg =
+		data_ptr->dot11b_psd_mask_cfg;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               configure 11ax HE capability or HE operation
+ *
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param respbuf      A pointer to response buffer
+ *  @param len          length used
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return         Number of bytes written if successful else negative value
+ */
+static int
+woal_priv_11axcfg_cmd(moal_private *priv, t_u8 *respbuf, t_u8 len,
+		      t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ax_cfg *cfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ax_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_11AX_CFG;
+	req->action = MLAN_ACT_SET;
+	cfg = (mlan_ds_11ax_cfg *) req->pbuf;
+	cfg->sub_command = MLAN_OID_11AX_HE_CFG;
+	if (len)
+		moal_memcpy_ext(priv->phandle, (t_u8 *)&cfg->param.he_cfg,
+				respbuf, len, sizeof(mlan_ds_11ax_he_cfg));
+	else
+		req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&cfg->param.he_cfg,
+			sizeof(mlan_ds_11ax_he_cfg), respbuflen);
+	ret = sizeof(mlan_ds_11ax_he_cfg);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Configure TWT Setup parameters
+ *
+ * @param priv          Pointer to the mlan_private driver data struct
+ * @param respbuf       A pointer to response buffer
+ * @param len           Length used
+ * @param respbuflen    Available length of response buffer
+ *
+ * @return              Number of bytes written if successful else negative
+ * value
+ */
+static int
+woal_priv_twt_setup(moal_private *priv, t_u8 *respbuf, t_u8 len,
+		    t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_twtcfg *cfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_twtcfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "Failed to allocate ioctl_req!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_11AX_CFG;
+	req->action = MLAN_ACT_SET;
+	cfg = (mlan_ds_twtcfg *) req->pbuf;
+	cfg->sub_command = MLAN_OID_11AX_TWT_CFG;
+	cfg->sub_id = MLAN_11AX_TWT_SETUP_SUBID;
+
+	if (len) {
+		moal_memcpy_ext(priv->phandle, (t_u8 *)&cfg->param.twt_setup,
+				respbuf, len, sizeof(mlan_ds_twt_setup));
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "woal_request_ioctl failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = sizeof(mlan_ds_twt_setup);
+done:
+	if (status != MLAN_STATUS_PENDING) {
+		kfree(req);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Configure TWT Tear down parameters
+ *
+ * @param priv          Pointer to the mlan_private driver data struct
+ * @param respbuf       A pointer to response buffer
+ * @param len           Length used
+ * @param respbuflen    Available length of response buffer
+ *
+ * @return              Number of bytes written if successful else negative
+ * value
+ */
+static int
+woal_priv_twt_teardown(moal_private *priv, t_u8 *respbuf, t_u8 len,
+		       t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_twtcfg *cfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_twtcfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "Failed to allocate ioctl_req!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_11AX_CFG;
+	req->action = MLAN_ACT_SET;
+	cfg = (mlan_ds_twtcfg *) req->pbuf;
+	cfg->sub_command = MLAN_OID_11AX_TWT_CFG;
+	cfg->sub_id = MLAN_11AX_TWT_TEARDOWN_SUBID;
+
+	if (len) {
+		moal_memcpy_ext(priv->phandle, (t_u8 *)&cfg->param.twt_teardown,
+				respbuf, len, sizeof(mlan_ds_twt_teardown));
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "woal_request_ioctl failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = sizeof(mlan_ds_twt_teardown);
+done:
+	if (status != MLAN_STATUS_PENDING) {
+		kfree(req);
+	}
+	LEAVE();
+	return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(UAP_CFG80211)
+/**
+ * @brief               Set/Get P2P NoA (Notice of Absence) parameters
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cfg_noa(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[7];
+	mlan_ds_wifi_direct_config noa_cfg;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFG_NOA);
+	memset(&noa_cfg, 0, sizeof(noa_cfg));
+
+	memset(data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len > 5) {
+		PRINTM(MERROR, "invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	noa_cfg.flags |= WIFI_DIRECT_NOA;
+
+	if (woal_p2p_config(priv, MLAN_ACT_GET, &noa_cfg) !=
+	    MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Could not get P2P noa config\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		moal_memcpy_ext(priv->phandle, respbuf, &noa_cfg,
+				sizeof(noa_cfg), respbuflen);
+		ret = sizeof(noa_cfg);
+	} else {
+		switch (user_data_len) {
+		case 5:
+			noa_cfg.noa_interval = (t_u32)data[4];
+			/* fall through */
+		case 4:
+			noa_cfg.noa_duration = (t_u32)data[3];
+			/* fall through */
+		case 3:
+			if (data[2] < 1 || data[2] > 255) {
+				PRINTM(MERROR,
+				       "Invalid number of absence intervals\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			noa_cfg.noa_count = (t_u8)data[2];
+			/* fall through */
+		case 2:
+			if (data[1] < 0 || data[1] > 255) {
+				PRINTM(MERROR, "Invalid Index\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			noa_cfg.index = (t_u16)data[1];
+			/* fall through */
+		case 1:
+			if (data[0] < 0 || data[0] > 1) {
+				PRINTM(MERROR, "Invalid noa enable\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			noa_cfg.noa_enable = (t_u8)data[0];
+			noa_cfg.flags |= WIFI_DIRECT_NOA;
+			break;
+		default:
+			break;
+		}
+		woal_p2p_config(priv, MLAN_ACT_SET, &noa_cfg);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get P2P OPP-PS parameters
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cfg_opp_ps(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[7];
+	mlan_ds_wifi_direct_config opp_ps_cfg;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFG_OPP_PS);
+	memset(&opp_ps_cfg, 0, sizeof(opp_ps_cfg));
+
+	memset(data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len > 2) {
+		PRINTM(MERROR, "invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	opp_ps_cfg.flags |= WIFI_DIRECT_OPP_PS;
+
+	if (woal_p2p_config(priv, MLAN_ACT_GET, &opp_ps_cfg) !=
+	    MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Could not get P2P opp ps config\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		moal_memcpy_ext(priv->phandle, respbuf, &opp_ps_cfg,
+				sizeof(opp_ps_cfg), respbuflen);
+		ret = sizeof(opp_ps_cfg);
+	} else {
+		switch (user_data_len) {
+		case 2:
+			opp_ps_cfg.ct_window = (t_u8)data[1];
+			/* fall through */
+		case 1:
+			if (data[0] < 0 || data[0] > 1) {
+				PRINTM(MERROR, "Invalid ps enable\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			opp_ps_cfg.opp_ps_enable = (t_u8)data[0];
+			opp_ps_cfg.flags |= WIFI_DIRECT_OPP_PS;
+			/* fall through */
+		default:
+			break;
+		}
+		woal_p2p_config(priv, MLAN_ACT_SET, &opp_ps_cfg);
+	}
+
+done:
+
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ * @brief               Set/Get GPIO TSF latch clock sync config parameters
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cfg_clock_sync(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[5];
+	mlan_ds_gpio_tsf_latch *clock_sync_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFG_CLOCK_SYNC);
+
+	memset(data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len > 5) {
+		PRINTM(MERROR, "invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_GPIO_TSF_LATCH;
+	clock_sync_cfg = &misc_cfg->param.gpio_tsf_latch_config;
+	memset(clock_sync_cfg, 0, sizeof(mlan_ds_gpio_tsf_latch));
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		req->action = MLAN_ACT_SET;
+		switch (user_data_len) {
+		case 5:
+			clock_sync_cfg->clock_sync_gpio_pulse_width =
+				(t_u16)data[4];
+			/* fall through */
+		case 4:
+			if (data[3] < 0 || data[3] > 1) {
+				PRINTM(MERROR, "Invalid Level/Trigger\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			clock_sync_cfg->clock_sync_gpio_level_toggle =
+				(t_u8)data[3];
+			/* fall through */
+		case 3:
+			if (data[2] < 1 || data[2] > 255) {
+				PRINTM(MERROR,
+				       "Invalid number of GPIO Pin Number\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			clock_sync_cfg->clock_sync_gpio_pin_number =
+				(t_u8)data[2];
+			/* fall through */
+		case 2:
+			if (data[1] < 0 || data[1] > 2) {
+				PRINTM(MERROR, "Invalid Role\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			clock_sync_cfg->clock_sync_Role = (t_u8)data[1];
+			/* fall through */
+		case 1:
+			if (data[0] < 0 || data[0] > 2) {
+				PRINTM(MERROR, "Invalid Mode\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			clock_sync_cfg->clock_sync_mode = (t_u8)data[0];
+			break;
+		default:
+			break;
+		}
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)clock_sync_cfg,
+				sizeof(mlan_ds_gpio_tsf_latch), respbuflen);
+		ret = sizeof(mlan_ds_gpio_tsf_latch);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get GPIO TSF latch get tsf info config parameters
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cfg_get_tsf_info(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[1];
+	mlan_ds_tsf_info *tsf_info;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFG_GET_TSF_INFO);
+
+	memset(data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len > 1) {
+		PRINTM(MERROR, "invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_GET_TSF_INFO;
+	tsf_info = &misc_cfg->param.tsf_info;
+	memset(tsf_info, 0, sizeof(mlan_ds_tsf_info));
+	if (user_data_len == 1) {
+		if (data[0] < 0 || data[0] > 1) {
+			PRINTM(MERROR, "Invalid tsf Format\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		tsf_info->tsf_format = data[0];
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)tsf_info,
+			sizeof(mlan_ds_tsf_info), respbuflen);
+	ret = sizeof(mlan_ds_tsf_info);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get transition channel
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_transition_channel(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[1];
+
+	ENTER();
+	if (!priv || (priv->bss_type != MLAN_BSS_TYPE_UAP)) {
+		PRINTM(MERROR, "priv is null or interface is not AP");
+		ret = -EFAULT;
+		LEAVE();
+		return ret;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TRANSITION_CHANNEL);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len > 1) {
+			PRINTM(MERROR, "Invalid parameter number\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (user_data_len)
+			priv->trans_chan = data[0];
+	}
+	data[0] = priv->trans_chan;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(int);
+done:
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#ifdef WIFI_DIRECT_SUPPORT
+#define DEF_NOA_INTERVAL 100
+/**
+ ** @brief               Set/Get P2P NoA (Notice of Absence) parameters
+ ** @param priv          Pointer to moal_private structure
+ ** @param respbuf       Pointer to response buffer
+ ** @param resplen       Response buffer length
+ **
+ **  @return             Number of bytes written, negative for failure.
+ **/
+static int
+woal_p2p_ps_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int user_data_len = 0;
+	int ret = 0, data[2];
+	u32 duration = priv->phandle->noa_duration;
+	u32 interval = 0;
+
+	ENTER();
+	if (strlen(respbuf) > strlen("P2P_PERIODIC_SLEEP")) {
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen("P2P_PERIODIC_SLEEP") + 1,
+				data, ARRAY_SIZE(data), &user_data_len);
+	}
+	if ((user_data_len != 1) && (user_data_len != 2)) {
+		PRINTM(MERROR,
+		       " Invalid parameter number for P2P_PERIODIC_SLEEP");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (data[0] < DEF_NOA_INTERVAL)
+		interval = DEF_NOA_INTERVAL;
+	else
+		interval = (data[0] + DEF_NOA_INTERVAL - 1) / DEF_NOA_INTERVAL *
+			DEF_NOA_INTERVAL;
+
+	if (user_data_len == 2)
+		duration = data[1];
+	if (duration >= interval) {
+		PRINTM(MERROR,
+		       " Invalid noa duration/interval! duration=%d interval=%d\n",
+		       duration, interval);
+		ret = -EINVAL;
+		goto done;
+	}
+	priv->phandle->noa_interval = interval;
+	priv->phandle->noa_duration = duration;
+	PRINTM(MIOCTL, "configure noa interval=%d, duration=%d\n",
+	       priv->phandle->noa_interval, priv->phandle->noa_duration);
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ * @brief               Set/Get DFS repeater mode
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_dfs_repeater_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data[1] = { 0 };
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_ds_misc_dfs_repeater *dfs_repeater = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DFS_REPEATER_CFG);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_DFS_REAPTER_MODE;
+	dfs_repeater =
+		(mlan_ds_misc_dfs_repeater *)&misc_cfg->param.dfs_repeater;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[0] != MTRUE) && (data[0] != MFALSE)) {
+			PRINTM(MERROR, "Invalid DFS repeater mode %d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		dfs_repeater->mode = (t_u16)data[0];
+
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)dfs_repeater,
+				sizeof(mlan_ds_misc_dfs_repeater), respbuflen);
+		ret = sizeof(mlan_ds_misc_dfs_repeater);
+	}
+
+	/* Store current value of DFS repeater mode for futher references. eg.,
+	 * for avoiding CAC timers
+	 */
+	priv->phandle->dfs_repeater_mode = dfs_repeater->mode;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/**
+ * @brief               Set/Get MIRACAST configuration parameters
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_miracast_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data[3] = { 0, 0, 0 };
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_MIRACAST_CFG);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		data[0] = priv->phandle->miracast_mode;
+		data[1] = priv->phandle->miracast_scan_time;
+		data[2] = priv->phandle->scan_chan_gap;
+
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	} else {
+		/* SET operation */
+		memset(data, 0, sizeof(data));
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+
+		if (user_data_len > 3) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] < 0 || data[0] > 2 || data[1] < 0 || data[2] < 0) {
+			PRINTM(MERROR, "Invalid argument\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	if (user_data_len >= 1)
+		priv->phandle->miracast_mode = (t_u8)data[0];
+	if (user_data_len >= 2)
+		priv->phandle->miracast_scan_time = (t_u16)data[1];
+	if (user_data_len == 3)
+		priv->phandle->scan_chan_gap = (t_u16)data[2];
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *   @brief Configuring scan gap for miracast mode
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             0 --success, otherwise failure
+ */
+static int
+woal_set_scan_chan_gap(moal_private *priv, t_u8 *respbuf, int respbuflen)
+{
+	t_u32 data[2];
+	int ret = 0;
+	int user_data_len = 0;
+
+	ENTER();
+
+	if (strlen(respbuf) > strlen("SCAN_TIMING")) {
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen("SCAN_TIMING") + 1, data,
+				ARRAY_SIZE(data), &user_data_len);
+	}
+
+	if (user_data_len != 2) {
+		PRINTM(MERROR, "Invalid arguments for scan timing\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	priv->phandle->miracast_scan_time = (t_u16)data[0];
+	priv->phandle->scan_chan_gap = (t_u16)data[1];
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ * @brief               Set/Get control to coex RX window size configuration
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_coex_rx_winsize(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_COEX_RX_WINSIZE);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_COEX_RX_WINSIZE;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data != MTRUE) && (data != MFALSE)) {
+			PRINTM(MERROR,
+			       "Invalid coex RX window size parameter %d\n",
+			       data);
+			ret = -EINVAL;
+			goto done;
+		}
+		cfg_11n->param.coex_rx_winsize = data;
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		moal_memcpy_ext(priv->phandle, respbuf,
+				(t_u8 *)&cfg_11n->param.coex_rx_winsize,
+				sizeof(t_u32), respbuflen);
+		ret = sizeof(t_u32);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get control to TX AMPDU configuration on infra link
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_txaggrctrl(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TX_AGGR_CTRL);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_TX_AGGR_CTRL;
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data != MTRUE) && (data != MFALSE)) {
+			PRINTM(MERROR, "Invalid txaggrctrl parameter %d\n",
+			       data);
+			ret = -EINVAL;
+			goto done;
+		}
+		cfg_11n->param.txaggrctrl = data;
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		moal_memcpy_ext(priv->phandle, respbuf,
+				(t_u8 *)&cfg_11n->param.txaggrctrl,
+				sizeof(t_u32), respbuflen);
+		ret = sizeof(t_u32);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get control to enable/disable auto TDLS
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_auto_tdls(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_AUTO_TDLS);
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		data = priv->enable_auto_tdls;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data != MTRUE) && (data != MFALSE)) {
+			PRINTM(MERROR, "Invalid autotdls parameter %d\n", data);
+			ret = -EINVAL;
+			goto done;
+		}
+		priv->enable_auto_tdls = (t_u8)data;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef PCIE
+/**
+ * @brief               Read/Write PCIE register
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_pcie_reg_rw(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	moal_handle *handle = priv->phandle;
+	int data[3];
+	t_u32 reg;
+	t_u32 value;
+	int ret = MLAN_STATUS_SUCCESS;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PCIE_REG_RW);
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if ((user_data_len != 1) && (user_data_len != 2)) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	reg = (t_u32)data[0];
+	if (user_data_len == 1) {
+		if (moal_read_reg(handle, reg, &value)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		data[1] = value;
+	} else {
+		value = data[1];
+		if (moal_write_reg(handle, reg, value)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	moal_memcpy_ext(handle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Read/Write PCIE register/memory from BAR0
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_pcie_bar0_reg_rw(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	moal_handle *handle = priv->phandle;
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+	int data[3];
+	t_u32 reg;
+	t_u32 value;
+	int ret = MLAN_STATUS_SUCCESS;
+	int user_data_len = 0, header_len = 0;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_PCIE_BAR0_REG_RW);
+	if ((int)strlen(respbuf) == header_len) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if ((user_data_len != 1) && (user_data_len != 2)) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	reg = (t_u32)data[0];
+	if (user_data_len == 1) {
+		value = ioread32(card->pci_mmap + reg);
+		if (value == MLAN_STATUS_FAILURE) {
+			ret = -EFAULT;
+			goto done;
+		}
+		data[1] = value;
+	} else {
+		value = data[1];
+		iowrite32(value, card->pci_mmap + reg);
+	}
+	moal_memcpy_ext(handle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief               Get SOC temperature
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_get_sensor_temp(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pcfg = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg->sub_command = MLAN_OID_MISC_GET_SENSOR_TEMP;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(respbuf, 0, respbuflen);
+	moal_memcpy_ext(priv->phandle, respbuf,
+			&pcfg->param.sensor_temp.temperature, sizeof(t_u32),
+			respbuflen);
+
+	ret = sizeof(t_u32);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/**
+ * @brief               Enable/disable DFS offload
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_dfs_offload_enable(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	struct wiphy *wiphy = NULL;
+	int ret = 0, dfs_offload_en = 0, user_data_len = 0, header_len = 0,
+		dfs_offload;
+
+	ENTER();
+
+	if (priv && priv->wdev)
+		wiphy = priv->wdev->wiphy;
+	if (!wiphy) {
+		PRINTM(MERROR, "wiphy is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	dfs_offload = moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD);
+	if (woal_is_any_interface_active(priv->phandle)) {
+		PRINTM(MERROR,
+		       "DFS offload enable/disable do not allowed after BSS started!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DFS_OFFLOAD);
+	parse_arguments(respbuf + header_len, &dfs_offload_en,
+			sizeof(dfs_offload_en) / sizeof(int), &user_data_len);
+	if (user_data_len != 1) {
+		PRINTM(MERROR, "Invalid number of args! %d\n", user_data_len);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (dfs_offload_en != 0 && dfs_offload_en != 1) {
+		PRINTM(MERROR, "Invalid args!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (dfs_offload != dfs_offload_en) {
+		dfs_offload = dfs_offload_en;
+		if (dfs_offload)
+			moal_extflg_set(priv->phandle, EXT_DFS_OFFLOAD);
+		else
+			moal_extflg_clear(priv->phandle, EXT_DFS_OFFLOAD);
+		woal_update_radar_chans_dfs_state(wiphy);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ * @brief               Set/Get TDLS CS off channel value
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_tdls_cs_chan(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TDLS_CS_CHANNEL;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen("TDLS_CS_CHAN");
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len + 1, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		ioctl_req->action = MLAN_ACT_SET;
+		misc->param.tdls_cs_channel = (t_u8)data;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = sprintf(respbuf, "off channel %d\n",
+		      misc->param.tdls_cs_channel) + 1;
+
+	PRINTM(MIOCTL, "tdls CS channel %d\n", misc->param.tdls_cs_channel);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get TDLS idle timeout value
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_tdls_idle_time(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TDLS_IDLE_TIME;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TDLS_IDLE_TIME);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		ioctl_req->action = MLAN_ACT_SET;
+		misc->param.tdls_idle_time = (t_u16)data;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf,
+			(t_u8 *)&misc->param.tdls_idle_time, sizeof(t_u16),
+			respbuflen);
+	ret = sizeof(t_u16);
+
+	PRINTM(MIOCTL, "tdls idle time %d\n", misc->param.tdls_idle_time);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Set/Get dynamic bandwidth
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_config_dyn_bw(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+	int user_data_len = 0, header_len = 0, data = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_DYN_BW;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DYN_BW);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, &data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid number of args! %d\n",
+			       user_data_len);
+			ret = -EINVAL;
+			goto done;
+		}
+		ioctl_req->action = MLAN_ACT_SET;
+		misc->param.dyn_bw = (t_u16)data;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&misc->param.dyn_bw,
+			sizeof(t_u16), respbuflen);
+	ret = sizeof(t_u16);
+
+	PRINTM(MIOCTL, "Dynamic bandwidth %d\n", misc->param.dyn_bw);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(UAP_SUPPORT)
+/**
+ * @brief               Check validation of channel and oper class
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param channel       channel
+ * @param oper_class    oper_class
+
+ *  @return             SUCCESS/FAIL
+ */
+static int
+woal_check_valid_channel_operclass(moal_private *priv, int channel,
+				   int oper_class)
+{
+	int ret = 0;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_OPER_CLASS_CHECK;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_GET;
+	misc->param.bw_chan_oper.oper_class = (t_u8)oper_class;
+	misc->param.bw_chan_oper.channel = (t_u8)channel;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief send CSA/ECSA action frame
+ *
+ ** @param priv          Pointer to moal_private structure
+ *  @param block_tx      0-no need block traffic 1- need block traffic
+ *  @param oper_class    oper_class
+ *  @param channel       channel
+ *  @param switch count  how many csa/ecsa beacon will send out
+ *  @param wait_option
+ *
+ *  @return             channel center frequency center, if found; O, otherwise
+ */
+static int
+woal_action_channel_switch(moal_private *priv, t_u8 block_tx, t_u8 oper_class,
+			   t_u8 channel, t_u8 switch_count, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_ACTION_CHAN_SWITCH;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+	bss->param.chanswitch.chan_switch_mode = block_tx;
+	bss->param.chanswitch.new_channel_num = channel;
+	bss->param.chanswitch.chan_switch_count = switch_count;
+	bss->param.chanswitch.new_oper_class = oper_class;
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+
+}
+
+/**
+ * @brief               Set extended channel switch ie
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_extend_channel_switch(moal_private *priv, t_u8 *respbuf,
+				t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0;
+	int data[5] = { 0 };
+	ENTER();
+
+	if (!priv || !priv->phandle ||
+	    (priv->bss_role != MLAN_BSS_ROLE_UAP) ||
+	    (priv->bss_started != MTRUE)) {
+		PRINTM(MERROR,
+		       "priv or handle is null or interface is not AP/GO"
+		       "or AP is not started\n");
+		ret = -EFAULT;
+		LEAVE();
+		return ret;
+	}
+
+	parse_arguments(respbuf + strlen(CMD_NXP) +
+			strlen(PRIV_CMD_EXTEND_CHAN_SWITCH),
+			data, ARRAY_SIZE(data), &user_data_len);
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		LEAVE();
+		return ret;
+	}
+	if (user_data_len < 4) {
+		PRINTM(MERROR, "Too few arguments\n");
+		ret = -EINVAL;
+		LEAVE();
+		return ret;
+	}
+	if (data[1]) {
+		if (woal_check_valid_channel_operclass(priv, data[2], data[1])) {
+			PRINTM(MERROR, "Wrong channel switch parameters!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+	if (data[3])
+		woal_channel_switch(priv, data[0], data[1], data[2], data[3],
+				    data[4], MFALSE);
+	else
+		woal_action_channel_switch(priv, data[0], data[1], data[2],
+					   data[3], MOAL_IOCTL_WAIT);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               P2P extended channel switch
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_p2p_ecsa(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0, header_len = 0;
+	int data[2] = { 0 };
+	t_u8 bw = 0, oper_class = 0, channel = 0;
+	IEEEtypes_ExtChanSwitchAnn_t *ext_chan_switch = NULL;
+	custom_ie *pcust_chansw_ie = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (priv->bss_role != MLAN_BSS_ROLE_UAP) {
+		PRINTM(MERROR,
+		       "Extended Channel Switch is only allowed for AP/GO mode\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (priv->bss_started != MTRUE) {
+		PRINTM(MERROR, "AP is not started!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+	misc->param.cust_ie.type = TLV_TYPE_MGMT_IE;
+	misc->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
+
+	pcust_chansw_ie = (custom_ie *)&misc->param.cust_ie.ie_data_list[0];
+	pcust_chansw_ie->ie_index = 0xffff;	/*Auto index */
+	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ExtChanSwitchAnn_t);
+	pcust_chansw_ie->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP;	/*Add IE for
+											   BEACON/probe resp */
+	ext_chan_switch =
+		(IEEEtypes_ExtChanSwitchAnn_t *) pcust_chansw_ie->ie_buffer;
+
+	header_len = strlen("P2P_ECSA");
+	parse_arguments(respbuf + header_len + 1, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len != 2) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	channel = data[0];
+	/* bandwidth 20:20M 40:40M 80:80M */
+	bw = data[1];
+	if (bw != 20 && bw != 40 && bw != 80) {
+		PRINTM(MERROR, "Unsupported bandwidth\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (channel >= 52 && channel <= 144) {
+		PRINTM(MERROR, "Switch to DFS channel is not allowed!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	woal_priv_get_nonglobal_operclass_by_bw_channel(priv, bw, channel,
+							&oper_class);
+	if (oper_class == 0) {
+		PRINTM(MERROR, "Wrong parameters!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	ext_chan_switch->element_id = EXTEND_CHANNEL_SWITCH_ANN;
+	ext_chan_switch->len = 4;
+	ext_chan_switch->chan_switch_mode = 1;
+	ext_chan_switch->new_oper_class = oper_class;
+	ext_chan_switch->new_channel_num = channel;
+	ext_chan_switch->chan_switch_count = DEF_CHAN_SWITCH_COUNT;
+
+	if (ext_chan_switch->chan_switch_mode) {
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		woal_stop_queue(priv->netdev);
+		priv->uap_tx_blocked = MTRUE;
+	}
+
+	DBG_HEXDUMP(MCMD_D, "ECSA IE", (t_u8 *)pcust_chansw_ie->ie_buffer,
+		    pcust_chansw_ie->ie_length);
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	priv->phandle->chsw_wait_q_woken = MFALSE;
+	/* wait for channel switch to complete  */
+	wait_event_interruptible_timeout(priv->phandle->chsw_wait_q,
+					 priv->phandle->chsw_wait_q_woken,
+					 (u32)HZ *
+					 (ext_chan_switch->chan_switch_count +
+					  2) * 110 / 1000);
+
+	pcust_chansw_ie->ie_index = 0xffff;	/*Auto index */
+	pcust_chansw_ie->mgmt_subtype_mask = 0;
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to clear ECSA IE\n");
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+* @brief               Set random mac configure value (ON/OFF)
+*
+* @param priv          Pointer to moal_private structure
+* @param respbuf       Pointer to response buffer
+* @param resplen       Response buffer length
+
+*  @return             Number of bytes written, negative for failure.
+*/
+static int
+woal_priv_config_random_mac(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	int header_len = 0, space_len = 0, i;
+	t_u8 rand_data[3];
+	const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	header_len = strlen("FAKEMAC");
+	if ((int)strlen(respbuf) >= header_len) {
+		for (i = 0; i < (int)(strlen(respbuf) - header_len - 1); i++) {
+			if (respbuf[header_len + 1 + i] != ' ')
+				break;
+		}
+		space_len = i;
+
+		if (strncmp(respbuf + header_len + 1 + space_len, "On",
+			    strlen("On")) == 0) {
+			if (memcmp(priv->random_mac, zero_mac,
+				   MLAN_MAC_ADDR_LENGTH)) {
+				ret = sprintf(respbuf,
+					      "FAKEMAC has been On\n") + 1;
+				goto done;
+			}
+			moal_memcpy_ext(priv->phandle, priv->random_mac,
+					priv->current_addr, ETH_ALEN,
+					MLAN_MAC_ADDR_LENGTH);
+			get_random_bytes(rand_data, 3);
+			moal_memcpy_ext(priv->phandle, priv->random_mac + 3,
+					rand_data, 3, 3);
+			PRINTM(MMSG, "FAKEMAC parameter is On\n");
+		} else if (strncmp(respbuf + header_len + 1 + space_len, "Off",
+				   strlen("Off")) == 0) {
+			memset(priv->random_mac, 0, ETH_ALEN);
+			PRINTM(MMSG, "FAKEMAC parameter is Off\n");
+		} else {
+			PRINTM(MERROR, "Invalid parameter!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid parameter!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Download start keep alive parameters
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param mkeep_alive_id       keep alive ID number
+ * @param ip_pke        IP packet from host
+ * @param ip_pke_len    IP packet length from host
+ * @param src_mac       Source MAC address
+ * @param dst_mac       Destination MAC address
+ * @param period_msec   Send keep alive packet interval
+
+ * @return      0: success  fail otherwise
+ */
+int
+woal_start_mkeep_alive(moal_private *priv, t_u8 mkeep_alive_id,
+		       t_u8 *ip_pkt, t_u16 ip_pkt_len, t_u8 *src_mac,
+		       t_u8 *dst_mac, t_u32 period_msec,
+		       t_u32 retry_interval, t_u8 retry_cnt)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CLOUD_KEEP_ALIVE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (mkeep_alive_id >= MAX_KEEP_ALIVE_ID) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* SET operation */
+	ioctl_req->action = MLAN_ACT_SET;
+	misc->param.keep_alive.mkeep_alive_id = mkeep_alive_id;
+	misc->param.keep_alive.enable = true;
+	misc->param.keep_alive.send_interval = period_msec;
+	misc->param.keep_alive.retry_interval = retry_interval;
+	misc->param.keep_alive.retry_count = retry_cnt;
+	moal_memcpy_ext(priv->phandle, misc->param.keep_alive.dst_mac, dst_mac,
+			MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	moal_memcpy_ext(priv->phandle, misc->param.keep_alive.src_mac, src_mac,
+			MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	misc->param.keep_alive.pkt_len =
+		MIN(ip_pkt_len, MKEEP_ALIVE_IP_PKT_MAX);
+	moal_memcpy_ext(priv->phandle, misc->param.keep_alive.packet, ip_pkt,
+			ip_pkt_len, MKEEP_ALIVE_IP_PKT_MAX);
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Download stop keep alive parameters
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param mkeep_alive_id       keep alive ID number
+ * @param ip_pkt        Last packet
+ * @param ip_pkt_len    Last packet length
+
+ * @return      0: success  fail otherwise
+ */
+int
+woal_stop_mkeep_alive(moal_private *priv, t_u8 mkeep_alive_id, t_u8 reset,
+		      t_u8 *ip_pkt, t_u8 *pkt_len)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_keep_alive *misc_keep_alive = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CLOUD_KEEP_ALIVE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc_keep_alive = &misc->param.keep_alive;
+
+	if (mkeep_alive_id >= MAX_KEEP_ALIVE_ID) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* GET operation */
+	ioctl_req->action = MLAN_ACT_GET;
+	misc_keep_alive->mkeep_alive_id = mkeep_alive_id;
+	misc_keep_alive->enable = false;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!misc_keep_alive->enable) {
+		PRINTM(MERROR, "ID %d is already stop\n", mkeep_alive_id);
+		goto done;
+	}
+
+	if (reset)
+		ioctl_req->action = MLAN_ACT_RESET;
+	else
+		/* SET operation */
+		ioctl_req->action = MLAN_ACT_SET;
+	misc_keep_alive->mkeep_alive_id = mkeep_alive_id;
+	misc_keep_alive->enable = false;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext)) {
+		ret = woal_mkeep_alive_vendor_event(priv,
+						    &misc->param.keep_alive);
+		if (ret)
+			PRINTM(MERROR,
+			       "Keep alive vendor event upload failed\n");
+	}
+#endif
+#endif
+	if (pkt_len) {
+		*pkt_len = MIN(misc_keep_alive->pkt_len,
+			       (MKEEP_ALIVE_IP_PKT_MAX - 1));
+		PRINTM(MINFO, "keep alive stop pkt_len is %d\n", *pkt_len);
+	}
+	if (*pkt_len && ip_pkt)
+		moal_memcpy_ext(priv->phandle, ip_pkt, misc_keep_alive->packet,
+				*pkt_len, *pkt_len);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Save cloud keep alive params in driver handle
+ *
+ * @param priv          Pointer to moal_private structure
+ * @params              Other params for keep alive
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+int
+woal_priv_save_cloud_keep_alive_params(moal_private *priv,
+				       t_u8 mkeep_alive_id, t_u8 enable,
+				       t_u16 ether_type, t_u8 *ip_pkt,
+				       t_u16 ip_pkt_len, t_u8 *src_mac,
+				       t_u8 *dst_mac, t_u32 period_msec,
+				       t_u32 retry_interval, t_u8 retry_cnt)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	mlan_ds_misc_keep_alive *keep_alive = NULL;
+	moal_handle *phandle = NULL;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	phandle = priv->phandle;
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CLOUD_KEEP_ALIVE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (mkeep_alive_id >= MAX_KEEP_ALIVE_ID) {
+		PRINTM(MERROR, "Invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* GET operation */
+	ioctl_req->action = MLAN_ACT_GET;
+	misc->param.keep_alive.mkeep_alive_id = mkeep_alive_id;
+	misc->param.keep_alive.enable = true;
+
+	ret = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (misc->param.keep_alive.enable) {
+		PRINTM(MERROR, "ID %d is in use\n", mkeep_alive_id);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	keep_alive = &phandle->keep_alive[mkeep_alive_id];
+	keep_alive->mkeep_alive_id = mkeep_alive_id;
+	keep_alive->enable = enable;
+	if (enable) {
+		keep_alive->cached = true;
+		keep_alive->send_interval = period_msec;
+		keep_alive->retry_interval = retry_interval;
+		keep_alive->retry_count = retry_cnt;
+		moal_memcpy_ext(phandle, keep_alive->dst_mac, dst_mac,
+				MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		moal_memcpy_ext(phandle, keep_alive->src_mac, src_mac,
+				MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		keep_alive->pkt_len = MIN(ip_pkt_len, MKEEP_ALIVE_IP_PKT_MAX);
+		moal_memcpy_ext(phandle, keep_alive->packet, ip_pkt, ip_pkt_len,
+				MKEEP_ALIVE_IP_PKT_MAX);
+		if (ether_type)
+			keep_alive->ether_type = ether_type;
+		else
+			keep_alive->ether_type = 0;
+	}
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               Cloud keep alive feature
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cloud_keep_alive(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	cloud_keep_alive *keep_alive = NULL;
+	int header_len = 0;
+
+	ENTER();
+
+	header_len = strlen(PRIV_CMD_CLOUD_KEEP_ALIVE);
+
+	keep_alive = (cloud_keep_alive *) (respbuf + header_len);
+
+	if (keep_alive->enable) {
+		ret = woal_priv_save_cloud_keep_alive_params(priv,
+							     keep_alive->
+							     mkeep_alive_id,
+							     keep_alive->enable,
+							     0, keep_alive->pkt,
+							     keep_alive->
+							     pkt_len,
+							     keep_alive->
+							     src_mac,
+							     keep_alive->
+							     dst_mac,
+							     keep_alive->
+							     sendInterval,
+							     keep_alive->
+							     retryInterval,
+							     keep_alive->
+							     retryCount);
+	} else {
+		if (0 != woal_stop_mkeep_alive(priv, keep_alive->mkeep_alive_id,
+					       keep_alive->reset,
+					       keep_alive->pkt,
+					       &keep_alive->pkt_len)) {
+			ret = -EFAULT;
+			return ret;
+		}
+		ret = respbuflen;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get static rx abort config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_rx_abort_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[2] = { 0 };
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RX_ABORT_CFG);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_RX_ABORT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 2 ||
+		    (data[0] == MTRUE && user_data_len != 2)) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == MTRUE && data[1] > 0x7f) {
+			PRINTM(MERROR, "Invalid threshold value\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.rx_abort_cfg.enable = (t_u8)data[0];
+		if (user_data_len == 2)
+			misc->param.rx_abort_cfg.rssi_threshold = (t_s8)data[1];
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.rx_abort_cfg.enable;
+	data[1] = misc->param.rx_abort_cfg.rssi_threshold;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get dynamic rx abort config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_rx_abort_cfg_ext(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[3] = { 0 };
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RX_ABORT_CFG_EXT);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_RX_ABORT_CFG_EXT;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 3 ||
+		    (data[0] == MTRUE && user_data_len != 3)) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == MTRUE) {
+			if (data[1] > 0x7f) {
+				PRINTM(MERROR, "Invalid margin value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (data[2] > 0x7f) {
+				PRINTM(MERROR,
+				       "Invalid ceil threshold value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		misc->param.rx_abort_cfg_ext.enable = (t_u8)data[0];
+		if (user_data_len > 1) {
+			misc->param.rx_abort_cfg_ext.rssi_margin =
+				(t_s8)data[1];
+			misc->param.rx_abort_cfg_ext.ceil_rssi_threshold =
+				(t_s8)data[2];
+		}
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.rx_abort_cfg_ext.enable;
+	data[1] = misc->param.rx_abort_cfg_ext.rssi_margin;
+	data[2] = misc->param.rx_abort_cfg_ext.ceil_rssi_threshold;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable/Disable Un-associated Dot11mc FTM Frame exchanges
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_dot11mc_unassoc_ftm_cfg(moal_private *priv, t_u8 *respbuf,
+				  t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[1] = { 0 };
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_DOT11MC_UNASSOC_FTM_CFG);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 1) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[0] != MTRUE) && (data[0] != MFALSE)) {
+			PRINTM(MERROR, "Invalid state for unassoc ftm\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.dot11mc_unassoc_ftm_cfg.state = (t_u16)data[0];
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.dot11mc_unassoc_ftm_cfg.state;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Tx  AMPDU protection mode
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_tx_ampdu_prot_mode(moal_private *priv, t_u8 *respbuf,
+			     t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[1] = { 0 };
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TX_AMPDU_PROT_MODE);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TX_AMPDU_PROT_MODE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 1) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] > TX_AMPDU_DYNAMIC_RTS_CTS) {
+			PRINTM(MERROR, "Invalid protection mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.tx_ampdu_prot_mode.mode = (t_u16)data[0];
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.tx_ampdu_prot_mode.mode;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Tx rate adapt config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_rate_adapt_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[4] = { 0 };
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_RATE_ADAPT_CFG);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_RATE_ADAPT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len < 1) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] > RATEADAPT_ALGO_SR) {
+			PRINTM(MERROR, "Invalid Rateadapt Algorithm\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == RATEADAPT_ALGO_SR && user_data_len > 1) {
+			if ((data[1] & data[2]) == 0xff) {
+				/* dynamic CCA noise based rate adapation enable
+				 * request nothing to do here
+				 */
+			} else if (data[1] > 100 || data[2] > 100) {
+				PRINTM(MERROR,
+				       "Invalid success rate threshold value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (data[3] < 10 || data[3] > 0xffff) {
+				PRINTM(MERROR, "Invalid interval value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		misc->param.rate_adapt_cfg.sr_rateadapt = (t_u8)data[0];
+		if (data[0] == RATEADAPT_ALGO_SR && user_data_len > 1) {
+			misc->param.rate_adapt_cfg.ra_low_thresh =
+				(t_u8)data[1];
+			misc->param.rate_adapt_cfg.ra_high_thresh =
+				(t_u8)data[2];
+			misc->param.rate_adapt_cfg.ra_interval = (t_u16)data[3];
+		}
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data[0] = misc->param.rate_adapt_cfg.sr_rateadapt;
+	data[1] = misc->param.rate_adapt_cfg.ra_low_thresh;
+	data[2] = misc->param.rate_adapt_cfg.ra_high_thresh;
+	data[3] = misc->param.rate_adapt_cfg.ra_interval;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get global cck desense config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_cck_desense_cfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[5] = { 0 };
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CCK_DESENSE_CFG);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CCK_DESENSE_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len > 5) {
+			PRINTM(MERROR, "Invalid number of args!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] > CCK_DESENSE_MODE_DYN_ENH) {
+			PRINTM(MERROR, "Invalid cck desense mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[0] == CCK_DESENSE_MODE_DISABLED &&
+		     user_data_len > 1) ||
+		    (data[0] == CCK_DESENSE_MODE_DYNAMIC &&
+		     user_data_len != 3) ||
+		    (data[0] == CCK_DESENSE_MODE_DYN_ENH &&
+		     (user_data_len < 3 || user_data_len == 4))) {
+			PRINTM(MERROR,
+			       "Invalid number of args for requested mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (user_data_len > 1) {
+			if (data[1] > 0x7f) {
+				PRINTM(MERROR, "Invalid margin value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (data[2] > 0x7f) {
+				PRINTM(MERROR,
+				       "Invalid ceil threshold value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		if (user_data_len > 3) {
+			if (data[3] > 0xff || data[4] > 0xff) {
+				PRINTM(MERROR,
+				       "Invalid ON/OFF intervals value\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		misc->param.cck_desense_cfg.mode = (t_u8)data[0];
+		if (user_data_len > 1) {
+			misc->param.cck_desense_cfg.margin = (t_s8)data[1];
+			misc->param.cck_desense_cfg.ceil_thresh = (t_s8)data[2];
+		}
+		if (data[0] == CCK_DESENSE_MODE_DYN_ENH) {
+			if (user_data_len > 3) {
+				misc->param.cck_desense_cfg.num_on_intervals =
+					(t_u8)data[3];
+				misc->param.cck_desense_cfg.num_off_intervals =
+					(t_u8)data[4];
+			} else {
+				/* set these to 0xff. This will indicate the FW
+				 * to use previously set values.
+				 */
+				misc->param.cck_desense_cfg.num_on_intervals =
+					0xff;
+				misc->param.cck_desense_cfg.num_off_intervals =
+					0xff;
+			}
+		}
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.cck_desense_cfg.mode;
+	data[1] = misc->param.cck_desense_cfg.margin;
+	data[2] = misc->param.cck_desense_cfg.ceil_thresh;
+	data[3] = misc->param.cck_desense_cfg.num_on_intervals;
+	data[4] = misc->param.cck_desense_cfg.num_off_intervals;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief               set/get low power mode
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_get_lpm(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_power_cfg *cfg = NULL;
+	int data = 0;
+	int user_data_len = 0, header_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (IS_CARD9098(priv->phandle->card_type) ||
+	    IS_CARD9097(priv->phandle->card_type)) {
+		header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_LPM);
+		if ((int)strlen(respbuf) == header_len) {
+			/* GET operation */
+			user_data_len = 0;
+		} else {
+			/* SET operation */
+			parse_arguments(respbuf + header_len, &data, 1,
+					&user_data_len);
+		}
+		if (user_data_len >= 2) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			req = woal_alloc_mlan_ioctl_req(sizeof
+							(mlan_ds_power_cfg));
+			if (req == NULL) {
+				ret = -ENOMEM;
+				goto done;
+			}
+
+			cfg = (mlan_ds_power_cfg *)req->pbuf;
+			if (user_data_len == 0) {
+				req->action = MLAN_ACT_GET;
+			} else {
+				cfg->param.lpm = data;
+				req->action = MLAN_ACT_SET;
+			}
+		}
+		cfg->sub_command = MLAN_OID_POWER_LOW_POWER_MODE;
+		req->req_id = MLAN_IOCTL_POWER_CFG;
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		data = cfg->param.lpm;
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)&data,
+				sizeof(data), respbuflen);
+		ret = sizeof(data);
+	} else
+		PRINTM(MERROR, "Low power mode command is not supported!\n");
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get HW ARB config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_arbcfg(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	int data[1];
+	int header_len = 0, user_data_len = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_ARB_CFG);
+	user_data_len = strlen(respbuf) - header_len;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_ARB_CONFIG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+				&user_data_len);
+		if (user_data_len != 1) {
+			PRINTM(MERROR, "Invalid Parameter\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[0] < 0 || data[0] > 4) {
+			PRINTM(MERROR, "Invalid Parameter: arb mode 0-4\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		misc->param.arb_cfg.arb_mode = (t_u32)data[0];
+		req->action = MLAN_ACT_SET;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.arb_cfg.arb_mode;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u32 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief      Timer function for TP state command.
+ *
+ *  @param data pointer to a buffer
+ *
+ *  @return     N/A
+ */
+void
+woal_tp_acnt_timer_func(void *context)
+{
+	moal_handle *phandle = (moal_handle *)context;
+	int i = 0;
+
+	if (phandle == NULL)
+		return;
+	PRINTM(MDATA, "####### CPU%d: tp acnt timer\n", smp_processor_id());
+	/* Tx TP accounting */
+	for (i = 0; i < MAX_TP_ACCOUNT_DROP_POINT_NUM; i++) {
+		phandle->tp_acnt.tx_bytes_rate[i] =
+			phandle->tp_acnt.tx_bytes[i] -
+			phandle->tp_acnt.tx_bytes_last[i];
+		phandle->tp_acnt.tx_bytes_last[i] =
+			phandle->tp_acnt.tx_bytes[i];
+		phandle->tp_acnt.tx_packets_rate[i] =
+			phandle->tp_acnt.tx_packets[i] -
+			phandle->tp_acnt.tx_packets_last[i];
+		phandle->tp_acnt.tx_packets_last[i] =
+			phandle->tp_acnt.tx_packets[i];
+	}
+	phandle->tp_acnt.tx_pending = atomic_read(&phandle->tx_pending);
+	/* Tx Interrupt accounting */
+	phandle->tp_acnt.tx_intr_rate =
+		phandle->tp_acnt.tx_intr_cnt - phandle->tp_acnt.tx_intr_last;
+	phandle->tp_acnt.tx_intr_last = phandle->tp_acnt.tx_intr_cnt;
+
+	/* Rx TP accounting */
+	for (i = 0; i < MAX_TP_ACCOUNT_DROP_POINT_NUM; i++) {
+		phandle->tp_acnt.rx_bytes_rate[i] =
+			phandle->tp_acnt.rx_bytes[i] -
+			phandle->tp_acnt.rx_bytes_last[i];
+		phandle->tp_acnt.rx_bytes_last[i] =
+			phandle->tp_acnt.rx_bytes[i];
+		phandle->tp_acnt.rx_packets_rate[i] =
+			phandle->tp_acnt.rx_packets[i] -
+			phandle->tp_acnt.rx_packets_last[i];
+		phandle->tp_acnt.rx_packets_last[i] =
+			phandle->tp_acnt.rx_packets[i];
+	}
+	phandle->tp_acnt.rx_pending = atomic_read(&phandle->rx_pending);
+	// Interrupt accounting, RX
+	phandle->tp_acnt.rx_intr_rate =
+		phandle->tp_acnt.rx_intr_cnt - phandle->tp_acnt.rx_intr_last;
+	phandle->tp_acnt.rx_intr_last = phandle->tp_acnt.rx_intr_cnt;
+	phandle->tp_acnt.rx_amsdu_cnt_rate =
+		phandle->tp_acnt.rx_amsdu_cnt -
+		phandle->tp_acnt.rx_amsdu_cnt_last;
+	phandle->tp_acnt.rx_amsdu_cnt_last = phandle->tp_acnt.rx_amsdu_cnt;
+
+	phandle->tp_acnt.rx_amsdu_pkt_cnt_rate =
+		phandle->tp_acnt.rx_amsdu_pkt_cnt -
+		phandle->tp_acnt.rx_amsdu_pkt_cnt_last;
+	phandle->tp_acnt.rx_amsdu_pkt_cnt_last =
+		phandle->tp_acnt.rx_amsdu_pkt_cnt;
+
+	phandle->tp_acnt.tx_amsdu_cnt_rate =
+		phandle->tp_acnt.tx_amsdu_cnt -
+		phandle->tp_acnt.tx_amsdu_cnt_last;
+	phandle->tp_acnt.tx_amsdu_cnt_last = phandle->tp_acnt.tx_amsdu_cnt;
+
+	phandle->tp_acnt.tx_amsdu_pkt_cnt_rate =
+		phandle->tp_acnt.tx_amsdu_pkt_cnt -
+		phandle->tp_acnt.tx_amsdu_pkt_cnt_last;
+	phandle->tp_acnt.tx_amsdu_pkt_cnt_last =
+		phandle->tp_acnt.tx_amsdu_pkt_cnt;
+
+	/* re-arm timer */
+	woal_mod_timer(&phandle->tp_acnt.timer, 1000);
+}
+
+/**
+ *  @brief      set tp state to mlan
+ *
+ *  @param priv  pointer to moal_private
+ *
+ *  @return     N/A
+ */
+void
+woal_set_tp_state(moal_private *priv)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	moal_handle *handle = priv->phandle;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL)
+		return;
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TP_STATE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->param.tp_state.on = handle->tp_acnt.on;
+	misc->param.tp_state.drop_point = handle->tp_acnt.drop_point;
+	req->action = MLAN_ACT_SET;
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	return;
+}
+
+/**
+ *  @brief Set/Get TP statistics.
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param respbuf      A pointer to response buffer
+ *  @param respbuflen   Available length of response buffer
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int
+woal_priv_set_tp_state(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen)
+{
+	moal_handle *handle = priv->phandle;
+	int ret = 0;
+	int data[2];
+	int header_len = 0, user_data_len = 0;
+
+	ENTER();
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TP_STATE);
+	user_data_len = strlen(respbuf) - header_len;
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+	if (user_data_len > 2) {
+		PRINTM(MERROR, "Invalid number of args!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (user_data_len) {
+		handle->tp_acnt.on = data[0];
+		/* Enable TP statistics collection */
+		if (data[0] == 1) {
+			handle->tp_acnt.drop_point = data[1];
+			if (handle->is_tp_acnt_timer_set == MFALSE) {
+				woal_initialize_timer(&handle->tp_acnt.timer,
+						      woal_tp_acnt_timer_func,
+						      handle);
+				handle->is_tp_acnt_timer_set = MTRUE;
+				woal_mod_timer(&handle->tp_acnt.timer, 1000);
+			}
+		} else {
+			if (handle->is_tp_acnt_timer_set) {
+				woal_cancel_timer(&handle->tp_acnt.timer);
+				handle->is_tp_acnt_timer_set = MFALSE;
+			}
+			memset((void *)&handle->tp_acnt, 0,
+			       sizeof(moal_tp_acnt_t));
+		}
+		woal_set_tp_state(priv);
+	}
+	/* Get command results */
+	if (user_data_len == 0) {
+		moal_memcpy_ext(handle, respbuf, (t_u8 *)(&handle->tp_acnt),
+				sizeof(handle->tp_acnt), respbuflen);
+		ret = sizeof(handle->tp_acnt);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set priv command for Android
+ *  @param dev          A pointer to net_device structure
+ *  @param req          A pointer to ifreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_android_priv_cmd(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+	android_wifi_priv_cmd priv_cmd;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	char *buf = NULL;
+	char *pdata;
+#ifdef STA_SUPPORT
+	int power_mode = 0;
+	int band = 0;
+	char *pband = NULL;
+	mlan_bss_info bss_info;
+	mlan_ds_get_signal signal;
+	mlan_rate_cfg_t rate;
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	int copy_len = 0;
+#endif
+	int len = 0;
+	gfp_t flag;
+	char *cmd_buf = NULL;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	int cfg80211_wext;
+#endif
+
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	cfg80211_wext = priv->phandle->params.cfg80211_wext;
+#endif
+	if (copy_from_user(&priv_cmd, req->ifr_data,
+			   sizeof(android_wifi_priv_cmd))) {
+		ret = -EFAULT;
+		goto done;
+	}
+#define CMD_BUF_LEN 4096
+	if (priv_cmd.used_len < 0 || priv_cmd.total_len <= 0 ||
+	    priv_cmd.used_len > priv_cmd.total_len) {
+		PRINTM(MERROR,
+		       "Invalid Android priv cmd len. used_len: %d, total_len: %d\n",
+		       priv_cmd.used_len, priv_cmd.total_len);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (priv_cmd.total_len + 1 > CMD_BUF_LEN)
+		priv_cmd.total_len = CMD_BUF_LEN - 1;
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	buf = kzalloc(CMD_BUF_LEN, flag);
+	if (!buf) {
+		PRINTM(MERROR, "%s: failed to allocate memory\n", __FUNCTION__);
+		ret = -ENOMEM;
+		goto done;
+	}
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+	moal_memcpy_ext(priv->phandle, &cmd_buf, &priv_cmd.buf, sizeof(cmd_buf),
+			sizeof(cmd_buf));
+#else
+	cmd_buf = priv_cmd.buf;
+#endif
+	if (copy_from_user(buf, (const void __user *)cmd_buf,
+			   priv_cmd.total_len)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	buf[CMD_BUF_LEN - 1] = '\0';
+
+	PRINTM(MIOCTL, "Android priv cmd: [%s] on [%s]\n", buf, req->ifr_name);
+
+	if (strncmp(buf, CMD_NXP, strlen(CMD_NXP)) &&
+	    woal_check_driver_status(priv->phandle)) {
+		PRINTM(MERROR, "%s fail when driver hang\n", buf);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (strncmp(buf, CMD_NXP, strlen(CMD_NXP)) == 0) {
+		/* This command has come from mlanutl app */
+
+		/* Check command */
+		if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_VERSION,
+			     strlen(PRIV_CMD_VERSION)) == 0) {
+			/* Get version */
+			len = woal_get_priv_driver_version(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_BANDCFG,
+				    strlen(PRIV_CMD_BANDCFG)) == 0) {
+			/* Set/Get band configuration */
+			len = woal_setget_priv_bandcfg(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HOSTCMD,
+				    strlen(PRIV_CMD_HOSTCMD)) == 0) {
+			/* hostcmd configuration */
+			len = woal_priv_hostcmd(priv, buf, priv_cmd.total_len,
+						MOAL_IOCTL_WAIT);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_11AXCMDCFG,
+				    strlen(PRIV_CMD_11AXCMDCFG)) == 0) {
+			/* 11ax command */
+			pdata = buf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_11AXCMDCFG);
+			len = priv_cmd.total_len - strlen(CMD_NXP) +
+				strlen(PRIV_CMD_11AXCMDCFG);
+			len = woal_setget_priv_11axcmdcfg(priv, pdata, len,
+							  MOAL_IOCTL_WAIT);
+			len += strlen(CMD_NXP) + strlen(PRIV_CMD_11AXCMDCFG);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_RANGE_EXT,
+				    strlen(PRIV_CMD_RANGE_EXT)) == 0) {
+			len = woal_setget_priv_range_ext(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HTTXCFG,
+				    strlen(PRIV_CMD_HTTXCFG)) == 0) {
+			/* Set/Get HT Tx configuration */
+			len = woal_setget_priv_httxcfg(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HTCAPINFO,
+				    strlen(PRIV_CMD_HTCAPINFO)) == 0) {
+			/* Set/Get HT Capability information */
+			len = woal_setget_priv_htcapinfo(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ADDBAPARA,
+				    strlen(PRIV_CMD_ADDBAPARA)) == 0) {
+			/* Set/Get Add BA parameters */
+			len = woal_setget_priv_addbapara(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AGGRPRIOTBL,
+				    strlen(PRIV_CMD_AGGRPRIOTBL)) == 0) {
+			/* Set/Get Aggregation priority table parameters */
+			len = woal_setget_priv_aggrpriotbl(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ADDBAREJECT,
+				    strlen(PRIV_CMD_ADDBAREJECT)) == 0) {
+			/* Set/Get Add BA reject parameters */
+			len = woal_setget_priv_addbareject(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DELBA,
+				    strlen(PRIV_CMD_DELBA)) == 0) {
+			/* Delete selective BA based on parameters */
+			len = woal_priv_delba(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_REJECTADDBAREQ,
+				    strlen(PRIV_CMD_REJECTADDBAREQ)) == 0) {
+			/* Set/Get the reject addba requst conditions */
+			len = woal_priv_rejectaddbareq(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_VHTCFG,
+				    strlen(PRIV_CMD_VHTCFG)) == 0) {
+			/* Set/Get 11AC configuration */
+			len = woal_setget_priv_vhtcfg(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_OPERMODECFG,
+				    strlen(PRIV_CMD_OPERMODECFG)) == 0) {
+			/* Set/Get 11AC configuration */
+			len = woal_setget_priv_opermodecfg(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DATARATE,
+				    strlen(PRIV_CMD_DATARATE)) == 0) {
+			/* Get data rate */
+			len = woal_get_priv_datarate(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TXRATECFG,
+				    strlen(PRIV_CMD_TXRATECFG)) == 0) {
+			/* Set/Get tx rate cfg */
+			len = woal_setget_priv_txratecfg(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GETLOG,
+				    strlen(PRIV_CMD_GETLOG)) == 0) {
+			/* Get wireless stats information */
+			len = woal_get_priv_getlog(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CUSTOMIE,
+				    strlen(PRIV_CMD_CUSTOMIE)) == 0) {
+			/* Custom IE configuration */
+			len = woal_priv_customie(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ESUPPMODE,
+				    strlen(PRIV_CMD_ESUPPMODE)) == 0) {
+			/* Esupplicant mode configuration */
+			len = woal_setget_priv_esuppmode(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PASSPHRASE,
+				    strlen(PRIV_CMD_PASSPHRASE)) == 0) {
+			/* Esupplicant passphrase configuration */
+			len = woal_setget_priv_passphrase(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DEAUTH,
+				    strlen(PRIV_CMD_DEAUTH)) == 0) {
+			/* Deauth */
+			len = woal_priv_deauth(priv, buf, priv_cmd.total_len);
+			goto handled;
+#ifdef UAP_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AP_DEAUTH,
+				    strlen(PRIV_CMD_AP_DEAUTH)) == 0) {
+			/* AP Deauth */
+			len = woal_priv_ap_deauth(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GET_STA_LIST,
+				    strlen(PRIV_CMD_GET_STA_LIST)) == 0) {
+			/* Get STA list */
+			len = woal_priv_get_sta_list(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_BSS_CONFIG,
+				    strlen(PRIV_CMD_BSS_CONFIG)) == 0) {
+			/* BSS config */
+			len = woal_priv_bss_config(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_BSSROLE,
+				    strlen(PRIV_CMD_BSSROLE)) == 0) {
+			/* BSS Role */
+			len = woal_priv_bssrole(priv, buf,
+						(t_u32)priv_cmd.total_len);
+			goto handled;
+#endif
+#endif
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SETUSERSCAN,
+				    strlen(PRIV_CMD_SETUSERSCAN)) == 0) {
+			/* Set user scan */
+			len = woal_priv_setuserscan(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GETSCANTABLE,
+				    strlen(PRIV_CMD_GETSCANTABLE)) == 0) {
+			/* Get scan table */
+			len = woal_priv_getscantable(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GETCHANSTATS,
+				    strlen(PRIV_CMD_GETCHANSTATS)) == 0) {
+			/* Get channel statistics */
+			len = woal_priv_get_chanstats(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_EXTCAPCFG,
+				    strlen(PRIV_CMD_EXTCAPCFG)) == 0) {
+			/* Extended capabilities configure */
+			len = woal_priv_extcapcfg(priv, buf,
+						  (t_u32)priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CANCELSCAN,
+				    strlen(PRIV_CMD_CANCELSCAN)) == 0) {
+			/* Cancel scan */
+			len = woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DEEPSLEEP,
+				    strlen(PRIV_CMD_DEEPSLEEP)) == 0) {
+			/* Deep sleep */
+			len = woal_priv_setgetdeepsleep(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_IPADDR,
+				    strlen(PRIV_CMD_IPADDR)) == 0) {
+			/* IP address */
+			len = woal_priv_setgetipaddr(priv, buf,
+						     (t_u32)priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_WPSSESSION,
+				    strlen(PRIV_CMD_WPSSESSION)) == 0) {
+			/* WPS Session */
+			len = woal_priv_setwpssession(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_OTPUSERDATA,
+				    strlen(PRIV_CMD_OTPUSERDATA)) == 0) {
+			/* OTP user data */
+			len = woal_priv_otpuserdata(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_COUNTRYCODE,
+				    strlen(PRIV_CMD_COUNTRYCODE)) == 0) {
+			/* Country code */
+			len = woal_priv_set_get_countrycode(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CFPINFO,
+				    strlen(PRIV_CMD_CFPINFO)) == 0) {
+			/* CFP info */
+			len = woal_priv_get_cfpinfo(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TCPACKENH,
+				    strlen(PRIV_CMD_TCPACKENH)) == 0) {
+			/* TCP ack enhancement */
+			len = woal_priv_setgettcpackenh(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+#ifdef REASSOCIATION
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ASSOCBSSID,
+				    strlen(PRIV_CMD_ASSOCBSSID)) == 0) {
+			/* Associate to essid */
+			len = woal_priv_assocessid(priv, buf,
+						   priv_cmd.total_len, 1);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ASSOCESSID,
+				    strlen(PRIV_CMD_ASSOCESSID)) == 0) {
+			/* Associate to essid */
+			len = woal_priv_assocessid(priv, buf,
+						   priv_cmd.total_len, 0);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_WAKEUPREASON,
+				    strlen(PRIV_CMD_WAKEUPREASON)) == 0) {
+			/* wakeup reason */
+			len = woal_priv_getwakeupreason(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_LISTENINTERVAL,
+				    strlen(PRIV_CMD_LISTENINTERVAL)) == 0) {
+			/* Listen Interval */
+			len = woal_priv_set_get_listeninterval(priv, buf,
+							       priv_cmd.
+							       total_len);
+			goto handled;
+#endif
+#ifdef DEBUG_LEVEL1
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DRVDBG,
+				    strlen(PRIV_CMD_DRVDBG)) == 0) {
+			/* Driver debug bit mask */
+			len = woal_priv_set_get_drvdbg(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HSCFG,
+				    strlen(PRIV_CMD_HSCFG)) == 0) {
+			/* HS configuration */
+			len = woal_priv_hscfg(priv, buf, priv_cmd.total_len,
+					      MTRUE);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HSSETPARA,
+				    strlen(PRIV_CMD_HSSETPARA)) == 0) {
+			/* Set HS parameter */
+			len = woal_priv_hssetpara(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_MGMT_FILTER,
+				    strlen(PRIV_CMD_MGMT_FILTER)) == 0) {
+			/* Management frame filter wakeup */
+			len = woal_priv_mgmt_filter(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SCANCFG,
+				    strlen(PRIV_CMD_SCANCFG)) == 0) {
+			/* Scan configuration */
+			len = woal_priv_set_get_scancfg(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GETNLNUM,
+				    strlen(PRIV_CMD_GETNLNUM)) == 0) {
+			/* Scan configuration */
+			len = woal_priv_getnlnum(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AGGRCTRL,
+				    strlen(PRIV_CMD_AGGRCTRL)) == 0) {
+			/* aggregation control */
+			len = woal_priv_set_get_aggrctrl(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#ifdef USB
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_USBAGGRCTRL,
+				    strlen(PRIV_CMD_USBAGGRCTRL)) == 0) {
+			/* USB aggregation control */
+			len = woal_priv_set_get_usbaggrctrl(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_SET_BSS_MODE,
+				    strlen(PRIV_CMD_SET_BSS_MODE)) == 0) {
+			/* Set bss mode */
+			len = woal_priv_set_bss_mode(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SET_AP,
+				    strlen(PRIV_CMD_SET_AP)) == 0) {
+			/* Set AP */
+			len = woal_priv_set_ap(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SET_POWER,
+				    strlen(PRIV_CMD_SET_POWER)) == 0) {
+			/* Set power management parameters */
+			len = woal_priv_set_power(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SET_ESSID,
+				    strlen(PRIV_CMD_SET_ESSID)) == 0) {
+			/* Set essid */
+			len = woal_priv_set_essid(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SET_AUTH,
+				    strlen(PRIV_CMD_SET_AUTH)) == 0) {
+			/* Set authentication mode parameters */
+			len = woal_priv_set_auth(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GET_AP,
+				    strlen(PRIV_CMD_GET_AP)) == 0) {
+			/* Get AP */
+			len = woal_priv_get_ap(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GET_POWER,
+				    strlen(PRIV_CMD_GET_POWER)) == 0) {
+			/* Get power management parameters */
+			len = woal_priv_get_power(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PSMODE,
+				    strlen(PRIV_CMD_PSMODE)) == 0) {
+			/* Set/Get PS mode */
+			len = woal_priv_set_get_psmode(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_WARMRESET,
+				    strlen(PRIV_CMD_WARMRESET)) == 0) {
+			/* Performs warm reset */
+			len = woal_priv_warmreset(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TXPOWERCFG,
+				    strlen(PRIV_CMD_TXPOWERCFG)) == 0) {
+			/* TX power configurations */
+			len = woal_priv_txpowercfg(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_RX_ABORT_CFG_EXT,
+				    strlen(PRIV_CMD_RX_ABORT_CFG_EXT)) == 0) {
+			/* dynamic Rx Abort config */
+			len = woal_priv_rx_abort_cfg_ext(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_RX_ABORT_CFG,
+				    strlen(PRIV_CMD_RX_ABORT_CFG)) == 0) {
+			/* static Rx Abort config */
+			len = woal_priv_rx_abort_cfg(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_TX_AMPDU_PROT_MODE,
+				    strlen(PRIV_CMD_TX_AMPDU_PROT_MODE)) == 0) {
+			/* tx ampdu protection mode setting */
+			len = woal_priv_tx_ampdu_prot_mode(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_DOT11MC_UNASSOC_FTM_CFG,
+				    strlen(PRIV_CMD_DOT11MC_UNASSOC_FTM_CFG)) ==
+			   0) {
+			/* setting for dot11mc un-associated case FTM frame exchange */
+			len = woal_priv_dot11mc_unassoc_ftm_cfg(priv, buf,
+								priv_cmd.
+								total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_RATE_ADAPT_CFG,
+				    strlen(PRIV_CMD_RATE_ADAPT_CFG)) == 0) {
+			/* rate adapt config */
+			len = woal_priv_rate_adapt_cfg(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_CCK_DESENSE_CFG,
+				    strlen(PRIV_CMD_CCK_DESENSE_CFG)) == 0) {
+			/* cck desense config */
+			len = woal_priv_cck_desense_cfg(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PSCFG,
+				    strlen(PRIV_CMD_PSCFG)) == 0) {
+			/* PS configurations */
+			len = woal_priv_pscfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_BCNTIMEOUTCFG,
+				    strlen(PRIV_CMD_BCNTIMEOUTCFG)) == 0) {
+			/* Beacon timeout configurations */
+			len = woal_priv_bcntimeoutcfg(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SLEEPPD,
+				    strlen(PRIV_CMD_SLEEPPD)) == 0) {
+			/* Sleep period */
+			len = woal_priv_sleeppd(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TXCONTROL,
+				    strlen(PRIV_CMD_TXCONTROL)) == 0) {
+			/* Tx control */
+			len = woal_priv_txcontrol(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_REGRDWR,
+				    strlen(PRIV_CMD_REGRDWR)) == 0) {
+			/* Register Read/Write */
+			len = woal_priv_regrdwr(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_RDEEPROM,
+				    strlen(PRIV_CMD_RDEEPROM)) == 0) {
+			/* Read the EEPROM contents of the card */
+			len = woal_priv_rdeeprom(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_MEMRDWR,
+				    strlen(PRIV_CMD_MEMRDWR)) == 0) {
+			/* Memory Read/Write */
+			len = woal_priv_memrdwr(priv, buf, priv_cmd.total_len);
+			goto handled;
+#ifdef SDIO
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SDCMD52RW,
+				    strlen(PRIV_CMD_SDCMD52RW)) == 0) {
+			/* Cmd52 read/write register */
+			len = woal_priv_sdcmd52rw(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SDIO_CLOCK,
+				    strlen(PRIV_CMD_SDIO_CLOCK)) == 0) {
+			/* Turn on/off the sdio clock */
+			len = woal_priv_sdio_clock_ioctl(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_MPA_CTRL,
+				    strlen(PRIV_CMD_MPA_CTRL)) == 0) {
+			/* Set SDIO Multi-point aggregation
+			 * control parameters */
+			len = woal_priv_sdio_mpa_ctrl(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SD_CMD53_RW,
+				    strlen(PRIV_CMD_SD_CMD53_RW)) == 0) {
+			/* Cmd53 read/write register */
+			len = woal_priv_cmd53rdwr(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ROBUSTCOEX,
+				    strlen(PRIV_CMD_ROBUSTCOEX)) == 0) {
+			/* Set Robustcoex GPIOcfg */
+			pdata = buf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_ROBUSTCOEX);
+			len = priv_cmd.total_len - strlen(PRIV_CMD_ROBUSTCOEX) -
+				strlen(CMD_NXP);
+			len = woal_priv_robustcoex(priv, pdata, len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DMCS,
+				    strlen(PRIV_CMD_DMCS)) == 0) {
+			/* Set/Get DMCS config */
+			len = woal_priv_dmcs(priv, buf, priv_cmd.total_len);
+			goto handled;
+#if defined(PCIE)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SSU,
+				    strlen(PRIV_CMD_SSU)) == 0) {
+			/* Set SSU config */
+			pdata = buf + strlen(CMD_NXP) + strlen(PRIV_CMD_SSU);
+			len = priv_cmd.used_len - strlen(PRIV_CMD_SSU) -
+				strlen(CMD_NXP);
+			len = woal_priv_ssu_cmd(priv, len, pdata,
+						priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HAL_PHY_CFG,
+				    strlen(PRIV_CMD_HAL_PHY_CFG)) == 0) {
+			/* Set hal_phy config */
+			pdata = buf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_HAL_PHY_CFG);
+			len = priv_cmd.total_len -
+				strlen(PRIV_CMD_HAL_PHY_CFG) - strlen(CMD_NXP);
+			len = woal_priv_hal_phy_cfg_cmd(priv, pdata, len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ARPFILTER,
+				    strlen(PRIV_CMD_ARPFILTER)) == 0) {
+			/* ARPFilter Configuration */
+			len = woal_priv_arpfilter(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AUTO_ARP,
+				    strlen(PRIV_CMD_AUTO_ARP)) == 0) {
+			/* Auto ARP enable/disable */
+			len = woal_priv_set_get_auto_arp(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_HOTSPOTCFG,
+				    strlen(PRIV_CMD_HOTSPOTCFG)) == 0) {
+			/* Hotspot CFG */
+			len = woal_priv_hotspotcfg(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+#ifdef RX_PACKET_COALESCE
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_RX_COAL_CFG,
+				    strlen(PRIV_CMD_RX_COAL_CFG)) == 0) {
+			/* RX packet coalescing Configuration */
+			len = woal_priv_rx_pkt_coalesce_cfg(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+#endif
+
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_MGMT_FRAME_CTRL,
+				    strlen(PRIV_CMD_MGMT_FRAME_CTRL)) == 0) {
+			/* Mgmt Frame Passthrough Ctrl */
+			len = woal_priv_mgmt_frame_passthru_ctrl(priv, buf,
+								 priv_cmd.
+								 total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_QCONFIG,
+				    strlen(PRIV_CMD_QCONFIG)) == 0) {
+			/* Queue config */
+			len = woal_priv_qconfig(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ADDTS,
+				    strlen(PRIV_CMD_ADDTS)) == 0) {
+			/* Send an ADDTS TSPEC */
+			len = woal_priv_wmm_addts_req_ioctl(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DELTS,
+				    strlen(PRIV_CMD_DELTS)) == 0) {
+			/* Send a DELTS TSPE */
+			len = woal_priv_wmm_delts_req_ioctl(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_QSTATUS,
+				    strlen(PRIV_CMD_QSTATUS)) == 0) {
+			/* Get the status of the WMM queues */
+			len = woal_priv_wmm_queue_status_ioctl(priv, buf,
+							       priv_cmd.
+							       total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TS_STATUS,
+				    strlen(PRIV_CMD_TS_STATUS)) == 0) {
+			/* Get the status of the WMM Traffic Streams */
+			len = woal_priv_wmm_ts_status_ioctl(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_QOS_CFG,
+				    strlen(PRIV_CMD_QOS_CFG)) == 0) {
+			t_u32 action = MLAN_ACT_GET;
+			if (strlen(buf) ==
+			    strlen(CMD_NXP) + strlen(PRIV_CMD_QOS_CFG)) {
+				pdata = buf;	/* GET operation */
+			} else {
+				pdata = buf + strlen(CMD_NXP) +
+					strlen(PRIV_CMD_QOS_CFG);
+				action = MLAN_ACT_SET;	/* SET operation */
+			}
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_priv_qos_cfg(priv, action, pdata)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			if (action == MLAN_ACT_GET)
+				len = sizeof(t_u8);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_MAC_CTRL,
+				    strlen(PRIV_CMD_MAC_CTRL)) == 0) {
+			/* MAC CTRL */
+			len = woal_priv_macctrl(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GETWAP,
+				    strlen(PRIV_CMD_GETWAP)) == 0) {
+			/* Get WAP */
+			len = woal_priv_getwap(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_REGION_CODE,
+				    strlen(PRIV_CMD_REGION_CODE)) == 0) {
+			/* Region Code */
+			len = woal_priv_region_code(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_FWMACADDR,
+				    strlen(PRIV_CMD_FWMACADDR)) == 0) {
+			/* Set FW MAC address */
+			len = woal_priv_fwmacaddr(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_OFFCHANNEL,
+				    strlen(PRIV_CMD_OFFCHANNEL)) == 0) {
+			if (IS_STA_CFG80211(cfg80211_wext)) {
+				/* Set offchannel */
+				len = woal_priv_offchannel(priv, buf,
+							   priv_cmd.total_len);
+			} else
+				len = sprintf(buf,
+					      "CFG80211 is not enabled\n") + 1;
+			goto handled;
+#endif
+#endif
+
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DSCP_MAP,
+				    strlen(PRIV_CMD_DSCP_MAP)) == 0) {
+			/* Set/Get DSCP Map */
+			len = woal_priv_set_get_dscp_map(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_VEREXT,
+				    strlen(PRIV_CMD_VEREXT)) == 0) {
+			/* Get Extended version */
+			len = woal_priv_get_driver_verext(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+#ifdef USB
+#ifdef CONFIG_USB_SUSPEND
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_USB_SUSPEND,
+				    strlen(PRIV_CMD_USB_SUSPEND)) == 0) {
+			/* Makes USB device to suspend */
+			len = woal_priv_enter_usb_suspend(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_USB_RESUME,
+				    strlen(PRIV_CMD_USB_RESUME)) == 0) {
+			/* Makes USB device to resume */
+			len = woal_priv_exit_usb_suspend(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#endif /* CONFIG_USB_SUSPEND */
+#endif
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_RADIO_CTRL,
+				    strlen(PRIV_CMD_RADIO_CTRL)) == 0) {
+			/* Set/Get radio */
+			len = woal_priv_radio_ctrl(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_WMM_CFG,
+				    strlen(PRIV_CMD_WMM_CFG)) == 0) {
+			/* Implement WMM enable command */
+			len = woal_priv_wmm_cfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_MIN_BA_THRESH_CFG,
+				    strlen(PRIV_CMD_MIN_BA_THRESH_CFG)) == 0) {
+			/* Implement Minimum BA threshold configuration command
+			 */
+			len = woal_priv_min_ba_threshold_cfg(priv, buf,
+							     priv_cmd.
+							     total_len);
+			goto handled;
+#if defined(STA_SUPPORT)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_11D_CFG,
+				    strlen(PRIV_CMD_11D_CFG)) == 0) {
+			/* Implement 802.11D enable command */
+			len = woal_priv_11d_cfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_11D_CLR_TBL,
+				    strlen(PRIV_CMD_11D_CLR_TBL)) == 0) {
+			/* Implement 802.11D clear chan table command */
+			len = woal_priv_11d_clr_chan_tbl(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#endif
+#ifndef OPCHAN
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_WWS_CFG,
+				    strlen(PRIV_CMD_WWS_CFG)) == 0) {
+			/* Set/Get WWS configuration */
+			len = woal_priv_wws_cfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+#endif
+#if defined(REASSOCIATION)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_REASSOCTRL,
+				    strlen(PRIV_CMD_REASSOCTRL)) == 0) {
+			/* Set/Get reassociation settings */
+			len = woal_priv_set_get_reassoc(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TXBUF_CFG,
+				    strlen(PRIV_CMD_TXBUF_CFG)) == 0) {
+			/* Get Transmit buffer size */
+			len = woal_priv_txbuf_cfg(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AUTH_TYPE,
+				    strlen(PRIV_CMD_AUTH_TYPE)) == 0) {
+			/* Set/Get auth type */
+			len = woal_priv_auth_type(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_POWER_CONS,
+				    strlen(PRIV_CMD_POWER_CONS)) == 0) {
+			/* Set/get user provisioned local power constraint */
+			len = woal_priv_11h_local_pwr_constraint(priv, buf,
+								 priv_cmd.
+								 total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_HT_STREAM_CFG,
+				    strlen(PRIV_CMD_HT_STREAM_CFG)) == 0) {
+			/* Set/get HT stream configurations */
+			len = woal_priv_ht_stream_cfg(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_MIMO_SWITCH,
+				    strlen(PRIV_CMD_MIMO_SWITCH)) == 0) {
+			/* Set mimo switch configurations */
+			len = woal_priv_mimo_switch(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_THERMAL,
+				    strlen(PRIV_CMD_THERMAL)) == 0) {
+			/* Get thermal reading */
+			len = woal_priv_thermal(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_BCN_INTERVAL,
+				    strlen(PRIV_CMD_BCN_INTERVAL)) == 0) {
+			/* Set/Get beacon interval */
+			len = woal_priv_beacon_interval(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+#ifdef STA_SUPPORT
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_SIGNALEXT_CFG,
+				    strlen(PRIV_CMD_SIGNALEXT_CFG)) == 0) {
+			/* Set signalext flag */
+			len = woal_priv_signalext_cfg(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GET_SIGNAL_EXT_V2,
+				    strlen(PRIV_CMD_GET_SIGNAL_EXT_V2)) == 0) {
+			/* Get signal info */
+			len = woal_priv_get_signal_ext_v2(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GET_SIGNAL_EXT,
+				    strlen(PRIV_CMD_GET_SIGNAL_EXT)) == 0) {
+			/* Get signal info */
+			len = woal_priv_get_signal_ext(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GET_SIGNAL,
+				    strlen(PRIV_CMD_GET_SIGNAL)) == 0) {
+			/* Get signal */
+			len = woal_priv_get_signal(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+#endif
+#if defined(STA_SUPPORT)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PMFCFG,
+				    strlen(PRIV_CMD_PMFCFG)) == 0) {
+			/* Configure PMF */
+			len = woal_priv_set_get_pmfcfg(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_INACTIVITYTO,
+				    strlen(PRIV_CMD_INACTIVITYTO)) == 0) {
+			/* Get/Set inactivity timeout extend */
+			len = woal_priv_inactivity_timeout_ext(priv, buf,
+							       priv_cmd.
+							       total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_AMSDU_AGGR_CTRL,
+				    strlen(PRIV_CMD_AMSDU_AGGR_CTRL)) == 0) {
+			/* Enable/Disable amsdu_aggr_ctrl */
+			len = woal_priv_11n_amsdu_aggr_ctrl(priv, buf,
+							    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TX_BF_CAP,
+				    strlen(PRIV_CMD_TX_BF_CAP)) == 0) {
+			/* Set/Get Transmit beamforming capabilities */
+			len = woal_priv_tx_bf_cap_ioctl(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_SLEEP_PARAMS,
+				    strlen(PRIV_CMD_SLEEP_PARAMS)) == 0) {
+			/* Configure sleep parameters */
+			len = woal_priv_sleep_params_ioctl(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DFS_TESTING,
+				    strlen(PRIV_CMD_DFS_TESTING)) == 0) {
+			/* Set/Get DFS Testing settings */
+			len = woal_priv_dfs_testing(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DFS53_CFG,
+				    strlen(PRIV_CMD_DFS53_CFG)) == 0) {
+			/* Set/Get DFS W53 settings */
+			len = woal_priv_dfs53cfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ARB_CFG,
+				    strlen(PRIV_CMD_ARB_CFG)) == 0) {
+			/* Set/Get CFP table codes */
+			len = woal_priv_arbcfg(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CFP_CODE,
+				    strlen(PRIV_CMD_CFP_CODE)) == 0) {
+			/* Set/Get CFP table codes */
+			len = woal_priv_cfp_code(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CWMODE,
+				    strlen(PRIV_CMD_CWMODE)) == 0) {
+			/* Set/Get Tx CWMode */
+			len = woal_priv_set_get_cwmode(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ANT_CFG,
+				    strlen(PRIV_CMD_ANT_CFG)) == 0) {
+			/* Set/Get Tx/Rx antenna */
+			len = woal_priv_set_get_tx_rx_ant(priv, buf,
+							  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_SYSCLOCK,
+				    strlen(PRIV_CMD_SYSCLOCK)) == 0) {
+			/* Get/Set system clock */
+			len = woal_priv_sysclock(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GET_KEY,
+				    strlen(PRIV_CMD_GET_KEY)) == 0) {
+			/* Get GTK/PTK */
+			len = woal_priv_get_key(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ASSOCIATE,
+				    strlen(PRIV_CMD_ASSOCIATE)) == 0) {
+			/* Associate to a specific indexed entry in the
+			 * ScanTable */
+			len = woal_priv_associate_ssid_bssid(priv, buf,
+							     priv_cmd.
+							     total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TX_BF_CFG,
+				    strlen(PRIV_CMD_TX_BF_CFG)) == 0) {
+			/* Set/Get Transmit beamforming configuration */
+			len = woal_priv_tx_bf_cfg(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_BOOTSLEEP,
+				    strlen(PRIV_CMD_BOOTSLEEP)) == 0) {
+			len = woal_priv_bootsleep(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PORT_CTRL,
+				    strlen(PRIV_CMD_PORT_CTRL)) == 0) {
+			/* Set/Get Port Control mode */
+			len = woal_priv_port_ctrl(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PB_BYPASS,
+				    strlen(PRIV_CMD_PB_BYPASS)) == 0) {
+			/* Private IOCTL entry to get the By-passed TX packet
+			 * from upper layer */
+			len = woal_priv_bypassed_packet(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(UAP_CFG80211)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CFG_NOA,
+				    strlen(PRIV_CMD_CFG_NOA)) == 0) {
+			/* Set/Get P2P NoA (Notice of Absence) parameters */
+			len = woal_priv_cfg_noa(priv, buf, priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CFG_OPP_PS,
+				    strlen(PRIV_CMD_CFG_OPP_PS)) == 0) {
+			/* Set/Get P2P OPP-PS parameters */
+			len = woal_priv_cfg_opp_ps(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+#endif
+#endif
+		} else if (strnicmp
+			   (buf + strlen(CMD_NXP), PRIV_CMD_CFG_CLOCK_SYNC,
+			    strlen(PRIV_CMD_CFG_CLOCK_SYNC)) == 0) {
+			/* Set/Get P2P NoA (Notice of Absence) parameters */
+			len = woal_priv_cfg_clock_sync(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_NXP), PRIV_CMD_CFG_GET_TSF_INFO,
+			    strlen(PRIV_CMD_CFG_GET_TSF_INFO)) == 0) {
+			/* Get TSF info */
+			len = woal_priv_cfg_get_tsf_info(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp
+			   (buf + strlen(CMD_NXP), PRIV_CMD_TRANSITION_CHANNEL,
+			    strlen(PRIV_CMD_TRANSITION_CHANNEL)) == 0) {
+			/* Get/Set Transition channel */
+			len = woal_priv_transition_channel(priv, buf,
+							   priv_cmd.total_len);
+			goto handled;
+
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_DFS_REPEATER_CFG,
+				    strlen(PRIV_CMD_DFS_REPEATER_CFG)) == 0) {
+			/* Set/Get DFS_REPEATER mode */
+			len = woal_priv_dfs_repeater_cfg(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_MIRACAST_CFG,
+				    strlen(PRIV_CMD_MIRACAST_CFG)) == 0) {
+			/* Set/Get MIRACAST configuration parameters */
+			len = woal_priv_miracast_cfg(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+#endif
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_COEX_RX_WINSIZE,
+				    strlen(PRIV_CMD_COEX_RX_WINSIZE)) == 0) {
+			/* Set/Get control to coex RX window size */
+			len = woal_priv_coex_rx_winsize(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_TX_AGGR_CTRL,
+				    strlen(PRIV_CMD_TX_AGGR_CTRL)) == 0) {
+			/* Set/Get control to TX AMPDU on infra link */
+			len = woal_priv_txaggrctrl(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AUTO_TDLS,
+				    strlen(PRIV_CMD_AUTO_TDLS)) == 0) {
+			/* Set/Get control to enable/disable auto TDLS */
+			len = woal_priv_auto_tdls(priv, buf,
+						  priv_cmd.total_len);
+			goto handled;
+#ifdef PCIE
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PCIE_REG_RW,
+				    strlen(PRIV_CMD_PCIE_REG_RW)) == 0) {
+			/* Read/Write PCIE register */
+			len = woal_priv_pcie_reg_rw(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_PCIE_BAR0_REG_RW,
+				    strlen(PRIV_CMD_PCIE_BAR0_REG_RW)) == 0) {
+			/* Read/Write PCIE register/memory from BAR0 */
+			len = woal_priv_pcie_bar0_reg_rw(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_TDLS_IDLE_TIME,
+				    strlen(PRIV_CMD_TDLS_IDLE_TIME)) == 0) {
+			/* Set/Get TDLS idle timeout value */
+			len = woal_priv_tdls_idle_time(priv, buf,
+						       priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GET_SENSOR_TEMP,
+				    strlen(PRIV_CMD_GET_SENSOR_TEMP)) == 0) {
+			/* Get SOC temperature */
+			len = woal_priv_get_sensor_temp(priv, buf,
+							priv_cmd.total_len);
+			goto handled;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DFS_OFFLOAD,
+				    strlen(PRIV_CMD_DFS_OFFLOAD)) == 0) {
+			/* Enable/disable DFS offload */
+			if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
+				len = woal_priv_dfs_offload_enable(priv, buf,
+								   priv_cmd.
+								   total_len);
+			else
+				len = sprintf(buf,
+					      "CFG80211 is not enabled\n") + 1;
+			goto handled;
+#endif
+#endif
+#if defined(UAP_SUPPORT)
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_EXTEND_CHAN_SWITCH,
+				    strlen(PRIV_CMD_EXTEND_CHAN_SWITCH)) == 0) {
+			/* Extended channel switch */
+			len = woal_priv_extend_channel_switch(priv, buf,
+							      priv_cmd.
+							      total_len);
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DYN_BW,
+				    strlen(PRIV_CMD_DYN_BW)) == 0) {
+			/* Set/Get dynamic bandwidth */
+			len = woal_priv_config_dyn_bw(priv, buf,
+						      priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_IND_RST_CFG,
+				    strlen(PRIV_CMD_IND_RST_CFG)) == 0) {
+			/* Set/Get out band independent reset */
+			len = woal_priv_ind_rst_cfg(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_PER_PKT_CFG,
+				    strlen(PRIV_CMD_PER_PKT_CFG)) == 0) {
+			/* Get/Set per packet Txctl and Rxinfo configuration */
+			len = woal_priv_per_pkt_cfg(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DEAUTH_CTRL,
+				    strlen(PRIV_CMD_DEAUTH_CTRL)) == 0) {
+			len = woal_priv_deauth_ctrl(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_11AXCFG,
+				    strlen(PRIV_CMD_11AXCFG)) == 0) {
+			pdata = buf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_11AXCFG);
+			len = priv_cmd.used_len - strlen(PRIV_CMD_11AXCFG) -
+				strlen(CMD_NXP);
+			len = woal_priv_11axcfg_cmd(priv, pdata, len,
+						    priv_cmd.total_len);
+			len += strlen(PRIV_CMD_11AXCFG) + strlen(CMD_NXP);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TWT_SETUP,
+				    strlen(PRIV_CMD_TWT_SETUP)) == 0) {
+			pdata = buf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_TWT_SETUP);
+			len = priv_cmd.used_len - strlen(PRIV_CMD_TWT_SETUP) -
+				strlen(CMD_NXP);
+			len = woal_priv_twt_setup(priv, pdata, len,
+						  priv_cmd.total_len);
+			len += strlen(PRIV_CMD_TWT_SETUP) + strlen(CMD_NXP);
+			goto handled;
+
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_TWT_TEARDOWN,
+				    strlen(PRIV_CMD_TWT_TEARDOWN)) == 0) {
+			pdata = buf + strlen(CMD_NXP) +
+				strlen(PRIV_CMD_TWT_TEARDOWN);
+			len = priv_cmd.used_len -
+				strlen(PRIV_CMD_TWT_TEARDOWN) - strlen(CMD_NXP);
+			len = woal_priv_twt_teardown(priv, pdata, len,
+						     priv_cmd.total_len);
+			len += strlen(PRIV_CMD_TWT_TEARDOWN) + strlen(CMD_NXP);
+			goto handled;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_GET_CFG_CHAN_LIST,
+				    strlen(PRIV_CMD_GET_CFG_CHAN_LIST)) == 0) {
+			/* Get txpwrlimit */
+			if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
+				len = woal_priv_getcfgchanlist(priv, buf,
+							       priv_cmd.
+							       total_len);
+			else
+				len = sprintf(buf,
+					      "CFG80211 is not enabled\n") + 1;
+			goto handled;
+#endif
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_LPM,
+				    strlen(PRIV_CMD_LPM)) == 0) {
+			/* Set/Get low power mode */
+			len = woal_priv_set_get_lpm(priv, buf,
+						    priv_cmd.total_len);
+			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TP_STATE,
+				    strlen(PRIV_CMD_TP_STATE)) == 0) {
+			/* Set/Get TP accounting state */
+			len = woal_priv_set_tp_state(priv, buf,
+						     priv_cmd.total_len);
+			goto handled;
+		} else {
+			PRINTM(MERROR,
+			       "Unknown NXP PRIVATE command %s, ignored\n",
+			       buf);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+#ifdef STA_SUPPORT
+	if (strncmp(buf, "RSSILOW-THRESHOLD", strlen("RSSILOW-THRESHOLD")) == 0) {
+		pdata = buf + strlen("RSSILOW-THRESHOLD") + 1;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_rssi_low_threshold(priv, pdata, MOAL_IOCTL_WAIT)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SCAN-CFG", strlen("SCAN-CFG")) == 0) {
+		PRINTM(MIOCTL, "Set SCAN CFG\n");
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_scan_cfg(priv, buf, priv_cmd.total_len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RSSI", strlen("RSSI")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (bss_info.media_connected) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_get_signal_info(priv, MOAL_IOCTL_WAIT,
+						 &signal)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "%.32s rssi %d\n",
+				      bss_info.ssid.ssid, signal.bcn_rssi_avg) +
+				1;
+		} else {
+			len = sprintf(buf, "OK\n") + 1;
+		}
+	} else if (strncmp(buf, "LINKSPEED", strlen("LINKSPEED")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_data_rate(priv, MLAN_ACT_GET, &rate)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		PRINTM(MIOCTL, "tx rate=%d\n", (int)rate.rate);
+		len = sprintf(buf, "LinkSpeed %d\n",
+			      (int)(rate.rate * 500000 / 1000000)) + 1;
+	} else
+#endif
+	if (strncmp(buf, "MACADDR", strlen("MACADDR")) == 0) {
+		len = sprintf(buf, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+			      priv->current_addr[0], priv->current_addr[1],
+			      priv->current_addr[2], priv->current_addr[3],
+			      priv->current_addr[4], priv->current_addr[5]) + 1;
+	}
+#ifdef STA_SUPPORT
+	else if (strncmp(buf, "GETPOWER", strlen("GETPOWER")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_powermode(priv, &power_mode)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "powermode = %d\n", power_mode) + 1;
+	} else if (strncmp(buf, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->scan_type = MLAN_SCAN_TYPE_ACTIVE;
+		PRINTM(MIOCTL, "Set Active Scan\n");
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->scan_type = MLAN_SCAN_TYPE_PASSIVE;
+		PRINTM(MIOCTL, "Set Passive Scan\n");
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "POWERMODE", strlen("POWERMODE")) == 0) {
+		pdata = buf + strlen("POWERMODE") + 1;
+		if (!moal_extflg_isset(priv->phandle, EXT_HW_TEST)) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_powermode(priv, pdata)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SETROAMING", strlen("SETROAMING")) == 0) {
+		pdata = buf + strlen("SETROAMING") + 1;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+			goto done;
+#endif
+#endif
+#ifdef STA_CFG80211
+		if (*pdata == '1') {
+			priv->roaming_enabled = MTRUE;
+			PRINTM(MIOCTL, "Roaming enabled\n");
+		} else if (*pdata == '0') {
+			priv->roaming_enabled = MFALSE;
+			PRINTM(MIOCTL, "Roaming disabled\n");
+		}
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "ROAM", strlen("ROAM")) == 0) {
+		pdata = buf + strlen("ROAM") + 1;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+			goto done;
+#endif
+#endif
+#ifdef STA_CFG80211
+		if (*pdata == '1') {
+			priv->roaming_enabled = MTRUE;
+			PRINTM(MIOCTL, "Roaming enabled\n");
+		} else if (*pdata == '0') {
+			priv->roaming_enabled = MFALSE;
+			PRINTM(MIOCTL, "Roaming disabled\n");
+		}
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "COUNTRY", strlen("COUNTRY")) == 0) {
+		copy_len = strlen(buf) - strlen("COUNTRY") - 1;
+		if (copy_len > COUNTRY_CODE_LEN || copy_len <= 0) {
+			PRINTM(MERROR, "Invalid country length\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		memset(country_code, 0, sizeof(country_code));
+		moal_memcpy_ext(priv->phandle, country_code,
+				buf + strlen("COUNTRY") + 1, copy_len,
+				COUNTRY_CODE_LEN);
+		PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code);
+		if (priv->phandle->params.cntry_txpwr) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_request_country_power_table(priv,
+							     country_code)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			PRINTM(MIOCTL, "Notify country code=%s\n",
+			       country_code);
+			if (!moal_extflg_isset(priv->phandle,
+					       EXT_DISABLE_REGD_BY_DRIVER))
+				regulatory_hint(priv->wdev->wiphy,
+						country_code);
+			len = sprintf(buf, "OK\n") + 1;
+			goto done;
+		}
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_region_code(priv, country_code)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (memcmp(buf, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == 0) {
+		PRINTM(MIOCTL, "Set Combo Scan\n");
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_combo_scan(priv, buf, priv_cmd.total_len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "GETBAND", strlen("GETBAND")) == 0) {
+		if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "Band %d\n", band) + 1;
+	} else if (strncmp(buf, "SETBAND", strlen("SETBAND")) == 0) {
+		pband = buf + strlen("SETBAND") + 1;
+		if (MLAN_STATUS_SUCCESS != woal_set_band(priv, pband)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#endif
+	else if (strncmp(buf, "START", strlen("START")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "STOP", strlen("STOP")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#ifdef UAP_SUPPORT
+	else if (strncmp(buf, "AP_BSS_START", strlen("AP_BSS_START")) == 0) {
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
+		if (ret)
+			goto done;
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+		if (ret)
+			goto done;
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "AP_SET_CFG", strlen("AP_SET_CFG")) == 0) {
+		if (priv_cmd.total_len <= (int)strlen("AP_SET_CFG") + 1)
+			goto done;
+		pdata = buf + strlen("AP_SET_CFG") + 1;
+		ret = woal_uap_set_ap_cfg(priv, pdata,
+					  priv_cmd.total_len -
+					  strlen("AP_SET_CFG") - 1);
+		if (ret)
+			goto done;
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "WL_FW_RELOAD", strlen("WL_FW_RELOAD")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "AP_GET_STA_LIST", strlen("AP_GET_STA_LIST")) ==
+		   0) {
+		/* TODO Add STA list support */
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#endif
+	else if (strncmp(buf, "SETSUSPENDOPT", strlen("SETSUSPENDOPT")) == 0) {
+		/* it will be done by GUI */
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SETSUSPENDMODE", strlen("SETSUSPENDMODE")) ==
+		   0) {
+		/* it will be done by GUI */
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BTCOEXSCAN-START",
+			   strlen("BTCOEXSCAN-START")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BTCOEXSCAN-STOP", strlen("BTCOEXSCAN-STOP")) ==
+		   0) {
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#ifdef STA_SUPPORT
+	else if (strncmp(buf, "BGSCAN-START", strlen("BGSCAN-START")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BGSCAN-CONFIG", strlen("BGSCAN-CONFIG")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_bg_scan(priv, buf, priv_cmd.total_len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->bg_scan_start = MTRUE;
+		priv->bg_scan_reported = MFALSE;
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) {
+		if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_stop_bg_scan(priv, MOAL_NO_WAIT)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			priv->bg_scan_start = MFALSE;
+			priv->bg_scan_reported = MFALSE;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RXFILTER-START", strlen("RXFILTER-START")) ==
+		   0) {
+#ifdef MEF_CFG_RX_FILTER
+		ret = woal_set_rxfilter(priv, MTRUE);
+		if (ret)
+			goto done;
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RXFILTER-STOP", strlen("RXFILTER-STOP")) == 0) {
+#ifdef MEF_CFG_RX_FILTER
+		ret = woal_set_rxfilter(priv, MFALSE);
+		if (ret)
+			goto done;
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#ifdef STA_CFG80211
+	else if (strncmp(buf, "GET_EVENT", strlen("GET_EVENT")) == 0) {
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			if (priv->last_event & EVENT_BG_SCAN_REPORT)
+				woal_inform_bss_from_scan_result(priv, NULL,
+								 MOAL_IOCTL_WAIT);
+		}
+		len = sprintf(buf, "EVENT=%d\n", priv->last_event) + 1;
+		priv->last_event = 0;
+	} else if (strncmp(buf, "GET_802_11W", strlen("GET_802_11W")) == 0) {
+		len = sprintf(buf, "802_11W=ENABLED\n") + 1;
+	}
+#endif /* STA_CFG80211 */
+	else if (strncmp(buf, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) {
+		pdata = buf + strlen("RXFILTER-ADD") + 1;
+		if (MLAN_STATUS_SUCCESS != woal_add_rxfilter(priv, pdata)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) ==
+		   0) {
+		pdata = buf + strlen("RXFILTER-REMOVE") + 1;
+		if (MLAN_STATUS_SUCCESS != woal_remove_rxfilter(priv, pdata)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "QOSINFO", strlen("QOSINFO")) == 0) {
+		pdata = buf + strlen("QOSINFO") + 1;
+#ifdef STA_SUPPORT
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_priv_qos_cfg(priv, MLAN_ACT_SET, pdata)) {
+			ret = -EFAULT;
+			goto done;
+		}
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SLEEPPD", strlen("SLEEPPD")) == 0) {
+		pdata = buf + strlen("SLEEPPD") + 1;
+		if (MLAN_STATUS_SUCCESS != woal_set_sleeppd(priv, pdata)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SET_AP_WPS_P2P_IE",
+			   strlen("SET_AP_WPS_P2P_IE")) == 0) {
+		pdata = buf + strlen("SET_AP_WPS_P2P_IE") + 1;
+		/* Android cmd format:
+		 * "SET_AP_WPS_P2P_IE 1"  -- beacon IE
+		 * "SET_AP_WPS_P2P_IE 2"  -- proberesp IE
+		 * "SET_AP_WPS_P2P_IE 4"  -- assocresp IE
+		 */
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_ap_wps_p2p_ie(priv, (t_u8 *)pdata,
+					   priv_cmd.used_len -
+					   strlen("SET_AP_WPS_P2P_IE") - 1)) {
+			ret = -EFAULT;
+			goto done;
+		}
+#endif
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#endif
+	else if (strncmp(buf, "P2P_DEV_ADDR", strlen("P2P_DEV_ADDR")) == 0) {
+		memset(buf, 0x0, (size_t) priv_cmd.total_len);
+		moal_memcpy_ext(priv->phandle, buf, priv->current_addr,
+				ETH_ALEN, (t_u32)priv_cmd.total_len);
+		len = ETH_ALEN;
+	} else if (strncmp(buf, ("P2P_GET_NOA"), strlen("P2P_GET_NOA")) == 0) {
+		/* TODO
+		 * Just return '\0'
+		 */
+		memset(buf, 0x0, (size_t) priv_cmd.total_len);
+		*buf = 0;
+		len = 1;
+	} else if (strnicmp(buf, "MIRACAST", strlen("MIRACAST")) == 0) {
+		pdata = buf + strlen("MIRACAST");
+		/* Android cmd format:
+		 * "MIRACAST 0"  -- disabled
+		 * "MIRACAST 1"  -- operating as source
+		 * "MIRACAST 2"  -- operating as sink
+		 */
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_miracast_mode(priv, (t_u8 *)pdata,
+					   priv_cmd.used_len -
+					   strlen("MIRACAST"))) {
+			ret = -EFAULT;
+			goto done;
+		}
+#endif
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strnicmp(buf, "SCAN_TIMING", strlen("SCAN_TIMING")) == 0) {
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_scan_chan_gap(priv, buf, priv_cmd.total_len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+#endif
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strnicmp(buf, "BA_WSIZE_RX", strlen("BA_WSIZE_RX")) == 0) {
+		pdata = buf + strlen("BA_WSIZE_RX") + 1;
+		len = priv_cmd.total_len - strlen("BA_WSIZE_RX") - 1;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_rx_ba_winsize(priv, pdata, len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strnicmp(buf, "BA_WSIZE_TX", strlen("BA_WSIZE_TX")) == 0) {
+		pdata = buf + strlen("BA_WSIZE_TX") + 1;
+		len = priv_cmd.total_len - strlen("BA_WSIZE_TX") - 1;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_tx_ba_winsize(priv, pdata, len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "FAKE_SCAN_COMPLETE",
+			   strlen("FAKE_SCAN_COMPLETE")) == 0) {
+		pdata = buf + strlen("FAKE_SCAN_COMPLETE") + 1;
+#ifdef STA_CFG80211
+		if (*pdata == '1') {
+			priv->fake_scan_complete = MTRUE;
+			PRINTM(MIOCTL, "fake scan complete enabled\n");
+		} else if (*pdata == '0') {
+			priv->fake_scan_complete = MFALSE;
+			PRINTM(MIOCTL, "fake scan complete disabled\n");
+		}
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#ifdef WIFI_DIRECT_SUPPORT
+	else if (strncmp(buf, "P2P_PERIODIC_SLEEP",
+			 strlen("P2P_PERIODIC_SLEEP")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_p2p_ps_cfg(priv, buf, priv_cmd.total_len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	}
+#endif
+#endif
+	else if (strncmp(buf, "WLS_BATCHING", strlen("WLS_BATCHING")) == 0) {
+		/* TODO */
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "TDLS_CS_CHAN", strlen("TDLS_CS_CHAN")) == 0) {
+		len = woal_priv_tdls_cs_chan(priv, buf, priv_cmd.total_len);
+	}
+#if defined(UAP_SUPPORT)
+	else if (strncmp(buf, "P2P_ECSA", strlen("P2P_ECSA")) == 0) {
+		len = woal_priv_p2p_ecsa(priv, buf, priv_cmd.total_len);
+	}
+#endif
+	else if (strncmp(buf, "FAKEMAC", strlen("FAKEMAC")) == 0) {
+		len = woal_priv_config_random_mac(priv, buf,
+						  priv_cmd.total_len);
+	} else if (strncmp(buf, PRIV_CMD_CLOUD_KEEP_ALIVE,
+			   strlen(PRIV_CMD_CLOUD_KEEP_ALIVE)) == 0) {
+		len = woal_priv_cloud_keep_alive(priv, buf, priv_cmd.total_len);
+	} else if (strnicmp(buf, PRIV_CMD_TX_RX_HISTOGRAM,
+			    strlen(PRIV_CMD_TX_RX_HISTOGRAM)) == 0) {
+		/* Get TX/RX histogram statistic */
+		len = woal_priv_get_rx_tx_histogram(priv, buf,
+						    priv_cmd.total_len);
+		goto handled;
+	} else if (strnicmp(buf, PRIV_CMD_GET_CHNRGPWR,
+			    strlen(PRIV_CMD_GET_CHNRGPWR)) == 0) {
+		/* Get chnrgpwr */
+		len = woal_priv_get_chnrgpwr(priv, buf, priv_cmd.total_len);
+		goto handled;
+	} else if (strnicmp(buf, PRIV_CMD_GET_TXPWR_LIMIT,
+			    strlen(PRIV_CMD_GET_TXPWR_LIMIT)) == 0) {
+		/* Get txpwrlimit */
+		len = woal_priv_get_txpwrlimit(priv, buf, priv_cmd.total_len);
+		goto handled;
+	} else {
+		PRINTM(MIOCTL, "Unknown PRIVATE command: %s, ignored\n", buf);
+		ret = -EFAULT;
+		goto done;
+	}
+
+handled:
+	PRINTM(MIOCTL, "PRIV Command return: %s, length=%d\n", buf, len);
+
+	if (len > 0) {
+		priv_cmd.used_len = len;
+		if (priv_cmd.used_len <= priv_cmd.total_len) {
+			memset(buf + priv_cmd.used_len, 0,
+			       (size_t) (CMD_BUF_LEN - priv_cmd.used_len));
+			if (copy_to_user((void __user *)cmd_buf, buf,
+					 priv_cmd.total_len)) {
+				PRINTM(MERROR,
+				       "%s: failed to copy data to user buffer\n",
+				       __FUNCTION__);
+				ret = -EFAULT;
+				goto done;
+			}
+			if (copy_to_user(req->ifr_data, &priv_cmd,
+					 sizeof(android_wifi_priv_cmd))) {
+				PRINTM(MERROR,
+				       "%s: failed to copy command header to user buffer\n",
+				       __FUNCTION__);
+				ret = -EFAULT;
+			}
+		} else {
+			PRINTM(MERROR,
+			       "%s: the buffer supplied by appl is too small (supplied: %d, used: %d)\n",
+			       __FUNCTION__, priv_cmd.total_len,
+			       priv_cmd.used_len);
+			ret = -EFAULT;
+		}
+	} else {
+		ret = len;
+	}
+
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *  @brief Create a brief scan resp to relay basic BSS info to the app layer
+ *
+ *  When the beacon/probe response has not been buffered, use the saved BSS
+ *    information available to provide a minimum response for the application
+ *    ioctl retrieval routines.  Include:
+ *        - Timestamp
+ *        - Beacon Period
+ *        - Capabilities (including WMM Element if available)
+ *        - SSID
+ *
+ *  @param ppbuffer  Output parameter: Buffer used to create basic scan rsp
+ *  @param pbss_desc Pointer to a BSS entry in the scan table to create
+ *                   scan response from for delivery to the application layer
+ *
+ *  @return          N/A
+ */
+void
+wlan_scan_create_brief_table_entry(t_u8 **ppbuffer, BSSDescriptor_t *pbss_desc)
+{
+	t_u8 *ptmp_buf = *ppbuffer;
+	t_u8 tmp_ssid_hdr[2];
+	t_u8 ie_len = 0;
+
+	ENTER();
+
+	moal_memcpy_ext(NULL, ptmp_buf, pbss_desc->time_stamp,
+			sizeof(pbss_desc->time_stamp),
+			sizeof(pbss_desc->time_stamp));
+	ptmp_buf += sizeof(pbss_desc->time_stamp);
+
+	moal_memcpy_ext(NULL, ptmp_buf, &pbss_desc->beacon_period,
+			sizeof(pbss_desc->beacon_period),
+			sizeof(pbss_desc->beacon_period));
+	ptmp_buf += sizeof(pbss_desc->beacon_period);
+
+	moal_memcpy_ext(NULL, ptmp_buf, &pbss_desc->cap_info,
+			sizeof(pbss_desc->cap_info),
+			sizeof(pbss_desc->cap_info));
+	ptmp_buf += sizeof(pbss_desc->cap_info);
+
+	tmp_ssid_hdr[0] = 0;	/* Element ID for SSID is zero */
+	tmp_ssid_hdr[1] = pbss_desc->ssid.ssid_len;
+	moal_memcpy_ext(NULL, ptmp_buf, tmp_ssid_hdr, sizeof(tmp_ssid_hdr),
+			sizeof(tmp_ssid_hdr));
+	ptmp_buf += sizeof(tmp_ssid_hdr);
+
+	moal_memcpy_ext(NULL, ptmp_buf, pbss_desc->ssid.ssid,
+			pbss_desc->ssid.ssid_len, pbss_desc->ssid.ssid_len);
+	ptmp_buf += pbss_desc->ssid.ssid_len;
+
+	if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE) {
+		ie_len = sizeof(IEEEtypes_Header_t) +
+			pbss_desc->wmm_ie.vend_hdr.len;
+		moal_memcpy_ext(NULL, ptmp_buf, &pbss_desc->wmm_ie, ie_len,
+				ie_len);
+		ptmp_buf += ie_len;
+	}
+
+	if (pbss_desc->pwpa_ie) {
+		if ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE) {
+			ie_len = sizeof(IEEEtypes_Header_t) +
+				(*(pbss_desc->pwpa_ie)).vend_hdr.len;
+			moal_memcpy_ext(NULL, ptmp_buf, pbss_desc->pwpa_ie,
+					ie_len, ie_len);
+		}
+
+		ptmp_buf += ie_len;
+	}
+	if (pbss_desc->prsn_ie) {
+		if ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE) {
+			ie_len = sizeof(IEEEtypes_Header_t) +
+				(*(pbss_desc->prsn_ie)).ieee_hdr.len;
+			moal_memcpy_ext(NULL, ptmp_buf, pbss_desc->prsn_ie,
+					ie_len, ie_len);
+		}
+
+		ptmp_buf += ie_len;
+	}
+	*ppbuffer = ptmp_buf;
+	LEAVE();
+}
+
+/**
+ *  @brief Create a wlan_ioctl_get_scan_table_entry for a given BSS
+ *         Descriptor for inclusion in the ioctl response to the user space
+ *         application.
+ *
+ *
+ *  @param pbss_desc   Pointer to a BSS entry in the scan table to form
+ *                     scan response from for delivery to the application layer
+ *  @param ppbuffer    Output parameter: Buffer used to output scan return
+ * struct
+ *  @param pspace_left Output parameter: Number of bytes available in the
+ *                     response buffer.
+ *
+ *  @return MLAN_STATUS_SUCCESS, or < 0 with IOCTL error code
+ */
+int
+wlan_get_scan_table_ret_entry(BSSDescriptor_t *pbss_desc, t_u8 **ppbuffer,
+			      int *pspace_left)
+{
+	wlan_ioctl_get_scan_table_entry *prsp_entry;
+	wlan_ioctl_get_scan_table_entry tmp_rsp_entry;
+	int space_needed;
+	t_u8 *pcurrent;
+	int variable_size;
+
+	const int fixed_size = sizeof(wlan_ioctl_get_scan_table_entry);
+
+	ENTER();
+
+	pcurrent = *ppbuffer;
+
+	/* The variable size returned is the stored beacon size */
+	variable_size = pbss_desc->beacon_buf_size;
+
+	/* If we stored a beacon and its size was zero, set the variable
+	 *  size return value to the size of the brief scan response
+	 *  wlan_scan_create_brief_table_entry creates.  Also used if
+	 *  we are not configured to store beacons in the first place
+	 */
+	if (!variable_size) {
+		variable_size = pbss_desc->ssid.ssid_len + 2;
+		variable_size += (sizeof(pbss_desc->beacon_period) +
+				  sizeof(pbss_desc->time_stamp) +
+				  sizeof(pbss_desc->cap_info));
+		if (pbss_desc->wmm_ie.vend_hdr.element_id == WMM_IE) {
+			variable_size += (sizeof(IEEEtypes_Header_t) +
+					  pbss_desc->wmm_ie.vend_hdr.len);
+		}
+
+		if (pbss_desc->pwpa_ie) {
+			if ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
+			    WPA_IE) {
+				variable_size +=
+					(sizeof(IEEEtypes_Header_t) +
+					 (*(pbss_desc->pwpa_ie)).vend_hdr.len);
+			}
+		}
+
+		if (pbss_desc->prsn_ie) {
+			if ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
+			    RSN_IE) {
+				variable_size +=
+					(sizeof(IEEEtypes_Header_t) +
+					 (*(pbss_desc->prsn_ie)).ieee_hdr.len);
+			}
+		}
+	}
+
+	space_needed = fixed_size + variable_size;
+
+	PRINTM(MINFO, "GetScanTable: need(%d), left(%d)\n", space_needed,
+	       *pspace_left);
+
+	if (space_needed >= *pspace_left) {
+		*pspace_left = 0;
+		LEAVE();
+		return -E2BIG;
+	}
+
+	*pspace_left -= space_needed;
+
+	tmp_rsp_entry.fixed_field_length =
+		(sizeof(tmp_rsp_entry) -
+		 sizeof(tmp_rsp_entry.fixed_field_length) -
+		 sizeof(tmp_rsp_entry.bss_info_length));
+
+	moal_memcpy_ext(NULL, tmp_rsp_entry.fixed_fields.bssid,
+			pbss_desc->mac_address,
+			sizeof(prsp_entry->fixed_fields.bssid),
+			sizeof(prsp_entry->fixed_fields.bssid));
+
+	tmp_rsp_entry.fixed_fields.rssi = pbss_desc->rssi;
+	tmp_rsp_entry.fixed_fields.channel = pbss_desc->channel;
+	tmp_rsp_entry.fixed_fields.chan_load = pbss_desc->chan_load;
+	tmp_rsp_entry.fixed_fields.network_tsf = pbss_desc->network_tsf;
+	tmp_rsp_entry.bss_info_length = variable_size;
+
+	/*
+	 *  Copy fixed fields to user space
+	 */
+	moal_memcpy_ext(NULL, pcurrent, &tmp_rsp_entry, fixed_size, fixed_size);
+	pcurrent += fixed_size;
+
+	if (pbss_desc->pbeacon_buf) {
+		/*
+		 *  Copy variable length elements to user space
+		 */
+		moal_memcpy_ext(NULL, pcurrent, pbss_desc->pbeacon_buf,
+				pbss_desc->beacon_buf_size,
+				pbss_desc->beacon_buf_size);
+
+		pcurrent += pbss_desc->beacon_buf_size;
+	} else {
+		wlan_scan_create_brief_table_entry(&pcurrent, pbss_desc);
+	}
+
+	*ppbuffer = pcurrent;
+
+	LEAVE();
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief ioctl function - entry point
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @param cmd      Command
+ *
+ *  @return          0 --success, otherwise fail
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+int
+woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user * data,
+	      int cmd)
+#else
+int
+woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+#endif
+{
+	int ret = 0;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+	if (in_compat_syscall())	/* not implemented yet */
+		return -EOPNOTSUPP;
+#endif
+
+	PRINTM(MINFO, "woal_do_ioctl: ioctl cmd = 0x%x\n", cmd);
+	switch (cmd) {
+	case WOAL_ANDROID_DEF_CMD:
+		/** android default ioctl ID is SIOCDEVPRIVATE + 1 */
+		ret = woal_android_priv_cmd(dev, req);
+		break;
+	case WOAL_CUSTOM_IE_CFG:
+		ret = woal_custom_ie_ioctl(dev, req);
+		break;
+	case WOAL_MGMT_FRAME_TX:
+		ret = woal_send_host_packet(dev, req);
+		break;
+	case WOAL_TDLS_CONFIG:
+		ret = woal_tdls_config_ioctl(dev, req);
+		break;
+	case WOAL_ANDROID_PRIV_CMD:
+		ret = woal_android_priv_cmd(dev, req);
+		break;
+	case WOAL_GET_BSS_TYPE:
+		ret = woal_get_bss_type(dev, req);
+		break;
+	default:
+#if defined(STA_WEXT)
+#ifdef STA_SUPPORT
+		ret = woal_wext_do_ioctl(dev, req, cmd);
+#else
+		ret = -EINVAL;
+#endif
+#else
+		ret = -EINVAL;
+#endif
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlinux/moal_eth_ioctl.h b/wlan_sd8987/mlinux/moal_eth_ioctl.h
new file mode 100755
index 0000000..ca5a5a2
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_eth_ioctl.h
@@ -0,0 +1,693 @@
+
+/** @file moal_eth_ioctl.h
+ *
+ * @brief This file contains definition for private IOCTL call.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    01/05/2012: initial version
+********************************************************/
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#endif
+
+#ifndef _WOAL_ETH_PRIV_H_
+#define _WOAL_ETH_PRIV_H_
+
+/** Command disabled */
+#define CMD_DISABLED 0
+/** Command enabled */
+#define CMD_ENABLED 1
+/** Command get */
+#define CMD_GET 2
+
+/** 2K bytes */
+#define WOAL_2K_BYTES 2000
+
+/** NXP private command identifier string */
+#define CMD_NXP "MRVL_CMD"
+
+/** Private command: Version */
+#define PRIV_CMD_VERSION "version"
+/** Private command: Band cfg */
+#define PRIV_CMD_BANDCFG "bandcfg"
+/** Private command: Host cmd */
+#define PRIV_CMD_HOSTCMD "hostcmd"
+/** Private command: Custom IE config*/
+#define PRIV_CMD_CUSTOMIE "customie"
+/** Private command: HT Tx Cfg */
+#define PRIV_CMD_HTTXCFG "httxcfg"
+/** Private command: HT Cap Info */
+#define PRIV_CMD_HTCAPINFO "htcapinfo"
+/** Private command: Add BA para */
+#define PRIV_CMD_ADDBAPARA "addbapara"
+/** Private command: Aggragation priority table */
+#define PRIV_CMD_AGGRPRIOTBL "aggrpriotbl"
+/** Private command: Add BA reject cfg */
+#define PRIV_CMD_ADDBAREJECT "addbareject"
+/** Private command: Delete BA */
+#define PRIV_CMD_DELBA "delba"
+/** Private command: Reject Addba Req */
+#define PRIV_CMD_REJECTADDBAREQ "rejectaddbareq"
+/** Private command: 11AC Cfg */
+#define PRIV_CMD_VHTCFG "vhtcfg"
+/** Private command: 11AC Oper Mode Cfg */
+#define PRIV_CMD_OPERMODECFG "opermodecfg"
+#define PRIV_CMD_DATARATE "getdatarate"
+#define PRIV_CMD_TXRATECFG "txratecfg"
+#define PRIV_CMD_GETLOG "getlog"
+#define PRIV_CMD_ESUPPMODE "esuppmode"
+#define PRIV_CMD_PASSPHRASE "passphrase"
+#define PRIV_CMD_DEAUTH "deauth"
+#ifdef UAP_SUPPORT
+#define PRIV_CMD_AP_DEAUTH "apdeauth"
+#define PRIV_CMD_GET_STA_LIST "getstalist"
+#define PRIV_CMD_BSS_CONFIG "bssconfig"
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#define PRIV_CMD_BSSROLE "bssrole"
+#endif
+#endif
+#ifdef STA_SUPPORT
+#define PRIV_CMD_GETSCANTABLE "getscantable"
+#define PRIV_CMD_GETCHANSTATS "getchanstats"
+typedef struct _chan_stats {
+	/** Number of records in the chan_stats */
+	t_u32 num_in_chan_stats;
+	/** channel statistics */
+	ChanStatistics_t stats[];
+} chan_stats;
+#define PRIV_CMD_SETUSERSCAN "setuserscan"
+#define PRIV_CMD_EXTCAPCFG "extcapcfg"
+#define PRIV_CMD_CANCELSCAN "cancelscan"
+#endif
+#define PRIV_CMD_DEEPSLEEP "deepsleep"
+#define PRIV_CMD_IPADDR "ipaddr"
+#define PRIV_CMD_WPSSESSION "wpssession"
+#define PRIV_CMD_OTPUSERDATA "otpuserdata"
+#define PRIV_CMD_COUNTRYCODE "countrycode"
+#define PRIV_CMD_TCPACKENH "tcpackenh"
+#ifdef REASSOCIATION
+#define PRIV_CMD_ASSOCESSID "assocessid"
+#define PRIV_CMD_ASSOCBSSID "assocessid_bssid"
+#endif
+#define PRIV_CMD_WAKEUPREASON "wakeupreason"
+#ifdef STA_SUPPORT
+#define PRIV_CMD_LISTENINTERVAL "listeninterval"
+#endif
+#ifdef DEBUG_LEVEL1
+#define PRIV_CMD_DRVDBG "drvdbg"
+#endif
+#define PRIV_CMD_HSCFG "hscfg"
+#define PRIV_CMD_HSSETPARA "hssetpara"
+#define PRIV_CMD_MGMT_FILTER "mgmtfilter"
+#define PRIV_CMD_SCANCFG "scancfg"
+#define PRIV_CMD_GETNLNUM "getnlnum"
+#define PRIV_CMD_AGGRCTRL "aggrctrl"
+#ifdef USB
+#define PRIV_CMD_USBAGGRCTRL "usbaggrctrl"
+#endif
+#define PRIV_CMD_SET_BSS_MODE "setbssmode"
+#ifdef STA_SUPPORT
+#define PRIV_CMD_SET_AP "setap"
+#define PRIV_CMD_SET_POWER "setpower"
+#define PRIV_CMD_SET_ESSID "setessid"
+#define PRIV_CMD_SET_AUTH "setauth"
+#define PRIV_CMD_GET_AP "getap"
+#define PRIV_CMD_GET_POWER "getpower"
+#define PRIV_CMD_PSMODE "psmode"
+#endif
+#define PRIV_CMD_WARMRESET "warmreset"
+#define PRIV_CMD_TXPOWERCFG "txpowercfg"
+#define PRIV_CMD_PSCFG "pscfg"
+#define PRIV_CMD_BCNTIMEOUTCFG "bcntimeoutcfg"
+#define PRIV_CMD_SLEEPPD "sleeppd"
+#define PRIV_CMD_TXCONTROL "txcontrol"
+#define PRIV_CMD_REGRDWR "regrdwr"
+#define PRIV_CMD_RDEEPROM "rdeeprom"
+#define PRIV_CMD_MEMRDWR "memrdwr"
+#ifdef SDIO
+#define PRIV_CMD_SDCMD52RW "sdcmd52rw"
+#endif
+#define PRIV_CMD_ARPFILTER "arpfilter"
+#define PRIV_CMD_HOTSPOTCFG "hotspotcfg"
+#define PRIV_CMD_MGMT_FRAME_CTRL "mgmtframectrl"
+#define PRIV_CMD_QCONFIG "qconfig"
+#define PRIV_CMD_ADDTS "addts"
+#define PRIV_CMD_DELTS "delts"
+#define PRIV_CMD_QSTATUS "qstatus"
+#define PRIV_CMD_TS_STATUS "ts_status"
+#define PRIV_CMD_QOS_CFG "qoscfg"
+#define PRIV_CMD_MAC_CTRL "macctrl"
+#define PRIV_CMD_GETWAP "getwap"
+#define PRIV_CMD_REGION_CODE "regioncode"
+#define PRIV_CMD_CFPINFO "cfpinfo"
+#define PRIV_CMD_FWMACADDR "fwmacaddr"
+#define PRIV_CMD_OFFCHANNEL "offchannel"
+#define PRIV_CMD_DSCP_MAP "dscpmap"
+/** Private command: Verext */
+#define PRIV_CMD_VEREXT "verext"
+#ifdef CONFIG_USB_SUSPEND
+#define PRIV_CMD_USB_SUSPEND "usbsuspend"
+#define PRIV_CMD_USB_RESUME "usbresume"
+#endif /* CONFIG_USB_SUSPEND */
+#if defined(STA_SUPPORT) && defined(STA_WEXT)
+#define PRIV_CMD_RADIO_CTRL "radioctrl"
+#endif
+#define PRIV_CMD_WMM_CFG "wmmcfg"
+#define PRIV_CMD_MIN_BA_THRESH_CFG "min_ba_threshold"
+#if defined(STA_SUPPORT)
+#define PRIV_CMD_11D_CFG "11dcfg"
+#define PRIV_CMD_11D_CLR_TBL "11dclrtbl"
+#endif
+#ifndef OPCHAN
+#define PRIV_CMD_WWS_CFG "wwscfg"
+#endif
+#if defined(REASSOCIATION)
+#define PRIV_CMD_REASSOCTRL "reassoctrl"
+#endif
+#define PRIV_CMD_TXBUF_CFG "txbufcfg"
+#ifdef STA_SUPPORT
+#define PRIV_CMD_AUTH_TYPE "authtype"
+#endif
+#define PRIV_CMD_POWER_CONS "powercons"
+#define PRIV_CMD_HT_STREAM_CFG "htstreamcfg"
+#define PRIV_CMD_MIMO_SWITCH "mimoswitch"
+#define PRIV_CMD_THERMAL "thermal"
+#define PRIV_CMD_BCN_INTERVAL "bcninterval"
+#ifdef STA_SUPPORT
+#define PRIV_CMD_GET_SIGNAL "getsignal"
+#define PRIV_CMD_SIGNALEXT_CFG "signalextcfg"
+#define PRIV_CMD_GET_SIGNAL_EXT_V2 "getsignalextv2"
+#define PRIV_CMD_GET_SIGNAL_EXT "getsignalext"
+#endif
+#if defined(STA_SUPPORT)
+#define PRIV_CMD_PMFCFG "pmfcfg"
+#endif
+#define PRIV_CMD_INACTIVITYTO "inactivityto"
+#define PRIV_CMD_AMSDU_AGGR_CTRL "amsduaggrctrl"
+#define PRIV_CMD_TX_BF_CAP "httxbfcap"
+#ifdef SDIO
+#define PRIV_CMD_SDIO_CLOCK "sdioclock"
+#endif
+#ifdef SDIO
+#define PRIV_CMD_MPA_CTRL "mpactrl"
+#endif
+#define PRIV_CMD_SLEEP_PARAMS "sleepparams"
+#define PRIV_CMD_DFS_TESTING "dfstesting"
+#define PRIV_CMD_DFS53_CFG "dfs53cfg"
+#define PRIV_CMD_CFP_CODE "cfpcode"
+#define PRIV_CMD_CWMODE "cwmode"
+#define PRIV_CMD_ANT_CFG "antcfg"
+#define PRIV_CMD_SYSCLOCK "sysclock"
+#define PRIV_CMD_GET_KEY "getkey"
+#define PRIV_CMD_ASSOCIATE "associate"
+#define PRIV_CMD_TX_BF_CFG "httxbfcfg"
+#define PRIV_CMD_PORT_CTRL "port_ctrl"
+#define PRIV_CMD_PB_BYPASS "pb_bypass"
+#ifdef SDIO
+#define PRIV_CMD_SD_CMD53_RW "sdcmd53rw"
+#endif
+#ifdef RX_PACKET_COALESCE
+#define PRIV_CMD_RX_COAL_CFG "rxpktcoal_cfg"
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(UAP_CFG80211)
+#define PRIV_CMD_CFG_NOA "cfg_noa"
+#define PRIV_CMD_CFG_OPP_PS "cfg_opp_ps"
+#endif
+#endif
+#define PRIV_CMD_CFG_CLOCK_SYNC "clocksync"
+#define PRIV_CMD_CFG_GET_TSF_INFO "gettsfinfo"
+#define PRIV_CMD_TRANSITION_CHANNEL "transchan"
+
+#define PRIV_CMD_DFS_REPEATER_CFG "dfs_repeater"
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#define PRIV_CMD_MIRACAST_CFG "miracastcfg"
+#endif
+#endif
+#define PRIV_CMD_COEX_RX_WINSIZE "coex_rx_winsize"
+#define PRIV_CMD_TX_AGGR_CTRL "txaggrctrl"
+#define PRIV_CMD_AUTO_TDLS "autotdls"
+
+#ifdef PCIE
+#define PRIV_CMD_PCIE_REG_RW "pcieregrw"
+#define PRIV_CMD_PCIE_BAR0_REG_RW "pciebar0regrw"
+#endif
+
+#define PRIV_CMD_GET_SENSOR_TEMP "get_sensor_temp"
+
+#define PRIV_CMD_GET_CHNRGPWR "get_chnrgpwr"
+#define PRIV_CMD_GET_TXPWR_LIMIT "get_txpwrlimit"
+#define PRIV_CMD_GET_CFG_CHAN_LIST "getcfgchanlist"
+#if defined(UAP_SUPPORT)
+#define PRIV_CMD_EXTEND_CHAN_SWITCH "channel_switch"
+#endif
+
+#define PRIV_CMD_TDLS_IDLE_TIME "tdls_idle_time"
+
+#define PRIV_CMD_DYN_BW "dyn_bw"
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#define PRIV_CMD_DFS_OFFLOAD "dfs_offload"
+#endif
+
+#define PRIV_CMD_AUTO_ARP "auto_arp"
+
+#define PRIV_CMD_PER_PKT_CFG "per_pkt_cfg"
+
+#define PRIV_CMD_DEAUTH_CTRL "ctrldeauth"
+
+#define PRIV_CMD_TX_RX_HISTOGRAM "txrxhistogram"
+
+/**Private command ID to set/get independent reset*/
+#define PRIV_CMD_IND_RST_CFG "indrstcfg"
+
+#define PRIV_CMD_ARB_CFG "arb"
+
+/**Private command to configure static rx abort config */
+#define PRIV_CMD_RX_ABORT_CFG "rx_abort_cfg"
+/**Private command to configure dynamic rx abort config */
+#define PRIV_CMD_RX_ABORT_CFG_EXT "rx_abort_cfg_ext"
+#define TX_AMPDU_RTS_CTS 0
+#define TX_AMPDU_CTS_2_SELF 1
+#define TX_AMPDU_DISABLE_PROTECTION 2
+#define TX_AMPDU_DYNAMIC_RTS_CTS 3
+/**Private command to set tx ampdu protection mode */
+#define PRIV_CMD_TX_AMPDU_PROT_MODE "tx_ampdu_prot_mode"
+/**Private command to configure tx rate adapt config */
+#define PRIV_CMD_RATE_ADAPT_CFG "rate_adapt_cfg"
+#define CCK_DESENSE_MODE_DISABLED 0
+#define CCK_DESENSE_MODE_DYNAMIC 1
+#define CCK_DESENSE_MODE_DYN_ENH 2
+/**Private command to configure cck desense config */
+#define PRIV_CMD_CCK_DESENSE_CFG "cck_desense_cfg"
+#define PRIV_CMD_DOT11MC_UNASSOC_FTM_CFG "dot11mc_unassoc_ftm_cfg"
+#define PRIV_CMD_HAL_PHY_CFG "hal_phy_cfg"
+
+/** Private command ID for Android default commands */
+#define WOAL_ANDROID_DEF_CMD (SIOCDEVPRIVATE + 1)
+
+/** Private command ID to send TLD configuration */
+#define WOAL_TDLS_CONFIG (SIOCDEVPRIVATE + 5)
+
+/** Private command ID to pass mgmt frame */
+#define WOAL_MGMT_FRAME_TX WOAL_MGMT_FRAME_TX_IOCTL
+
+/** Private command ID to pass custom IE list */
+#define WOAL_CUSTOM_IE_CFG (SIOCDEVPRIVATE + 13)
+
+/** Private command ID for Android ICS priv CMDs */
+#define WOAL_ANDROID_PRIV_CMD (SIOCDEVPRIVATE + 14)
+
+/** Private command ID to get BSS type */
+#define WOAL_GET_BSS_TYPE (SIOCDEVPRIVATE + 15)
+
+/** Private command ID for robustcoex */
+#define PRIV_CMD_ROBUSTCOEX "robustcoex"
+
+#define PRIV_CMD_DMCS "dmcs"
+
+#if defined(PCIE)
+#define PRIV_CMD_SSU "ssu"
+/** ssu_params_ctrl */
+typedef struct _ssu_params_cfg {
+	/* ssu mode */
+	t_u8 ssu_mode;
+	/* 0-3; # of FFT samples to skip */
+	t_u32 nskip;
+	/* 0-3: # of FFT samples selected to dump */
+	t_u32 nsel;
+	/* 0-3: Down sample ADC input for buffering */
+	t_u32 adcdownsample;
+	/* 0-1: Mask out ADC Data from spectral packet */
+	t_u32 mask_adc_pkt;
+	/* 0-1: Enable 16-Bit FFT output data precision in spectral packet */
+	t_u32 out_16bits;
+	/* 0-1: Enable power spectrum in dB for spectral packe */
+	t_u32 spec_pwr_enable;
+	/* 0-1: Enable spectral packet rate reduction in DB output format */
+	t_u32 rate_deduction;
+	/* 0-7: Number of spectral packets over which spectral data is to be
+	 * averaged. */
+	t_u32 n_pkt_avg;
+} __attribute__ ((packed)) ssu_params_cfg;
+#endif
+
+#define PRIV_CMD_BOOTSLEEP "bootsleep"
+
+/** Private command: 11AX Cfg */
+#define PRIV_CMD_11AXCFG "11axcfg"
+/** Private command: 11AX Cmd */
+#define PRIV_CMD_11AXCMDCFG "11axcmd"
+/** Private command: Range ext Cmd */
+#define PRIV_CMD_RANGE_EXT "range_ext"
+/** Private command: TWT Setup Cfg */
+#define PRIV_CMD_TWT_SETUP "twt_setup"
+/** Private command: TWT Teardown Cfg */
+#define PRIV_CMD_TWT_TEARDOWN "twt_teardown"
+
+#define PRIV_CMD_LPM "lpm"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+int woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user * data,
+		  int cmd);
+#else
+int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+#endif
+/*
+ * For android private commands, fixed value of ioctl is used.
+ * Internally commands are differentiated using strings.
+ *
+ * application needs to specify "total_len" of data for copy_from_user
+ * kernel updates "used_len" during copy_to_user
+ */
+/** Private command structure from app */
+#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
+typedef struct _android_wifi_priv_cmd {
+	/** Buffer pointer */
+	t_u64 buf;
+	/** buffer updated by driver */
+	int used_len;
+	/** buffer sent by application */
+	int total_len;
+} __attribute__ ((packed))
+     android_wifi_priv_cmd;
+#else
+typedef struct _android_wifi_priv_cmd {
+	/** Buffer pointer */
+	char *buf;
+	/** buffer updated by driver */
+	int used_len;
+	/** buffer sent by application */
+	int total_len;
+} android_wifi_priv_cmd;
+#endif
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+/* Maximum size of the ESSID and NICKN strings */
+#define MW_ESSID_MAX_SIZE 32
+
+/* Modes of operation */
+#define MW_MODE_AUTO 0		/* Let the driver decides */
+#define MW_MODE_ADHOC 1		/* Single cell network */
+#define MW_MODE_INFRA 2		/* Multi cell network, roaming, ... */
+#define MW_MODE_MASTER 3	/* Synchronisation master or Access Point */
+#define MW_MODE_REPEAT 4	/* Wireless Repeater (forwarder) */
+#define MW_MODE_SECOND 5	/* Secondary master/repeater (backup) */
+#define MW_MODE_MONITOR 6	/* Passive monitor (listen only) */
+#define MW_MODE_MESH 7		/* Mesh (IEEE 802.11s) network */
+
+#define MW_POWER_TYPE 0xF000	/* Type of parameter */
+#define MW_POWER_PERIOD 0x1000	/* Value is a period/duration of  */
+#define MW_POWER_TIMEOUT 0x2000	/* Value is a timeout (to go asleep) */
+
+#define MW_AUTH_INDEX 0x0FFF
+#define MW_AUTH_FLAGS 0xF000
+#define MW_AUTH_WPA_VERSION 0
+#define MW_AUTH_CIPHER_PAIRWISE 1
+#define MW_AUTH_CIPHER_GROUP 2
+#define MW_AUTH_KEY_MGMT 3
+#define MW_AUTH_TKIP_COUNTERMEASURES 4
+#define MW_AUTH_DROP_UNENCRYPTED 5
+#define MW_AUTH_80211_AUTH_ALG 6
+#define MW_AUTH_WPA_ENABLED 7
+#define MW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define MW_AUTH_ROAMING_CONTROL 9
+#define MW_AUTH_PRIVACY_INVOKED 10
+#define MW_AUTH_CIPHER_GROUP_MGMT 11
+#define MW_AUTH_MFP 12
+
+#define MW_AUTH_CIPHER_NONE 0x00000001
+#define MW_AUTH_CIPHER_WEP40 0x00000002
+#define MW_AUTH_CIPHER_TKIP 0x00000004
+#define MW_AUTH_CIPHER_CCMP 0x00000008
+#define MW_AUTH_CIPHER_WEP104 0x00000010
+#define MW_AUTH_CIPHER_AES_CMAC 0x00000020
+
+#define MW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define MW_AUTH_ALG_SHARED_KEY 0x00000002
+#define MW_AUTH_ALG_LEAP 0x00000004
+
+/* Generic format for most parameters that fit in an int */
+struct mw_param {
+	t_s32 value;		/* The value of the parameter itself */
+	t_u8 fixed;		/* Hardware should not use auto select */
+	t_u8 disabled;		/* Disable the feature */
+	t_u16 flags;		/* Various specifc flags (if any) */
+};
+
+/*
+ *  For all data larger than 16 octets, we need to use a
+ *  pointer to memory allocated in user space.
+ */
+struct mw_point {
+	t_u8 *pointer;		/* Pointer to the data  (in user space) */
+	t_u16 length;		/* number of fields or size in bytes */
+	t_u16 flags;		/* Optional params */
+};
+
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ */
+union mwreq_data {
+	/* Config - generic */
+	char name[IFNAMSIZ];
+
+	struct mw_point essid;	/* Extended network name */
+	t_u32 mode;		/* Operation mode */
+	struct mw_param power;	/* PM duration/timeout */
+	struct sockaddr ap_addr;	/* Access point address */
+	struct mw_param param;	/* Other small parameters */
+	struct mw_point data;	/* Other large parameters */
+};
+
+/* The structure to exchange data for ioctl */
+struct mwreq {
+	union {
+		char ifrn_name[IFNAMSIZ];	/* if name, e.g. "eth0" */
+	} ifr_ifrn;
+
+	/* Data part */
+	union mwreq_data u;
+};
+
+typedef struct woal_priv_ht_cap_info {
+	t_u32 ht_cap_info_bg;
+	t_u32 ht_cap_info_a;
+} woal_ht_cap_info;
+
+typedef struct woal_priv_addba {
+	t_u32 time_out;
+	t_u32 tx_win_size;
+	t_u32 rx_win_size;
+	t_u32 tx_amsdu;
+	t_u32 rx_amsdu;
+} woal_addba;
+
+typedef struct _txrate_setting {
+	t_u16 preamble:2;	/*BIT1-BIT0:
+				 *  For legacy 11b: preamble type
+				 *    00    = long
+				 *    01    = short
+				 *    10/11  = reserved
+				 *  For legacy 11g: reserved
+				 *  For 11n: Green field PPDU indicator
+				 *    00 = HT-mix
+				 *    01 = HT-GF
+				 *    10/11 = reserved.
+				 *  For 11ac: reserved.
+				 *  For 11ax:
+				 *    00 = HE-SU
+				 *    01 = HE-EXT-SU
+				 *    10 = HE-MU
+				 *    11 = HE trigger based
+				 */
+	t_u16 bandwidth:3;	/* BIT2- BIT4
+				 * For 11n and 11ac traffic: Bandwidth
+				 *    0 = 20Mhz
+				 *    1 = 40Mhz
+				 *    2 = 80 Mhz
+				 *    3 = 160 Mhz
+				 *    4-7 = reserved
+				 *  For legacy rate : BW>0 implies non-HT duplicates.
+				 *  For HE SU PPDU:
+				 *    0 = 20Mhz
+				 *    1 = 40Mhz
+				 *    2 = 80 Mhz
+				 *    3 = 160 Mhz
+				 *    4-7 = reserved
+				 *  For HE ER SU PPDU:
+				 *    0 = 242-tone RU
+				 *    1 = upper frequency 106 tone RU within the primary 20 Mhz.
+				 *  For HE MU PPDU:
+				 *    0 = 20Mhz.
+				 *    1 = 40Mhz.
+				 *    2 = 80Mhz non-preamble puncturing mode
+				 *    3 = 160Mhz and 80+80 Mhz non-preamble.
+				 *    4 = for preemble puncturing in 80 Mhz ,
+				 *        where in the preamble only the secondary 20Mhz is punctured.
+				 *    5 = for preemble puncturing in 80 Mhz ,
+				 *        where in the preamble only one of the two 20Mhz subchannels in the secondary 40Mhz is punctured.
+				 *    6 = for preemble puncturing in 160 Mhz or 80 Mhz + 80 Mhz,
+				 *        where in the primary 80 Mhz of the preamble only the secondary 20 Mhz is punctured.
+				 *    7 = for preemble puncturing in 160 Mhz or 80 Mhz + 80 Mhz,
+				 *        where in the primary 80 Mhz of the preamble the primary 40 Mhz is present.
+				 */
+	t_u16 shortGI:2;	/*BIT5- BIT6
+				 *  For legacy: not used
+				 *  For 11n: 00 = normal, 01 =shortGI, 10/11 = reserved
+				 *  For 11ac: SGI map to VHT-SIG-A2[0]
+				 *           VHT-SIG-A2[1] is set to 1 if short guard interval is used
+				 *           and NSYM mod 10 = 9, otherwise set to 0.
+				 *  For 11ax:
+				 *           00 = 1xHELTF+GI0.8usec
+				 *           01 = 2xHELTF+GI0.8usec
+				 *           10 = 2xHELTF+GI1.6usec
+				 *           11 = 4xHELTF+GI0.8 usec if both DCM and STBC are 1
+				 *                4xHELTF+GI3.2 usec otherwise
+				 */
+	t_u16 stbc:1;		// BIT7, 0: no STBC; 1: STBC
+	t_u16 dcm:1;		// BIT8, 0: no DCM; 1: DCM used.
+	t_u16 adv_coding:1;	// BIT9, 0: BCC; 1: LDPC.
+	t_u16 doppler:2;	/* BIT11-BIT10,
+				   00: Doppler0
+				   01: Doppler 1 with Mma =10
+				   10: Doppler 1 with Mma =20
+				 */
+	t_u16 max_pktext:2;	/*BIT12-BIT13:
+				 * Max packet extension
+				 *  0 - 0 usec
+				 *  1 - 8 usec
+				 *  2 - 16 usec.
+				 */
+	t_u16 reserverd:2;	// BIT14-BIT15
+} __ATTRIB_PACK__ txrate_setting;
+
+/** data structure for cmd txratecfg */
+typedef struct woal_priv_tx_rate_cfg {
+	/* LG rate: 0, HT rate: 1, VHT rate: 2 */
+	t_u32 rate_format;
+	/** Rate/MCS index (0xFF: auto) */
+	t_u32 rate_index;
+	/** Data rate */
+	t_u32 rate;
+	/** NSS */
+	t_u32 nss;
+	/** Rate Setting */
+	t_u16 rate_setting;
+} woal_tx_rate_cfg;
+
+typedef struct woal_priv_esuppmode_cfg {
+	/* RSN mode */
+	t_u16 rsn_mode;
+	/* Pairwise cipher */
+	t_u8 pairwise_cipher;
+	/* Group cipher */
+	t_u8 group_cipher;
+} woal_esuppmode_cfg;
+
+mlan_status woal_set_ap_wps_p2p_ie(moal_private *priv, t_u8 *ie, size_t len);
+
+int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req);
+
+#define PRIV_CMD_CLOUD_KEEP_ALIVE "cloud_keep_alive"
+/** cloud keep alive parameters */
+typedef struct _cloud_keep_alive {
+	/** id */
+	t_u8 mkeep_alive_id;
+	/** enable/disable of this id */
+	t_u8 enable;
+	/** enable/disable reset*/
+	t_u8 reset;
+	/** Reserved */
+	t_u8 reserved;
+	/** Destination MAC address */
+	t_u8 dst_mac[ETH_ALEN];
+	/** Source MAC address */
+	t_u8 src_mac[ETH_ALEN];
+	/** packet send period */
+	t_u32 sendInterval;
+	/** packet retry interval */
+	t_u32 retryInterval;
+	/** packet retry count */
+	t_u8 retryCount;
+	/** packet length */
+	t_u8 pkt_len;
+	/** packet content */
+	t_u8 pkt[255];
+} __ATTRIB_PACK__ cloud_keep_alive;
+
+#define TLV_TYPE_PER_PKT_CFG 0x0001
+#define TX_PKT_CTRL MBIT(0)
+#define RX_PKT_INFO MBIT(1)
+
+#define FLAG_TX_HISTOGRAM 0x01
+#define FLAG_RX_HISTOGRAM 0x02
+#define DISABLE_TX_RX_HISTOGRAM 0x00
+#define ENABLE_TX_RX_HISTOGRAM 0x01
+#define GET_TX_RX_HISTOGRAM 0x02
+#define PRIV_CMD_TX_RX_HISTOGRAM "txrxhistogram"
+/** TX and RX histogram statistic parameters*/
+typedef struct _tx_rx_histogram {
+	/** Enable or disable get tx/rx histogram statistic */
+	t_u8 enable;
+	/** Choose to get TX, RX or both histogram statistic */
+	t_u8 action;
+} __ATTRIB_PACK__ tx_rx_histogram;
+
+/* Enum for different CW mode type */
+typedef enum _cw_modes_e {
+	CWMODE_DISABLE,
+	CWMODE_TXCONTPKT,
+	CWMODE_TXCONTWAVE,
+} cw_modes_e;
+
+/** wlan_ieee80211_chan */
+typedef struct {
+	/** center freq */
+	t_u16 center_freq;
+	/** chan num */
+	t_u16 hw_value;
+	/** chan flags */
+	t_u32 flags;
+	/** max power */
+	int max_power;
+	/** dfs_state */
+	t_u8 dfs_state;
+} __ATTRIB_PACK__ wlan_ieee80211_chan;
+
+/** wlan_ieee80211_chan_list*/
+typedef struct {
+	/** num of chan */
+	t_u8 num_chan;
+	/** chan_list */
+	wlan_ieee80211_chan chan_list[];
+} __ATTRIB_PACK__ wlan_ieee80211_chan_list;
+
+#define PRIV_CMD_TP_STATE "tp_state"
+#endif /* _WOAL_ETH_PRIV_H_ */
diff --git a/wlan_sd8987/mlinux/moal_init.c b/wlan_sd8987/mlinux/moal_init.c
new file mode 100755
index 0000000..628e792
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_init.c
@@ -0,0 +1,2523 @@
+/** @file moal_init.c
+ *
+ * @brief This file contains the major functions in WLAN
+ * driver.
+ *
+ *
+ * Copyright 2018-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+#include "moal_main.h"
+
+/** Global moal_handle array */
+extern pmoal_handle m_handle[];
+
+/** Firmware name */
+static char *fw_name;
+static int req_fw_nowait;
+int fw_reload;
+
+static char *hw_name;
+
+/** MAC address */
+static char *mac_addr;
+/** Module param cfg file */
+static char *mod_para;
+
+#ifdef MFG_CMD_SUPPORT
+/** Mfg mode */
+int mfg_mode;
+#endif
+
+#if defined(SDIO)
+/** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */
+static int intmode = INT_MODE_SDIO;
+/** GPIO interrupt pin number */
+static int gpiopin;
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+static int disable_regd_by_driver = 1;
+/** Region alpha2 string */
+static char *reg_alpha2;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+static int country_ie_ignore;
+static int beacon_hints;
+#endif
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int host_mlme;
+#endif
+#endif
+
+/** Auto deep sleep */
+static int auto_ds;
+
+/** net_rx mode*/
+static int net_rx;
+/** amsdu deaggr mode */
+static int amsdu_deaggr;
+
+static int ext_scan;
+
+/** IEEE PS mode */
+static int ps_mode;
+/** passive to active scan */
+static int p2a_scan;
+/** scan chan gap */
+static int scan_chan_gap;
+/** sched scan */
+static int sched_scan = 1;
+/** Max Tx buffer size */
+int max_tx_buf;
+
+#ifdef STA_SUPPORT
+/** Max STA interfaces */
+static int max_sta_bss = DEF_STA_BSS;
+/** STA interface name */
+static char *sta_name;
+#endif
+
+#ifdef UAP_SUPPORT
+/** Max uAP interfaces */
+static int max_uap_bss = DEF_UAP_BSS;
+/** uAP interface name */
+static char *uap_name;
+/** Max uAP station number */
+static int uap_max_sta;
+/** WACP mode */
+static int wacp_mode = WACP_MODE_DEFAULT;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+/** Max WIFIDIRECT interfaces */
+static int max_wfd_bss = DEF_WIFIDIRECT_BSS;
+/** WIFIDIRECT interface name */
+static char *wfd_name;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+/** max VIRTUAL bss */
+static int max_vir_bss = DEF_VIRTUAL_BSS;
+#endif
+#endif
+
+/** PM keep power */
+static int pm_keep_power = 1;
+#ifdef SDIO_SUSPEND_RESUME
+/** HS when shutdown */
+static int shutdown_hs;
+#endif
+
+#if defined(SDIO)
+/** SDIO slew rate */
+static int slew_rate = 3;
+#endif
+int tx_work = 0;
+static int rps = 0;
+static int tx_skb_clone = 0;
+#ifdef IMX_SUPPORT
+static int pmqos = 1;
+#else
+static int pmqos = 0;
+#endif
+
+#if defined(STA_SUPPORT)
+/** 802.11d configuration */
+static int cfg_11d;
+#endif
+
+/** fw serial download check */
+static int fw_serial = 1;
+
+/** napi support*/
+static int napi;
+
+/** DPD data config file */
+static char *dpd_data_cfg;
+
+/** CAL data config file */
+static char *cal_data_cfg;
+/** Init config file (MAC address, register etc.) */
+static char *init_cfg;
+
+/** Set configuration data of Tx power limitation */
+static char *txpwrlimit_cfg;
+/** Allow setting tx power table of country */
+static int cntry_txpwr;
+
+/** Init hostcmd file */
+static char *init_hostcmd_cfg;
+static char *band_steer_cfg;
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/** CFG80211 and WEXT mode */
+static int cfg80211_wext =
+	STA_WEXT_MASK | UAP_WEXT_MASK | STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#else
+/** CFG80211 mode */
+static int cfg80211_wext = STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#endif
+
+/** Work queue priority */
+static int wq_sched_prio;
+/** Work queue scheduling policy */
+static int wq_sched_policy = SCHED_NORMAL;
+/** rx_work flag */
+static int rx_work;
+
+#if defined(USB)
+int skip_fwdnld;
+#endif
+
+/* Enable/disable aggrctrl */
+static int aggrctrl;
+
+#ifdef USB
+/* Enable/disable USB aggregation feature */
+static int usb_aggr;
+#endif
+
+#ifdef PCIE
+/* Enable/disable Message Signaled Interrupt (MSI) */
+int pcie_int_mode = PCIE_INT_MODE_MSI;
+static int ring_size;
+#endif /* PCIE */
+
+static int low_power_mode_enable;
+
+static int hw_test;
+
+#ifdef CONFIG_OF
+int dts_enable = 1;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+static int dfs_offload;
+#endif
+
+#ifdef ANDROID_KERNEL
+int wakelock_timeout = WAKE_LOCK_TIMEOUT;
+#endif
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#ifdef WIFI_DIRECT_SUPPORT
+static int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP | DRV_MODE_WIFIDIRECT);
+#else
+static int drv_mode = (DRV_MODE_STA | DRV_MODE_UAP);
+#endif /* WIFI_DIRECT_SUPPORT */
+#else
+#ifdef STA_SUPPORT
+static int drv_mode = DRV_MODE_STA;
+#else
+static int drv_mode = DRV_MODE_UAP;
+#endif /* STA_SUPPORT */
+#endif /* STA_SUPPORT & UAP_SUPPORT */
+
+static int gtk_rekey_offload = GTK_REKEY_OFFLOAD_DISABLE;
+
+static int pmic;
+
+static int antcfg;
+
+static t_u32 uap_oper_ctrl;
+
+static int hs_wake_interval = 400;
+static int indication_gpio = 0xff;
+static int disconnect_on_suspend;
+static int hs_mimo_switch;
+
+static int indrstcfg = 0xffffffff;
+
+/** all the feature are enabled */
+#define DEFAULT_DEV_CAP_MASK 0xffffffff
+static t_u32 dev_cap_mask = DEFAULT_DEV_CAP_MASK;
+#ifdef SDIO
+static int sdio_rx_aggr = MTRUE;
+#endif
+
+/** The global variable of scan beacon buffer **/
+static int fixed_beacon_buffer;
+
+#ifdef WIFI_DIRECT_SUPPORT
+static int GoAgeoutTime;
+#endif
+
+static t_u16 multi_dtim;
+
+static t_u16 inact_tmo;
+
+#ifdef DEBUG_LEVEL1
+#ifdef DEBUG_LEVEL2
+#define DEFAULT_DEBUG_MASK (0xffffffff)
+#else
+#define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR | MREG_D)
+#endif /* DEBUG_LEVEL2 */
+t_u32 drvdbg = DEFAULT_DEBUG_MASK;
+
+#endif /* DEBUG_LEVEL1 */
+
+static card_type_entry card_type_map_tbl[] = {
+#ifdef SD8801
+	{CARD_TYPE_SD8801, 0, CARD_SD8801},
+#endif
+#ifdef SD8887
+	{CARD_TYPE_SD8887, 0, CARD_SD8887},
+#endif
+#ifdef SD8897
+	{CARD_TYPE_SD8897, 0, CARD_SD8897},
+#endif
+#ifdef SD8977
+	{CARD_TYPE_SD8977, 0, CARD_SD8977},
+#endif
+#ifdef SD8978
+	{CARD_TYPE_SD8978, 0, CARD_SD8978},
+#endif
+#ifdef SD8997
+	{CARD_TYPE_SD8997, 0, CARD_SD8997},
+#endif
+#ifdef SD8987
+	{CARD_TYPE_SD8987, 0, CARD_SD8987},
+#endif
+#ifdef SD9097
+	{CARD_TYPE_SD9097, 0, CARD_SD9097},
+#endif
+#ifdef SD9098
+	{CARD_TYPE_SD9098, 0, CARD_SD9098},
+#endif
+#ifdef SD9177
+	{CARD_TYPE_SD9177, 0, CARD_SD9177},
+#endif
+#ifdef PCIE8897
+	{CARD_TYPE_PCIE8897, 0, CARD_PCIE8897},
+#endif
+#ifdef PCIE8997
+	{CARD_TYPE_PCIE8997, 0, CARD_PCIE8997},
+#endif
+#ifdef PCIE9097
+	{CARD_TYPE_PCIE9097, 0, CARD_PCIE9097},
+#endif
+#ifdef PCIE9098
+	{CARD_TYPE_PCIE9098, 0, CARD_PCIE9098},
+#endif
+#ifdef USB8801
+	{CARD_TYPE_USB8801, 0, CARD_USB8801},
+#endif
+
+#ifdef USB8897
+	{CARD_TYPE_USB8897, 0, CARD_USB8897},
+#endif
+#ifdef USB8997
+	{CARD_TYPE_USB8997, 0, CARD_USB8997},
+#endif
+#ifdef USB8978
+	{CARD_TYPE_USB8978, 0, CARD_USB8978},
+#endif
+#ifdef USB9098
+	{CARD_TYPE_USB9098, 0, CARD_USB9098},
+#endif
+#ifdef USB9097
+	{CARD_TYPE_USB9097, 0, CARD_USB9097},
+#endif
+};
+
+static int dfs53cfg = DFS_W53_DEFAULT_FW;
+
+/**
+ *  @brief This function read a line in module parameter file
+ *
+ *  @param data     A pointer to module parameter data buffer
+ *  @param size     module parameter file size
+ *  @param line_pos A pointer to offset of current line
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static t_size
+parse_cfg_get_line(t_u8 *data, t_size size, t_u8 *line_pos)
+{
+	t_u8 *src, *dest;
+	static t_s32 pos;
+
+	ENTER();
+
+	if (pos >= (t_s32)size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		LEAVE();
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while (pos < (t_s32)size && *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	/* parse new line */
+	pos++;
+	*dest = '\0';
+	LEAVE();
+	return strlen(line_pos);
+}
+
+/**
+ *  @brief This function duplicate a string
+ *
+ *  @param dst   A pointer to destination string
+ *  @param src   A pointer to source string
+ *
+ *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static void
+woal_dup_string(char **dst, char *src)
+{
+	size_t len = 0;
+	if (src) {
+		len = strlen(src);
+		if (len != 0) {
+			if (*dst != NULL)
+				kfree(*dst);
+			*dst = kzalloc(len + 1, GFP_KERNEL);
+			if (*dst == NULL) {
+				PRINTM(MERROR,
+				       "Failed to alloc mem for param: %s\n",
+				       src);
+				return;
+			}
+			moal_memcpy_ext(NULL, *dst, src, len, len);
+		}
+	}
+}
+
+/**
+ *  @brief This function read an integer value in module parameter file
+ *
+ *  @param line     A pointer to a line
+ *  @param out_data A pointer to parsed integer value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+parse_line_read_int(t_u8 *line, int *out_data)
+{
+	t_u8 *p = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	if (line == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	p = strstr(line, "=");
+	if (p == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	p++;
+	ret = woal_atoi(out_data, p);
+out:
+	if (ret != MLAN_STATUS_SUCCESS)
+		*out_data = 0;
+	return ret;
+}
+
+/**
+ *  @brief This function read a string in module parameter file
+ *
+ *  @param line     A pointer to a line
+ *  @param out_str  A pointer to parsed string
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+parse_line_read_string(t_u8 *line, char **out_str)
+{
+	t_u8 *p = NULL, *pstr = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	if (line == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	p = strstr(line, "=");
+	if (p == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	p++;
+	pstr = p;
+	while (*pstr) {
+		if (*pstr == '\"')
+			*pstr = '\0';
+		pstr++;
+	}
+	if (*p == '\0')
+		p++;
+	*out_str = p;
+out:
+	return ret;
+}
+
+/**
+ *  @brief This function read card info in module parameter file
+ *
+ *  @param line     A pointer to a line
+ *  @param type     A pointer to card type
+ *  @param if_id    A pointer to interface id
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+parse_line_read_card_info(t_u8 *line, char **type, char **if_id)
+{
+	t_u8 *p = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	if (line == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+
+	p = strstr(line, "=");
+	if (p == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	*p = '\0';
+
+	p = strstr(line, "_");
+	if (p != NULL) {
+		*p++ = '\0';
+		*if_id = p;
+	} else {
+		*if_id = NULL;
+	}
+	*type = line;
+out:
+	return ret;
+}
+
+/**
+ *  @brief This function read blocks in module parameter file
+ *
+ *  @param data     A pointer to a line
+ *  @param size     line size
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+parse_cfg_read_block(t_u8 *data, t_u32 size, moal_handle *handle)
+{
+	int out_data = 0, end = 0;
+	char *out_str = NULL;
+	t_u8 line[MAX_LINE_LEN];
+	moal_mod_para *params = &handle->params;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	while ((int)parse_cfg_get_line(data, size, line) != -1) {
+		if (strncmp(line, "}", strlen("}")) == 0) {
+			end = 1;
+			break;
+		}
+		if (end == 0 && strstr(line, "{") != NULL)
+			break;
+		if (strncmp(line, "hw_test", strlen("hw_test")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_HW_TEST);
+			else
+				moal_extflg_clear(handle, EXT_HW_TEST);
+			PRINTM(MMSG, "hw_test %s\n",
+			       moal_extflg_isset(handle, EXT_HW_TEST) ? "on" :
+			       "off");
+		}
+#ifdef CONFIG_OF
+		else if (strncmp(line, "dts_enable", strlen("dts_enable")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_DTS_ENABLE);
+			else
+				moal_extflg_clear(handle, EXT_DTS_ENABLE);
+			PRINTM(MMSG, "dts_enable %s\n",
+			       moal_extflg_isset(handle, EXT_DTS_ENABLE) ?
+			       "on" : "off");
+		}
+#endif
+		else if (strncmp(line, "fw_name", strlen("fw_name")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->fw_name, out_str);
+			PRINTM(MMSG, "fw_name=%s\n", params->fw_name);
+		} else if (strncmp(line, "req_fw_nowait",
+				   strlen("req_fw_nowait")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_REQ_FW_NOWAIT);
+			else
+				moal_extflg_clear(handle, EXT_REQ_FW_NOWAIT);
+			PRINTM(MMSG, "req fw nowait %s\n",
+			       moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT) ?
+			       "on" : "off");
+		} else if (strncmp(line, "fw_reload", strlen("fw_reload")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->fw_reload = out_data;
+			PRINTM(MMSG, "fw_reload %d\n", params->fw_reload);
+		} else if (strncmp(line, "fw_serial", strlen("fw_serial")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_FW_SERIAL);
+			else
+				moal_extflg_clear(handle, EXT_FW_SERIAL);
+			PRINTM(MMSG, "fw_serial %s\n",
+			       moal_extflg_isset(handle, EXT_FW_SERIAL) ?
+			       "on" : "off");
+		} else if (strncmp(line, "hw_name", strlen("hw_name")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->hw_name, out_str);
+			PRINTM(MMSG, "hw_name=%s\n", params->hw_name);
+		} else if (strncmp(line, "mac_addr", strlen("mac_addr")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->mac_addr, out_str);
+			PRINTM(MMSG, "mac_addr=%s\n", params->mac_addr);
+		}
+#ifdef MFG_CMD_SUPPORT
+		else if (strncmp(line, "mfg_mode", strlen("mfg_mode")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->mfg_mode = out_data;
+			PRINTM(MMSG, "mfg_mode = %d\n", params->mfg_mode);
+		}
+#endif
+		else if (strncmp(line, "drv_mode", strlen("drv_mode")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->drv_mode = out_data;
+			PRINTM(MMSG, "drv_mode = %d\n", params->drv_mode);
+		}
+#ifdef DEBUG_LEVEL1
+		else if (strncmp(line, "drvdbg", strlen("drvdbg")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->drvdbg = out_data;
+			PRINTM(MMSG, "drvdbg = %d\n", params->drvdbg);
+		}
+#endif
+#ifdef STA_SUPPORT
+		else if (strncmp(line, "max_sta_bss", strlen("max_sta_bss")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->max_sta_bss = out_data;
+			PRINTM(MMSG, "max_sta_bss = %d\n", params->max_sta_bss);
+		} else if (strncmp(line, "sta_name", strlen("sta_name")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->sta_name, out_str);
+			PRINTM(MMSG, "sta_name=%s\n", params->sta_name);
+		}
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+		else if (strncmp(line, "max_uap_bss", strlen("max_uap_bss")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->max_uap_bss = out_data;
+			PRINTM(MMSG, "max_uap_bss = %d\n", params->max_uap_bss);
+		} else if (strncmp(line, "uap_name", strlen("uap_name")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->uap_name, out_str);
+			PRINTM(MMSG, "uap_name=%s\n", params->uap_name);
+		}
+#endif /* UAP_SUPPORT */
+#ifdef WIFI_DIRECT_SUPPORT
+		else if (strncmp(line, "wfd_name", strlen("wfd_name")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->wfd_name, out_str);
+			PRINTM(MMSG, "wfd_name=%s\n", params->wfd_name);
+		}
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		else if (strncmp(line, "max_vir_bss", strlen("max_vir_bss")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->max_vir_bss = out_data;
+			PRINTM(MMSG, "max_vir_bss=%d\n", params->max_vir_bss);
+		}
+#endif
+#endif
+		else if (strncmp(line, "auto_ds", strlen("auto_ds")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->auto_ds = out_data;
+			PRINTM(MMSG, "auto_ds = %d\n", params->auto_ds);
+		} else if (strncmp(line, "net_rx", strlen("net_rx")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->net_rx = out_data;
+			PRINTM(MMSG, "net_rx = %d\n", params->net_rx);
+		} else if (strncmp(line, "amsdu_deaggr", strlen("amsdu_deaggr"))
+			   == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->amsdu_deaggr = out_data;
+			PRINTM(MMSG, "amsdu_deaggr = %d\n",
+			       params->amsdu_deaggr);
+		} else if (strncmp(line, "ext_scan", strlen("ext_scan")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->ext_scan = out_data;
+			PRINTM(MMSG, "ext_scan = %d\n", params->ext_scan);
+		} else if (strncmp(line, "ps_mode", strlen("ps_mode")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->ps_mode = out_data;
+			PRINTM(MMSG, "ps_mode = %d\n", params->ps_mode);
+		} else if (strncmp(line, "p2a_scan", strlen("p2a_scan")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->p2a_scan = out_data;
+			PRINTM(MMSG, "p2a_scan = %d\n", params->p2a_scan);
+		} else if (strncmp(line, "scan_chan_gap",
+				   strlen("scan_chan_gap")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->scan_chan_gap = out_data;
+			PRINTM(MMSG, "scan_chan_gap = %d\n",
+			       params->scan_chan_gap);
+		} else if (strncmp(line, "sched_scan", strlen("sched_scan")) ==
+			   0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->sched_scan = out_data;
+			PRINTM(MMSG, "sched_scan = %d\n", params->sched_scan);
+		} else if (strncmp(line, "max_tx_buf", strlen("max_tx_buf")) ==
+			   0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->max_tx_buf = out_data;
+			PRINTM(MMSG, "max_tx_buf = %d\n", params->max_tx_buf);
+		}
+#if defined(SDIO)
+		else if (strncmp(line, "intmode", strlen("intmode")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_INTMODE);
+			else
+				moal_extflg_clear(handle, EXT_INTMODE);
+			PRINTM(MMSG, "intmode %s\n",
+			       moal_extflg_isset(handle, EXT_INTMODE) ? "on" :
+			       "off");
+		} else if (strncmp(line, "gpiopin", strlen("gpiopin")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->gpiopin = out_data;
+			PRINTM(MMSG, "gpiopin = %d\n", params->gpiopin);
+		}
+#endif
+		else if (strncmp(line, "pm_keep_power",
+				 strlen("pm_keep_power")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_PM_KEEP_POWER);
+			else
+				moal_extflg_clear(handle, EXT_PM_KEEP_POWER);
+			PRINTM(MMSG, "pm_keep_power %s\n",
+			       moal_extflg_isset(handle, EXT_PM_KEEP_POWER) ?
+			       "on" : "off");
+		}
+#if defined(SDIO) && defined(SDIO_SUSPEND_RESUME)
+		else if (strncmp(line, "shutdown_hs",
+				 strlen("shutdown_hs")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_SHUTDOWN_HS);
+			else
+				moal_extflg_clear(handle, EXT_SHUTDOWN_HS);
+			PRINTM(MMSG, "shutdown_hs %s\n",
+			       moal_extflg_isset(handle, EXT_SHUTDOWN_HS) ?
+			       "on" : "off");
+		}
+#endif
+#if defined(STA_SUPPORT)
+		else if (strncmp(line, "cfg_11d", strlen("cfg_11d")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->cfg_11d = out_data;
+			PRINTM(MMSG, "cfg_11d = %d\n", params->cfg_11d);
+		}
+#endif
+#if defined(SDIO)
+		else if (strncmp(line, "slew_rate", strlen("slew_rate")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->slew_rate = out_data;
+			PRINTM(MMSG, "slew_rate = %d\n", params->slew_rate);
+		}
+#endif
+		else if (strncmp(line, "dpd_data_cfg",
+				 strlen("dpd_data_cfg")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->dpd_data_cfg, out_str);
+			PRINTM(MMSG, "dpd_data_cfg=%s\n", params->dpd_data_cfg);
+		} else if (strncmp(line, "init_cfg", strlen("init_cfg")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->init_cfg, out_str);
+			PRINTM(MMSG, "init_cfg=%s\n", params->init_cfg);
+		} else if (strncmp(line, "cal_data_cfg",
+				   strlen("cal_data_cfg")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->cal_data_cfg, out_str);
+			PRINTM(MMSG, "cal_data_cfg=%s\n", params->cal_data_cfg);
+		} else if (strncmp(line, "txpwrlimit_cfg",
+				   strlen("txpwrlimit_cfg")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->txpwrlimit_cfg, out_str);
+			PRINTM(MMSG, "txpwrlimit_cfg=%s\n",
+			       params->txpwrlimit_cfg);
+		} else if (strncmp(line, "cntry_txpwr",
+				   strlen("cntry_txpwr")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->cntry_txpwr = out_data;
+			PRINTM(MMSG, "cntry_txpwr = %d\n", params->cntry_txpwr);
+		} else if (strncmp(line, "init_hostcmd_cfg",
+				   strlen("init_hostcmd_cfg")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->init_hostcmd_cfg, out_str);
+			PRINTM(MMSG, "init_hostcmd_cfg=%s\n",
+			       params->init_hostcmd_cfg);
+		} else if (strncmp(line, "band_steer_cfg",
+				   strlen("band_steer_cfg")) == 0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->band_steer_cfg, out_str);
+			PRINTM(MMSG, "band_steer_cfg=%s\n",
+			       params->band_steer_cfg);
+		} else if (strncmp(line, "cfg80211_wext",
+				   strlen("cfg80211_wext")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->cfg80211_wext = out_data;
+			PRINTM(MMSG, "cfg80211_wext=0x%x\n",
+			       params->cfg80211_wext);
+		}
+#if defined(USB)
+		else if (IS_USB(handle->card_type) &&
+			 strncmp(line, "skip_fwdnld", strlen("skip_fwdnld")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_SKIP_FWDNLD);
+			else
+				moal_extflg_clear(handle, EXT_SKIP_FWDNLD);
+			PRINTM(MMSG, "skip_fwdnld %s\n",
+			       moal_extflg_isset(handle, EXT_SKIP_FWDNLD) ?
+			       "on" : "off");
+		}
+#endif
+		else if (strncmp(line, "wq_sched_prio",
+				 strlen("wq_sched_prio")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->wq_sched_prio = out_data;
+			PRINTM(MMSG, "wq_sched_prio=0x%x\n",
+			       params->wq_sched_prio);
+		} else if (strncmp(line, "wq_sched_policy",
+				   strlen("wq_sched_policy")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->wq_sched_policy = out_data;
+			PRINTM(MMSG, "wq_sched_policy=0x%x\n",
+			       params->wq_sched_policy);
+		} else if (strncmp(line, "rx_work", strlen("rx_work")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->rx_work = out_data;
+			PRINTM(MMSG, "rx_work=0x%x\n", params->rx_work);
+		} else if (strncmp(line, "aggrctrl", strlen("aggrctrl")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_AGGR_CTRL);
+			else
+				moal_extflg_clear(handle, EXT_AGGR_CTRL);
+			PRINTM(MMSG, "aggrctrl %s\n",
+			       moal_extflg_isset(handle, EXT_AGGR_CTRL) ?
+			       "on" : "off");
+		}
+#ifdef USB
+		else if (IS_USB(handle->card_type) &&
+			 strncmp(line, "usb_aggr", strlen("usb_aggr")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->usb_aggr = out_data;
+			PRINTM(MMSG, "usb_aggr=0x%x\n", params->usb_aggr);
+		}
+#endif
+#ifdef PCIE
+		else if (IS_PCIE(handle->card_type) &&
+			 strncmp(line, "pcie_int_mode",
+				 strlen("pcie_int_mode")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->pcie_int_mode = out_data;
+			PRINTM(MMSG, "pcie_int_mode=%d\n",
+			       params->pcie_int_mode);
+		} else if (IS_PCIE(handle->card_type) &&
+			   strncmp(line, "ring_size",
+				   strlen("ring_size")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->ring_size = out_data;
+			PRINTM(MMSG, "ring_size=%d\n", params->ring_size);
+		}
+#endif
+		else if (strncmp(line, "low_power_mode_enable",
+				 strlen("low_power_mode_enable")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_LOW_PW_MODE);
+			else
+				moal_extflg_clear(handle, EXT_LOW_PW_MODE);
+			PRINTM(MMSG, "low_power_mode_enable %s\n",
+			       moal_extflg_isset(handle, EXT_LOW_PW_MODE) ?
+			       "on" : "off");
+		}
+#ifdef ANDROID_KERNEL
+		else if (strncmp(line, "wakelock_timeout",
+				 strlen("wakelock_timeout")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->wakelock_timeout = out_data;
+			PRINTM(MMSG, "wakelock_timeout=%d\n",
+			       params->wakelock_timeout);
+		}
+#endif
+		else if (strncmp(line, "dev_cap_mask",
+				 strlen("dev_cap_mask")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->dev_cap_mask = out_data;
+			PRINTM(MMSG, "dev_cap_mask=%d\n", params->dev_cap_mask);
+		}
+#ifdef SDIO
+		else if (strncmp(line, "sdio_rx_aggr",
+				 strlen("sdio_rx_aggr")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_SDIO_RX_AGGR);
+			else
+				moal_extflg_clear(handle, EXT_SDIO_RX_AGGR);
+			PRINTM(MMSG, "sdio_rx_aggr %s\n",
+			       moal_extflg_isset(handle, EXT_SDIO_RX_AGGR) ?
+			       "on" : "off");
+		}
+#endif
+#if defined(SD8997) || defined(PCIE8997) || defined(USB8997) || defined(SD8977) || defined(SD8987) || defined(SD9098) || defined(USB9098) || defined(PCIE9098) || defined(SD9097) || defined(USB9097) || defined(PCIE9097) || defined(SD8978) || defined(SD9177)
+		else if (strncmp(line, "pmic", strlen("pmic")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_PMIC);
+			else
+				moal_extflg_clear(handle, EXT_PMIC);
+			PRINTM(MMSG, "pmic %s\n",
+			       moal_extflg_isset(handle, EXT_PMIC) ? "on" :
+			       "off");
+		}
+#endif
+		else if (strncmp(line, "antcfg", strlen("antcfg")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->antcfg = out_data;
+			PRINTM(MMSG, "antcfg=%d\n", params->antcfg);
+		} else if (strncmp(line, "uap_oper_ctrl",
+				   strlen("uap_oper_ctrl")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->uap_oper_ctrl = out_data;
+			PRINTM(MMSG, "uap_oper_ctrl=%d\n",
+			       params->uap_oper_ctrl);
+		} else if (strncmp(line, "hs_wake_interval",
+				   strlen("hs_wake_interval")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->hs_wake_interval = out_data;
+			PRINTM(MMSG, "hs_wake_interval=%d\n",
+			       params->hs_wake_interval);
+		} else if (strncmp(line, "indication_gpio",
+				   strlen("indication_gpio")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->indication_gpio = out_data;
+			PRINTM(MMSG, "indication_gpio=%d\n",
+			       params->indication_gpio);
+		} else if (strncmp(line, "disconnect_on_suspend",
+				   strlen("disconnect_on_suspend")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle,
+						EXT_DISCONNECT_ON_SUSPEND);
+			else
+				moal_extflg_clear(handle,
+						  EXT_DISCONNECT_ON_SUSPEND);
+			PRINTM(MMSG, "disconnect_on_suspend %s\n",
+			       moal_extflg_isset(handle,
+						 EXT_DISCONNECT_ON_SUSPEND) ?
+			       "on" : "off");
+		} else if (strncmp(line, "hs_mimo_switch",
+				   strlen("hs_mimo_switch")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_HS_MIMO_SWITCH);
+			else
+				moal_extflg_clear(handle, EXT_HS_MIMO_SWITCH);
+			PRINTM(MMSG, "hs_mimo_switch %s\n",
+			       moal_extflg_isset(handle, EXT_HS_MIMO_SWITCH) ?
+			       "on" : "off");
+		} else if (strncmp(line, "indrstcfg", strlen("indrstcfg")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->indrstcfg = out_data;
+			PRINTM(MMSG, "indrstcfg=%d\n", params->indrstcfg);
+		} else if (strncmp(line, "fixed_beacon_buffer",
+				   strlen("fixed_beacon_buffer")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_FIX_BCN_BUF);
+			else
+				moal_extflg_clear(handle, EXT_FIX_BCN_BUF);
+			PRINTM(MMSG, "fixed_beacon_buffer %s\n",
+			       moal_extflg_isset(handle, EXT_FIX_BCN_BUF) ?
+			       "on" : "off");
+		}
+#ifdef WIFI_DIRECT_SUPPORT
+		else if (strncmp(line, "GoAgeoutTime",
+				 strlen("GoAgeoutTime")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->GoAgeoutTime = out_data;
+			PRINTM(MMSG, "GoAgeoutTime=%d\n", params->GoAgeoutTime);
+		}
+#endif
+		else if (strncmp(line, "gtk_rekey_offload",
+				 strlen("gtk_rekey_offload")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->gtk_rekey_offload = out_data;
+			PRINTM(MMSG, "gtk_rekey_offload=%d\n",
+			       params->gtk_rekey_offload);
+		} else if (strncmp(line, "multi_dtim", strlen("multi_dtim")) ==
+			   0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->multi_dtim = out_data;
+			PRINTM(MMSG, "multi_dtim=%d\n", params->multi_dtim);
+		} else if (strncmp(line, "inact_tmo", strlen("inact_tmo")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->inact_tmo = out_data;
+			PRINTM(MMSG, "inact_tmo=%d\n", params->inact_tmo);
+		} else if (strncmp(line, "napi", strlen("napi")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_NAPI);
+			else
+				moal_extflg_clear(handle, EXT_NAPI);
+			PRINTM(MMSG, "napi %s\n",
+			       moal_extflg_isset(handle, EXT_NAPI) ? "on" :
+			       "off");
+		} else if (strncmp(line, "tx_work", strlen("tx_work")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_TX_WORK);
+			else
+				moal_extflg_clear(handle, EXT_TX_WORK);
+			PRINTM(MMSG, "tx_work %s\n",
+			       moal_extflg_isset(handle, EXT_TX_WORK) ? "on" :
+			       "off");
+		} else if (strncmp(line, "rps", strlen("rps")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_RPS);
+			else
+				moal_extflg_clear(handle, EXT_RPS);
+			PRINTM(MMSG, "rps %s\n",
+			       moal_extflg_isset(handle, EXT_RPS) ? "on" :
+			       "off");
+		} else if (strncmp(line, "tx_skb_clone", strlen("tx_skb_clone"))
+			   == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_TX_SKB_CLONE);
+			else
+				moal_extflg_clear(handle, EXT_TX_SKB_CLONE);
+			PRINTM(MMSG, "tx_skb_clone %s\n",
+			       moal_extflg_isset(handle,
+						 EXT_TX_SKB_CLONE) ? "on" :
+			       "off");
+		} else if (strncmp(line, "pmqos", strlen("pmqos")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_PMQOS);
+			else
+				moal_extflg_clear(handle, EXT_PMQOS);
+			PRINTM(MMSG, "pmqos %s\n",
+			       moal_extflg_isset(handle, EXT_PMQOS) ? "on" :
+			       "off");
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		else if (strncmp(line, "dfs_offload", strlen("dfs_offload")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_DFS_OFFLOAD);
+			else
+				moal_extflg_clear(handle, EXT_DFS_OFFLOAD);
+			PRINTM(MMSG, "dfs_offload %s\n",
+			       moal_extflg_isset(handle, EXT_DFS_OFFLOAD) ?
+			       "on" : "off");
+		}
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		else if (strncmp(line, "disable_regd_by_driver",
+				 strlen("disable_regd_by_driver")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle,
+						EXT_DISABLE_REGD_BY_DRIVER);
+			else
+				moal_extflg_clear(handle,
+						  EXT_DISABLE_REGD_BY_DRIVER);
+			PRINTM(MMSG, "reg domain set by driver=%s\n",
+			       moal_extflg_isset(handle,
+						 EXT_DISABLE_REGD_BY_DRIVER) ?
+			       "enable" : "disable");
+		} else if (strncmp(line, "reg_alpha2", strlen("reg_alpha2")) ==
+			   0) {
+			if (parse_line_read_string(line, &out_str) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			woal_dup_string(&params->reg_alpha2, out_str);
+			PRINTM(MMSG, "reg_alpha2=%s\n", params->reg_alpha2);
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		else if (strncmp(line, "country_ie_ignore",
+				 strlen("country_ie_ignore")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_COUNTRY_IE_IGNORE);
+			else
+				moal_extflg_clear(handle,
+						  EXT_COUNTRY_IE_IGNORE);
+			PRINTM(MMSG, "country_ie_ignore=%s\n",
+			       moal_extflg_isset(handle,
+						 EXT_COUNTRY_IE_IGNORE) ?
+			       "on" : "off");
+		} else if (strncmp(line, "beacon_hints",
+				   strlen("beacon_hints")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_BEACON_HINTS);
+			else
+				moal_extflg_clear(handle, EXT_BEACON_HINTS);
+			PRINTM(MMSG, "beacon_hints=%s\n",
+			       moal_extflg_isset(handle, EXT_BEACON_HINTS) ?
+			       "enable" : "disable");
+		}
+#endif
+#endif
+#ifdef UAP_SUPPORT
+		else if (strncmp(line, "uap_max_sta", strlen("uap_max_sta")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->uap_max_sta = out_data;
+			PRINTM(MMSG, "uap_max_sta=%d\n", params->uap_max_sta);
+		} else if (strncmp(line, "wacp_mode", strlen("wacp_mode")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->wacp_mode = out_data;
+			PRINTM(MMSG, "wacp_moe=%d\n", params->wacp_mode);
+		}
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		else if (strncmp(line, "host_mlme", strlen("host_mlme")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			if (out_data)
+				moal_extflg_set(handle, EXT_HOST_MLME);
+			else
+				moal_extflg_clear(handle, EXT_HOST_MLME);
+			PRINTM(MMSG, "host_mlme=%s\n",
+			       moal_extflg_isset(handle, EXT_HOST_MLME) ?
+			       "enable" : "disable");
+		}
+#endif
+#endif
+		else if (strncmp(line, "dfs53cfg", strlen("dfs53cfg")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->dfs53cfg = out_data;
+			PRINTM(MMSG, "dfs53cfg= %d\n", params->dfs53cfg);
+		}
+	}
+	if (end)
+		return ret;
+err:
+	PRINTM(MMSG, "Invalid line: %s\n", line);
+	ret = MLAN_STATUS_FAILURE;
+	return ret;
+}
+
+/**
+ *  @brief This function initialize module parameter
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param params   A pointer to moal_mod_para structure
+ *
+ *  @return         N/A
+ */
+static void
+woal_setup_module_param(moal_handle *handle, moal_mod_para * params)
+{
+	if (hw_test)
+		moal_extflg_set(handle, EXT_HW_TEST);
+#ifdef CONFIG_OF
+	if (dts_enable)
+		moal_extflg_set(handle, EXT_DTS_ENABLE);
+#endif
+	woal_dup_string(&handle->params.fw_name, fw_name);
+	if (params && params->fw_name)
+		woal_dup_string(&handle->params.fw_name, params->fw_name);
+	if (req_fw_nowait)
+		moal_extflg_set(handle, EXT_REQ_FW_NOWAIT);
+	handle->params.fw_reload = fw_reload;
+	if (fw_reload == FW_RELOAD_WITH_EMULATION) {
+		if (!IS_USB(handle->card_type))
+			handle->params.fw_reload = 0;
+		else
+			fw_reload = 0;
+	}
+	if (params)
+		handle->params.fw_reload = params->fw_reload;
+	if (fw_serial)
+		moal_extflg_set(handle, EXT_FW_SERIAL);
+	woal_dup_string(&handle->params.hw_name, hw_name);
+	if (params && params->hw_name)
+		woal_dup_string(&handle->params.hw_name, params->hw_name);
+
+	woal_dup_string(&handle->params.mac_addr, mac_addr);
+	if (params && params->mac_addr)
+		woal_dup_string(&handle->params.mac_addr, params->mac_addr);
+#ifdef MFG_CMD_SUPPORT
+	handle->params.mfg_mode = mfg_mode;
+	if (params)
+		handle->params.mfg_mode = params->mfg_mode;
+#endif
+	handle->params.drv_mode = drv_mode;
+	if (params)
+		handle->params.drv_mode = params->drv_mode;
+#ifdef DEBUG_LEVEL1
+	handle->params.drvdbg = drvdbg;
+	if (params)
+		handle->params.drvdbg = params->drvdbg;
+#endif
+
+#ifdef STA_SUPPORT
+	handle->params.max_sta_bss = max_sta_bss;
+	woal_dup_string(&handle->params.sta_name, sta_name);
+	if (params) {
+		handle->params.max_sta_bss = params->max_sta_bss;
+		woal_dup_string(&handle->params.sta_name, params->sta_name);
+	}
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	handle->params.max_uap_bss = max_uap_bss;
+	woal_dup_string(&handle->params.uap_name, uap_name);
+	handle->params.uap_max_sta = uap_max_sta;
+	handle->params.wacp_mode = wacp_mode;
+	if (params) {
+		handle->params.max_uap_bss = params->max_uap_bss;
+		woal_dup_string(&handle->params.uap_name, params->uap_name);
+		handle->params.uap_max_sta = params->uap_max_sta;
+		handle->params.wacp_mode = params->wacp_mode;
+	}
+#endif /* UAP_SUPPORT */
+#ifdef WIFI_DIRECT_SUPPORT
+	handle->params.max_wfd_bss = max_wfd_bss;
+	woal_dup_string(&handle->params.wfd_name, wfd_name);
+	if (params) {
+		handle->params.max_wfd_bss = params->max_wfd_bss;
+		woal_dup_string(&handle->params.wfd_name, params->wfd_name);
+	}
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	handle->params.max_vir_bss = max_vir_bss;
+	if (params)
+		handle->params.max_vir_bss = params->max_vir_bss;
+#endif
+#endif /* WIFI_DIRECT_SUPPORT */
+	handle->params.auto_ds = auto_ds;
+	if (params)
+		handle->params.auto_ds = params->auto_ds;
+	handle->params.net_rx = net_rx;
+	if (params)
+		handle->params.net_rx = params->net_rx;
+
+	handle->params.amsdu_deaggr = amsdu_deaggr;
+	if (params)
+		handle->params.amsdu_deaggr = params->amsdu_deaggr;
+
+	handle->params.ext_scan = ext_scan;
+	if (params)
+		handle->params.ext_scan = params->ext_scan;
+
+	handle->params.ps_mode = ps_mode;
+	handle->params.p2a_scan = p2a_scan;
+	handle->params.scan_chan_gap = scan_chan_gap;
+	handle->params.sched_scan = sched_scan;
+	handle->params.max_tx_buf = max_tx_buf;
+	if (params) {
+		handle->params.ps_mode = params->ps_mode;
+		handle->params.max_tx_buf = params->max_tx_buf;
+		handle->params.p2a_scan = params->p2a_scan;
+		handle->params.scan_chan_gap = params->scan_chan_gap;
+		handle->params.sched_scan = params->sched_scan;
+	}
+#if defined(SDIO)
+	if (intmode)
+		moal_extflg_set(handle, EXT_INTMODE);
+	handle->params.gpiopin = gpiopin;
+	if (params)
+		handle->params.gpiopin = params->gpiopin;
+#endif
+	if (pm_keep_power)
+		moal_extflg_set(handle, EXT_PM_KEEP_POWER);
+#if defined(SDIO) && defined(SDIO_SUSPEND_RESUME)
+	if (shutdown_hs)
+		moal_extflg_set(handle, EXT_SHUTDOWN_HS);
+#endif
+#if defined(STA_SUPPORT)
+	handle->params.cfg_11d = cfg_11d;
+	if (params)
+		handle->params.cfg_11d = params->cfg_11d;
+#endif
+#if defined(SDIO)
+	handle->params.slew_rate = slew_rate;
+	if (params)
+		handle->params.slew_rate = params->slew_rate;
+#endif
+	woal_dup_string(&handle->params.dpd_data_cfg, dpd_data_cfg);
+	if (params)
+		woal_dup_string(&handle->params.dpd_data_cfg,
+				params->dpd_data_cfg);
+	woal_dup_string(&handle->params.init_cfg, init_cfg);
+	woal_dup_string(&handle->params.cal_data_cfg, cal_data_cfg);
+	if (params) {
+		woal_dup_string(&handle->params.init_cfg, params->init_cfg);
+		woal_dup_string(&handle->params.cal_data_cfg,
+				params->cal_data_cfg);
+	}
+	woal_dup_string(&handle->params.txpwrlimit_cfg, txpwrlimit_cfg);
+	if (params)
+		woal_dup_string(&handle->params.txpwrlimit_cfg,
+				params->txpwrlimit_cfg);
+	handle->params.cntry_txpwr = cntry_txpwr;
+	if (params)
+		handle->params.cntry_txpwr = params->cntry_txpwr;
+	woal_dup_string(&handle->params.init_hostcmd_cfg, init_hostcmd_cfg);
+	if (params)
+		woal_dup_string(&handle->params.init_hostcmd_cfg,
+				params->init_hostcmd_cfg);
+
+	woal_dup_string(&handle->params.band_steer_cfg, band_steer_cfg);
+	if (params)
+		woal_dup_string(&handle->params.band_steer_cfg,
+				params->band_steer_cfg);
+	handle->params.cfg80211_wext = cfg80211_wext;
+	if (params)
+		handle->params.cfg80211_wext = params->cfg80211_wext;
+#if defined(USB)
+	if (skip_fwdnld)
+		moal_extflg_set(handle, EXT_SKIP_FWDNLD);
+#endif
+	handle->params.wq_sched_prio = wq_sched_prio;
+	handle->params.wq_sched_policy = wq_sched_policy;
+	handle->params.rx_work = rx_work;
+	if (params) {
+		handle->params.wq_sched_prio = params->wq_sched_prio;
+		handle->params.wq_sched_policy = params->wq_sched_policy;
+		handle->params.rx_work = params->rx_work;
+	}
+	if (aggrctrl)
+		moal_extflg_set(handle, EXT_AGGR_CTRL);
+#ifdef USB
+	handle->params.usb_aggr = usb_aggr;
+	if (params)
+		handle->params.usb_aggr = params->usb_aggr;
+#endif
+#ifdef PCIE
+	handle->params.pcie_int_mode = pcie_int_mode;
+	if (params)
+		handle->params.pcie_int_mode = params->pcie_int_mode;
+	handle->params.ring_size = ring_size;
+	if (params)
+		handle->params.ring_size = params->ring_size;
+#endif /* PCIE */
+	if (low_power_mode_enable)
+		moal_extflg_set(handle, EXT_LOW_PW_MODE);
+
+#ifdef ANDROID_KERNEL
+	handle->params.wakelock_timeout = wakelock_timeout;
+	if (params)
+		handle->params.wakelock_timeout = params->wakelock_timeout;
+#endif
+	handle->params.dev_cap_mask = dev_cap_mask;
+	if (params)
+		handle->params.dev_cap_mask = params->dev_cap_mask;
+#ifdef SDIO
+	if (sdio_rx_aggr)
+		moal_extflg_set(handle, EXT_SDIO_RX_AGGR);
+#endif
+#if defined(SD8997) || defined(PCIE8997) || defined(USB8997) || defined(SD8977) || defined(SD8987) || defined(SD9098) || defined(USB9098) || defined(PCIE9098) || defined(SD9097) || defined(USB9097) || defined(PCIE9097) || defined(SD8978) || defined(SD9177)
+	if (pmic)
+		moal_extflg_set(handle, EXT_PMIC);
+#endif
+	handle->params.antcfg = antcfg;
+	if (params)
+		handle->params.antcfg = params->antcfg;
+	handle->params.uap_oper_ctrl = uap_oper_ctrl;
+	if (params)
+		handle->params.uap_oper_ctrl = params->uap_oper_ctrl;
+	handle->params.hs_wake_interval = hs_wake_interval;
+	handle->params.indication_gpio = indication_gpio;
+	if (params) {
+		handle->params.hs_wake_interval = params->hs_wake_interval;
+		handle->params.indication_gpio = params->indication_gpio;
+	}
+	if (disconnect_on_suspend)
+		moal_extflg_set(handle, EXT_DISCONNECT_ON_SUSPEND);
+	if (hs_mimo_switch)
+		moal_extflg_set(handle, EXT_HS_MIMO_SWITCH);
+	handle->params.indrstcfg = indrstcfg;
+	if (params)
+		handle->params.indrstcfg = params->indrstcfg;
+	if (fixed_beacon_buffer)
+		moal_extflg_set(handle, EXT_FIX_BCN_BUF);
+#ifdef WIFI_DIRECT_SUPPORT
+	handle->params.GoAgeoutTime = GoAgeoutTime;
+	if (params)
+		handle->params.GoAgeoutTime = params->GoAgeoutTime;
+#endif
+	handle->params.gtk_rekey_offload = gtk_rekey_offload;
+	if (params)
+		handle->params.gtk_rekey_offload = params->gtk_rekey_offload;
+	handle->params.multi_dtim = multi_dtim;
+	handle->params.inact_tmo = inact_tmo;
+	if (params) {
+		handle->params.multi_dtim = params->multi_dtim;
+		handle->params.inact_tmo = params->inact_tmo;
+	}
+	if (napi)
+		moal_extflg_set(handle, EXT_NAPI);
+	if (tx_work)
+		moal_extflg_set(handle, EXT_TX_WORK);
+	if (rps)
+		moal_extflg_set(handle, EXT_RPS);
+	if (tx_skb_clone)
+		moal_extflg_set(handle, EXT_TX_SKB_CLONE);
+	if (pmqos)
+		moal_extflg_set(handle, EXT_PMQOS);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (dfs_offload)
+		moal_extflg_set(handle, EXT_DFS_OFFLOAD);
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (host_mlme)
+		moal_extflg_set(handle, EXT_HOST_MLME);
+#endif
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	if (disable_regd_by_driver)
+		moal_extflg_set(handle, EXT_DISABLE_REGD_BY_DRIVER);
+	if (reg_alpha2)
+		woal_dup_string(&handle->params.reg_alpha2, reg_alpha2);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (country_ie_ignore)
+		moal_extflg_set(handle, EXT_COUNTRY_IE_IGNORE);
+	if (beacon_hints)
+		moal_extflg_set(handle, EXT_BEACON_HINTS);
+#endif
+#endif
+	if (params && params->reg_alpha2)
+		woal_dup_string(&handle->params.reg_alpha2, params->reg_alpha2);
+	if (params)
+		moal_memcpy_ext(handle, handle->params.ext_flgs,
+				params->ext_flgs, sizeof(params->ext_flgs),
+				sizeof(handle->params.ext_flgs));
+
+	/* do some special handle for MFG mode */
+#ifdef MFG_CMD_SUPPORT
+	if (handle->params.mfg_mode) {
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+		handle->params.cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK;
+#else
+		handle->params.cfg80211_wext = 0;
+#endif
+		handle->params.drv_mode = DRV_MODE_STA;
+	}
+#endif
+	if (dfs53cfg > DFS_W53_OLD) {
+		PRINTM(MERROR, "Invalid value for dfs53cfg !\n");
+		handle->params.dfs53cfg = DFS_W53_DEFAULT_FW;
+	} else {
+		handle->params.dfs53cfg = dfs53cfg;
+		if (params)
+			handle->params.dfs53cfg = params->dfs53cfg;
+	}
+}
+
+/**
+ *  @brief This function free module parameter memory
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         N/A
+ */
+void
+woal_free_module_param(moal_handle *handle)
+{
+	moal_mod_para *params = &handle->params;
+	PRINTM(MMSG, "Free module params\n");
+	if (params->fw_name) {
+		kfree(params->fw_name);
+		params->fw_name = NULL;
+	}
+	if (params->hw_name) {
+		kfree(params->hw_name);
+		params->hw_name = NULL;
+	}
+
+	if (params->mac_addr) {
+		kfree(params->mac_addr);
+		params->mac_addr = NULL;
+	}
+#ifdef STA_SUPPORT
+	if (params->sta_name) {
+		kfree(params->sta_name);
+		params->sta_name = NULL;
+	}
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	if (params->uap_name) {
+		kfree(params->uap_name);
+		params->uap_name = NULL;
+	}
+#endif /* UAP_SUPPORT */
+#ifdef WIFI_DIRECT_SUPPORT
+	if (params->wfd_name) {
+		kfree(params->wfd_name);
+		params->wfd_name = NULL;
+	}
+#endif /* WIFI_DIRECT_SUPPORT */
+	if (params->dpd_data_cfg) {
+		kfree(params->dpd_data_cfg);
+		params->dpd_data_cfg = NULL;
+	}
+	if (params->init_cfg) {
+		kfree(params->init_cfg);
+		params->init_cfg = NULL;
+	}
+	if (params->cal_data_cfg) {
+		kfree(params->cal_data_cfg);
+		params->cal_data_cfg = NULL;
+	}
+	if (params->txpwrlimit_cfg) {
+		kfree(params->txpwrlimit_cfg);
+		params->txpwrlimit_cfg = NULL;
+	}
+	if (params->init_hostcmd_cfg) {
+		kfree(params->init_hostcmd_cfg);
+		params->init_hostcmd_cfg = NULL;
+	}
+	if (params->band_steer_cfg) {
+		kfree(params->band_steer_cfg);
+		params->band_steer_cfg = NULL;
+	}
+	if (params->reg_alpha2) {
+		kfree(params->reg_alpha2);
+		params->reg_alpha2 = NULL;
+	}
+}
+
+/**
+ *  @brief This function request module parameter data from user space
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param mod_file A pointer to module parameter file path
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_req_mod_param(moal_handle *handle, char *mod_file)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct device *dev = handle->hotplug_device;
+
+	if (dev == NULL) {
+		PRINTM(MERROR, "No device attached\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+
+	ret = request_firmware(&handle->param_data, mod_file, dev);
+	if (ret < 0)
+		PRINTM(MERROR, "Request firmware: %s failed, error: %d\n",
+		       mod_file, ret);
+out:
+	return ret;
+}
+
+#ifdef CONFIG_OF
+/**
+ *  @brief This function read the initial parameter from device tress
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         N/A
+ */
+void
+woal_init_from_dev_tree(void)
+{
+	struct device_node *dt_node = NULL;
+	struct property *prop;
+	t_u32 data;
+	const char *string_data;
+
+	ENTER();
+
+	if (!dts_enable) {
+		PRINTM(MIOCTL, "DTS is disabled!");
+		return;
+	}
+
+	dt_node = of_find_node_by_name(NULL, "sdxxx-wlan");
+	if (!dt_node) {
+		LEAVE();
+		return;
+	}
+	for_each_property_of_node(dt_node, prop) {
+		if (!strncmp(prop->name, "drv_mode", strlen("drv_mode"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "drv_mode=0x%x\n", data);
+				drv_mode = data;
+			}
+		}
+#ifdef DEBUG_LEVEL1
+		else if (!strncmp(prop->name, "drvdbg", strlen("drvdbg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "drvdbg=0x%x\n", data);
+				drvdbg = data;
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "dev_cap_mask",
+				  strlen("dev_cap_mask"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "dev_cap_mask=0x%x\n", data);
+				dev_cap_mask = data;
+			}
+		} else if (!strncmp(prop->name, "hw_test", strlen("hw_test"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "hw_test=0x%x\n", data);
+				hw_test = data;
+			}
+		}
+#if defined(SDIO)
+		else if (!strncmp(prop->name, "slew_rate", strlen("slew_rate"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "slew_rate=0x%x\n", data);
+				slew_rate = data;
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "tx_work", strlen("tx_work"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "tx_work=0x%x\n", data);
+				tx_work = data;
+			}
+		} else if (!strncmp(prop->name, "rps", strlen("rps"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "rps=0x%x\n", data);
+				rps = data;
+			}
+		} else if (!strncmp(prop->name, "tx_skb_clone",
+				    strlen("tx_skb_clone"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "tx_skb_clone=0x%x\n", data);
+				tx_skb_clone = data;
+			}
+		} else if (!strncmp(prop->name, "pmqos", strlen("pmqos"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "pmqos=0x%x\n", data);
+				pmqos = data;
+			}
+		}
+#ifdef MFG_CMD_SUPPORT
+		else if (!strncmp(prop->name, "mfg_mode", strlen("mfg_mode"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "mfg_mode=0x%x\n", data);
+				mfg_mode = data;
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "mac_addr", strlen("mac_addr"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				mac_addr = (char *)string_data;
+				PRINTM(MIOCTL, "mac_addr=%s\n", mac_addr);
+			}
+		} else if (!strncmp(prop->name, "fw_name", strlen("fw_name"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				fw_name = (char *)string_data;
+				PRINTM(MIOCTL, "fw_name=%s\n", fw_name);
+			}
+		} else if (!strncmp(prop->name, "hw_name", strlen("hw_name"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				hw_name = (char *)string_data;
+				PRINTM(MIOCTL, "hw_name=%s\n", hw_name);
+			}
+		}
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+		else if (!strncmp(prop->name, "cfg80211_wext",
+				  strlen("cfg80211_wext"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "cfg80211_wext=0x%x\n", data);
+				cfg80211_wext = data;
+			}
+		}
+#endif
+#ifdef STA_SUPPORT
+		else if (!strncmp(prop->name, "sta_name", strlen("sta_name"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				sta_name = (char *)string_data;
+				PRINTM(MIOCTL, "sta_name=%s\n", sta_name);
+			}
+		}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		else if (!strncmp(prop->name, "wfd_name", strlen("wfd_name"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				wfd_name = (char *)string_data;
+				PRINTM(MIOCTL, "wfd_name=%s\n", wfd_name);
+			}
+		}
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		else if (!strncmp(prop->name, "disable_regd_by_driver",
+				  strlen("disable_regd_by_driver"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "disable_regd_by_driver=0x%x\n",
+				       data);
+				disable_regd_by_driver = data;
+			}
+		} else if (!strncmp(prop->name, "reg_alpha2",
+				    strlen("reg_alpha2"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				reg_alpha2 = (char *)string_data;
+				PRINTM(MIOCTL, "reg_alpha2=%s\n", reg_alpha2);
+			}
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		else if (!strncmp(prop->name, "country_ie_ignore",
+				  strlen("country_ie_ignore"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "country_ie_ignore=0x%x\n",
+				       data);
+				country_ie_ignore = data;
+			}
+		} else if (!strncmp(prop->name, "beacon_hints",
+				    strlen("beacon_hints"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "beacon_hints=0x%x\n", data);
+				beacon_hints = data;
+			}
+		}
+#endif
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		else if (!strncmp(prop->name, "max_vir_bss",
+				  strlen("max_vir_bss"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "max_vir_bss=0x%x\n", data);
+				max_vir_bss = data;
+			}
+		}
+#endif
+#endif
+		else if (!strncmp(prop->name, "dpd_data_cfg",
+				  strlen("dpd_data_cfg"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				dpd_data_cfg = (char *)string_data;
+				PRINTM(MIOCTL, "dpd_data_cfg=%s\n",
+				       dpd_data_cfg);
+			}
+		} else if (!strncmp(prop->name, "init_cfg", strlen("init_cfg"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				init_cfg = (char *)string_data;
+				PRINTM(MIOCTL, "init_cfg=%s\n", init_cfg);
+			}
+		} else if (!strncmp(prop->name, "cal_data_cfg",
+				    strlen("cal_data_cfg"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				cal_data_cfg = (char *)string_data;
+				PRINTM(MIOCTL, "cal_data_cfg=%s\n",
+				       cal_data_cfg);
+			}
+		} else if (!strncmp(prop->name, "txpwrlimit_cfg",
+				    strlen("txpwrlimit_cfg"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				txpwrlimit_cfg = (char *)string_data;
+				PRINTM(MIOCTL, "txpwrlimit_cfg=%s\n",
+				       txpwrlimit_cfg);
+			}
+		} else if (!strncmp(prop->name, "cntry_txpwr",
+				    strlen("cntry_txpwr"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				cntry_txpwr = data;
+				PRINTM(MIOCTL, "cntry_txpwr=%d\n", cntry_txpwr);
+			}
+		} else if (!strncmp(prop->name, "init_hostcmd_cfg",
+				    strlen("init_hostcmd_cfg"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				init_hostcmd_cfg = (char *)string_data;
+				PRINTM(MIOCTL, "init_hostcmd_cfg=%s\n",
+				       init_hostcmd_cfg);
+			}
+		} else if (!strncmp(prop->name, "band_steer_cfg",
+				    strlen("band_steer_cfg"))) {
+			if (!of_property_read_string(dt_node, prop->name,
+						     &string_data)) {
+				band_steer_cfg = (char *)string_data;
+				PRINTM(MIOCTL, "band_steer_cfg=%s\n",
+				       band_steer_cfg);
+			}
+		} else if (!strncmp(prop->name, "pmic", strlen("pmic"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				pmic = data;
+				PRINTM(MIOCTL, "pmic=%d\n", pmic);
+			}
+		} else if (!strncmp(prop->name, "antcfg", strlen("antcfg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				antcfg = data;
+				PRINTM(MIOCTL, "antcfg=%d\n", antcfg);
+			}
+		} else if (!strncmp(prop->name, "hs_wake_interval",
+				    strlen("hs_wake_interval"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				hs_wake_interval = data;
+				PRINTM(MIOCTL, "hs_wake_interval=%d\n",
+				       hs_wake_interval);
+			}
+		} else if (!strncmp(prop->name, "indication_gpio",
+				    strlen("indication_gpio"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				indication_gpio = (t_u8)data;
+				PRINTM(MIOCTL, "indication_gpio=%d\n",
+				       indication_gpio);
+			}
+		} else if (!strncmp(prop->name, "hs_mimo_switch",
+				    strlen("hs_mimo_switch"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				hs_mimo_switch = data;
+				PRINTM(MIOCTL, "hs_mimo_switch=%d\n",
+				       hs_mimo_switch);
+			}
+		}
+#ifdef WIFI_DIRECT_SUPPORT
+		else if (!strncmp(prop->name, "GoAgeoutTime",
+				  strlen("GoAgeoutTime"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				GoAgeoutTime = data;
+				PRINTM(MIOCTL, "GoAgeoutTime=%d\n",
+				       GoAgeoutTime);
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "indrstcfg", strlen("indrstcfg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				indrstcfg = data;
+				PRINTM(MIOCTL, "indrstcfg=%d\n", indrstcfg);
+			}
+		} else if (!strncmp(prop->name, "fixed_beacon_buffer",
+				    strlen("fixed_beacon_buffer"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				fixed_beacon_buffer = data;
+				PRINTM(MIOCTL, "fixed_beacon_buffer=%d\n",
+				       fixed_beacon_buffer);
+			}
+		} else if (!strncmp(prop->name, "multi_dtim",
+				    strlen("multi_dtim"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				multi_dtim = data;
+				PRINTM(MIOCTL, "multi_dtim=%d\n", multi_dtim);
+			}
+		} else if (!strncmp(prop->name, "inact_tmo",
+				    strlen("inact_tmo"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				inact_tmo = data;
+				PRINTM(MIOCTL, "inact_tmo=%d\n", inact_tmo);
+			}
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		else if (!strncmp(prop->name, "dfs_offload",
+				  strlen("dfs_offload"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				dfs_offload = data;
+				PRINTM(MIOCTL, "dfs_offload=%d\n", dfs_offload);
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "gtk_rekey_offload",
+				  strlen("gtk_rekey_offload"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				gtk_rekey_offload = data;
+				PRINTM(MIOCTL, "gtk_rekey_offload=%d\n",
+				       gtk_rekey_offload);
+			}
+		}
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		else if (!strncmp(prop->name, "host_mlme", strlen("host_mlme"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "host_mlme=0x%x\n", data);
+				host_mlme = data;
+			}
+		}
+#endif
+#endif
+#ifdef UAP_SUPPORT
+		else if (!strncmp(prop->name, "uap_max_sta",
+				  strlen("uap_max_sta"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MERROR, "uap_max_sta=0x%x\n", data);
+				uap_max_sta = data;
+			}
+		} else if (!strncmp(prop->name, "wacp_mode",
+				    strlen("wacp_mode"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MERROR, "wacp_mode=0x%x\n", data);
+				wacp_mode = data;
+			}
+		}
+#endif
+		else if (!strncmp(prop->name, "sched_scan",
+				  strlen("sched_scan"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "sched_scan=%d\n", data);
+				sched_scan = data;
+			}
+		}
+	}
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief This function check if configuration block id could be used
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_validate_cfg_id(moal_handle *handle)
+{
+	int i;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	for (i = 0; i < MAX_MLAN_ADAPTER; i++) {
+		if (m_handle[i] == NULL || m_handle[i] == handle)
+			continue;
+		if (m_handle[i]->card_type == handle->card_type) {
+			if (m_handle[i]->blk_id == handle->blk_id) {
+				ret = MLAN_STATUS_FAILURE;
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function skip current configuration block
+ *
+ *  @param data   A pointer to buffer of module configuration file
+ *  @param size   Size of module configuration file
+ *
+ *  @return       MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+parse_skip_cfg_block(t_u8 *data, t_u32 size)
+{
+	int end = 0;
+	t_u8 line[MAX_LINE_LEN];
+	while ((int)parse_cfg_get_line(data, size, line) != -1) {
+		if (strncmp(line, "}", strlen("}")) == 0) {
+			end = 1;
+			break;
+		}
+		if (end == 0 && strstr(line, "{") != NULL)
+			break;
+	}
+	return (end == 1) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function handle fallback processing for invalid
+ *  block id with same card type
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return       MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_cfg_fallback_process(moal_handle *handle)
+{
+	int i, blk_id = 0x7fffffff, idx = -1;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	PRINTM(MMSG, "Configuration block, fallback processing\n");
+	for (i = 0; i < MAX_MLAN_ADAPTER; i++) {
+		if (m_handle[i] == NULL || m_handle[i] == handle ||
+		    m_handle[i]->card_type != handle->card_type)
+			continue;
+		/* use configuratino with lowest blk_id value */
+		if (m_handle[i]->blk_id >= 0 && m_handle[i]->blk_id <= blk_id) {
+			idx = i;
+			blk_id = m_handle[i]->blk_id;
+		}
+	}
+	if (idx >= 0 && idx < MAX_MLAN_ADAPTER) {
+		ret = MLAN_STATUS_SUCCESS;
+		handle->blk_id = m_handle[idx]->blk_id;
+		PRINTM(MMSG,
+		       "Configuration fallback to, card_type: 0x%x, blk_id: 0x%x\n",
+		       handle->card_type, handle->blk_id);
+		woal_setup_module_param(handle, &m_handle[idx]->params);
+	}
+	return ret;
+}
+
+/**
+ *  @brief This function parse and initialize module parameters
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_init_module_param(moal_handle *handle)
+{
+	int no_match = 1;
+	t_u32 size, i, tbl_size;
+	t_u8 line[MAX_LINE_LEN], *data = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	char *card_type = NULL, *blk_id = NULL;
+
+	memset(line, 0, MAX_LINE_LEN);
+	woal_setup_module_param(handle, NULL);
+	if (mod_para == NULL) {
+		PRINTM(MMSG, "No module param cfg file specified\n");
+		goto out;
+	}
+	if (woal_req_mod_param(handle, mod_para)) {
+		PRINTM(MERROR, "Failed to get module param file\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	tbl_size = sizeof(card_type_map_tbl) / sizeof(card_type_map_tbl[0]);
+	for (i = 0; i < tbl_size; i++)
+		if (handle->card_type == card_type_map_tbl[i].card_type)
+			break;
+	if (i >= tbl_size) {
+		PRINTM(MERROR, "No card type entry found for card type: 0x%x\n",
+		       handle->card_type);
+		ret = MLAN_STATUS_FAILURE;
+		goto out;
+	}
+	PRINTM(MMSG, "%s: init module param from usr cfg\n",
+	       card_type_map_tbl[i].name);
+	size = handle->param_data->size;
+	data = (t_u8 *)handle->param_data->data;
+	while ((int)parse_cfg_get_line(data, size, line) != -1) {
+		if (line[0] == '#')
+			continue;
+		if (strstr(line, "={")) {
+			ret = parse_line_read_card_info(line,
+							&card_type, &blk_id);
+			if (ret != MLAN_STATUS_SUCCESS)
+				goto out;
+			PRINTM(MINFO,
+			       "Traverse, card_type: %s, config block: %s\n",
+			       card_type, blk_id);
+			if (strcmp(card_type_map_tbl[i].name, card_type) == 0) {
+				/* parse config block id */
+				if (blk_id == NULL)
+					handle->blk_id = 0;
+				else
+					woal_atoi(&handle->blk_id, blk_id);
+				PRINTM(MINFO,
+				       "Validation check, %s, config block: %d\n",
+				       card_type, handle->blk_id);
+				/* check validation of config id */
+				if (woal_validate_cfg_id(handle) !=
+				    MLAN_STATUS_SUCCESS) {
+					ret = parse_skip_cfg_block(data, size);
+					if (ret != MLAN_STATUS_SUCCESS) {
+						PRINTM(MMSG,
+						       "failed to skip block\n");
+						goto out;
+					}
+					continue;
+				}
+				no_match = 0;
+				PRINTM(MMSG,
+				       "card_type: %s, config block: %d\n",
+				       card_type, handle->blk_id);
+				/* parse config block */
+				ret = parse_cfg_read_block(data, size, handle);
+				if (ret != MLAN_STATUS_SUCCESS)
+					goto out;
+				break;
+			}
+		}
+	}
+	if (no_match)
+		ret = woal_cfg_fallback_process(handle);
+out:
+	if (handle->param_data) {
+		release_firmware(handle->param_data);
+		/* rewind pos */
+		parse_cfg_get_line(NULL, 0, NULL);
+	}
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Invalid block: %s\n", line);
+		woal_free_module_param(handle);
+		woal_setup_module_param(handle, NULL);
+	}
+	return ret;
+}
+
+module_param(mod_para, charp, 0);
+MODULE_PARM_DESC(mod_para, "Module parameters configuration file");
+module_param(hw_test, int, 0660);
+MODULE_PARM_DESC(hw_test, "0: Disable hardware test; 1: Enable hardware test");
+#ifdef CONFIG_OF
+module_param(dts_enable, int, 0);
+MODULE_PARM_DESC(dts_enable, "0: Disable DTS; 1: Enable DTS");
+#endif
+module_param(hw_name, charp, 0660);
+MODULE_PARM_DESC(hw_name, "hardware name");
+
+module_param(fw_name, charp, 0660);
+MODULE_PARM_DESC(fw_name, "Firmware name");
+module_param(req_fw_nowait, int, 0);
+MODULE_PARM_DESC(req_fw_nowait,
+		 "0: Use request_firmware API; 1: Use request_firmware_nowait API");
+module_param(fw_reload, int, 0);
+MODULE_PARM_DESC(fw_reload,
+		 "0: disable fw_reload; 1: enable fw reload feature");
+module_param(fw_serial, int, 0);
+MODULE_PARM_DESC(fw_serial,
+		 "0: support parallel download FW; 1: support serial download FW");
+module_param(mac_addr, charp, 0660);
+MODULE_PARM_DESC(mac_addr, "MAC address");
+#ifdef MFG_CMD_SUPPORT
+module_param(mfg_mode, int, 0660);
+MODULE_PARM_DESC(mfg_mode,
+		 "0: Download normal firmware; 1: Download MFG firmware");
+#endif /* MFG_CMD_SUPPORT */
+module_param(drv_mode, int, 0660);
+MODULE_PARM_DESC(drv_mode, "Bit 0: STA; Bit 1: uAP; Bit 2: WIFIDIRECT");
+
+#ifdef STA_SUPPORT
+module_param(max_sta_bss, int, 0);
+MODULE_PARM_DESC(max_sta_bss, "Number of STA interfaces (1)");
+module_param(sta_name, charp, 0);
+MODULE_PARM_DESC(sta_name, "STA interface name");
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+module_param(max_uap_bss, int, 0);
+MODULE_PARM_DESC(max_uap_bss, "Number of uAP interfaces (1)");
+module_param(uap_name, charp, 0);
+MODULE_PARM_DESC(uap_name, "uAP interface name");
+#endif /* UAP_SUPPORT */
+#ifdef WIFI_DIRECT_SUPPORT
+module_param(max_wfd_bss, int, 0);
+MODULE_PARM_DESC(max_wfd_bss, "Number of WIFIDIRECT interfaces (1)");
+module_param(wfd_name, charp, 0);
+MODULE_PARM_DESC(wfd_name, "WIFIDIRECT interface name");
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+module_param(max_vir_bss, int, 0);
+MODULE_PARM_DESC(max_vir_bss, "Number of Virtual interfaces (0)");
+#endif
+#endif /* WIFI_DIRECT_SUPPORT */
+#ifdef DEBUG_LEVEL1
+module_param(drvdbg, uint, 0660);
+MODULE_PARM_DESC(drvdbg, "Driver debug");
+#endif /* DEBUG_LEVEL1 */
+module_param(auto_ds, int, 0660);
+MODULE_PARM_DESC(auto_ds,
+		 "0: MLAN default; 1: Enable auto deep sleep; 2: Disable auto deep sleep");
+module_param(ext_scan, int, 0660);
+MODULE_PARM_DESC(ext_scan,
+		 "0: MLAN default; 1: Enable Extended Scan; 2: Enable Enhanced Extended Scan");
+module_param(ps_mode, int, 0660);
+MODULE_PARM_DESC(ps_mode,
+		 "0: MLAN default; 1: Enable IEEE PS mode; 2: Disable IEEE PS mode");
+module_param(p2a_scan, int, 0660);
+MODULE_PARM_DESC(p2a_scan,
+		 "0: MLAN default; 1: Enable passive to active scan for DFS channel; 2: Disable passive to active scan for DFS channel");
+module_param(scan_chan_gap, int, 0660);
+MODULE_PARM_DESC(scan_chan_gap,
+		 "Time gap between two scans in milliseconds when connected to AP(max value 500ms)");
+module_param(sched_scan, int, 0);
+MODULE_PARM_DESC(sched_scan,
+		 "0: disable sched_scan; 1: enable sched_scan default");
+module_param(max_tx_buf, int, 0);
+MODULE_PARM_DESC(max_tx_buf, "Maximum Tx buffer size (2048/4096/8192)");
+
+#if defined(SDIO)
+module_param(intmode, int, 0);
+MODULE_PARM_DESC(intmode, "0: INT_MODE_SDIO, 1: INT_MODE_GPIO");
+module_param(gpiopin, int, 0);
+MODULE_PARM_DESC(gpiopin, "255:new GPIO int mode, other vlue: gpio pin number");
+#endif
+
+module_param(pm_keep_power, int, 0);
+MODULE_PARM_DESC(pm_keep_power, "1: PM keep power; 0: PM no power");
+#ifdef SDIO_SUSPEND_RESUME
+module_param(shutdown_hs, int, 0);
+MODULE_PARM_DESC(shutdown_hs,
+		 "1: Enable HS when shutdown; 0: No HS when shutdown");
+#endif
+#if defined(STA_SUPPORT)
+module_param(cfg_11d, int, 0);
+MODULE_PARM_DESC(cfg_11d,
+		 "0: MLAN default; 1: Enable 802.11d; 2: Disable 802.11d");
+#endif
+#if defined(SDIO)
+module_param(slew_rate, int, 0);
+MODULE_PARM_DESC(slew_rate,
+		 "0:has the slowest slew rate, then 01, then 02, and 03 has the highest slew rate");
+#endif
+module_param(tx_work, uint, 0660);
+MODULE_PARM_DESC(tx_work, "1: Enable tx_work; 0: Disable tx_work");
+module_param(rps, uint, 0660);
+MODULE_PARM_DESC(rps, "1: Enable rps; 0: Disable rps");
+module_param(tx_skb_clone, uint, 0660);
+MODULE_PARM_DESC(tx_skb_clone,
+		 "1: Enable tx_skb_clone; 0: Disable tx_skb_clone");
+module_param(pmqos, uint, 0660);
+MODULE_PARM_DESC(pmqos, "1: Enable pmqos; 0: Disable pmqos");
+
+module_param(dpd_data_cfg, charp, 0);
+MODULE_PARM_DESC(dpd_data_cfg, "DPD data file name");
+module_param(init_cfg, charp, 0);
+MODULE_PARM_DESC(init_cfg, "Init config file name");
+module_param(cal_data_cfg, charp, 0);
+MODULE_PARM_DESC(cal_data_cfg, "Calibration data file name");
+module_param(txpwrlimit_cfg, charp, 0);
+MODULE_PARM_DESC(txpwrlimit_cfg,
+		 "Set configuration data of Tx power limitation");
+module_param(cntry_txpwr, int, 0);
+MODULE_PARM_DESC(cntry_txpwr,
+		 "0: disable (default), 1: enable set country txpower table 2: enable set country rgpower table");
+module_param(init_hostcmd_cfg, charp, 0);
+MODULE_PARM_DESC(init_hostcmd_cfg, "Init hostcmd file name");
+module_param(band_steer_cfg, charp, 0);
+MODULE_PARM_DESC(band_steer_cfg, "band steer cfg file name");
+module_param(cfg80211_wext, int, 0660);
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+MODULE_PARM_DESC(cfg80211_wext,
+		 "Bit 0: STA WEXT Bit 1: UAP WEXT Bit 2: STA CFG80211 Bit 3: UAP CFG80211");
+#else
+MODULE_PARM_DESC(cfg80211_wext, "Bit 0: STA WEXT Bit 1: UAP WEXT Bit 2");
+#endif
+#if defined(USB)
+module_param(skip_fwdnld, int, 0);
+MODULE_PARM_DESC(skip_fwdnld, "0: Enable FW download; 1: Disable FW download");
+#endif
+module_param(wq_sched_prio, int, 0);
+module_param(wq_sched_policy, int, 0);
+MODULE_PARM_DESC(wq_sched_prio, "Priority of work queue");
+MODULE_PARM_DESC(wq_sched_policy,
+		 "0: SCHED_NORMAL; 1: SCHED_FIFO; 2: SCHED_RR; 3: SCHED_BATCH; 5: SCHED_IDLE");
+module_param(rx_work, int, 0);
+MODULE_PARM_DESC(rx_work,
+		 "0: default; 1: Enable rx_work_queue; 2: Disable rx_work_queue");
+module_param(aggrctrl, int, 0);
+MODULE_PARM_DESC(aggrctrl,
+		 "1: Enable Tx aggregation; 0: Disable Tx aggregation");
+#ifdef USB
+module_param(usb_aggr, int, 0);
+MODULE_PARM_DESC(usb_aggr,
+		 "0: MLAN default; 1: Enable USB aggr; 2: Disable USB aggr");
+#endif
+#ifdef PCIE
+module_param(ring_size, int, 0);
+MODULE_PARM_DESC(ring_size,
+		 "adma dma ring size: 32/64/128/256/512, default 128");
+module_param(pcie_int_mode, int, 0);
+MODULE_PARM_DESC(pcie_int_mode, "0: Legacy mode; 1: MSI mode; 2: MSI-X mode");
+#endif /* PCIE */
+module_param(low_power_mode_enable, int, 0);
+MODULE_PARM_DESC(low_power_mode_enable, "0/1: Disable/Enable Low Power Mode");
+
+#ifdef ANDROID_KERNEL
+module_param(wakelock_timeout, int, 0);
+MODULE_PARM_DESC(wakelock_timeout, "set wakelock_timeout value (ms)");
+#endif
+
+module_param(dev_cap_mask, uint, 0);
+MODULE_PARM_DESC(dev_cap_mask, "Device capability mask");
+module_param(net_rx, int, 0);
+MODULE_PARM_DESC(net_rx,
+		 "0: use netif_rx_ni in rx; 1: use netif_receive_skb in rx");
+module_param(amsdu_deaggr, int, 0);
+MODULE_PARM_DESC(amsdu_deaggr,
+		 "0: default; 1: Try to avoid buf copy in amsud deaggregation");
+
+#ifdef SDIO
+module_param(sdio_rx_aggr, int, 0);
+MODULE_PARM_DESC(sdio_rx_aggr,
+		 "1: Enable SDIO rx aggr; 0: Disable SDIO rx aggr");
+#endif
+
+module_param(pmic, int, 0);
+MODULE_PARM_DESC(pmic,
+		 "1: Send pmic configure cmd to firmware; 0: No pmic configure cmd sent to firmware");
+
+module_param(antcfg, int, 0660);
+MODULE_PARM_DESC(antcfg,
+		 "0:default; SD8887/SD8987-[1:Tx/Rx antenna 1, 2:Tx/Rx antenna 2, 0xffff:enable antenna diversity];SD8897/SD8997-[Bit0:Rx Path A, Bit1:Rx Path B, Bit 4:Tx Path A, Bit 5:Tx Path B];9098/9097-[Bit 0: 2G Tx/Rx path A, Bit 1: 2G Tx/Rx path B,Bit 8: 5G Tx/Rx path A, Bit 9: 5G Tx/Rx path B]");
+
+module_param(uap_oper_ctrl, uint, 0);
+MODULE_PARM_DESC(uap_oper_ctrl, "0:default; 0x20001:uap restarts on channel 6");
+
+module_param(hs_wake_interval, int, 0660);
+MODULE_PARM_DESC(hs_wake_interval,
+		 "Host sleep wakeup interval,it will round to nearest multiple dtim*beacon_period in fw");
+module_param(indication_gpio, int, 0);
+MODULE_PARM_DESC(indication_gpio,
+		 "GPIO to indicate wakeup source; high four bits: level for normal wakeup; low four bits: GPIO pin number.");
+module_param(disconnect_on_suspend, int, 0);
+MODULE_PARM_DESC(disconnect_on_suspend,
+		 "1: Enable disconnect wifi on suspend; 0: Disable disconnect wifi on suspend");
+module_param(hs_mimo_switch, int, 0660);
+MODULE_PARM_DESC(hs_mimo_switch,
+		 "Dynamic MIMO-SISO switch during host sleep; 0: disable (default), 1: enable");
+
+module_param(indrstcfg, int, 0);
+MODULE_PARM_DESC(indrstcfg,
+		 "Independent reset configuration; high byte: GPIO pin number; low byte: IR mode");
+
+module_param(fixed_beacon_buffer, int, 0);
+MODULE_PARM_DESC(fixed_beacon_buffer,
+		 "0: allocate default buffer size; 1: allocate max buffer size.");
+
+#ifdef WIFI_DIRECT_SUPPORT
+module_param(GoAgeoutTime, int, 0);
+MODULE_PARM_DESC(GoAgeoutTime,
+		 "0: use default ageout time; set Go age out time (TU 100ms)");
+#endif
+
+module_param(gtk_rekey_offload, int, 0);
+MODULE_PARM_DESC(gtk_rekey_offload,
+		 "0: disable gtk_rekey_offload; 1: enable gtk_rekey_offload (default); 2: enable gtk_rekey_offload in suspend mode only;");
+
+module_param(multi_dtim, ushort, 0);
+MODULE_PARM_DESC(multi_dtim, "DTIM interval");
+
+module_param(inact_tmo, ushort, 0);
+MODULE_PARM_DESC(inact_tmo, "IEEE ps inactivity timout value");
+
+module_param(napi, int, 0);
+MODULE_PARM_DESC(napi, "1: enable napi api; 0: disable napi");
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+module_param(dfs_offload, int, 0);
+MODULE_PARM_DESC(dfs_offload, "1: enable dfs offload; 0: disable dfs offload.");
+#endif
+
+#ifdef UAP_SUPPORT
+module_param(uap_max_sta, int, 0);
+MODULE_PARM_DESC(uap_max_sta, "Maximum station number for UAP/GO.");
+module_param(wacp_mode, int, 0);
+MODULE_PARM_DESC(wacp_mode,
+		 "WACP mode for UAP/GO 0: WACP_MODE_DEFAULT; 1: WACP_MODE_1; 2: WACP_MODE_2");
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+module_param(host_mlme, int, 0);
+MODULE_PARM_DESC(host_mlme,
+		 "1: Enable Host MLME Support; 0: Disable Host MLME support");
+#endif
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+module_param(disable_regd_by_driver, int, 0);
+MODULE_PARM_DESC(disable_regd_by_driver,
+		 "0: reg domain set by driver enable(default); 1: reg domain set by driver disable");
+module_param(reg_alpha2, charp, 0660);
+MODULE_PARM_DESC(reg_alpha2, "Regulatory alpha2");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+module_param(country_ie_ignore, int, 0);
+MODULE_PARM_DESC(country_ie_ignore,
+		 "0: Follow countryIE from AP and beacon hint enable; 1: Ignore countryIE from AP and beacon hint disable");
+module_param(beacon_hints, int, 0);
+MODULE_PARM_DESC(beacon_hints,
+		 "0: enable beacon hints(default); 1: disable beacon hints");
+#endif
+#endif
+
+module_param(dfs53cfg, int, 0);
+MODULE_PARM_DESC(dfs53cfg, "0: fw default; 1: new w53 dfs; 2: old w53 dfs");
diff --git a/wlan_sd8987/mlinux/moal_ioctl.c b/wlan_sd8987/mlinux/moal_ioctl.c
new file mode 100755
index 0000000..7593db2
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_ioctl.c
@@ -0,0 +1,7728 @@
+/** @file moal_ioctl.c
+ *
+ * @brief This file contains ioctl function to MLAN
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#include "moal_eth_ioctl.h"
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif
+#ifdef USB
+#include "moal_usb.h"
+#endif
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#include "moal_cfg80211_util.h"
+#endif
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+#define MRVL_TLV_HEADER_SIZE 4
+/* NXP Channel config TLV ID */
+#define MRVL_CHANNELCONFIG_TLV_ID (0x0100 + 0x2a)	/* 0x012a */
+
+typedef struct _hostcmd_header {
+	/** Command Header : Command */
+	t_u16 command;
+	/** Command Header : Size */
+	t_u16 size;
+	/** Command Header : Sequence number */
+	t_u16 seq_num;
+	/** Command Header : Result */
+	t_u16 result;
+	/** Command action */
+	t_u16 action;
+} hostcmd_header, *phostcmd_header;
+
+/** Region code mapping */
+typedef struct _region_code_mapping_t {
+	/** Region */
+	t_u8 region[COUNTRY_CODE_LEN];
+	/** Code */
+	t_u8 code;
+} region_code_mapping_t;
+
+#define EU_REGION_CODE 0x30
+
+/** Region code mapping table */
+static region_code_mapping_t region_code_mapping[] = {
+	{"00", 0x00},		/* World       */
+	{"US", 0x10},		/* US FCC      */
+	{"CA", 0x20},		/* IC Canada   */
+	{"SG", 0x10},		/* Singapore   */
+	{"EU", 0x30},		/* ETSI        */
+	{"AU", 0x30},		/* Australia   */
+	{"KR", 0x30},		/* Republic Of Korea */
+	{"JP", 0x40},		/* Japan       */
+	{"CN", 0x50},		/* China       */
+	{"BR", 0x09},		/* Brazil      */
+	{"RU", 0x0f},		/* Russia      */
+	{"IN", 0x06},		/* India       */
+	{"MY", 0x06},		/* Malaysia    */
+	{"MX", 0x07},		/* Mexico    */
+	{"NE", 0x30},		/* New Zeland  */
+};
+
+/** EEPROM Region code mapping table */
+static region_code_mapping_t hw_region_code_mapping[] = {
+	{"00 ", 0x00},		/* World       */
+	{"US ", 0x10},		/* US FCC      */
+	{"CA ", 0x20},		/* IC Canada   */
+	{"KR ", 0x30},		/* Korea       */
+	{"CN ", 0x50},		/* China       */
+	{"ES ", 0x31},		/* Spain       */
+	{"FR ", 0x32},		/* France      */
+	{"JP ", 0x40},		/* Japan       */
+	{"JP ", 0x41},		/* Japan       */
+};
+
+/** Country code for ETSI */
+static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
+	"AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY", "CZ", "DK",
+	"EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "KR", "LV",
+	"LI", "LT", "LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "RU",
+	"SM", "RS", "SI", "SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NE"
+};
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#ifdef UAP_SUPPORT
+/** Network device handlers for uAP */
+extern const struct net_device_ops woal_uap_netdev_ops;
+#endif
+#ifdef STA_SUPPORT
+/** Network device handlers for STA */
+extern const struct net_device_ops woal_netdev_ops;
+#endif
+#endif
+
+/********************************************************
+			Local Functions
+********************************************************/
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param country_code     Region string
+ *
+ *  @return                 Region code
+ */
+static t_bool
+woal_is_country_code_supported(t_u8 *country_code)
+{
+	t_u8 i;
+	ENTER();
+
+	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
+		if (!memcmp(country_code, region_code_mapping[i].region,
+			    COUNTRY_CODE_LEN - 1)) {
+			PRINTM(MIOCTL,
+			       "found country code in region_code table\n");
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param region_string    Region string
+ *
+ *  @return                 Region code
+ */
+static t_u8
+region_string_2_region_code(char *region_string)
+{
+	t_u8 i;
+
+	ENTER();
+	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
+		if (!memcmp(region_string, region_code_mapping[i].region,
+			    strlen(region_string))) {
+			LEAVE();
+			return region_code_mapping[i].code;
+		}
+	}
+
+	/* If still not found, look for code in EU country code table */
+	for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
+		if (!memcmp(region_string, eu_country_code_table[i],
+			    COUNTRY_CODE_LEN - 1)) {
+			PRINTM(MIOCTL, "found region code=%d in EU table\n",
+			       EU_REGION_CODE);
+			LEAVE();
+			return EU_REGION_CODE;
+		}
+	}
+
+	/* Default is US */
+	LEAVE();
+	return region_code_mapping[0].code;
+}
+
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param country_code     Region string
+ *
+ *  @return                 Region code
+ */
+t_bool
+woal_is_etsi_country(t_u8 *country_code)
+{
+	t_u8 i;
+	ENTER();
+
+	for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
+		if (!memcmp(country_code, eu_country_code_table[i],
+			    COUNTRY_CODE_LEN - 1)) {
+			PRINTM(MIOCTL, "found region code=%d in EU table\n",
+			       EU_REGION_CODE);
+			LEAVE();
+			return MTRUE;
+		}
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief This function converts region string to region code
+ *
+ *  @param region_code      region code
+ *
+ *  @return                 Region string or NULL
+ */
+char *
+region_code_2_string(t_u8 region_code)
+{
+	t_u8 i;
+
+	ENTER();
+	for (i = 0; i < ARRAY_SIZE(hw_region_code_mapping); i++) {
+		if (hw_region_code_mapping[i].code == region_code) {
+			LEAVE();
+			return hw_region_code_mapping[i].region;
+		}
+	}
+	LEAVE();
+	return NULL;
+}
+
+t_u8
+woal_is_valid_alpha2(char *alpha2)
+{
+	if (!alpha2 || strlen(alpha2) < 2)
+		return MFALSE;
+	if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
+		return MTRUE;
+	return MFALSE;
+}
+
+/**
+ * @brief Get second channel offset
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param chan             channel num
+ * @return                second channel offset
+ */
+t_u8
+woal_get_second_channel_offset(moal_private *priv, int chan)
+{
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+	mlan_bss_info bss_info;
+
+	/* Special Case: 20Mhz-only Channel */
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (chan == 165)
+		return chan2Offset;
+
+	switch (chan) {
+	case 36:
+	case 44:
+	case 52:
+	case 60:
+	case 100:
+	case 108:
+	case 116:
+	case 124:
+	case 132:
+	case 140:
+	case 149:
+	case 157:
+		chan2Offset = SEC_CHAN_ABOVE;
+		break;
+	case 40:
+	case 48:
+	case 56:
+	case 64:
+	case 104:
+	case 112:
+	case 120:
+	case 128:
+	case 136:
+	case 144:
+	case 153:
+	case 161:
+		chan2Offset = SEC_CHAN_BELOW;
+		break;
+	}
+	return chan2Offset;
+}
+
+/**
+ *  @brief Copy mc address to the mlist
+ *
+ *  @param mlist    A pointer to mlan_multicast_list structure
+ *  @param mac      mc address
+ *
+ *  @return         N/A
+ */
+static inline void
+woal_copy_mc_addr(mlan_multicast_list *mlist, mlan_802_11_mac_addr mac)
+{
+	t_u32 i = 0;
+	for (i = 0; i < mlist->num_multicast_addr; i++) {
+		if (!memcmp(&mlist->mac_list[i], mac, ETH_ALEN))
+			return;
+	}
+	if (mlist->num_multicast_addr < MLAN_MAX_MULTICAST_LIST_SIZE)
+		moal_memcpy_ext(NULL,
+				&mlist->mac_list[mlist->num_multicast_addr],
+				mac, ETH_ALEN, sizeof(mlan_802_11_mac_addr));
+	mlist->num_multicast_addr++;
+	return;
+}
+
+/**
+ *  @brief Copy multicast table
+ *
+ *  @param mlist    A pointer to mlan_multicast_list structure
+ *  @param dev      A pointer to net_device structure
+ *
+ *  @return         Number of multicast addresses
+ */
+static inline int
+woal_copy_mcast_addr(mlan_multicast_list *mlist, struct net_device *dev)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+	struct dev_mc_list *mcptr = dev->mc_list;
+	int i = 0;
+#else
+	struct netdev_hw_addr *mcptr = NULL;
+#endif /* < 2.6.35 */
+
+	ENTER();
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+	for (i = 0; i < dev->mc_count && mcptr; i++) {
+		woal_copy_mc_addr(mlist, mcptr->dmi_addr);
+		mcptr = mcptr->next;
+	}
+#else
+	netdev_for_each_mc_addr(mcptr, dev)
+		woal_copy_mc_addr(mlist, mcptr->addr);
+#endif /* < 2.6.35 */
+	LEAVE();
+	return mlist->num_multicast_addr;
+}
+
+/**
+ *  @brief copy mc list from all the active interface
+ *
+ *  @param handle  A pointer to moal_handle
+ *  @param mlist  A pointer to multicast list
+ *
+ *  @return       total_mc_count
+ */
+static int
+woal_copy_all_mc_list(moal_handle *handle, mlan_multicast_list *mlist)
+{
+	int i;
+	moal_private *priv = NULL;
+#ifdef STA_SUPPORT
+	int mc_count = 0;
+#endif
+	ENTER();
+	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
+			if (handle->priv[i]->media_connected == MTRUE) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+				mc_count = priv->netdev->mc_count;
+#else
+				mc_count = netdev_mc_count(priv->netdev);
+#endif
+				if (mc_count)
+					woal_copy_mcast_addr(mlist,
+							     priv->netdev);
+			}
+		}
+#endif
+	}
+	PRINTM(MIOCTL, "total mc_count=%d\n", mlist->num_multicast_addr);
+	LEAVE();
+	return mlist->num_multicast_addr;
+}
+
+/**
+ *  @brief Fill in wait queue
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait         A pointer to wait_queue structure
+ *  @param wait_option  Wait option
+ *
+ *  @return             N/A
+ */
+static inline void
+woal_fill_wait_queue(moal_private *priv, wait_queue *wait, t_u8 wait_option)
+{
+	ENTER();
+	wait->start_time = jiffies;
+	wait->condition = MFALSE;
+	wait->wait_timeout = MFALSE;
+	switch (wait_option) {
+	case MOAL_NO_WAIT:
+		break;
+	case MOAL_IOCTL_WAIT:
+		init_waitqueue_head(&wait->wait);
+		break;
+	case MOAL_IOCTL_WAIT_TIMEOUT:
+		init_waitqueue_head(&wait->wait);
+		wait->wait_timeout = MTRUE;
+		break;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Wait mlan ioctl complete
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param req          A pointer to mlan_ioctl_req structure
+ *  @param wait_option  Wait option
+ *
+ *  @return             N/A
+ */
+static inline mlan_status
+woal_wait_ioctl_complete(moal_private *priv,
+			 mlan_ioctl_req *req, t_u8 wait_option)
+{
+	mlan_status status;
+	wait_queue *wait = (wait_queue *)req->reserved_1;
+	unsigned long flags;
+
+	ENTER();
+
+	priv->phandle->ioctl_timeout = MFALSE;
+
+	switch (wait_option) {
+	case MOAL_NO_WAIT:
+		break;
+	case MOAL_IOCTL_WAIT:
+		while (wait_event_interruptible_exclusive
+		       (wait->wait, wait->condition) == -ERESTARTSYS &&
+		       wait->retry < MAX_RETRY_CNT) {
+			wait->retry++;
+		}
+		break;
+	case MOAL_IOCTL_WAIT_TIMEOUT:
+		wait_event_timeout(wait->wait, wait->condition,
+				   MOAL_IOCTL_TIMEOUT);
+		break;
+	}
+	spin_lock_irqsave(&priv->phandle->driver_lock, flags);
+	if (wait->condition == MFALSE) {
+		if (wait_option == MOAL_IOCTL_WAIT_TIMEOUT) {
+			priv->phandle->ioctl_timeout = MTRUE;
+			PRINTM(MMSG,
+			       "wlan: IOCTL timeout %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
+			       req, req->req_id, (*(t_u32 *)req->pbuf),
+			       wait_option, (int)req->action);
+		} else {
+			PRINTM(MMSG,
+			       "wlan: IOCTL by signal %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
+			       req, req->req_id, (*(t_u32 *)req->pbuf),
+			       wait_option, (int)req->action);
+		}
+		req->reserved_1 = 0;
+		status = MLAN_STATUS_PENDING;
+	} else {
+		status = wait->status;
+	}
+	spin_unlock_irqrestore(&priv->phandle->driver_lock, flags);
+
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief CAC period block cmd handler
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param req      A pointer to mlan_ioctl_req buffer
+ *
+ *  @return         MTRUE/MFALSE
+ */
+static inline t_bool
+woal_cac_period_block_cmd(moal_private *priv, pmlan_ioctl_req req)
+{
+	mlan_status ret = MFALSE;
+	t_u32 sub_command;
+
+	ENTER();
+	if (req == NULL || req->pbuf == NULL)
+		goto done;
+
+	sub_command = *(t_u32 *)req->pbuf;
+
+	switch (req->req_id) {
+	case MLAN_IOCTL_SCAN:
+		if (sub_command == MLAN_OID_SCAN_NORMAL ||
+		    sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
+		    sub_command == MLAN_OID_SCAN_USER_CONFIG)
+			ret = MTRUE;
+		break;
+	case MLAN_IOCTL_BSS:
+		if (sub_command == MLAN_OID_BSS_STOP ||
+		    sub_command == MLAN_OID_BSS_CHANNEL
+		    /* sub_command == MLAN_OID_BSS_ROLE */ )
+			ret = MTRUE;
+#ifdef UAP_SUPPORT
+		else if (sub_command == MLAN_OID_UAP_BSS_CONFIG) {
+			mlan_ds_bss *bss = (mlan_ds_bss *)req->pbuf;
+			if (bss->param.bss_config.channel)
+				ret = MTRUE;
+			else
+				ret = MFALSE;
+		}
+#endif
+		break;
+	case MLAN_IOCTL_RADIO_CFG:
+		if (sub_command == MLAN_OID_BAND_CFG ||
+		    sub_command == MLAN_OID_REMAIN_CHAN_CFG)
+			ret = MTRUE;
+		break;
+	case MLAN_IOCTL_SNMP_MIB:
+		if (sub_command == MLAN_OID_SNMP_MIB_DOT11D)
+			ret = MTRUE;
+#if defined(UAP_SUPPORT)
+		if (sub_command == MLAN_OID_SNMP_MIB_DOT11H)
+			ret = MTRUE;
+#endif
+		break;
+	case MLAN_IOCTL_11D_CFG:
+#ifdef STA_SUPPORT
+		if (sub_command == MLAN_OID_11D_CFG_ENABLE)
+			ret = MTRUE;
+#endif
+#ifdef UAP_SUPPORT
+		if (sub_command == MLAN_OID_11D_DOMAIN_INFO)
+			ret = MTRUE;
+#endif
+		if (sub_command == MLAN_OID_11D_DOMAIN_INFO_EXT)
+			ret = MTRUE;
+		break;
+	case MLAN_IOCTL_MISC_CFG:
+		if (sub_command == MLAN_OID_MISC_REGION)
+			ret = MTRUE;
+		if (sub_command == MLAN_OID_MISC_HOST_CMD) {
+			phostcmd_header phostcmd;
+			t_u8 *ptlv_buf;
+			t_u16 tag, length;
+
+			phostcmd =
+				(phostcmd_header)((pmlan_ds_misc_cfg)req->pbuf)
+				->param.hostcmd.cmd;
+			ptlv_buf = (t_u8 *)phostcmd + sizeof(hostcmd_header);
+			if (phostcmd->action == MLAN_ACT_SET) {
+				while (ptlv_buf <
+				       (t_u8 *)phostcmd + phostcmd->size) {
+					tag = *(t_u16 *)ptlv_buf;
+					length = *(t_u16 *)(ptlv_buf + 2);
+					/* Check Blocking TLV here, should add
+					 * more... */
+					if (tag == MRVL_CHANNELCONFIG_TLV_ID) {
+						ret = MTRUE;
+						break;
+					}
+					ptlv_buf +=
+						(length + MRVL_TLV_HEADER_SIZE);
+				}
+			}
+		}
+		break;
+	case MLAN_IOCTL_11H_CFG:
+		/* Prevent execute more than once */
+		if (sub_command == MLAN_OID_11H_CHANNEL_CHECK)
+			ret = MTRUE;
+		break;
+	default:
+		ret = MFALSE;
+		break;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief Send ioctl request to MLAN
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param req           A pointer to mlan_ioctl_req buffer
+ *  @param wait_option   Wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ *
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ *                          -- success, otherwise fail
+ */
+mlan_status
+woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req, t_u8 wait_option)
+{
+	wait_queue *wait = NULL;
+	mlan_status status;
+	unsigned long flags;
+	t_u32 sub_command = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle || !priv->phandle->pmlan_adapter ||!req) {
+		PRINTM(MINFO,
+		       "priv or priv->phandle or priv->phandle->pmlan_adapter or req is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	sub_command = *(t_u32 *)req->pbuf;
+
+	if (sub_command != MLAN_OID_GET_DEBUG_INFO &&
+	    sub_command != MLAN_OID_MISC_WARM_RESET) {
+		if (priv->phandle->surprise_removed == MTRUE ||
+		    priv->phandle->driver_status) {
+			PRINTM(MCMND,
+			       "IOCTL is not allowed while the device is not present or hang\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+		if (priv->phandle->is_suspended == MTRUE) {
+			PRINTM(MCMND, "IOCTL is not allowed while suspended\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#ifdef MFG_CMD_SUPPORT
+		if (mfg_mode && sub_command != MLAN_OID_MISC_HOST_CMD) {
+			PRINTM(MCMND, "Only HOST_CMD allowed in MFG mode\n");
+			LEAVE();
+			return MLAN_STATUS_FAILURE;
+		}
+#endif
+	}
+	/* For MLAN_OID_MISC_HOST_CMD, action is 0, "action set" is checked
+	 * later */
+	if ((req->action == MLAN_ACT_SET || req->action == 0) &&
+	    priv->phandle->cac_period == MTRUE) {
+		/* CAC checking period left to complete jiffies */
+		long cac_left_jiffies;
+
+		/* cac_left_jiffies will be negative if and only if
+		 * event MLAN_EVENT_ID_DRV_MEAS_REPORT recieved from FW
+		 * after CAC measure period ends,
+		 * usually this could be considered as a FW bug
+		 */
+		cac_left_jiffies =
+			priv->phandle->cac_timer_jiffies -
+			(jiffies - priv->phandle->meas_start_jiffies);
+		if (priv->phandle->cac_period_jiffies) {
+			cac_left_jiffies =
+				priv->phandle->cac_period_jiffies -
+				(jiffies - priv->phandle->meas_start_jiffies);
+		}
+		if (priv->phandle->cac_restart)
+			cac_left_jiffies = DEF_CAC_DWELL_TIME * HZ / 1000;
+		if (cac_left_jiffies < 0) {
+			/* Avoid driver hang in FW died during CAC measure
+			 * period */
+			priv->phandle->cac_period = MFALSE;
+			PRINTM(MERROR,
+			       "CAC measure period spends longer than scheduled time "
+			       "or meas done event never received\n");
+			status = MLAN_STATUS_FAILURE;
+#ifdef UAP_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (priv->uap_host_based &&
+			    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+				woal_cfg80211_dfs_vendor_event(priv,
+							       event_dfs_cac_aborted,
+							       &priv->chan);
+#endif
+#endif
+#endif
+
+			goto done;
+		}
+
+		/* Check BSS START first */
+		if (sub_command == MLAN_OID_BSS_START) {
+			mlan_ds_bss *bss;
+			bss = (mlan_ds_bss *)req->pbuf;
+			/*
+			 * Bss delay start after channel report received,
+			 * not block the driver by delay executing. This is
+			 * because a BSS_START cmd is always executed right
+			 * after channel check issued.
+			 */
+			if (priv->phandle->delay_bss_start == MFALSE) {
+				PRINTM(MMSG,
+				       "Received BSS Start command during CAC period, delay executing %ld seconds\n",
+				       cac_left_jiffies / HZ);
+				priv->phandle->delay_bss_start = MTRUE;
+				moal_memcpy_ext(priv->phandle,
+						&priv->phandle->
+						delay_ssid_bssid,
+						&bss->param.ssid_bssid,
+						sizeof(mlan_ssid_bssid),
+						sizeof(mlan_ssid_bssid));
+				/* TODO: return success to allow the half below
+				 * of routines of which calling BSS start to
+				 * execute
+				 */
+				status = MLAN_STATUS_SUCCESS;
+				goto done;
+			} else {
+				/* TODO: not blocking it, just return failure */
+				PRINTM(MMSG,
+				       "Only one BSS Start command allowed for delay executing!\n");
+				status = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		if (woal_cac_period_block_cmd(priv, req)) {
+			priv->phandle->meas_wait_q_woken = MFALSE;
+			PRINTM(MMSG,
+			       "CAC check is on going... Blocking Command %ld seconds\n",
+			       cac_left_jiffies / HZ);
+			/* blocking timeout set to 1.5 * CAC checking period
+			 * left time */
+			wait_event_interruptible_timeout(priv->phandle->
+							 meas_wait_q,
+							 priv->phandle->
+							 meas_wait_q_woken,
+							 cac_left_jiffies * 3 /
+							 2);
+		}
+	}
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	else if (priv->phandle->is_cac_timer_set &&
+		 (req->action == MLAN_ACT_SET || req->action == 0)) {
+		if (woal_cac_period_block_cmd(priv, req)) {
+			PRINTM(MMSG,
+			       "CAC check is on going... Blocking Command\n");
+			status = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#endif
+#endif
+	else if (priv->phandle->cac_period) {
+		PRINTM(MINFO, "Operation during CAC check period.\n");
+	}
+	wait = (wait_queue *)req->reserved_1;
+	req->bss_index = priv->bss_index;
+	if (wait_option)
+		woal_fill_wait_queue(priv, wait, wait_option);
+	else
+		req->reserved_1 = 0;
+
+	/* Call MLAN ioctl handle */
+	atomic_inc(&priv->phandle->ioctl_pending);
+	spin_lock_irqsave(&priv->phandle->ioctl_lock, flags);
+	status = mlan_ioctl(priv->phandle->pmlan_adapter, req);
+	spin_unlock_irqrestore(&priv->phandle->ioctl_lock, flags);
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		if (wait_option == MOAL_NO_WAIT)
+			PRINTM(MIOCTL, "IOCTL MOAL_NO_WAIT: %p\n", req);
+		else
+			PRINTM(MIOCTL,
+			       "IOCTL pending: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d\n",
+			       req, req->req_id, (*(t_u32 *)req->pbuf),
+			       wait_option, (int)req->action);
+		/* Status pending, wake up main process */
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+
+		/* Wait for completion */
+		if (wait_option)
+			status = woal_wait_ioctl_complete(priv, req,
+							  wait_option);
+		break;
+	case MLAN_STATUS_SUCCESS:
+	case MLAN_STATUS_FAILURE:
+	case MLAN_STATUS_RESOURCE:
+		if (req)
+			PRINTM(MIOCTL,
+			       "IOCTL: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d status=%d\n",
+			       req, req->req_id, (*(t_u32 *)req->pbuf),
+			       wait_option, (int)req->action, status);
+		atomic_dec(&priv->phandle->ioctl_pending);
+		break;
+	default:
+		atomic_dec(&priv->phandle->ioctl_pending);
+		break;
+	}
+
+done:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Send set MAC address request to MLAN
+ *
+ *  @param priv   A pointer to moal_private structure
+ *  @param wait_option wait option
+ *
+ *  @return       MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
+ *                  -- success, otherwise fail
+ */
+mlan_status
+woal_request_set_mac_address(moal_private *priv, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MAC_ADDR;
+	moal_memcpy_ext(priv->phandle, &bss->param.mac_addr, priv->current_addr,
+			sizeof(mlan_802_11_mac_addr),
+			sizeof(mlan_802_11_mac_addr));
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR,
+		       "set mac address failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+	} else {
+		moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
+				priv->current_addr, ETH_ALEN, ETH_ALEN);
+		HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Send multicast list request to MLAN
+ *
+ *  @param priv   A pointer to moal_private structure
+ *  @param dev    A pointer to net_device structure
+ *
+ *  @return       N/A
+ */
+void
+woal_request_set_multicast_list(moal_private *priv, struct net_device *dev)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status;
+	int mc_count = 0;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		PRINTM(MERROR, "%s:Fail to allocate ioctl req buffer\n",
+		       __func__);
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+	if (dev->flags & IFF_PROMISC) {
+		bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
+	} else if (dev->flags & IFF_ALLMULTI) {
+		bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
+	} else {
+		bss->param.multicast_list.mode = MLAN_MULTICAST_MODE;
+		mc_count = woal_copy_all_mc_list(priv->phandle,
+						 &bss->param.multicast_list);
+		if (mc_count > MLAN_MAX_MULTICAST_LIST_SIZE)
+			bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
+	}
+	PRINTM(MCMND, "%s set multicast_list\n", dev->name);
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Send deauth command to MLAN
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param mac           MAC address to deauthenticate
+ *  @param reason code   reason code to deauthenticate
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_disconnect(moal_private *priv, t_u8 wait_option, t_u8 *mac,
+		t_u16 reason_code)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_STOP;
+	if (mac)
+		moal_memcpy_ext(priv->phandle,
+				&bss->param.deauth_param.mac_addr, mac,
+				sizeof(mlan_802_11_mac_addr),
+				sizeof(bss->param.deauth_param.mac_addr));
+	bss->param.deauth_param.reason_code = reason_code;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+#ifdef REASSOCIATION
+	priv->reassoc_required = MFALSE;
+#endif /* REASSOCIATION */
+	LEAVE();
+	return status;
+}
+
+#if defined(UAP_SUPPORT)
+/**
+ * @brief               Get non-global oper class
+ *
+ * @param priv          Pointer to moal_private structure
+ * @param bw            bandwidth
+ * @param channel       channel
+ * @param oper_class    pointer to oper_class
+
+ *  @return             non-global operclass
+ */
+int
+woal_priv_get_nonglobal_operclass_by_bw_channel(moal_private *priv,
+						t_u8 bandwidth,
+						t_u8 channel, t_u8 *oper_class)
+{
+	int ret = 0;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_OPER_CLASS;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_GET;
+	misc->param.bw_chan_oper.bandwidth = bandwidth;
+	misc->param.bw_chan_oper.channel = channel;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	*oper_class = misc->param.bw_chan_oper.oper_class;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Send bss_start command to MLAN
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param ssid_bssid    A point to mlan_ssid_bssid structure
+ *
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_bss_start(moal_private *priv, t_u8 wait_option,
+	       mlan_ssid_bssid *ssid_bssid)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	/* Stop the O.S. TX queue When we are roaming */
+	woal_stop_queue(priv->netdev);
+	if (priv->media_connected == MFALSE) {
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_START;
+	if (ssid_bssid)
+		moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid,
+				ssid_bssid, sizeof(mlan_ssid_bssid),
+				sizeof(mlan_ssid_bssid));
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (ssid_bssid)
+		moal_memcpy_ext(priv->phandle, ssid_bssid,
+				&bss->param.ssid_bssid, sizeof(mlan_ssid_bssid),
+				sizeof(mlan_ssid_bssid));
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+	priv->assoc_status = req->status_code;
+#endif
+#endif
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get BSS info
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param bss_info             A pointer to mlan_bss_info structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_bss_info(moal_private *priv, t_u8 wait_option, mlan_bss_info *bss_info)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		PRINTM(MERROR,
+		       "Fail to allocate the buffer for get bss_info\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_BSS_INFO;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (bss_info)
+			moal_memcpy_ext(priv->phandle, bss_info,
+					&info->param.bss_info,
+					sizeof(mlan_bss_info),
+					sizeof(mlan_bss_info));
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get generic IE
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action set or get
+ *  @param ie           Information element
+ *  @param ie_len       Length of the IE
+ *  @param wait_option  wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_get_gen_ie(moal_private *priv, t_u32 action, t_u8 *ie,
+		    int *ie_len, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	if ((action == MLAN_ACT_GET) && (ie == NULL || ie_len == NULL)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_SET && *ie_len > MAX_IE_SIZE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GEN_IE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
+
+	if (action == MLAN_ACT_SET) {
+		misc->param.gen_ie.len = *ie_len;
+		if (*ie_len)
+			moal_memcpy_ext(priv->phandle,
+					misc->param.gen_ie.ie_data, ie, *ie_len,
+					MAX_IE_SIZE);
+	}
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (action == MLAN_ACT_GET) {
+		*ie_len = misc->param.gen_ie.len;
+		if (*ie_len)
+			moal_memcpy_ext(priv->phandle, ie,
+					misc->param.gen_ie.ie_data, *ie_len,
+					*ie_len);
+	}
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Set/Get retry count
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param wait_option          Wait option
+ *  @param value                Retry value
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_get_retry(moal_private *priv, t_u32 action,
+		   t_u8 wait_option, int *value)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_snmp_mib *mib = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	mib = (mlan_ds_snmp_mib *)req->pbuf;
+	mib->sub_command = MLAN_OID_SNMP_MIB_RETRY_COUNT;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET) {
+		if (*value < MLAN_TX_RETRY_MIN || *value > MLAN_TX_RETRY_MAX) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		mib->param.retry_count = *value;
+	}
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
+		*value = mib->param.retry_count;
+#ifdef STA_CFG80211
+	/* If set is invoked from other than iw i.e iwconfig,
+	 * wiphy retry count should be updated as well */
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
+	    priv->wdev && priv->wdev->wiphy &&
+	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+	    (action == MLAN_ACT_SET)) {
+		priv->wdev->wiphy->retry_long = (t_u8)*value;
+		priv->wdev->wiphy->retry_short = (t_u8)*value;
+	}
+#endif
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Performs pre-warm-reset
+ *
+ * @param priv         A pointer to moal_private structure
+ *
+ * @return         0 if successful else negative value
+ */
+int
+woal_pre_warmreset(moal_private *priv)
+{
+	moal_handle *handle = priv->phandle;
+	int ret = 0;
+	int intf_num;
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+	t_u8 bss_role = MLAN_BSS_ROLE_STA;
+#endif
+#endif
+#endif /* WIFI_DIRECT_SUPPORT */
+
+	ENTER();
+#ifdef USB
+#ifdef CONFIG_USB_SUSPEND
+	if (IS_USB(handle->card_type) && handle->is_suspended &&
+	    woal_exit_usb_suspend(handle)) {
+		PRINTM(MERROR, "Failed to resume the suspended device\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#endif /* CONFIG_USB_SUSPEND */
+#endif
+	woal_cancel_cac_block(priv);
+	/* Reset all interfaces */
+	ret = woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE);
+	/* Initialize private structures */
+	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+		woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+		if ((handle->priv[intf_num]->bss_type ==
+		     MLAN_BSS_TYPE_WIFIDIRECT) &&
+		    (GET_BSS_ROLE(handle->priv[intf_num]) ==
+		     MLAN_BSS_ROLE_UAP)) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_bss_role_cfg(handle->priv[intf_num],
+					      MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					      &bss_role)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+#endif /* STA_WEXT || UAP_WEXT */
+#endif /* STA_SUPPORT && UAP_SUPPORT */
+#endif /* WIFI_DIRECT_SUPPORT */
+	}
+	woal_shutdown_fw(priv, MOAL_IOCTL_WAIT);
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+done:
+#endif /* STA_WEXT || UAP_WEXT */
+#endif /* STA_SUPPORT && UAP_SUPPORT */
+#endif /* WIFI_DIRECT_SUPPORT */
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief warm reset
+ *
+ * @param priv         A pointer to moal_private structure
+ *
+ * @return        0 success, otherwise failure
+ */
+int
+woal_warmreset(moal_private *priv)
+{
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+	int intf_num;
+
+	/* Restart the firmware */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req) {
+		misc = (mlan_ds_misc_cfg *)req->pbuf;
+		misc->sub_command = MLAN_OID_MISC_WARM_RESET;
+		misc->param.fw_reload = MTRUE;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		req->action = MLAN_ACT_SET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			PRINTM(MERROR, "warm reset failure!\n");
+			ret = -EFAULT;
+			if (status != MLAN_STATUS_PENDING)
+				kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+#ifdef USB
+	if (IS_USB(handle->card_type) && handle->params.usb_aggr == 1) {
+		/* Enable USB aggregation in FW */
+		if (woal_usb_aggr_init(handle)) {
+			PRINTM(MERROR, "usb aggr init fail\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+#endif
+
+	if (moal_extflg_isset(handle, EXT_AGGR_CTRL)) {
+		/* Enable aggregation in FW */
+		if (woal_init_aggr_ctrl(handle, MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Fail to init aggr ctrl\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	/* Enable interfaces */
+	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+		netif_device_attach(handle->priv[intf_num]->netdev);
+		woal_start_queue(handle->priv[intf_num]->netdev);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get RTS threshold
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param wait_option          Wait option
+ *  @param value                RTS threshold value
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_get_rts(moal_private *priv, t_u32 action, t_u8 wait_option, int *value)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_snmp_mib *mib = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	mib = (mlan_ds_snmp_mib *)req->pbuf;
+	mib->sub_command = MLAN_OID_SNMP_MIB_RTS_THRESHOLD;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET) {
+		if (*value < MLAN_RTS_MIN_VALUE || *value > MLAN_RTS_MAX_VALUE) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		mib->param.rts_threshold = *value;
+	}
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
+		*value = mib->param.rts_threshold;
+#ifdef STA_CFG80211
+	/* If set is invoked from other than iw i.e iwconfig,
+	 * wiphy RTS threshold should be updated as well */
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
+	    priv->wdev && priv->wdev->wiphy &&
+	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+	    (action == MLAN_ACT_SET))
+		priv->wdev->wiphy->rts_threshold = *value;
+#endif
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Fragment threshold
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param wait_option          Wait option
+ *  @param value                Fragment threshold value
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_get_frag(moal_private *priv, t_u32 action,
+		  t_u8 wait_option, int *value)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_snmp_mib *mib = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	mib = (mlan_ds_snmp_mib *)req->pbuf;
+	mib->sub_command = MLAN_OID_SNMP_MIB_FRAG_THRESHOLD;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET) {
+		if (*value < MLAN_FRAG_MIN_VALUE ||
+		    *value > MLAN_FRAG_MAX_VALUE) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		mib->param.frag_threshold = *value;
+	}
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
+		*value = mib->param.frag_threshold;
+#ifdef STA_CFG80211
+	/* If set is invoked from other than iw i.e iwconfig,
+	 * wiphy fragment threshold should be updated as well */
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
+	    priv->wdev && priv->wdev->wiphy &&
+	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+	    (action == MLAN_ACT_SET))
+		priv->wdev->wiphy->frag_threshold = *value;
+#endif
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get TX power
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param power_cfg            A pinter to mlan_power_cfg_t structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_get_tx_power(moal_private *priv, t_u32 action,
+		      mlan_power_cfg_t *power_cfg)
+{
+	mlan_ds_power_cfg *pcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pcfg = (mlan_ds_power_cfg *)req->pbuf;
+	pcfg->sub_command = MLAN_OID_POWER_CFG;
+	req->req_id = MLAN_IOCTL_POWER_CFG;
+	req->action = action;
+	if (action == MLAN_ACT_SET && power_cfg)
+		moal_memcpy_ext(priv->phandle, &pcfg->param.power_cfg,
+				power_cfg, sizeof(mlan_power_cfg_t),
+				sizeof(mlan_power_cfg_t));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (ret == MLAN_STATUS_SUCCESS && power_cfg)
+		moal_memcpy_ext(priv->phandle, power_cfg,
+				&pcfg->param.power_cfg,
+				sizeof(mlan_power_cfg_t),
+				sizeof(mlan_power_cfg_t));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get IEEE power management
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param disabled             A pointer to disabled flag
+ *  @param power_type           IEEE power type
+ *  @param wait_option          wait option
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_get_power_mgmt(moal_private *priv, t_u32 action,
+			int *disabled, int power_type, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET) {
+		PRINTM(MINFO, "PS_MODE set power disabled=%d power type=%#x\n",
+		       *disabled, power_type);
+		if (*disabled)
+			pm_cfg->param.ps_mode = 0;
+		else {
+			/* Check not support case only (vwrq->disabled == FALSE)
+			 */
+			if ((power_type & MW_POWER_TYPE) == MW_POWER_TIMEOUT) {
+				PRINTM(MERROR,
+				       "Setting power timeout is not supported\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			} else if ((power_type & MW_POWER_TYPE) ==
+				   MW_POWER_PERIOD) {
+				PRINTM(MERROR,
+				       "Setting power period is not supported\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			pm_cfg->param.ps_mode = 1;
+		}
+	}
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
+		*disabled = pm_cfg->param.ps_mode;
+
+#ifdef STA_CFG80211
+	/* If set is invoked from other than iw i.e iwconfig,
+	 * wiphy IEEE power save mode should be updated */
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
+	    priv->wdev && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+	    (action == MLAN_ACT_SET)) {
+		if (*disabled)
+			priv->wdev->ps = MFALSE;
+		else
+			priv->wdev->ps = MTRUE;
+	}
+#endif
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set Country Code
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param region   A pointer to region string
+ *
+ * @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
+ * fail
+ */
+static int
+woal_set_countrycode(moal_private *priv, char *country)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	mlan_ds_misc_country_code *country_code = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	country_code = &pcfg_misc->param.country_code;
+	pcfg_misc->sub_command = MLAN_OID_MISC_COUNTRY_CODE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	memset(country_code->country_code, 0, COUNTRY_CODE_LEN);
+	moal_memcpy_ext(priv->phandle, country_code->country_code, country,
+			COUNTRY_CODE_LEN - 1, COUNTRY_CODE_LEN - 1);
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set region code
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param region   A pointer to region string
+ *
+ * @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
+ * fail
+ */
+mlan_status
+woal_set_region_code(moal_private *priv, char *region)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+	if (woal_is_country_code_supported(region))
+		return woal_set_countrycode(priv, region);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_REGION;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	cfg->param.region_code = region_string_2_region_code(region);
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get data rate
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param datarate             A pointer to mlan_rate_cfg_t structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_get_data_rate(moal_private *priv, t_u8 action,
+		       mlan_rate_cfg_t *datarate)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_rate *rate = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->param.rate_cfg.rate_type = MLAN_RATE_VALUE;
+	rate->sub_command = MLAN_OID_RATE_CFG;
+	req->req_id = MLAN_IOCTL_RATE;
+	req->action = action;
+
+	if (datarate && (action == MLAN_ACT_SET))
+		moal_memcpy_ext(priv->phandle, &rate->param.rate_cfg, datarate,
+				sizeof(mlan_rate_cfg_t),
+				sizeof(mlan_rate_cfg_t));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, datarate, &rate->param.rate_cfg,
+				sizeof(mlan_rate_cfg_t),
+				sizeof(mlan_rate_cfg_t));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get assoc_resp buffer
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param assoc_rsp            A pointer to mlan_ds_misc_assoc_rsp structure
+ *  @param wait_option          wait option
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_get_assoc_rsp(moal_private *priv,
+		   mlan_ds_misc_assoc_rsp *assoc_rsp, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "Fail to allocate buffer for get assoc resp\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc = (pmlan_ds_misc_cfg)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_ASSOC_RSP;
+	req->action = MLAN_ACT_GET;
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS && assoc_rsp)
+		moal_memcpy_ext(priv->phandle, assoc_rsp,
+				&misc->param.assoc_resp,
+				sizeof(mlan_ds_misc_assoc_rsp),
+				sizeof(mlan_ds_misc_assoc_rsp));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Send get FW info request to MLAN
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param fw_info          FW information
+ *
+ *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
+			 mlan_fw_info *fw_info)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info;
+	mlan_status status;
+	ENTER();
+	memset(priv->current_addr, 0xff, ETH_ALEN);
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+	info->sub_command = MLAN_OID_GET_FW_INFO;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		priv->phandle->fw_release_number = info->param.fw_info.fw_ver;
+		priv->phandle->fw_hotfix_version =
+			info->param.fw_info.hotfix_version;
+		priv->phandle->fw_ecsa_enable = info->param.fw_info.ecsa_enable;
+		priv->phandle->fw_getlog_enable =
+			info->param.fw_info.getlog_enable;
+		if (priv->current_addr[0] == 0xff)
+			moal_memcpy_ext(priv->phandle, priv->current_addr,
+					&info->param.fw_info.mac_addr,
+					sizeof(mlan_802_11_mac_addr), ETH_ALEN);
+		moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
+				priv->current_addr, ETH_ALEN, ETH_ALEN);
+		if (fw_info)
+			moal_memcpy_ext(priv->phandle, fw_info,
+					&info->param.fw_info,
+					sizeof(mlan_fw_info),
+					sizeof(mlan_fw_info));
+		DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6);
+	} else
+		PRINTM(MERROR,
+		       "get fw info failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get current channel of active interface
+ *
+ *  @param priv        A pointer to moal_private
+ *  @param channel 	   A pointer to chan_band_info structure
+ *
+ *  @return            MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_get_active_intf_channel(moal_private *priv, chan_band_info * channel)
+{
+	moal_handle *handle = priv->phandle;
+	int i;
+	for (i = 0; i < handle->priv_num; i++) {
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
+			if (handle->priv[i]->media_connected == MTRUE)
+				return woal_get_sta_channel(handle->priv[i],
+							    MOAL_IOCTL_WAIT,
+							    channel);
+		}
+#endif
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+			if (handle->priv[i]->bss_started == MTRUE)
+				return woal_set_get_ap_channel(handle->priv[i],
+							       MLAN_ACT_GET,
+							       MOAL_IOCTL_WAIT,
+							       channel);
+		}
+#endif
+	}
+	return MLAN_STATUS_FAILURE;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Send get ext cap info request to MLAN
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param buf              data buffer
+ *  @param len              data buffer length
+ *
+ *  @return                 number of bytes of extended capability -- success,
+ * otherwise error
+ */
+int
+woal_request_extcap(moal_private *priv, t_u8 *buf, t_u8 len)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (buf == NULL || len <= 0 || len < sizeof(ExtCap_t)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto out;
+	}
+	memset(buf, 0, len);
+	moal_memcpy_ext(priv->phandle, buf, &cfg->param.ext_cap,
+			sizeof(ExtCap_t), len);
+	ret = sizeof(ExtCap_t);
+out:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Get debug info
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param debug_info           A pointer to mlan_debug_info structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_debug_info(moal_private *priv, t_u8 wait_option,
+		    mlan_debug_info *debug_info)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_get_info *info = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
+					sizeof(mlan_debug_info));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_DEBUG_INFO;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (debug_info) {
+			moal_memcpy_ext(priv->phandle, debug_info,
+					&info->param.debug_info,
+					sizeof(mlan_debug_info),
+					sizeof(mlan_debug_info));
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/**
+ *  @brief host command ioctl function
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_host_command(moal_private *priv, struct iwreq *wrq)
+{
+	HostCmd_Header cmd_header;
+	int ret = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (wrq->u.data.pointer == NULL) {
+		PRINTM(MERROR, "hostcmd IOCTL corrupt data\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	memset(&cmd_header, 0, sizeof(cmd_header));
+
+	/* get command header */
+	if (copy_from_user(&cmd_header, wrq->u.data.pointer,
+			   sizeof(HostCmd_Header))) {
+		PRINTM(MERROR, "copy from user failed: Host command header\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
+
+	PRINTM(MINFO, "Host command len = %u\n", misc->param.hostcmd.len);
+
+	if (!misc->param.hostcmd.len ||
+	    misc->param.hostcmd.len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+		PRINTM(MERROR, "Invalid data buffer length\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* get the whole command from user */
+	if (copy_from_user(misc->param.hostcmd.cmd, wrq->u.data.pointer,
+			   woal_le16_to_cpu(cmd_header.size))) {
+		PRINTM(MERROR, "copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	misc->sub_command = MLAN_OID_MISC_HOST_CMD;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)misc->param.hostcmd.cmd,
+			 misc->param.hostcmd.len)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = misc->param.hostcmd.len;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT)
+/**
+ *  @brief host command ioctl function
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+/*********  format of ifr_data *************/
+/*    buf_len + Hostcmd_body               */
+/*    buf_len: 4 bytes                     */
+/*             the length of the buf which */
+/*             can be used to return data  */
+/*             to application              */
+/*    Hostcmd_body                         */
+/*******************************************/
+int
+woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u32 buf_len = 0;
+	HostCmd_Header cmd_header;
+	int ret = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_hostcmd_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&cmd_header, 0, sizeof(cmd_header));
+
+	/* get command header */
+	if (copy_from_user(&cmd_header, req->ifr_data + sizeof(buf_len),
+			   sizeof(HostCmd_Header))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MINFO, "Host command len = %d\n",
+	       woal_le16_to_cpu(cmd_header.size));
+
+	if (woal_le16_to_cpu(cmd_header.size) > MRVDRV_SIZE_OF_CMD_BUFFER) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+
+	misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
+
+	/* get the whole command from user */
+	if (copy_from_user(misc->param.hostcmd.cmd,
+			   req->ifr_data + sizeof(buf_len),
+			   misc->param.hostcmd.len)) {
+		PRINTM(MERROR, "copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	misc->sub_command = MLAN_OID_MISC_HOST_CMD;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (misc->param.hostcmd.len > buf_len) {
+		PRINTM(MERROR,
+		       "buf_len is too small, resp_len=%d, buf_len=%d\n",
+		       (int)misc->param.hostcmd.len, (int)buf_len);
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_to_user(req->ifr_data + sizeof(buf_len),
+			 (t_u8 *)misc->param.hostcmd.cmd,
+			 misc->param.hostcmd.len)) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief CUSTOM_IE ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_custom_ie_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_custom_ie *pcustom_ie = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	gfp_t flag;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_custom_ie_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	pcustom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
+	if (!pcustom_ie) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (copy_from_user(pcustom_ie, req->ifr_data,
+			   sizeof(mlan_ds_misc_custom_ie))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	if ((pcustom_ie->len == 0) ||
+	    (pcustom_ie->len == sizeof(pcustom_ie->ie_data_list[0].ie_index)))
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, &misc->param.cust_ie, pcustom_ie,
+			sizeof(mlan_ds_misc_custom_ie),
+			sizeof(mlan_ds_misc_custom_ie));
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		if (copy_to_user(req->ifr_data, &misc->param.cust_ie,
+				 sizeof(mlan_ds_misc_custom_ie))) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) {
+		/* send a separate error code to indicate error from driver */
+		ret = EFAULT;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	kfree(pcustom_ie);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief send raw data packet ioctl function
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_send_host_packet(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u32 packet_len = 0;
+	int ret = 0;
+	pmlan_buffer pmbuf = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_send_host_packet() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (copy_from_user(&packet_len, req->ifr_data, sizeof(packet_len))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+#define PACKET_HEADER_LEN 8
+#define MV_ETH_FRAME_LEN 1514
+	if (packet_len > MV_ETH_FRAME_LEN) {
+		PRINTM(MERROR, "Invalid packet length %d\n", packet_len);
+		ret = -EFAULT;
+		goto done;
+	}
+	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
+				       (int)(MLAN_MIN_DATA_HEADER_LEN +
+					     (int)packet_len +
+					     PACKET_HEADER_LEN));
+	if (!pmbuf) {
+		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
+
+	/* get whole packet and header */
+	if (copy_from_user(pmbuf->pbuf + pmbuf->data_offset,
+			   req->ifr_data + sizeof(packet_len),
+			   PACKET_HEADER_LEN + packet_len)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		goto done;
+	}
+	pmbuf->data_len = PACKET_HEADER_LEN + packet_len;
+	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
+	pmbuf->bss_index = priv->bss_index;
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		ret = -EFAULT;
+		break;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#if defined(UAP_WEXT)
+/**
+ *  @brief Set/Get CUSTOM_IE ioctl handler
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param mask         Mask to set or clear from caller
+ *  @param ie           IE buffer to set for beacon
+ *  @param ie_len       Length of the IE
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_set_get_custom_ie(moal_private *priv, t_u16 mask, t_u8 *ie, int ie_len)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_custom_ie *misc_ie = NULL;
+	int ret = 0;
+	custom_ie *pcust_bcn_ie = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+	misc_ie = &misc->param.cust_ie;
+
+	misc_ie->type = TLV_TYPE_MGMT_IE;
+	misc_ie->len = (sizeof(custom_ie) - MAX_IE_SIZE) + ie_len;
+	pcust_bcn_ie = misc_ie->ie_data_list;
+	pcust_bcn_ie->ie_index = 0xffff;
+	pcust_bcn_ie->mgmt_subtype_mask = mask;
+	pcust_bcn_ie->ie_length = ie_len;
+	moal_memcpy_ext(priv->phandle, pcust_bcn_ie->ie_buffer, ie, ie_len,
+			MAX_IE_SIZE);
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		ret = -EFAULT;
+
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+#endif /* defined(HOST_TXRX_MGMT_FRAME) && defined(UAP_WEXT) */
+
+/**
+ *  @brief TDLS configuration ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_tdls_config_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_tdls_config *tdls_data = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	gfp_t flag;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_tdls_config_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	tdls_data = kzalloc(sizeof(mlan_ds_misc_tdls_config), flag);
+	if (!tdls_data) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (copy_from_user(tdls_data, req->ifr_data,
+			   sizeof(mlan_ds_misc_tdls_config))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TDLS_CONFIG;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ ||
+	    tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS)
+		ioctl_req->action = MLAN_ACT_GET;
+	else
+		ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, &misc->param.tdls_config, tdls_data,
+			sizeof(mlan_ds_misc_tdls_config),
+			sizeof(mlan_ds_misc_tdls_config));
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ
+	    || tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS) {
+		if (copy_to_user(req->ifr_data, &misc->param.tdls_config,
+				 sizeof(mlan_ds_misc_tdls_config))) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	kfree(tdls_data);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief ioctl function get BSS type
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_get_bss_type(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int bss_type;
+
+	ENTER();
+
+	bss_type = (int)priv->bss_type;
+	if (copy_to_user(req->ifr_data, &bss_type, sizeof(int))) {
+		PRINTM(MINFO, "Copy to user failed!\n");
+		ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/**
+ * @brief Swithces BSS role of interface
+ *
+ * @param priv          A pointer to moal_private structure
+ * @param action        Action: set or get
+ * @param wait_option   Wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ * @param bss_role      A pointer to bss role
+ *
+ * @return         0 --success, otherwise fail
+ */
+mlan_status
+woal_bss_role_cfg(moal_private *priv, t_u8 action, t_u8 wait_option,
+		  t_u8 *bss_role)
+{
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	struct net_device *dev = priv->netdev;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_ROLE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = action;
+	if (action == MLAN_ACT_SET) {
+		if (priv->bss_role == *bss_role) {
+			PRINTM(MWARN, "BSS is in desired role already\n");
+			goto done;
+		} else {
+			bss->param.bss_role = *bss_role;
+		}
+	}
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_GET) {
+		*bss_role = bss->param.bss_role;
+	} else {
+		/* Update moal_private */
+		priv->bss_role = *bss_role;
+		if (priv->bss_type == MLAN_BSS_TYPE_UAP)
+			priv->bss_type = MLAN_BSS_TYPE_STA;
+		else if (priv->bss_type == MLAN_BSS_TYPE_STA)
+			priv->bss_type = MLAN_BSS_TYPE_UAP;
+
+		if (*bss_role == MLAN_BSS_ROLE_UAP) {
+			/* Switch: STA -> uAP */
+			/* Setup the OS Interface to our functions */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
+			dev->do_ioctl = woal_uap_do_ioctl;
+			dev->set_multicast_list = woal_uap_set_multicast_list;
+#else
+			dev->netdev_ops = &woal_uap_netdev_ops;
+#endif
+#ifdef UAP_WEXT
+			if (IS_UAP_WEXT(priv->phandle->params.cfg80211_wext)) {
+#if WIRELESS_EXT < 21
+				dev->get_wireless_stats =
+					woal_get_uap_wireless_stats;
+#endif
+				dev->wireless_handlers =
+					(struct iw_handler_def
+					 *)&woal_uap_handler_def;
+			}
+#endif /* UAP_WEXT */
+		} else if (*bss_role == MLAN_BSS_ROLE_STA) {
+			/* Switch: uAP -> STA */
+			/* Setup the OS Interface to our functions */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
+			dev->do_ioctl = woal_do_ioctl;
+			dev->set_multicast_list = woal_set_multicast_list;
+#else
+			dev->netdev_ops = &woal_netdev_ops;
+#endif
+#ifdef STA_WEXT
+			if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
+#if WIRELESS_EXT < 21
+				dev->get_wireless_stats =
+					woal_get_wireless_stats;
+#endif
+				dev->wireless_handlers =
+					(struct iw_handler_def
+					 *)&woal_handler_def;
+			}
+#endif /* STA_WEXT */
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/**
+ * @brief Set/Get BSS role
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+int
+woal_set_get_bss_role(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	int bss_role = 0;
+	t_u8 action = MLAN_ACT_GET;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&bss_role, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((bss_role != MLAN_BSS_ROLE_STA &&
+		     bss_role != MLAN_BSS_ROLE_UAP)
+#ifdef WIFI_DIRECT_SUPPORT
+		    || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+			) {
+			PRINTM(MWARN, "Invalid BSS role\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (bss_role == (int)GET_BSS_ROLE(priv)) {
+			PRINTM(MWARN, "Already BSS is in desired role\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		action = MLAN_ACT_SET;
+		/* Reset interface */
+		woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE);
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv, action,
+						     MOAL_IOCTL_WAIT,
+						     (t_u8 *)&bss_role)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!wrq->u.data.length) {
+		if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	} else {
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_STA_OR_UAP_CFG80211(priv->phandle->params.cfg80211_wext))
+			woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
+#endif
+		/* Initialize private structures */
+		woal_init_priv(priv, MOAL_IOCTL_WAIT);
+
+		/* Enable interfaces */
+		netif_device_attach(priv->netdev);
+		woal_start_queue(priv->netdev);
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* STA_WEXT || UAP_WEXT */
+#endif /* STA_SUPPORT && UAP_SUPPORT */
+
+/**
+ *  @brief Enable IPv6 Router Advertisement offload
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *  @param enable  enable or disable
+ *
+ *  @return        MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise
+ * fail
+ */
+static mlan_status
+woal_set_ipv6_ra_offload(moal_handle *handle, t_u8 enable)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_ipv6_ra_offload *ipv6_ra;
+	int i = 0;
+
+	ENTER();
+
+	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
+		if (priv->ipv6_addr_configured)
+			break;
+	}
+
+	if (!priv || !priv->ipv6_addr_configured) {
+		PRINTM(MIOCTL, "No IPv6 address configured\n");
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_IPV6_RA_OFFLOAD;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	ipv6_ra = &misc->param.ipv6_ra_offload;
+	ipv6_ra->enable = enable;
+	moal_memcpy_ext(priv->phandle, ipv6_ra->ipv6_addr, priv->ipv6_addr, 16,
+			sizeof(ipv6_ra->ipv6_addr));
+	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_STA), req,
+				 MOAL_NO_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
+		PRINTM(MIOCTL, "Set IPv6 RA offload failed\n");
+
+done:
+	if (ret != MLAN_STATUS_PENDING && req != NULL)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable IPv6 Neighbor Solicitation offload
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *  @param enable  enable or disable mef entry
+ *
+ *  @return        MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise
+ * fail
+ */
+static mlan_status
+woal_set_ipv6_ns_offload(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
+	mef_entry_t *entry = NULL;
+	mef_filter_t *filter = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&misc->param.mef_flt_cfg);
+	mef_cfg->mef_act_type = MEF_ACT_IPV6_NS;
+	mef_cfg->criteria = (MBIT(1) | MBIT(3));
+
+	entry = (mef_entry_t *)&mef_cfg->mef_entry;
+	entry->mode = MBIT(0);
+	entry->action = 0x40;
+
+	filter = (mef_filter_t *)entry->filter_item;
+	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
+			     FILLING_BYTE_SEQ);
+	filter->type = TYPE_BYTE_EQ;
+	filter->repeat = 1;
+	filter->offset = 20;
+	filter->num_byte_seq = 2;
+	moal_memcpy_ext(handle, filter->byte_seq, "\x86\xdd", 2,
+			sizeof(filter->byte_seq));
+	entry->rpn[1] = RPN_TYPE_AND;
+
+	filter++;
+	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
+			     FILLING_BYTE_SEQ);
+	filter->type = TYPE_BYTE_EQ;
+	filter->repeat = 1;
+	filter->offset = 62;
+	filter->num_byte_seq = 1;
+	moal_memcpy_ext(handle, filter->byte_seq, "\x87", 1,
+			sizeof(filter->byte_seq));
+
+	entry->filter_num = 2;
+
+	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
+				 MOAL_NO_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
+		PRINTM(MIOCTL, "Set ipv6 ns offload failed! ret=%d\n", ret);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set auto arp resp
+ *
+ *  @param handle         A pointer to moal_handle structure
+ *  @param enable         enable/disable
+ *
+ *  @return               MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_set_auto_arp(moal_handle *handle, t_u8 enable)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int i = 0;
+	moal_private *priv = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
+
+	ENTER();
+
+	memset(&ipaddr_cfg, 0, sizeof(ipaddr_cfg));
+	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
+		if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
+			moal_memcpy_ext(handle,
+					ipaddr_cfg.ip_addr[ipaddr_cfg.
+							   ip_addr_num],
+					priv->ip_addr, IPADDR_LEN, IPADDR_LEN);
+			ipaddr_cfg.ip_addr_num++;
+		}
+	}
+	if (ipaddr_cfg.ip_addr_num == 0) {
+		PRINTM(MIOCTL, "No IP addr configured.\n");
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_IP_ADDR;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	moal_memcpy_ext(handle, &misc->param.ipaddr_cfg, &ipaddr_cfg,
+			sizeof(ipaddr_cfg), sizeof(misc->param.ipaddr_cfg));
+	if (enable) {
+		misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_ARP_FILTER |
+			MLAN_IPADDR_OP_AUTO_ARP_RESP;
+		misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
+	} else {
+		/** remove ip */
+		misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_IP_REMOVE;
+	}
+	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
+				 MOAL_NO_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
+		PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set auto arp resp with enhancement method
+ *
+ *  @param handle         A pointer to moal_handle structure
+ *  @param enable         enable/disable
+ *
+ *  @return               MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_set_auto_arp_ext(moal_handle *handle, t_u8 enable)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int i = 0, ip_addr_num = 0;
+	moal_private *priv = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
+	mef_entry_t *entry = NULL;
+	mef_filter_t *filter = NULL;
+	t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN];
+
+	ENTER();
+
+	memset(&mef_cfg, 0, sizeof(mef_cfg));
+	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
+		if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
+			moal_memcpy_ext(handle, ip_addr[ip_addr_num],
+					priv->ip_addr, IPADDR_LEN, IPADDR_LEN);
+			ip_addr_num++;
+		}
+	}
+	if (ip_addr_num == 0) {
+		PRINTM(MIOCTL, "No IP addr configured.\n");
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&(misc->param.mef_flt_cfg));
+	mef_cfg->mef_act_type = MEF_ACT_AUTOARP;
+	mef_cfg->criteria = (MBIT(0) | MBIT(1));
+
+	entry = (mef_entry_t *)&mef_cfg->mef_entry;
+	entry->mode = MBIT(0);
+	entry->action = 0x10;
+
+	filter = (mef_filter_t *)(entry->filter_item);
+	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
+			     FILLING_BYTE_SEQ);
+	filter->type = TYPE_BYTE_EQ;
+	filter->repeat = 1;
+	filter->offset = 20;
+	filter->num_byte_seq = 2;
+	moal_memcpy_ext(handle, filter->byte_seq, "\x08\x06", 2,
+			sizeof(filter->byte_seq));
+	entry->rpn[1] = RPN_TYPE_AND;
+
+	for (i = 0; i < ip_addr_num; i++) {
+		filter++;
+		filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT |
+				     FILLING_OFFSET | FILLING_BYTE_SEQ);
+		filter->type = TYPE_BYTE_EQ;
+		filter->repeat = 1;
+		filter->offset = 46;
+		filter->num_byte_seq = 4;
+		moal_memcpy_ext(handle, filter->byte_seq, &ip_addr[i],
+				sizeof(t_u32), sizeof(filter->byte_seq));
+		if (i > 1)
+			entry->rpn[i] = RPN_TYPE_OR;
+	}
+	entry->filter_num = ip_addr_num + 1;
+
+	if (enable)
+		mef_cfg->op_code = MLAN_IPADDR_OP_ARP_FILTER |
+			MLAN_IPADDR_OP_AUTO_ARP_RESP;
+	else
+		/** remove ip */
+		mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
+	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
+				 MOAL_NO_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
+		PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get DTIM period
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param wait_option          Wait option
+ *  @param value                DTIM period
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_get_dtim_period(moal_private *priv, t_u32 action,
+			 t_u8 wait_option, t_u8 *value)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_snmp_mib *mib = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	mib = (mlan_ds_snmp_mib *)req->pbuf;
+	mib->sub_command = MLAN_OID_SNMP_MIB_DTIM_PERIOD;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET)
+		mib->param.dtim_period = *value;
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
+		*value = (t_u8)mib->param.dtim_period;
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Host Sleep parameters
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action: set or get
+ *  @param wait_option  Wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ *  @param hscfg        A pointer to mlan_ds_hs_cfg structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_set_get_hs_params(moal_private *priv, t_u16 action,
+		       t_u8 wait_option, mlan_ds_hs_cfg *hscfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pmcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	req->action = action;
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &pmcfg->param.hs_cfg, hscfg,
+				sizeof(mlan_ds_hs_cfg), sizeof(mlan_ds_hs_cfg));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (hscfg && action == MLAN_ACT_GET) {
+			moal_memcpy_ext(priv->phandle, hscfg,
+					&pmcfg->param.hs_cfg,
+					sizeof(mlan_ds_hs_cfg),
+					sizeof(mlan_ds_hs_cfg));
+		}
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get wakeup reason
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wakeup_reason        A pointer to mlan_ds_hs_wakeup_reason  structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_get_wakeup_reason(moal_private *priv,
+		       mlan_ds_hs_wakeup_reason *wakeup_reason)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pmcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pmcfg->sub_command = MLAN_OID_PM_HS_WAKEUP_REASON;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT_TIMEOUT);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		wakeup_reason->hs_wakeup_reason =
+			pmcfg->param.wakeup_reason.hs_wakeup_reason;
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set or Get wowlan config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action: action to config wowlan
+ *  @param wait_option  Wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ *  @param mefcfg        A pointer to mlan_ds_misc_mef_flt_cfg structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_set_get_wowlan_config(moal_private *priv, t_u16 action,
+			   t_u8 wait_option, mlan_ds_misc_mef_flt_cfg *mefcfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misccfg = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	/** Allocate an IOCTL request buffer*/
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	/** Fill request buffer */
+	misccfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misccfg->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	moal_memcpy_ext(priv->phandle, &misccfg->param.mef_flt_cfg, mefcfg,
+			sizeof(mlan_ds_misc_mef_flt_cfg),
+			sizeof(mlan_ds_misc_mef_flt_cfg));
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (mefcfg && action == MLAN_ACT_GET) {
+			moal_memcpy_ext(priv->phandle, mefcfg,
+					&misccfg->param.mef_flt_cfg,
+					sizeof(mlan_ds_misc_mef_flt_cfg),
+					sizeof(mlan_ds_misc_mef_flt_cfg));
+		}
+	}
+	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
+		PRINTM(MIOCTL, "Set Get wowlan IOCTL failed!\n");
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Cancel Host Sleep configuration
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      wait option
+ *
+ *  @return                 MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING,
+ *                              or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_cancel_hs(moal_private *priv, t_u8 wait_option)
+{
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	moal_handle *handle = NULL;
+#endif
+#endif
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_hs_cfg hscfg;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	int i;
+#endif
+#endif
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Cancel Host Sleep */
+	hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
+	hscfg.is_invoke_hostcmd = MTRUE;
+	ret = woal_set_get_hs_params(priv, MLAN_ACT_SET, wait_option, &hscfg);
+
+#if IS_ENABLED(CONFIG_IPV6)
+	if (priv->phandle->hs_auto_arp) {
+		PRINTM(MIOCTL, "Canecl Host Sleep... remove ipv6 offload\n");
+		/** Set ipv6 router advertisement message offload */
+		woal_set_ipv6_ra_offload(priv->phandle, MFALSE);
+	}
+#endif
+
+	if (priv->phandle->hs_auto_arp) {
+		PRINTM(MIOCTL, "Cancel Host Sleep... remove FW auto arp\n");
+		/* remove auto arp from FW */
+		woal_set_auto_arp(priv->phandle, MFALSE);
+		/* remove auto arp from FW */
+		woal_set_auto_arp_ext(priv->phandle, MFALSE);
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	handle = priv->phandle;
+	if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) {
+		PRINTM(MIOCTL,
+		       "Cancel Host Sleep... clear gtk rekey offload of FW\n");
+		for (i = 0; i < handle->priv_num; i++) {
+			if (handle->priv[i] && handle->priv[i]->gtk_data_ready) {
+				PRINTM(MCMND, "clear GTK in resume\n");
+				woal_set_rekey_data(handle->priv[i], NULL,
+						    MLAN_ACT_CLEAR,
+						    wait_option);
+			}
+		}
+	}
+#endif
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**  @brief This function enables the host sleep
+ *
+ *  @param priv     A Pointer to the moal_private structure
+ *  @return         MTRUE or MFALSE
+ */
+int
+woal_enable_hs(moal_private *priv)
+{
+	mlan_ds_hs_cfg hscfg;
+	moal_handle *handle = NULL;
+	int hs_actived = MFALSE;
+	int timeout = 0;
+	int i;
+#ifdef SDIO_SUSPEND_RESUME
+	mlan_ds_ps_info pm_info;
+#endif
+	pmlan_ds_misc_keep_alive keep_alive = NULL;
+	t_u8 media_connected = MFALSE;
+
+	ENTER();
+
+	if (priv == NULL) {
+		PRINTM(MERROR, "Invalid priv\n");
+		goto done;
+	}
+	handle = priv->phandle;
+	if (handle->hs_activated == MTRUE) {
+		PRINTM(MIOCTL, "HS Already actived\n");
+		hs_actived = MTRUE;
+		goto done;
+	}
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
+			if (moal_extflg_isset(handle,
+					      EXT_DISCONNECT_ON_SUSPEND) &&
+			    handle->priv[i]->media_connected == MTRUE) {
+				PRINTM(MIOCTL, "disconnect on suspend\n");
+				woal_disconnect(handle->priv[i], MOAL_NO_WAIT,
+						NULL, DEF_DEAUTH_REASON_CODE);
+			}
+		}
+		if (handle->priv[i]) {
+			PRINTM(MIOCTL, "woal_delba_all on priv[%d]\n", i);
+			woal_delba_all(handle->priv[i], MOAL_NO_WAIT);
+		}
+	}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	if (priv->phandle->is_remain_timer_set) {
+		woal_cancel_timer(&priv->phandle->remain_timer);
+		woal_remain_timer_func(priv->phandle);
+	}
+	/* cancel pending remain on channel */
+	if (priv->phandle->remain_on_channel) {
+		t_u8 channel_status;
+		moal_private *remain_priv =
+			priv->phandle->priv[priv->phandle->remain_bss_index];
+		if (remain_priv) {
+			woal_cfg80211_remain_on_channel_cfg(remain_priv,
+							    MOAL_NO_WAIT, MTRUE,
+							    &channel_status,
+							    NULL, 0, 0);
+			if (priv->phandle->cookie) {
+				cfg80211_remain_on_channel_expired(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+									  remain_priv->
+									  netdev,
+#else
+									  remain_priv->
+									  wdev,
+#endif
+									  priv->
+									  phandle->
+									  cookie,
+									  &priv->
+									  phandle->
+									  chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+									  priv->
+									  phandle->
+									  channel_type,
+#endif
+									  GFP_ATOMIC);
+				priv->phandle->cookie = 0;
+			}
+		}
+		priv->phandle->remain_on_channel = MFALSE;
+	}
+#endif
+#endif
+
+#ifdef STA_SUPPORT
+	woal_reconfig_bgscan(priv->phandle);
+#endif
+
+	media_connected = woal_check_media_connected(handle);
+#if IS_ENABLED(CONFIG_IPV6)
+	if (handle->hs_auto_arp && media_connected) {
+		PRINTM(MIOCTL, "Host Sleep enabled... set ipv6 offload\n");
+		/** Set ipv6 router advertisement message offload */
+		woal_set_ipv6_ra_offload(handle, MTRUE);
+		/** Set Neighbor Solitation message offload */
+		woal_set_ipv6_ns_offload(handle);
+	}
+#endif
+	if (handle->hs_auto_arp && media_connected) {
+		PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n");
+		/* Set auto arp response configuration to Fw */
+		woal_set_auto_arp(handle, MTRUE);
+		/* Set auto arp response configuration to Fw */
+		woal_set_auto_arp_ext(handle, MTRUE);
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) {
+		PRINTM(MIOCTL,
+		       "Host Sleep enabled... set gtk rekey offload to FW\n");
+		for (i = 0; i < handle->priv_num; i++) {
+			if (handle->priv[i] && handle->priv[i]->gtk_data_ready) {
+				PRINTM(MCMND, "set GTK before suspend\n");
+				woal_set_rekey_data(handle->priv[i],
+						    &handle->priv[i]->
+						    gtk_rekey_data,
+						    MLAN_ACT_SET, MOAL_NO_WAIT);
+			}
+		}
+	}
+#endif
+#endif
+
+	for (i = 0; i < MAX_KEEP_ALIVE_ID; i++) {
+		keep_alive = &handle->keep_alive[i];
+		if (keep_alive && keep_alive->cached && keep_alive->enable) {
+			keep_alive->cached = false;
+			woal_start_mkeep_alive(woal_get_priv
+					       (handle, MLAN_BSS_ROLE_ANY),
+					       keep_alive->mkeep_alive_id,
+					       keep_alive->packet,
+					       keep_alive->pkt_len,
+					       keep_alive->src_mac,
+					       keep_alive->dst_mac,
+					       keep_alive->send_interval,
+					       keep_alive->retry_interval,
+					       keep_alive->retry_count);
+			keep_alive->pkt_len = 0;
+			memset(keep_alive->packet, 0, MKEEP_ALIVE_IP_PKT_MAX);
+		}
+	}
+	/* Enable Host Sleep */
+	handle->hs_activate_wait_q_woken = MFALSE;
+	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
+	hscfg.is_invoke_hostcmd = MTRUE;
+	if (woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) ==
+	    MLAN_STATUS_FAILURE) {
+		PRINTM(MIOCTL, "IOCTL request HS enable failed\n");
+		goto done;
+	}
+	timeout = wait_event_timeout(handle->hs_activate_wait_q,
+				     handle->hs_activate_wait_q_woken,
+				     HS_ACTIVE_TIMEOUT);
+#ifdef SDIO_MMC
+	if (IS_SD(handle->card_type)) {
+		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	}
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+	memset(&pm_info, 0, sizeof(mlan_ds_ps_info));
+#endif
+	if ((handle->hs_activated == MTRUE) || (handle->is_suspended == MTRUE)) {
+		PRINTM(MCMND, "suspend success! force=%u skip=%u\n",
+		       handle->hs_force_count, handle->hs_skip_count);
+		hs_actived = MTRUE;
+	}
+#ifdef SDIO_SUSPEND_RESUME
+	else if (IS_SD(handle->card_type)) {
+		handle->suspend_fail = MTRUE;
+		woal_get_pm_info(priv, &pm_info);
+		if (pm_info.is_suspend_allowed == MTRUE) {
+#ifdef MMC_PM_FUNC_SUSPENDED
+			woal_wlan_is_suspended(priv->phandle);
+#endif
+			handle->hs_force_count++;
+			PRINTM(MCMND, "suspend allowed! force=%u skip=%u\n",
+			       handle->hs_force_count, handle->hs_skip_count);
+			hs_actived = MTRUE;
+		}
+	}
+#endif /* SDIO_SUSPEND_RESUME */
+#ifdef SDIO_MMC
+	if (IS_SD(handle->card_type)) {
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	}
+#endif
+	if (hs_actived != MTRUE) {
+		handle->hs_skip_count++;
+#ifdef SDIO_SUSPEND_RESUME
+		if (IS_SD(handle->card_type)) {
+			PRINTM(MCMND,
+			       "suspend skipped! timeout=%d allow=%d force=%u skip=%u\n",
+			       timeout, (int)pm_info.is_suspend_allowed,
+			       handle->hs_force_count, handle->hs_skip_count);
+		}
+#else
+		PRINTM(MCMND, "suspend skipped! timeout=%d skip=%u\n", timeout,
+		       handle->hs_skip_count);
+#endif
+		woal_cancel_hs(priv, MOAL_NO_WAIT);
+	}
+done:
+	LEAVE();
+	return hs_actived;
+}
+
+#ifdef CONFIG_PROC_FS
+/**
+ *  @brief This function send soft_reset command to firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
+ *                      otherwise failure code
+ */
+mlan_status
+woal_request_soft_reset(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req) {
+		misc = (mlan_ds_misc_cfg *)req->pbuf;
+		misc->sub_command = MLAN_OID_MISC_SOFT_RESET;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		req->action = MLAN_ACT_SET;
+		ret = woal_request_ioctl(woal_get_priv(handle,
+						       MLAN_BSS_ROLE_ANY),
+					 req, MOAL_IOCTL_WAIT);
+	}
+
+	handle->surprise_removed = MTRUE;
+	woal_sched_timeout(5);
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif /* CONFIG_PROC_FS */
+
+/**
+ *  @brief Set wapi enable
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param enable               MTRUE or MFALSE
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_wapi_enable(moal_private *priv, t_u8 wait_option, t_u32 enable)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_WAPI_ENABLED;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+	sec->param.wapi_enabled = enable;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get version
+ *
+ *  @param handle       A pointer to moal_handle structure
+ *  @param version      A pointer to version buffer
+ *  @param max_len      max length of version buffer
+ *
+ *  @return             N/A
+ */
+void
+woal_get_version(moal_handle *handle, char *version, int max_len)
+{
+	t_u8 hotfix_ver = 0;
+	union {
+		t_u32 l;
+		t_u8 c[4];
+	} ver;
+	char fw_ver[32];
+
+	ENTER();
+
+	hotfix_ver = handle->fw_hotfix_version;
+	ver.l = handle->fw_release_number;
+
+	if (hotfix_ver) {
+		snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u.%u", ver.c[2],
+			 ver.c[1], ver.c[0], ver.c[3], hotfix_ver);
+
+	} else {
+		snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u", ver.c[2],
+			 ver.c[1], ver.c[0], ver.c[3]);
+	}
+
+	snprintf(version, max_len, handle->driver_version, fw_ver);
+
+	LEAVE();
+}
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/**
+ *  @brief Get Driver Version
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param req          A pointer to ifreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_get_driver_version(moal_private *priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	int len;
+	char buf[MLAN_MAX_VER_STR_LEN];
+	ENTER();
+
+	woal_get_version(priv->phandle, buf, sizeof(buf) - 1);
+
+	len = strlen(buf);
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, buf, len)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			LEAVE();
+			return -EFAULT;
+		}
+		wrq->u.data.length = len;
+	}
+	PRINTM(MINFO, "MOAL VERSION: %s\n", buf);
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get extended driver version
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param ireq         A pointer to ifreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_get_driver_verext(moal_private *priv, struct ifreq *ireq)
+{
+	struct iwreq *wrq = (struct iwreq *)ireq;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_VER_EXT;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	if (!wrq->u.data.flags) {
+		info->param.ver_ext.version_str_sel =
+			*((int *)(wrq->u.name + SUBCMD_OFFSET));
+	} else {
+		if (copy_from_user(&info->param.ver_ext.version_str_sel,
+				   wrq->u.data.pointer,
+				   sizeof(info->param.ver_ext.
+					  version_str_sel))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		} else {
+			if (((t_s32)(info->param.ver_ext.version_str_sel)) < 0) {
+				PRINTM(MERROR, "Invalid arguments!\n");
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer,
+				 info->param.ver_ext.version_str,
+				 strlen(info->param.ver_ext.version_str))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = strlen(info->param.ver_ext.version_str);
+	}
+
+	PRINTM(MINFO, "MOAL EXTENDED VERSION: %s\n",
+	       info->param.ver_ext.version_str);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#ifdef DEBUG_LEVEL1
+/**
+ *  @brief Set driver debug bit masks to mlan in order to enhance performance
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param drv_dbg       Driver debug level
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_set_drvdbg(moal_private *priv, t_u32 drv_dbg)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_DRVDBG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	misc->param.drvdbg = drv_dbg;
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Mgmt frame forward registration
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action: set or get
+ *  @param pmgmt_subtype_mask   A Pointer to mgmt frame subtype mask
+ *  @param wait_option  wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_reg_rx_mgmt_ind(moal_private *priv, t_u16 action,
+		     t_u32 *pmgmt_subtype_mask, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	misc->param.mgmt_subtype_mask = *pmgmt_subtype_mask;
+	if (req->action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &misc->param.mgmt_subtype_mask,
+				pmgmt_subtype_mask,
+				sizeof(misc->param.mgmt_subtype_mask),
+				sizeof(misc->param.mgmt_subtype_mask));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+	if (req->action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, pmgmt_subtype_mask,
+				&misc->param.mgmt_subtype_mask,
+				sizeof(misc->param.mgmt_subtype_mask),
+				sizeof(misc->param.mgmt_subtype_mask));
+
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Transmit beamforming capabilities
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param action       Action: set or get
+ *  @param tx_bf_cap    A pointer to tx_buf_cap buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_get_tx_bf_cap(moal_private *priv, t_u16 action, t_u32 *tx_bf_cap)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *bf_cfg = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!tx_bf_cap) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
+	req->action = action;
+	if (action == MLAN_ACT_SET)
+		bf_cfg->param.tx_bf_cap = *tx_bf_cap;
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		goto done;
+	}
+
+	if (action == MLAN_ACT_GET)
+		*tx_bf_cap = bf_cfg->param.tx_bf_cap;
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Transmit beamforming configuration
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action: set or get
+ *  @param tx_bf_cfg    A pointer to tx_bf_cfg structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_get_tx_bf_cfg(moal_private *priv, t_u16 action,
+		       mlan_ds_11n_tx_bf_cfg *tx_bf_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *bf_cfg = NULL;
+
+	ENTER();
+
+	/* Sanity test */
+	if (tx_bf_cfg == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CFG;
+
+	req->action = action;
+	moal_memcpy_ext(priv->phandle, &bf_cfg->param.tx_bf, tx_bf_cfg,
+			sizeof(mlan_ds_11n_tx_bf_cfg),
+			sizeof(mlan_ds_11n_tx_bf_cfg));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, tx_bf_cfg, &bf_cfg->param.tx_bf,
+				sizeof(mlan_ds_11n_tx_bf_cfg),
+				sizeof(mlan_ds_11n_tx_bf_cfg));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle ioctl resp
+ *
+ *  @param priv     Pointer to moal_private structure
+ *  @param req      Pointer to mlan_ioctl_req structure
+ *
+ *  @return         N/A
+ */
+void
+woal_process_ioctl_resp(moal_private *priv, mlan_ioctl_req *req)
+{
+	int cfg80211_wext;
+
+	ENTER();
+
+	if (priv == NULL) {
+		LEAVE();
+		return;
+	}
+	cfg80211_wext = priv->phandle->params.cfg80211_wext;
+	switch (req->req_id) {
+	case MLAN_IOCTL_GET_INFO:
+#ifdef STA_WEXT
+#ifdef STA_SUPPORT
+		if (IS_STA_WEXT(cfg80211_wext) &&
+		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+			woal_ioctl_get_info_resp(priv,
+						 (mlan_ds_get_info *)req->pbuf);
+#endif
+#endif
+#ifdef UAP_WEXT
+#ifdef UAP_SUPPORT
+		if (IS_UAP_WEXT(cfg80211_wext) &&
+		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+			woal_ioctl_get_uap_info_resp(priv,
+						     (mlan_ds_get_info *)req->
+						     pbuf);
+#endif
+#endif
+		break;
+#ifdef STA_WEXT
+#ifdef STA_SUPPORT
+	case MLAN_IOCTL_BSS:
+		if (IS_STA_WEXT(cfg80211_wext) &&
+		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+			woal_ioctl_get_bss_resp(priv, (mlan_ds_bss *)req->pbuf);
+		break;
+#endif
+#endif
+	case MLAN_IOCTL_MISC_CFG:
+		woal_ioctl_get_misc_conf(priv, (mlan_ds_misc_cfg *)req->pbuf);
+	default:
+		break;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Get PM info
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param pm_info              A pointer to mlan_ds_ps_info structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_pm_info(moal_private *priv, mlan_ds_ps_info *pm_info)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pmcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "Fail to alloc mlan_ds_pm_cfg buffer\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pmcfg->sub_command = MLAN_OID_PM_INFO;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (pm_info) {
+			moal_memcpy_ext(priv->phandle, pm_info,
+					&pmcfg->param.ps_info,
+					sizeof(mlan_ds_ps_info),
+					sizeof(mlan_ds_ps_info));
+		}
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Deep Sleep
+ *
+ *  @param priv      Pointer to the moal_private driver data struct
+ *  @param data      Pointer to return deep_sleep setting
+ *
+ *  @return          0 --success, otherwise fail
+ */
+int
+woal_get_deep_sleep(moal_private *priv, t_u32 *data)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pm = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	pm = (mlan_ds_pm_cfg *)req->pbuf;
+	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	*data = pm->param.auto_deep_sleep.auto_ds;
+	*(data + 1) = pm->param.auto_deep_sleep.idletime;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Deep Sleep
+ *
+ *  @param priv         Pointer to the moal_private driver data struct
+ *  @param wait_option  wait option
+ *  @param bdeep_sleep  TRUE--enalbe deepsleep, FALSE--disable deepsleep
+ *  @param idletime     Idle time for optimized PS API
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_set_deep_sleep(moal_private *priv, t_u8 wait_option,
+		    BOOLEAN bdeep_sleep, t_u16 idletime)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pm = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	pm = (mlan_ds_pm_cfg *)req->pbuf;
+	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	req->action = MLAN_ACT_SET;
+	if (bdeep_sleep == MTRUE) {
+		PRINTM(MIOCTL, "Deep Sleep: sleep\n");
+		pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
+		if (idletime)
+			pm->param.auto_deep_sleep.idletime = idletime;
+		ret = woal_request_ioctl(priv, req, wait_option);
+		if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		PRINTM(MIOCTL, "%lu : Deep Sleep: wakeup\n", jiffies);
+		pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
+		ret = woal_request_ioctl(priv, req, wait_option);
+		if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Cancel CAC period block
+ *
+ *  @param priv         A pointer to moal_private structure
+ *
+ *  @return         N/A
+ */
+void
+woal_cancel_cac_block(moal_private *priv)
+{
+	ENTER();
+	/* if during CAC period, wake up wait queue */
+	if (priv->phandle->cac_period == MTRUE) {
+		priv->phandle->cac_period = MFALSE;
+		/* Make sure Chan Report is cancelled */
+		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->meas_start_jiffies = 0;
+		if (priv->phandle->delay_bss_start == MTRUE)
+			priv->phandle->delay_bss_start = MFALSE;
+		if (priv->phandle->meas_wait_q_woken == MFALSE) {
+			priv->phandle->meas_wait_q_woken = MTRUE;
+			wake_up_interruptible(&priv->phandle->meas_wait_q);
+		}
+#ifdef UAP_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		if (priv->uap_host_based &&
+		    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+			woal_cfg80211_dfs_vendor_event(priv,
+						       event_dfs_cac_aborted,
+						       &priv->chan);
+#endif
+#endif
+#endif
+	}
+	LEAVE();
+}
+
+/** MEAS report timeout value in seconds */
+
+/**
+ *  @brief Issue MLAN_OID_11H_CHANNEL_CHECK ioctl
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wait_option wait option
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_11h_channel_check_ioctl(moal_private *priv, t_u8 wait_option)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+#ifdef UAP_SUPPORT
+	if (priv->skip_cac) {
+		LEAVE();
+		return ret;
+	}
+#endif
+
+	/* Skip sending request/report query when DFS_REPEATER_MODE is on. This
+	 * would get rid of CAC timers before starting BSSes in
+	 * DFS_REPEATER_MODE
+	 */
+	if (priv->phandle->dfs_repeater_mode) {
+		LEAVE();
+		return ret;
+	}
+
+	if (woal_is_any_interface_active(priv->phandle)) {
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+
+	ds_11hcfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
+	ds_11hcfg->param.chan_rpt_req.host_based = MFALSE;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+	req->action = MLAN_ACT_SET;
+	/* Send Channel Check command and wait until the report is ready */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		goto done;
+	}
+
+	/* set flag from here */
+	priv->phandle->cac_period = MTRUE;
+	priv->phandle->meas_start_jiffies = jiffies;
+	priv->phandle->cac_timer_jiffies =
+		ds_11hcfg->param.chan_rpt_req.millisec_dwell_time * HZ / 1000;
+
+#ifdef UAP_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (priv->uap_host_based &&
+	    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+		woal_cfg80211_dfs_vendor_event(priv, event_dfs_cac_started,
+					       &priv->chan);
+#endif
+#endif
+#endif
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wait_option wait option
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_11h_cancel_chan_report_ioctl(moal_private *priv, t_u8 wait_option)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	PRINTM(MCMND, "wlan: woal_11h_cancel_chan_report\n");
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+
+	ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_REPORT_REQUEST;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+	req->action = MLAN_ACT_SET;
+	ds_11hcfg->param.chan_rpt_req.millisec_dwell_time = 0;
+	/* Send Channel Check command and wait until the report is ready */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set remain channel
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *  @param pchan        A pointer to mlan_ds_remain_chan structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_remain_channel_ioctl(moal_private *priv, t_u8 wait_option,
+			      mlan_ds_remain_chan *pchan)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_REMAIN_CHAN_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+
+	req->action = MLAN_ACT_SET;
+	moal_memcpy_ext(priv->phandle, &radio_cfg->param.remain_chan, pchan,
+			sizeof(mlan_ds_remain_chan),
+			sizeof(mlan_ds_remain_chan));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		moal_memcpy_ext(priv->phandle, pchan,
+				&radio_cfg->param.remain_chan,
+				sizeof(mlan_ds_remain_chan),
+				sizeof(mlan_ds_remain_chan));
+		PRINTM(MCMND,
+		       "Remain_chan_cfg: remove=%d, channel=%d, remain_period=%d\n",
+		       pchan->remove, pchan->channel, pchan->remain_period);
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+/**
+ *  @brief set/get wifi direct mode
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       set or get
+ *  @param mode         A pointer to wifi direct mode
+ *
+ *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_wifi_direct_mode_cfg(moal_private *priv, t_u16 action, t_u16 *mode)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_WIFI_DIRECT_MODE;
+	req->req_id = MLAN_IOCTL_BSS;
+
+	req->action = action;
+	if (action == MLAN_ACT_SET)
+		bss->param.wfd_mode = *mode;
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		*mode = bss->param.wfd_mode;
+		PRINTM(MIOCTL, "ACT=%d, wifi_direct_mode=%d\n", action, *mode);
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set p2p config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param action       Action set or get
+ *  @param p2p_config   A pointer to  mlan_ds_wifi_direct_config structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_p2p_config(moal_private *priv, t_u32 action,
+		mlan_ds_wifi_direct_config *p2p_config)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+
+	ENTER();
+	if (!p2p_config) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_WIFI_DIRECT_CONFIG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	moal_memcpy_ext(priv->phandle, &misc_cfg->param.p2p_config, p2p_config,
+			sizeof(mlan_ds_wifi_direct_config),
+			sizeof(mlan_ds_wifi_direct_config));
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		if (action == MLAN_ACT_GET)
+			moal_memcpy_ext(priv->phandle, p2p_config,
+					&misc_cfg->param.p2p_config,
+					sizeof(mlan_ds_wifi_direct_config),
+					sizeof(mlan_ds_wifi_direct_config));
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif /* WIFI_DIRECT_SUPPORT */
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief Get STA Channel Info
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param channel          A pointer to channel info
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_sta_channel(moal_private *priv, t_u8 wait_option,
+		     chan_band_info * channel)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		PRINTM(MERROR, "woal_get_sta_channel req alloc fail\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_CHAN_INFO;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS && channel)
+		moal_memcpy_ext(priv->phandle, channel,
+				&(bss->param.sta_channel),
+				sizeof(chan_band_info), sizeof(chan_band_info));
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get RSSI info
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *  @param signal       A pointer tp mlan_ds_get_signal structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_get_signal_info(moal_private *priv, t_u8 wait_option,
+		     mlan_ds_get_signal *signal)
+{
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_SIGNAL;
+	info->param.signal.selector = ALL_RSSI_INFO_MASK;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (signal)
+			moal_memcpy_ext(priv->phandle, signal,
+					&info->param.signal,
+					sizeof(mlan_ds_get_signal),
+					sizeof(mlan_ds_get_signal));
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
+			if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
+				priv->w_stats.qual.level =
+					info->param.signal.bcn_rssi_avg;
+			if (info->param.signal.selector & BCN_NF_AVG_MASK)
+				priv->w_stats.qual.noise =
+					info->param.signal.bcn_nf_avg;
+		}
+#endif
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get scan table
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *  @param scan_resp    A pointer to mlan_scan_resp structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_get_scan_table(moal_private *priv, t_u8 wait_option,
+		    mlan_scan_resp *scan_resp)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_scan *scan = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	if (!scan_resp) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_NORMAL;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_GET;
+	moal_memcpy_ext(priv->phandle, (void *)&scan->param.scan_resp,
+			(void *)scan_resp, sizeof(mlan_scan_resp),
+			sizeof(mlan_scan_resp));
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (scan_resp) {
+			moal_memcpy_ext(priv->phandle, scan_resp,
+					&scan->param.scan_resp,
+					sizeof(mlan_scan_resp),
+					sizeof(mlan_scan_resp));
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Request a scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param req_ssid             A pointer to mlan_802_11_ssid structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_request_scan(moal_private *priv, t_u8 wait_option,
+		  mlan_802_11_ssid *req_ssid)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_scan *scan = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle->scan_pending_on_block = MTRUE;
+	handle->scan_priv = priv;
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (ioctl_req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	scan = (mlan_ds_scan *)ioctl_req->pbuf;
+
+	if (req_ssid && req_ssid->ssid_len != 0) {
+		/* Specific SSID scan */
+		ioctl_req->req_id = MLAN_IOCTL_SCAN;
+		ioctl_req->action = MLAN_ACT_SET;
+
+		scan->sub_command = MLAN_OID_SCAN_SPECIFIC_SSID;
+
+		moal_memcpy_ext(handle, scan->param.scan_req.scan_ssid.ssid,
+				req_ssid->ssid, req_ssid->ssid_len,
+				MLAN_MAX_SSID_LENGTH);
+		scan->param.scan_req.scan_ssid.ssid_len =
+			MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len);
+	} else {
+		/* Normal scan */
+		ioctl_req->req_id = MLAN_IOCTL_SCAN;
+		ioctl_req->action = MLAN_ACT_SET;
+
+		scan->sub_command = MLAN_OID_SCAN_NORMAL;
+	}
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	if (ret == MLAN_STATUS_FAILURE) {
+		handle->scan_pending_on_block = MFALSE;
+		handle->scan_priv = NULL;
+		MOAL_REL_SEMAPHORE(&handle->async_sem);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Change Adhoc Channel
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param channel      The channel to be set.
+ *  @param wait_option  wait_option
+ *
+ *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
+ */
+mlan_status
+woal_change_adhoc_chan(moal_private *priv, int channel, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_bss_info bss_info;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	/* Get BSS information */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, wait_option, &bss_info)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (bss_info.bss_mode == MLAN_BSS_MODE_INFRA) {
+		ret = MLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Get current channel */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_IBSS_CHANNEL;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (bss->param.bss_chan.channel == (unsigned int)channel) {
+		ret = MLAN_STATUS_SUCCESS;
+		goto done;
+	}
+	PRINTM(MINFO, "Updating Channel from %d to %d\n",
+	       (int)bss->param.bss_chan.channel, channel);
+
+	if (bss_info.media_connected != MTRUE) {
+		ret = MLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	/* Do disonnect */
+	bss->sub_command = MLAN_OID_BSS_STOP;
+	memset((t_u8 *)&bss->param.bssid, 0, ETH_ALEN);
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* Do specific SSID scanning */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_request_scan(priv, wait_option, &bss_info.ssid)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* Start/Join Adhoc network */
+	bss->sub_command = MLAN_OID_BSS_START;
+	memset(&bss->param.ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid.ssid,
+			&bss_info.ssid, sizeof(mlan_802_11_ssid),
+			sizeof(mlan_802_11_ssid));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Find the best network to associate
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param ssid_bssid       A pointer to mlan_ssid_bssid structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_find_best_network(moal_private *priv, t_u8 wait_option,
+		       mlan_ssid_bssid *ssid_bssid)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!ssid_bssid) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+	bss->sub_command = MLAN_OID_BSS_FIND_BSS;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid, ssid_bssid,
+			sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_SUCCESS) {
+		moal_memcpy_ext(priv->phandle, ssid_bssid,
+				&bss->param.ssid_bssid, sizeof(mlan_ssid_bssid),
+				sizeof(mlan_ssid_bssid));
+		PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
+		       ssid_bssid->ssid.ssid,
+		       MAC2STR((t_u8 *)&ssid_bssid->bssid),
+		       (int)ssid_bssid->idx);
+	}
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Find the best network to associate
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param bssid       		A pointer to bssid
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_find_bssid(moal_private *priv, mlan_802_11_mac_addr bssid)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+	bss->sub_command = MLAN_OID_BSS_FIND_BSSID;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.bssid, bssid,
+			sizeof(mlan_802_11_mac_addr),
+			sizeof(mlan_802_11_mac_addr));
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check if AP channel is valid for STA Region
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param ssid_bssid       A pointer to mlan_ssid_bssid structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_11d_check_ap_channel(moal_private *priv, t_u8 wait_option,
+			  mlan_ssid_bssid *ssid_bssid)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!ssid_bssid) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+	bss->sub_command = MLAN_OID_BSS_11D_CHECK_CHANNEL;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid, ssid_bssid,
+			sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
+
+	PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n", ssid_bssid->ssid.ssid,
+	       MAC2STR((t_u8 *)&ssid_bssid->bssid), (int)ssid_bssid->idx);
+
+	/* Send IOCTL request to MLAN */
+	ret = woal_request_ioctl(priv, req, wait_option);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get authentication mode
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param auth_mode        A pointer to authentication mode
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_auth_mode(moal_private *priv, t_u8 wait_option, t_u32 *auth_mode)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS && auth_mode)
+		*auth_mode = sec->param.auth_mode;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get encrypt mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param encrypt_mode         A pointer to encrypt mode
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_encrypt_mode(moal_private *priv, t_u8 wait_option, t_u32 *encrypt_mode)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS && encrypt_mode)
+		*encrypt_mode = sec->param.encrypt_mode;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get WPA enable
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param enable           A pointer to wpa enable status
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_get_wpa_enable(moal_private *priv, t_u8 wait_option, t_u32 *enable)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS && enable)
+		*enable = sec->param.wpa_enabled;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set authentication mode
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param auth_mode        Authentication mode
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_auth_mode(moal_private *priv, t_u8 wait_option, t_u32 auth_mode)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+	sec->param.auth_mode = auth_mode;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set encrypt mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param encrypt_mode         Encryption mode
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_encrypt_mode(moal_private *priv, t_u8 wait_option, t_u32 encrypt_mode)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+	sec->param.encrypt_mode = encrypt_mode;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set wpa enable
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param enable               MTRUE or MFALSE
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_set_wpa_enable(moal_private *priv, t_u8 wait_option, t_u32 enable)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+	sec->param.wpa_enabled = enable;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief enable wep key
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_enable_wep_key(moal_private *priv, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+	sec->param.encrypt_key.key_disable = MFALSE;
+	sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
+	sec->param.encrypt_key.is_current_wep_key = MTRUE;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Request user scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param scan_cfg             A pointer to wlan_user_scan_config structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_request_userscan(moal_private *priv, t_u8 wait_option,
+		      wlan_user_scan_cfg *scan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_scan *scan = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	ENTER();
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle->scan_pending_on_block = MTRUE;
+	handle->scan_priv = priv;
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
+					      sizeof(wlan_user_scan_cfg));
+	if (ioctl_req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	scan = (mlan_ds_scan *)ioctl_req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
+	ioctl_req->req_id = MLAN_IOCTL_SCAN;
+	ioctl_req->action = MLAN_ACT_SET;
+	moal_memcpy_ext(handle, scan->param.user_scan.scan_cfg_buf, scan_cfg,
+			sizeof(wlan_user_scan_cfg), sizeof(wlan_user_scan_cfg));
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	else if (wait_option != MOAL_NO_WAIT) {
+		PRINTM(MMSG, "scan interrupted by Signal, Cancel it...");
+		woal_cancel_scan(priv, MOAL_IOCTL_WAIT_TIMEOUT);
+	}
+	if (ret == MLAN_STATUS_FAILURE) {
+		handle->scan_pending_on_block = MFALSE;
+		handle->scan_priv = NULL;
+		MOAL_REL_SEMAPHORE(&handle->async_sem);
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief woal_get_scan_config
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param scan_cfg             A pointer to scan_cfg structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_get_scan_config(moal_private *priv, mlan_scan_cfg *scan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_GET;
+	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret == MLAN_STATUS_SUCCESS && scan_cfg)
+		moal_memcpy_ext(priv->phandle, scan_cfg, &scan->param.scan_cfg,
+				sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set scan time
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param active_scan_time     Active scan time
+ *  @param passive_scan_time    Passive scan time
+ *  @param specific_scan_time   Specific scan time
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_scan_time(moal_private *priv, t_u16 active_scan_time,
+		   t_u16 passive_scan_time, t_u16 specific_scan_time)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_scan_cfg scan_cfg;
+
+	ENTER();
+
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_SET;
+	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
+	scan_cfg.scan_time.active_scan_time = active_scan_time;
+	scan_cfg.scan_time.specific_scan_time = specific_scan_time;
+	scan_cfg.scan_time.passive_scan_time = passive_scan_time;
+	PRINTM(MIOCTL, "Set specific=%d, active=%d, passive=%d\n",
+	       (int)active_scan_time, (int)passive_scan_time,
+	       (int)specific_scan_time);
+	moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
+			sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief request scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param scan_cfg             A pointer to wlan_user_scan_cfg structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_do_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+
+	ENTER();
+	if (handle->scan_pending_on_block == MTRUE) {
+		PRINTM(MINFO, "scan already in processing...\n");
+		LEAVE();
+		return ret;
+	}
+#ifdef REASSOCIATION
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#endif /* REASSOCIATION */
+	priv->report_scan_result = MTRUE;
+
+	if (!scan_cfg)
+		ret = woal_request_scan(priv, MOAL_NO_WAIT, NULL);
+	else
+		ret = woal_request_userscan(priv, MOAL_NO_WAIT, scan_cfg);
+
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Cancel pending scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_cancel_scan(moal_private *priv, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	moal_private *scan_priv = handle->scan_priv;
+#ifdef STA_CFG80211
+	unsigned long flags;
+#endif
+	/* If scan is in process, cancel the scan command */
+	if (!handle->scan_pending_on_block || !scan_priv)
+		return ret;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_SET;
+	((mlan_ds_scan *)req->pbuf)->sub_command = MLAN_OID_SCAN_CANCEL;
+	ret = woal_request_ioctl(scan_priv, req, wait_option);
+	handle->scan_pending_on_block = MFALSE;
+	MOAL_REL_SEMAPHORE(&handle->async_sem);
+#ifdef STA_CFG80211
+	spin_lock_irqsave(&handle->scan_req_lock, flags);
+	if (IS_STA_CFG80211(handle->params.cfg80211_wext) &&
+	    handle->scan_request) {
+		cancel_delayed_work(&handle->scan_timeout_work);
+		/** some supplicant can not handle SCAN abort event */
+		if (scan_priv->bss_type == MLAN_BSS_TYPE_STA)
+			woal_cfg80211_scan_done(handle->scan_request, MTRUE);
+		else
+			woal_cfg80211_scan_done(handle->scan_request, MFALSE);
+		handle->scan_request = NULL;
+	}
+	spin_unlock_irqrestore(&handle->scan_req_lock, flags);
+#endif
+	/* add 10ms delay, incase firmware delay 0x7f event after scan cancel
+	 * command response */
+	woal_sched_timeout(10);
+	handle->scan_priv = NULL;
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	return ret;
+}
+
+/**
+ *  @brief find ssid in scan_table
+ *
+ *  @param priv         A pointer to moal_private
+ *  @param ssid_bssid   A pointer to mlan_ssid_bssid structure
+ *
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
+ */
+int
+woal_find_essid(moal_private *priv, mlan_ssid_bssid *ssid_bssid,
+		t_u8 wait_option)
+{
+	int ret = 0;
+	mlan_scan_resp scan_resp;
+	wifi_timeval t;
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, wait_option, &scan_resp)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#ifdef STA_CFG80211
+	if (priv->ft_pre_connect || priv->ft_ie_len) {
+		/** skip check the scan age out */
+		ret = woal_find_best_network(priv, wait_option, ssid_bssid);
+		LEAVE();
+		return ret;
+	}
+#endif
+	woal_get_monotonic_time(&t);
+/** scan result timeout value */
+#define SCAN_RESULT_AGEOUT 10
+	if (t.time_sec > (scan_resp.age_in_secs + SCAN_RESULT_AGEOUT)) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = woal_find_best_network(priv, wait_option, ssid_bssid);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Request user scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param scan_cfg             A pointer to wlan_bgscan_cfg structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_request_bgscan(moal_private *priv, t_u8 wait_option,
+		    wlan_bgscan_cfg *scan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_scan *scan = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
+					      sizeof(wlan_bgscan_cfg));
+	if (ioctl_req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	scan = (mlan_ds_scan *)ioctl_req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_BGSCAN_CONFIG;
+	ioctl_req->req_id = MLAN_IOCTL_SCAN;
+	ioctl_req->action = MLAN_ACT_SET;
+	moal_memcpy_ext(priv->phandle, scan->param.user_scan.scan_cfg_buf,
+			scan_cfg, sizeof(wlan_bgscan_cfg),
+			sizeof(wlan_bgscan_cfg));
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, ioctl_req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set bgscan config
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param buf                  A pointer to scan command buf
+ *  @param length               buf length
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_bg_scan(moal_private *priv, char *buf, int length)
+{
+	t_u8 *ptr = buf + strlen("BGSCAN-CONFIG") + 1;
+	int buf_left = length - (strlen("BGSCAN-CONFIG") + 1);
+	int band = 0;
+	int num_ssid = 0;
+	int ssid_len = 0;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+
+	ENTER();
+	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
+	priv->scan_cfg.report_condition =
+		BG_SCAN_SSID_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
+	while (buf_left >= 2) {
+		switch (*ptr) {
+		case WEXT_CSCAN_SSID_SECTION:
+			ssid_len = *(ptr + 1);
+			if ((buf_left < (ssid_len + 2)) ||
+			    (ssid_len > MLAN_MAX_SSID_LENGTH)) {
+				PRINTM(MERROR,
+				       "Invalid ssid, buf_left=%d, ssid_len=%d\n",
+				       buf_left, ssid_len);
+				buf_left = 0;
+				break;
+			}
+			if (ssid_len &&
+			    (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
+				strncpy(priv->scan_cfg.ssid_list[num_ssid].ssid,
+					ptr + 2, ssid_len);
+				priv->scan_cfg.ssid_list[num_ssid].max_len = 0;
+				PRINTM(MIOCTL, "BG scan: ssid=%s\n",
+				       priv->scan_cfg.ssid_list[num_ssid].ssid);
+				num_ssid++;
+			}
+			buf_left -= ssid_len + 2;
+			ptr += ssid_len + 2;
+			break;
+		case WEXT_BGSCAN_RSSI_SECTION:
+			priv->scan_cfg.report_condition =
+				BG_SCAN_SSID_RSSI_MATCH |
+				BG_SCAN_WAIT_ALL_CHAN_DONE;
+			priv->scan_cfg.rssi_threshold = ptr[1];
+			PRINTM(MIOCTL, "BG scan: rssi_threshold=%d\n",
+			       (int)priv->scan_cfg.rssi_threshold);
+			ptr += 2;
+			buf_left -= 2;
+			break;
+		case WEXT_BGSCAN_REPEAT_SECTION:
+			priv->scan_cfg.repeat_count = (t_u16)ptr[1];
+			PRINTM(MIOCTL, "BG scan: repeat_count=%d\n",
+			       (int)priv->scan_cfg.repeat_count);
+			ptr += 2;
+			buf_left -= 2;
+			break;
+		case WEXT_BGSCAN_INTERVAL_SECTION:
+			if (buf_left < 3) {
+				PRINTM(MERROR,
+				       "Invalid scan_interval, buf_left=%d\n",
+				       buf_left);
+				buf_left = 0;
+				break;
+			}
+			priv->scan_cfg.scan_interval =
+				(ptr[2] << 8 | ptr[1]) * 1000;
+			PRINTM(MIOCTL, "BG scan: scan_interval=%d\n",
+			       (int)priv->scan_cfg.scan_interval);
+			ptr += 3;
+			buf_left -= 3;
+			break;
+		default:
+			buf_left = 0;
+			break;
+		}
+	}
+	/** set bgscan when ssid_num > 0 */
+	if (num_ssid) {
+		if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		switch (band) {
+		case WIFI_FREQUENCY_BAND_2GHZ:
+			priv->scan_cfg.chan_list[0].radio_type =
+				0 | BAND_SPECIFIED;
+			break;
+		case WIFI_FREQUENCY_BAND_5GHZ:
+			priv->scan_cfg.chan_list[0].radio_type =
+				1 | BAND_SPECIFIED;
+			break;
+		default:
+			break;
+		}
+		priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
+		priv->scan_cfg.action = BG_SCAN_ACT_SET;
+		priv->scan_cfg.enable = MTRUE;
+		moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
+				priv->random_mac, ETH_ALEN,
+				sizeof(priv->scan_cfg.random_mac));
+		ret = woal_request_bgscan(priv, MOAL_IOCTL_WAIT,
+					  &priv->scan_cfg);
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_CFG80211
+/**
+ *  @brief set bgscan and new rssi_low_threshold
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param set_rssi             flag for set rssi_low_threshold
+ *
+ *  @return                     N/A
+ */
+void
+woal_config_bgscan_and_rssi(moal_private *priv, t_u8 set_rssi)
+{
+	char rssi_low[11];
+	mlan_bss_info bss_info;
+	int band = 0;
+
+	ENTER();
+	if (!priv->rssi_low) {
+		LEAVE();
+		return;
+	}
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (!bss_info.media_connected) {
+		PRINTM(MIOCTL, "We already lost connection\n");
+		LEAVE();
+		return;
+	}
+	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
+	strncpy(priv->scan_cfg.ssid_list[0].ssid, bss_info.ssid.ssid,
+		bss_info.ssid.ssid_len);
+	priv->scan_cfg.ssid_list[0].max_len = 0;
+
+	priv->scan_cfg.report_condition =
+		BG_SCAN_SSID_RSSI_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
+	priv->scan_cfg.rssi_threshold = priv->rssi_low - RSSI_HYSTERESIS;
+	priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT;
+	priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL;
+	woal_get_band(priv, &band);
+	switch (band) {
+	case WIFI_FREQUENCY_BAND_2GHZ:
+		priv->scan_cfg.chan_list[0].radio_type = 0 | BAND_SPECIFIED;
+		break;
+	case WIFI_FREQUENCY_BAND_5GHZ:
+		priv->scan_cfg.chan_list[0].radio_type = 1 | BAND_SPECIFIED;
+		break;
+	default:
+		break;
+	}
+	priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
+	priv->scan_cfg.action = BG_SCAN_ACT_SET;
+	priv->scan_cfg.enable = MTRUE;
+	moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
+			priv->random_mac, ETH_ALEN,
+			sizeof(priv->scan_cfg.random_mac));
+	woal_request_bgscan(priv, MOAL_NO_WAIT, &priv->scan_cfg);
+	if (set_rssi &&
+	    ((priv->rssi_low + RSSI_HYSTERESIS) <= LOWEST_RSSI_THRESHOLD)) {
+		priv->rssi_low += RSSI_HYSTERESIS;
+		snprintf(rssi_low, sizeof(rssi_low), "%d", priv->rssi_low);
+		woal_set_rssi_low_threshold(priv, rssi_low, MOAL_NO_WAIT);
+	}
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief stop bg scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          wait option
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_stop_bg_scan(moal_private *priv, t_u8 wait_option)
+{
+	wlan_bgscan_cfg scan_cfg;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+	scan_cfg.action = BG_SCAN_ACT_SET;
+	scan_cfg.enable = MFALSE;
+	ret = woal_request_bgscan(priv, wait_option, &scan_cfg);
+
+	LEAVE();
+	return ret;
+}
+
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+/**
+ *  @brief Enable/disable WiFi low-latency mode
+ *
+ *  If low-latency mode is set to WIFI_LATENCY_MODE_LOW, this function
+ *  will cancel existing pending Wi-Fi scans and suppress future Wi-Fi scans
+ *  via setting |priv->scan_suppressed| to |MTRUE|. Future scans will be supressed
+ *  until low-latency mode is set back to WIFI_LATENCY_MODE_NORMAL.
+ *  If low-latency mode is set to WIFI_LATENCY_MODE_NORMAL, this function
+ *  will set |priv-scan_suppressed| to |MFALSE| and any future will be run as
+ *  normal.
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param mode                 1 -- low-latency mode, 0 -- normal mode
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_wifi_low_latency_mode(moal_private *priv, t_u8 mode)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	/** WIFI_LATENCY_MODE_NORMAL : 0,  WIFI_LATENCY_MODE_LOW : 1,*/
+	t_bool low_latency_mode_enabled = (mode == 1 ? MTRUE : MFALSE);
+	PRINTM(MMSG, "wlan: enter %s.\n", __FUNCTION__);
+	if (MTRUE == low_latency_mode_enabled) {
+		PRINTM(MINFO, "Setting Wi-Fi latency mode to low-latency mode.");
+		/** Cancel pending Wi-Fi scanning if exist. */
+		if (priv->phandle->scan_request) {
+			woal_cancel_scan(priv, MOAL_NO_WAIT);
+			PRINTM(MINFO, "Cancel existing scan due to low-latency mode.");
+		}
+		/** Suppress future Wi-Fi scan requests. */
+		priv->scan_suppressed = MTRUE;
+	} else {
+		PRINTM(MINFO, "Setting Wi-Fi latency mode to normal mode.");
+		priv->scan_suppressed = MFALSE;
+	}
+	return ret;
+}
+#endif  // defined(WIFI_LATENCY_MODE_SUPPORT)
+
+/**
+ *  @brief set bgscan config
+ *
+ *  @param handle               A pointer to moal_handle structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+void
+woal_reconfig_bgscan(moal_handle *handle)
+{
+	int i;
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
+			if (handle->priv[i]->bg_scan_start &&
+			    handle->priv[i]->bg_scan_reported) {
+				PRINTM(MIOCTL, "Reconfig BGSCAN\n");
+				woal_request_bgscan(handle->priv[i],
+						    MOAL_NO_WAIT,
+						    &handle->priv[i]->scan_cfg);
+				handle->priv[i]->bg_scan_reported = MFALSE;
+			}
+		}
+	}
+}
+
+/**
+ *  @brief set rssi low threshold
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param rssi                 A pointer to low rssi
+ *  @param wait_option          Wait option
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_rssi_low_threshold(moal_private *priv, char *rssi, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int low_rssi = 0;
+
+	ENTER();
+	if (priv->media_connected == MFALSE)
+		goto done;
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
+	req->action = MLAN_ACT_SET;
+	misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET;
+	misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW;
+	misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST;
+	misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS;
+
+	if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#ifdef STA_CFG80211
+	priv->mrvl_rssi_low = low_rssi;
+#endif
+	misc->param.subscribe_event.low_rssi = low_rssi;
+	misc->param.subscribe_event.low_rssi_freq = 0;
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MERROR, "request set rssi_low_threshold fail!\n");
+		goto done;
+	}
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(STA_CFG80211)
+/**
+ *  @brief set rssi low threshold
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param event_id             event id.
+ *  @param wait_option          wait option
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_rssi_threshold(moal_private *priv, t_u32 event_id, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+
+	ENTER();
+	if (priv->media_connected == MFALSE)
+		goto done;
+	if (priv->mrvl_rssi_low || !priv->cqm_rssi_thold)
+		goto done;
+	if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) {
+		if (priv->last_rssi_low < 100)
+			priv->last_rssi_low += priv->cqm_rssi_hyst;
+		priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
+	} else if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_HIGH) {
+		priv->last_rssi_low = abs(priv->cqm_rssi_thold);
+		if (priv->last_rssi_high > priv->cqm_rssi_hyst)
+			priv->last_rssi_high -= priv->cqm_rssi_hyst;
+	} else {
+		priv->last_rssi_low = abs(priv->cqm_rssi_thold);
+		priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
+	req->action = MLAN_ACT_SET;
+	if (!event_id && !priv->cqm_rssi_thold && !priv->cqm_rssi_hyst)
+		misc->param.subscribe_event.evt_action =
+			SUBSCRIBE_EVT_ACT_BITWISE_CLR;
+	else
+		misc->param.subscribe_event.evt_action =
+			SUBSCRIBE_EVT_ACT_BITWISE_SET;
+	misc->param.subscribe_event.evt_bitmap =
+		SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH;
+	misc->param.subscribe_event.low_rssi_freq = 0;
+	misc->param.subscribe_event.low_rssi = priv->last_rssi_low;
+	misc->param.subscribe_event.high_rssi_freq = 0;
+	misc->param.subscribe_event.high_rssi = priv->last_rssi_high;
+	PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d action=%d\n",
+	       (int)priv->last_rssi_low, (int)priv->last_rssi_high,
+	       misc->param.subscribe_event.evt_action);
+	ret = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief  Get power mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param powermode            A pointer to powermode buf
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_get_powermode(moal_private *priv, int *powermode)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int ps_mode;
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
+							   &ps_mode, 0,
+							   MOAL_IOCTL_WAIT)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (ps_mode)
+		*powermode = MFALSE;
+	else
+		*powermode = MTRUE;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set scan type
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param scan_type            MLAN_SCAN_TYPE_ACTIVE/MLAN_SCAN_TYPE_PASSIVE
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_scan_type(moal_private *priv, t_u32 scan_type)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_scan_cfg scan_cfg;
+
+	ENTER();
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_SET;
+	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
+	scan_cfg.scan_type = scan_type;
+	PRINTM(MIOCTL, "Set scan_type=%d\n", (int)scan_type);
+	moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
+			sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief enable/disable ext_scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param enable               MTRUE -- enable, MFALSE --disable
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_enable_ext_scan(moal_private *priv, t_u8 enable)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_scan_cfg scan_cfg;
+
+	ENTER();
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_SET;
+	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
+	scan_cfg.ext_scan = enable;
+	PRINTM(MIOCTL, "Set ext_scan=%d\n", (int)enable);
+	moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
+			sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set power mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param powermode            A pointer to powermode string.
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_powermode(moal_private *priv, char *powermode)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int disabled;
+
+	ENTER();
+
+	if (*powermode == '1') {
+		PRINTM(MIOCTL, "Disable power save\n");
+		disabled = 1;
+	} else if (*powermode == '0') {
+		PRINTM(MIOCTL, "Enable power save\n");
+		disabled = 0;
+	} else {
+		PRINTM(MERROR, "unsupported power mode\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_SET,
+							   &disabled, 0,
+							   MOAL_IOCTL_WAIT))
+		ret = MLAN_STATUS_FAILURE;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set combo scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param buf                  A pointer to scan command buf
+ *  @param length               buf length
+ *
+ *  @return                     0 -- success, otherwise fail
+ */
+int
+woal_set_combo_scan(moal_private *priv, char *buf, int length)
+{
+	int ret = 0;
+	wlan_user_scan_cfg scan_cfg;
+	t_u8 *ptr = buf + WEXT_CSCAN_HEADER_SIZE;
+	int buf_left = length - WEXT_CSCAN_HEADER_SIZE;
+	int num_ssid = 0;
+	int num_chan = 0;
+	int ssid_len = 0;
+	int i = 0;
+	t_u16 passive_scan_time = 0;
+	t_u16 specific_scan_time = 0;
+
+	ENTER();
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+	while (buf_left >= 2) {
+		switch (*ptr) {
+		case WEXT_CSCAN_SSID_SECTION:
+			ssid_len = *(ptr + 1);
+			if ((buf_left < (ssid_len + 2)) ||
+			    (ssid_len > MLAN_MAX_SSID_LENGTH)) {
+				PRINTM(MERROR,
+				       "Invalid ssid, buf_left=%d, ssid_len=%d\n",
+				       buf_left, ssid_len);
+				buf_left = 0;
+				break;
+			}
+			if (ssid_len &&
+			    (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
+				strncpy(scan_cfg.ssid_list[num_ssid].ssid,
+					ptr + 2, ssid_len);
+				scan_cfg.ssid_list[num_ssid].max_len = 0;
+				PRINTM(MIOCTL, "Combo scan: ssid=%s\n",
+				       scan_cfg.ssid_list[num_ssid].ssid);
+				num_ssid++;
+			}
+			buf_left -= ssid_len + 2;
+			ptr += ssid_len + 2;
+			break;
+		case WEXT_CSCAN_CHANNEL_SECTION:
+			num_chan = ptr[1];
+			if ((buf_left < (num_chan + 2)) ||
+			    (num_chan > WLAN_USER_SCAN_CHAN_MAX)) {
+				PRINTM(MERROR,
+				       "Invalid channel list, buf_left=%d, num_chan=%d\n",
+				       buf_left, num_chan);
+				buf_left = 0;
+				break;
+			}
+			for (i = 0; i < num_chan; i++) {
+				scan_cfg.chan_list[i].chan_number = ptr[2 + i];
+				PRINTM(MIOCTL, "Combo scan: chan=%d\n",
+				       scan_cfg.chan_list[i].chan_number);
+			}
+			buf_left -= 2 + num_chan;
+			ptr += 2 + num_chan;
+			break;
+		case WEXT_CSCAN_PASV_DWELL_SECTION:
+			if (buf_left < 3) {
+				PRINTM(MERROR,
+				       "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
+				       buf_left);
+				buf_left = 0;
+				break;
+			}
+			passive_scan_time = ptr[2] << 8 | ptr[1];
+			ptr += 3;
+			buf_left -= 3;
+			break;
+		case WEXT_CSCAN_HOME_DWELL_SECTION:
+			if (buf_left < 3) {
+				PRINTM(MERROR,
+				       "Invalid HOME_DWELL_SECTION, buf_left=%d\n",
+				       buf_left);
+				buf_left = 0;
+				break;
+			}
+			specific_scan_time = ptr[2] << 8 | ptr[1];
+			ptr += 3;
+			buf_left -= 3;
+			break;
+		default:
+			buf_left = 0;
+			break;
+		}
+	}
+	if (passive_scan_time || specific_scan_time) {
+		PRINTM(MIOCTL,
+		       "Set passive_scan_time=%d specific_scan_time=%d\n",
+		       passive_scan_time, specific_scan_time);
+		if (MLAN_STATUS_FAILURE ==
+		    woal_set_scan_time(priv, 0, passive_scan_time,
+				       specific_scan_time)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	if (num_ssid || num_chan) {
+		if (num_ssid) {
+			/* Add broadcast scan to ssid_list */
+			scan_cfg.ssid_list[num_ssid].max_len = 0xff;
+			if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+				woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
+		}
+		if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
+			ret = -EFAULT;
+		if (num_ssid && (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE))
+			woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+	} else {
+		/* request broadcast scan */
+		if (MLAN_STATUS_FAILURE == woal_do_scan(priv, NULL))
+			ret = -EFAULT;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Get band
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param band                 A pointer to band buf
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_get_band(moal_private *priv, int *band)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+	int support_band = 0;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	/* Get config_bands, adhoc_start_band and adhoc_channel values from MLAN
+	 */
+	req->action = MLAN_ACT_GET;
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (radio_cfg->param.band_cfg.config_bands &
+	    (BAND_B | BAND_G | BAND_GN))
+		support_band |= WIFI_FREQUENCY_BAND_2GHZ;
+	if (radio_cfg->param.band_cfg.config_bands & (BAND_A | BAND_AN))
+		support_band |= WIFI_FREQUENCY_BAND_5GHZ;
+	*band = support_band;
+	if (support_band == WIFI_FREQUENCY_ALL_BAND)
+		*band = WIFI_FREQUENCY_BAND_AUTO;
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set band
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param pband            A pointer to band string.
+ *
+ *  @return                 MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_band(moal_private *priv, char *pband)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int band = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	int cfg80211_wext = priv->phandle->params.cfg80211_wext;
+#endif
+
+	ENTER();
+	if (priv->media_connected == MTRUE) {
+		PRINTM(MERROR, "Set band is not allowed in connected state\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+
+	/* Get fw supported values from MLAN */
+	req->action = MLAN_ACT_GET;
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (*pband == '0') {
+		PRINTM(MIOCTL, "Set band to AUTO\n");
+		band = radio_cfg->param.band_cfg.fw_bands;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
+		    priv->wdev->wiphy) {
+			if (radio_cfg->param.band_cfg.fw_bands & BAND_A)
+				priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
+					&cfg80211_band_5ghz;
+			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
+				&cfg80211_band_2ghz;
+		}
+#endif
+	} else if (*pband == '1') {
+		PRINTM(MIOCTL, "Set band to 5G\n");
+		if (!(radio_cfg->param.band_cfg.fw_bands & BAND_A)) {
+			PRINTM(MERROR, "Don't support 5G band\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		band = BAND_A;
+		if (radio_cfg->param.band_cfg.fw_bands & BAND_AN)
+			band |= BAND_AN;
+		if (radio_cfg->param.band_cfg.fw_bands & BAND_AAC)
+			band |= BAND_AAC;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
+		    priv->wdev->wiphy) {
+			priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
+				&cfg80211_band_5ghz;
+			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+		}
+#endif
+	} else if (*pband == '2') {
+		PRINTM(MIOCTL, "Set band to 2G\n");
+		band = BAND_B | BAND_G;
+		band |= BAND_GN;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
+		    priv->wdev->wiphy) {
+			priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
+				&cfg80211_band_2ghz;
+		}
+#endif
+	} else {
+		PRINTM(MERROR, "unsupported band\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	/* Set config_bands to MLAN */
+	req->action = MLAN_ACT_SET;
+	memset(&radio_cfg->param.band_cfg, 0, sizeof(mlan_ds_band_cfg));
+	radio_cfg->param.band_cfg.config_bands = band;
+	radio_cfg->param.band_cfg.adhoc_start_band = band;
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Add RX Filter
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param rxfilter             A pointer to rxfilter string.
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_add_rxfilter(moal_private *priv, char *rxfilter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	/*  Android command:
+	   "DRIVER RXFILTER-ADD 0"
+	   "DRIVER RXFILTER-ADD 1"
+	   "DRIVER RXFILTER-ADD 3" */
+	if (*rxfilter == '0') {
+		PRINTM(MIOCTL, "Add IPV4 multicast filter\n");
+		priv->rx_filter |= RX_FILTER_IPV4_MULTICAST;
+	} else if (*rxfilter == '1') {
+		PRINTM(MIOCTL, "Add broadcast filter\n");
+		priv->rx_filter |= RX_FILTER_BROADCAST;
+	} else if (*rxfilter == '2') {
+		PRINTM(MIOCTL, "Add unicast filter\n");
+		priv->rx_filter |= RX_FILTER_UNICAST;
+	} else if (*rxfilter == '3') {
+		PRINTM(MIOCTL, "Add IPV6 multicast fitler\n");
+		priv->rx_filter |= RX_FILTER_IPV6_MULTICAST;
+	} else {
+		PRINTM(MERROR, "unsupported rx fitler\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Remove RX Filter
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param rxfilter             A pointer to rxfilter string.
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_remove_rxfilter(moal_private *priv, char *rxfilter)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	if (*rxfilter == '0') {
+		PRINTM(MIOCTL, "Remove IPV4 multicast filter\n");
+		priv->rx_filter &= ~RX_FILTER_IPV4_MULTICAST;
+	} else if (*rxfilter == '1') {
+		PRINTM(MIOCTL, "Remove broadcast filter\n");
+		priv->rx_filter &= ~RX_FILTER_BROADCAST;
+	} else if (*rxfilter == '2') {
+		PRINTM(MIOCTL, "Remove unicast filter\n");
+		priv->rx_filter &= ~RX_FILTER_UNICAST;
+	} else if (*rxfilter == '3') {
+		PRINTM(MIOCTL, "Remove IPV6 multicast fitler\n");
+		priv->rx_filter &= ~RX_FILTER_IPV6_MULTICAST;
+	} else {
+		PRINTM(MERROR, "unsupported rx fitler\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get WMM IE QoS configuration
+ *
+ * @param priv     A pointer to moal_private structure
+ *  @param action  Action set or get
+ * @param qos_cfg  A pointer to QoS configuration structure
+ *
+ * @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_priv_qos_cfg(moal_private *priv, t_u32 action, char *qos_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_wmm_cfg *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int qosinfo = 0;
+
+	ENTER();
+
+	if (qos_cfg == NULL) {
+		PRINTM(MERROR, "QOS info buffer is null\n");
+		return MLAN_STATUS_FAILURE;
+	}
+	if ((action == MLAN_ACT_SET) &&
+	    (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg))) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	req->action = action;
+	if (action == MLAN_ACT_SET) {
+		cfg->param.qos_cfg = (t_u8)qosinfo;
+		PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo);
+	}
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+	if (action == MLAN_ACT_GET)
+		*qos_cfg = cfg->param.qos_cfg;
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set sleep period
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param psleeppd A pointer to sleep period configuration structure
+ *
+ * @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_set_sleeppd(moal_private *priv, char *psleeppd)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int sleeppd = 0;
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS != woal_atoi(&sleeppd, psleeppd)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	PRINTM(MIOCTL, "set sleeppd=%d\n", sleeppd);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	if ((sleeppd <= MAX_SLEEP_PERIOD && sleeppd >= MIN_SLEEP_PERIOD) ||
+	    (sleeppd == 0)
+	    || (sleeppd == SLEEP_PERIOD_RESERVED_FF)
+		) {
+		req->action = MLAN_ACT_SET;
+		pm_cfg->param.sleep_period = sleeppd;
+	} else {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief  Set scan period function
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param buf       A pointer to scan command buf
+ * @param length    buf length
+ *
+ * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+int
+woal_set_scan_cfg(moal_private *priv, char *buf, int length)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *ptr = buf + NL80211_SCANCFG_HEADER_SIZE;
+	int buf_left = length - NL80211_SCANCFG_HEADER_SIZE;
+	t_u16 active_scan_time = 0;
+	t_u16 passive_scan_time = 0;
+	t_u16 specific_scan_time = 0;
+
+	ENTER();
+	while (buf_left >= 2) {
+		switch (*ptr) {
+		case NL80211_SCANCFG_ACTV_DWELL_SECTION:
+			if (buf_left < 3) {
+				PRINTM(MERROR,
+				       "Invalid ACTV_DWELL_SECTION, buf_left=%d\n",
+				       buf_left);
+				buf_left = 0;
+				break;
+			}
+			active_scan_time = ptr[2] << 8 | ptr[1];
+			ptr += 3;
+			buf_left -= 3;
+			break;
+		case NL80211_SCANCFG_PASV_DWELL_SECTION:
+			if (buf_left < 3) {
+				PRINTM(MERROR,
+				       "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
+				       buf_left);
+				buf_left = 0;
+				break;
+			}
+			passive_scan_time = ptr[2] << 8 | ptr[1];
+			ptr += 3;
+			buf_left -= 3;
+			break;
+		case NL80211_SCANCFG_SPCF_DWELL_SECTION:
+			if (buf_left < 3) {
+				PRINTM(MERROR,
+				       "Invalid SPCF_DWELL_SECTION, buf_left=%d\n",
+				       buf_left);
+				buf_left = 0;
+				break;
+			}
+			specific_scan_time = ptr[2] << 8 | ptr[1];
+			ptr += 3;
+			buf_left -= 3;
+			break;
+		default:
+			buf_left = 0;
+			break;
+		}
+	}
+
+	if (active_scan_time || passive_scan_time || specific_scan_time) {
+		PRINTM(MIOCTL,
+		       "Set active_scan_time= %d passive_scan_time=%d specific_scan_time=%d\n",
+		       active_scan_time, passive_scan_time, specific_scan_time);
+		if (MLAN_STATUS_FAILURE ==
+		    woal_set_scan_time(priv, active_scan_time,
+				       passive_scan_time, specific_scan_time)) {
+			ret = -EFAULT;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Radio On/OFF
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param option               Radio Option
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+int
+woal_set_radio(moal_private *priv, t_u8 option)
+{
+	int ret = 0;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+	if ((option != 0) && (option != 1)) {
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_RADIO_CTRL;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	req->action = MLAN_ACT_SET;
+	radio->param.radio_on_off = option;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		ret = -EFAULT;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#endif /* STA_SUPPORT */
+
+#ifdef USB
+/**
+ * @brief Initialize USB packet aggregation control
+ *
+ * @param handle    A pointer to moal_private structure
+ *
+ * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+mlan_status
+woal_usb_aggr_init(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	mlan_ds_misc_usb_aggr_ctrl *aggr_param = NULL;
+	t_u8 usb_aggr_enable;
+	struct usb_card_rec *cardp = NULL;
+	int i = 0, resubmit_urbs = 0;
+
+	ENTER();
+
+	if (!handle) {
+		PRINTM(MERROR, "Handle is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	if (!priv) {
+		PRINTM(MERROR, "STA priv is null\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (handle->card == NULL) {
+		PRINTM(MERROR, "Card is null in %s()\n", __func__);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cardp = (struct usb_card_rec *)handle->card;
+
+	/* Check module parameter */
+	if (handle->params.usb_aggr == 0 || handle->params.usb_aggr == 2) {
+		usb_aggr_enable = MFALSE;
+	} else if (handle->params.usb_aggr == 1) {
+		usb_aggr_enable = MTRUE;
+	} else {
+		PRINTM(MWARN,
+		       "Invalid module param (usb_aggr) value %d, "
+		       "using MLAN default\n", handle->params.usb_aggr);
+		handle->params.usb_aggr = 0;
+		usb_aggr_enable = MFALSE;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg_misc->sub_command = MLAN_OID_MISC_USB_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	aggr_param = &pcfg_misc->param.usb_aggr_params;
+	/* Initialize TX aggr default values */
+	aggr_param->tx_aggr_ctrl.enable = usb_aggr_enable;
+	aggr_param->tx_aggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
+	aggr_param->tx_aggr_ctrl.aggr_align =
+		MAX(handle->params.max_tx_buf, MLAN_USB_TX_AGGR_ALIGN);
+	aggr_param->tx_aggr_ctrl.aggr_max = MLAN_USB_TX_MAX_AGGR_NUM;
+	aggr_param->tx_aggr_ctrl.aggr_tmo =
+		MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
+
+	/* Initialize RX deaggr default values */
+	aggr_param->rx_deaggr_ctrl.enable = usb_aggr_enable;
+	aggr_param->rx_deaggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
+	aggr_param->rx_deaggr_ctrl.aggr_align = MLAN_USB_RX_ALIGN_SIZE;
+	aggr_param->rx_deaggr_ctrl.aggr_max = MLAN_USB_RX_MAX_AGGR_NUM;
+	aggr_param->rx_deaggr_ctrl.aggr_tmo = MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
+
+	/* Do not fail driver init due to command failure */
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	/* Disable the feature if FW return failure/unsupported */
+	if (req->status_code)
+		cardp->tx_aggr_ctrl.enable = MFALSE;
+	else
+		moal_memcpy_ext(handle, &cardp->tx_aggr_ctrl,
+				&aggr_param->tx_aggr_ctrl,
+				sizeof(usb_aggr_ctrl_cfg),
+				sizeof(usb_aggr_ctrl_cfg));
+
+	if (req->status_code) {
+		/* Disable the feature if FW return failure/unsupported */
+		cardp->rx_deaggr_ctrl.enable = MFALSE;
+	} else {
+		/* Default is disable, resubmit URBs only for enable */
+		if (cardp->rx_deaggr_ctrl.enable != usb_aggr_enable)
+			resubmit_urbs = 1;
+	}
+	if (resubmit_urbs) {
+		/* Indicate resubmition from here */
+		cardp->resubmit_urbs = 1;
+		/* Rx SG feature is disabled due to FW failure/unsupported,
+		 * kill the URBs, they will be resubmitted after saving the
+		 * parameters to USB card */
+		if (atomic_read(&cardp->rx_data_urb_pending)) {
+			for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+				if (cardp->rx_data_list[i].urb) {
+					usb_kill_urb(cardp->rx_data_list[i].
+						     urb);
+					usb_init_urb(cardp->rx_data_list[i].
+						     urb);
+				}
+			}
+		}
+
+		/* Default is disable, update only for enable case */
+		moal_memcpy_ext(handle, &cardp->rx_deaggr_ctrl,
+				&aggr_param->rx_deaggr_ctrl,
+				sizeof(usb_aggr_ctrl_cfg),
+				sizeof(usb_aggr_ctrl_cfg));
+
+		/* Ensure the next data URBs will use the modified parameters */
+		if (!atomic_read(&cardp->rx_data_urb_pending)) {
+			/* Submit multiple Rx data URBs */
+			woal_usb_submit_rx_data_urbs(handle);
+		}
+		cardp->resubmit_urbs = 0;
+	}
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set hotspot configuration value to mlan layer
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  wait option
+ *  @param hotspotcfg   Hotspot configuration value
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_set_hotspotcfg(moal_private *priv, t_u8 wait_option, t_u32 hotspotcfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->param.hotspot_cfg = hotspotcfg;
+	req->action = MLAN_ACT_SET;
+
+	cfg->sub_command = MLAN_OID_MISC_HOTSPOT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Send delelte all BA command to MLAN
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_delba_all(moal_private *priv, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_ds_11n_delba *del_ba = NULL;
+	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int ret = 0;
+
+	req = (mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_DELBA;
+
+	del_ba = &cfg_11n->param.del_ba;
+	memset(del_ba, 0, sizeof(mlan_ds_11n_delba));
+	del_ba->direction = DELBA_RX | DELBA_TX;
+	del_ba->tid = DELBA_ALL_TIDS;
+	moal_memcpy_ext(priv->phandle, del_ba->peer_mac_addr, zero_mac,
+			ETH_ALEN, sizeof(del_ba->peer_mac_addr));
+
+	status = woal_request_ioctl(priv, req, wait_option);
+
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Send 11d enable/disable command to firmware.
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param enable           Enable/Disable 11d
+ *
+ *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_set_11d(moal_private *priv, t_u8 wait_option, t_u8 enable)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_snmp_mib *snmp = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	req->action = MLAN_ACT_SET;
+	req->req_id = MLAN_IOCTL_SNMP_MIB;
+
+	snmp = (mlan_ds_snmp_mib *)req->pbuf;
+	snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
+	snmp->param.oid_value = enable;
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle miscellaneous ioctls for asynchronous command response
+ *
+ *  @param priv     Pointer to moal_private structure
+ *  @param info     Pointer to mlan_ds_misc_cfg structure
+ *
+ *  @return         N/A
+ */
+void
+woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info)
+{
+	ENTER();
+	switch (info->sub_command) {
+	default:
+		break;
+	}
+}
+
+#ifdef CONFIG_PROC_FS
+#define RADIO_MODE_STR_LEN 20
+#define TX_PWR_STR_LEN   20
+#define TX_CONT_STR_LEN  50
+#define TX_FRAME_STR_LEN 200
+#define HE_TB_TX_STR_LEN 30
+
+/*
+ *  @brief Parse mfg cmd radio mode string
+ *
+ *  @param s        A pointer to user buffer
+ *  @param len      Length of user buffer
+ *  @param d        A pointer to mfg_cmd_generic_cfg struct
+ *  @return         0 on success, -EINVAL otherwise
+ */
+static int
+parse_radio_mode_string(const char *s, size_t len,
+			struct mfg_cmd_generic_cfg *d)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *tmp = NULL;
+	char *pos = NULL;
+	gfp_t flag;
+
+	ENTER();
+	if (!s || !d) {
+		LEAVE();
+		return -EINVAL;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	string = kzalloc(RADIO_MODE_STR_LEN, flag);
+	if (string == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	moal_memcpy_ext(NULL, string, s + strlen("radio_mode="),
+			len - strlen("radio_mode="), RADIO_MODE_STR_LEN - 1);
+
+	tmp = string;
+	string = strstrip(string);
+
+	/* radio mode index 0 */
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->data1 = (t_u32)woal_string_to_number(pos);
+
+	/* radio mode index 1 */
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->data2 = (t_u32)woal_string_to_number(pos);
+
+	if ((d->data1 > 14 || d->data1 < 0) || (d->data2 > 14 || d->data2 < 0))
+		ret = -EINVAL;
+
+	kfree(tmp);
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  @brief Parse mfg cmd tx pwr string
+ *
+ *  @param s        A pointer to user buffer
+ *  @param len      Length of user buffer
+ *  @param d        A pointer to mfg_cmd_generic_cfg struct
+ *  @return         0 on success, -EINVAL otherwise
+ */
+static int
+parse_tx_pwr_string(const char *s, size_t len, struct mfg_cmd_generic_cfg *d)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *tmp = NULL;
+	char *pos = NULL;
+	gfp_t flag;
+
+	ENTER();
+	if (!s || !d) {
+		LEAVE();
+		return -EINVAL;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	string = kzalloc(TX_PWR_STR_LEN, flag);
+	if (string == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	moal_memcpy_ext(NULL, string, s + strlen("tx_power="),
+			len - strlen("tx_power="), TX_PWR_STR_LEN - 1);
+
+	tmp = string;
+	string = strstrip(string);
+
+	/* tx power value */
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->data1 = (t_u32)woal_string_to_number(pos);
+
+	/* modulation */
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->data2 = (t_u32)woal_string_to_number(pos);
+
+	/* path id */
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->data3 = (t_u32)woal_string_to_number(pos);
+
+	if ((d->data1 > 24) || (d->data2 > 2))
+		ret = -EINVAL;
+
+	kfree(tmp);
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  @brief Parse mfg cmd tx cont string
+ *
+ *  @param s        A pointer to user buffer
+ *  @param len      Length of user buffer
+ *  @param d        A pointer to mfg_cmd_tx_cont struct
+ *  @return         0 on success, -EINVAL otherwise
+ */
+static int
+parse_tx_cont_string(const char *s, size_t len, struct mfg_cmd_tx_cont *d)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *tmp = NULL;
+	char *pos = NULL;
+	gfp_t flag;
+
+	ENTER();
+	if (!s || !d) {
+		LEAVE();
+		return -EINVAL;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	string = kzalloc(TX_CONT_STR_LEN, flag);
+	if (string == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	moal_memcpy_ext(NULL, string, s + strlen("tx_continuous="),
+			len - strlen("tx_continuous="), TX_CONT_STR_LEN - 1);
+
+	tmp = string;
+	string = strstrip(string);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->enable_tx = (t_u32)woal_string_to_number(pos);
+
+	if (d->enable_tx == MFALSE)
+		goto done;
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->cw_mode = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->payload_pattern = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->cs_mode = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->act_sub_ch = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->tx_rate = (t_u32)woal_string_to_number(pos);
+
+	if ((d->enable_tx > 1) || (d->cw_mode > 1) || (d->cs_mode > 1)
+	    || (d->act_sub_ch == 2 || d->act_sub_ch > 3))
+		ret = -EINVAL;
+done:
+	kfree(tmp);
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  @brief Parse mfg cmd tx frame string
+ *
+ *  @param s        A pointer to user buffer
+ *  @param len      Length of user buffer
+ *  @param d        A pointer to mfg_cmd_tx_frame2 struct
+ *  @return         0 on success, -EINVAL otherwise
+ */
+static int
+parse_tx_frame_string(const char *s, size_t len, struct mfg_cmd_tx_frame2 *d)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *tmp = NULL;
+	char *pos = NULL;
+	int i;
+	gfp_t flag;
+
+	ENTER();
+	if (!s || !d) {
+		LEAVE();
+		return -EINVAL;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	string = kzalloc(TX_FRAME_STR_LEN, flag);
+	if (string == NULL)
+		return -ENOMEM;
+
+	moal_memcpy_ext(NULL, string, s + strlen("tx_frame="),
+			len - strlen("tx_frame="), TX_FRAME_STR_LEN - 1);
+
+	tmp = string;
+	string = strstrip(string);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->enable = (t_u32)woal_string_to_number(pos);
+
+	if (d->enable == MFALSE)
+		goto done;
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->data_rate = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->frame_pattern = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->frame_length = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->adjust_burst_sifs = (t_u16)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->burst_sifs_in_us = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->short_preamble = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->act_sub_ch = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->short_gi = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->adv_coding = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->tx_bf = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->gf_mode = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->stbc = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->NumPkt = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->MaxPE = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->BeamChange = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->Dcm = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->Doppler = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->MidP = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->QNum = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos) {
+		for (i = 0; i < ETH_ALEN; i++) {
+			pos = strsep(&string, ":");
+			if (pos)
+				d->bssid[i] = woal_atox(pos);
+		}
+	}
+
+	if ((d->enable > 1)
+	    || (d->frame_length == 0) || (d->adjust_burst_sifs > 1)
+	    || (d->burst_sifs_in_us > 255) || (d->short_preamble > 1)
+	    || (d->act_sub_ch == 2 || d->act_sub_ch > 3)
+	    || (d->short_gi > 1) || (d->adv_coding > 1) || (d->tx_bf > 1)
+	    || (d->gf_mode > 1) || (d->stbc > 1))
+		ret = -EINVAL;
+done:
+	kfree(tmp);
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  @brief Parse mfg cmd HE TB Tx string
+ *
+ *  @param s        A pointer to user buffer
+ *  @param len      Length of user buffer
+ *  @param d        A pointer to mfg_Cmd_HE_TBTx_t struct
+ *  @return         0 on success, -EINVAL otherwise
+ */
+static int
+parse_he_tb_tx_string(const char *s, size_t len, struct mfg_Cmd_HE_TBTx_t *d)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *tmp = NULL;
+	char *pos = NULL;
+	gfp_t flag;
+
+	ENTER();
+	if (!s || !d) {
+		LEAVE();
+		return -EINVAL;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	string = kzalloc(HE_TB_TX_STR_LEN, flag);
+	if (string == NULL)
+		return -ENOMEM;
+
+	moal_memcpy_ext(NULL, string, s + strlen("he_tb_tx="),
+			len - strlen("he_tb_tx="), HE_TB_TX_STR_LEN - 1);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->enable = (t_u32)woal_string_to_number(pos);
+
+	if (d->enable == MFALSE)
+		goto done;
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->qnum = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->aid = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->axq_mu_timer = (t_u32)woal_string_to_number(pos);
+
+	pos = strsep(&string, " \t");
+	if (pos)
+		d->tx_power = (t_u16)woal_string_to_number(pos);
+
+	if (d->enable > 1)
+		ret = -EINVAL;
+
+done:
+	kfree(tmp);
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  @brief This function enables/disables RF test mode in firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
+ *                  otherwise failure code
+ */
+mlan_status
+woal_process_rf_test_mode(moal_handle *handle, t_u32 mode)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	t_u32 flag = 0;
+
+	ENTER();
+#ifdef MFG_CMD_SUPPORT
+	if (mfg_mode) {
+		LEAVE();
+		return ret;
+	}
+#endif
+	if (mode != MFG_CMD_SET_TEST_MODE && mode != MFG_CMD_UNSET_TEST_MODE) {
+		LEAVE();
+		return ret;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req) {
+		misc = (mlan_ds_misc_cfg *)req->pbuf;
+		misc->sub_command = MLAN_OID_MISC_RF_TEST_GENERIC;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		req->action = MLAN_ACT_SET;
+		if (mode == MFG_CMD_SET_TEST_MODE)
+			misc->param.mfg_generic_cfg.mfg_cmd =
+				MFG_CMD_SET_TEST_MODE;
+		ret = woal_request_ioctl(woal_get_priv(handle,
+						       MLAN_BSS_ROLE_ANY),
+					 req, MOAL_IOCTL_WAIT);
+	}
+
+	if (ret == MLAN_STATUS_SUCCESS && mode == MFG_CMD_SET_TEST_MODE
+	    && handle->rf_data == NULL) {
+		flag = (in_atomic() || irqs_disabled())?
+			GFP_ATOMIC : GFP_KERNEL;
+		/* Allocate memory to hold RF test mode data */
+		handle->rf_data = kzalloc(sizeof(struct rf_test_mode_data),
+					  flag);
+		if (!handle->rf_data)
+			PRINTM(MERROR,
+			       "Couldn't allocate memory for RF test mode\n");
+		handle->rf_test_mode = MTRUE;
+		if (handle->rf_data) {
+			/* antenna is set to 1 by default */
+			handle->rf_data->tx_antenna = 1;
+			handle->rf_data->rx_antenna = 1;
+		}
+	} else if (mode == MFG_CMD_UNSET_TEST_MODE) {
+		if (handle->rf_data) {
+			/* Free RF test mode data memory */
+			kfree(handle->rf_data);
+			handle->rf_data = NULL;
+		}
+		handle->rf_test_mode = MFALSE;
+	}
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sends RF test mode command in firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
+ *                      otherwise failure code
+ */
+mlan_status
+woal_process_rf_test_mode_cmd(moal_handle *handle, t_u32 cmd,
+			      const char *buffer, size_t len,
+			      t_u32 action, t_u32 val)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int err = MFALSE;
+	int i;
+
+	ENTER();
+
+	if (!handle->rf_test_mode || !handle->rf_data)
+		goto done;
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (!req)
+		goto done;
+
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->sub_command = MLAN_OID_MISC_RF_TEST_GENERIC;
+	req->action = action;
+
+	switch (cmd) {
+	case MFG_CMD_TX_ANT:
+		if (val != 1 && val != 2 && val != 3)
+			err = MTRUE;
+		break;
+	case MFG_CMD_RX_ANT:
+		if (val != 1 && val != 2 && val != 3)
+			err = MTRUE;
+		break;
+	case MFG_CMD_RF_BAND_AG:
+		if (val != 0 && val != 1)
+			err = MTRUE;
+		break;
+	case MFG_CMD_RF_CHANNELBW:
+		if (val != 0
+		    && val != 1
+		    && (val != 4
+			|| (val == 4 && handle->rf_data->band == BAND_2GHZ))
+			)
+			err = MTRUE;
+		break;
+	case MFG_CMD_RF_CHAN:
+		break;
+	case MFG_CMD_CLR_RX_ERR:
+		break;
+	case MFG_CMD_RADIO_MODE_CFG:
+		if (parse_radio_mode_string(buffer, len,
+					    &misc->param.mfg_generic_cfg))
+			err = MTRUE;
+		break;
+	case MFG_CMD_RFPWR:
+		if (parse_tx_pwr_string(buffer, len,
+					&misc->param.mfg_generic_cfg))
+			err = MTRUE;
+		break;
+	case MFG_CMD_TX_CONT:
+		misc->sub_command = MLAN_OID_MISC_RF_TEST_TX_CONT;
+		if (parse_tx_cont_string(buffer, len, &misc->param.mfg_tx_cont))
+			err = MTRUE;
+		break;
+	case MFG_CMD_TX_FRAME:
+		misc->sub_command = MLAN_OID_MISC_RF_TEST_TX_FRAME;
+		if (parse_tx_frame_string(buffer, len,
+					  &misc->param.mfg_tx_frame2))
+			err = MTRUE;
+		break;
+	case MFG_CMD_CONFIG_MAC_HE_TB_TX:
+		misc->sub_command = MLAN_OID_MISC_RF_TEST_HE_POWER;
+		if (parse_he_tb_tx_string(buffer, len,
+					  &misc->param.mfg_he_power))
+			err = MTRUE;
+		break;
+	default:
+		err = MTRUE;
+	}
+
+	if (!err) {
+		misc->param.mfg_generic_cfg.mfg_cmd = (t_u32)cmd;
+		if (cmd != MFG_CMD_RFPWR &&
+		    misc->sub_command == MLAN_OID_MISC_RF_TEST_GENERIC)
+			misc->param.mfg_generic_cfg.data1 = val;
+
+		ret = woal_request_ioctl(woal_get_priv(handle,
+						       MLAN_BSS_ROLE_ANY),
+					 req, MOAL_IOCTL_WAIT);
+	}
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	switch (cmd) {
+	case MFG_CMD_TX_ANT:
+		handle->rf_data->tx_antenna = misc->param.mfg_generic_cfg.data1;
+		break;
+	case MFG_CMD_RX_ANT:
+		handle->rf_data->rx_antenna = misc->param.mfg_generic_cfg.data1;
+		break;
+	case MFG_CMD_RADIO_MODE_CFG:
+		handle->rf_data->radio_mode[0] =
+			misc->param.mfg_generic_cfg.data1;
+		handle->rf_data->radio_mode[1] =
+			misc->param.mfg_generic_cfg.data2;
+		break;
+	case MFG_CMD_RF_BAND_AG:
+		handle->rf_data->band = misc->param.mfg_generic_cfg.data1;
+		/* set fw default bw and channel config on band change */
+		handle->rf_data->bandwidth = CHANNEL_BW_20MHZ;
+		if (handle->rf_data->band == BAND_2GHZ)
+			handle->rf_data->channel = 6;
+		else if (handle->rf_data->band == BAND_5GHZ)
+			handle->rf_data->channel = 36;
+		break;
+	case MFG_CMD_RF_CHANNELBW:
+		handle->rf_data->bandwidth = misc->param.mfg_generic_cfg.data1;
+		break;
+	case MFG_CMD_RF_CHAN:
+		handle->rf_data->channel = misc->param.mfg_generic_cfg.data1;
+		break;
+	case MFG_CMD_CLR_RX_ERR:
+		handle->rf_data->rx_tot_pkt_count =
+			misc->param.mfg_generic_cfg.data1;
+		handle->rf_data->rx_mcast_bcast_pkt_count =
+			misc->param.mfg_generic_cfg.data2;
+		handle->rf_data->rx_pkt_fcs_err_count =
+			misc->param.mfg_generic_cfg.data3;
+		break;
+	case MFG_CMD_RFPWR:
+		handle->rf_data->tx_power_data[0] =
+			misc->param.mfg_generic_cfg.data1;
+		handle->rf_data->tx_power_data[1] =
+			misc->param.mfg_generic_cfg.data2;
+		handle->rf_data->tx_power_data[2] =
+			misc->param.mfg_generic_cfg.data3;
+		break;
+	case MFG_CMD_TX_CONT:
+		handle->rf_data->tx_cont_data[0] =
+			misc->param.mfg_tx_cont.enable_tx;
+		handle->rf_data->tx_cont_data[1] =
+			misc->param.mfg_tx_cont.cw_mode;
+		handle->rf_data->tx_cont_data[2] =
+			misc->param.mfg_tx_cont.payload_pattern;
+		handle->rf_data->tx_cont_data[3] =
+			misc->param.mfg_tx_cont.cs_mode;
+		handle->rf_data->tx_cont_data[4] =
+			misc->param.mfg_tx_cont.act_sub_ch;
+		handle->rf_data->tx_cont_data[5] =
+			misc->param.mfg_tx_cont.tx_rate;
+		break;
+	case MFG_CMD_TX_FRAME:
+		handle->rf_data->tx_frame_data[0] =
+			misc->param.mfg_tx_frame2.enable;
+		handle->rf_data->tx_frame_data[1] =
+			misc->param.mfg_tx_frame2.data_rate;
+		handle->rf_data->tx_frame_data[2] =
+			misc->param.mfg_tx_frame2.frame_pattern;
+		handle->rf_data->tx_frame_data[3] =
+			misc->param.mfg_tx_frame2.frame_length;
+		handle->rf_data->tx_frame_data[4] =
+			misc->param.mfg_tx_frame2.adjust_burst_sifs;
+		handle->rf_data->tx_frame_data[5] =
+			misc->param.mfg_tx_frame2.burst_sifs_in_us;
+		handle->rf_data->tx_frame_data[6] =
+			misc->param.mfg_tx_frame2.short_preamble;
+		handle->rf_data->tx_frame_data[7] =
+			misc->param.mfg_tx_frame2.act_sub_ch;
+		handle->rf_data->tx_frame_data[8] =
+			misc->param.mfg_tx_frame2.short_gi;
+		handle->rf_data->tx_frame_data[9] =
+			misc->param.mfg_tx_frame2.adv_coding;
+		handle->rf_data->tx_frame_data[10] =
+			misc->param.mfg_tx_frame2.tx_bf;
+		handle->rf_data->tx_frame_data[11] =
+			misc->param.mfg_tx_frame2.gf_mode;
+		handle->rf_data->tx_frame_data[12] =
+			misc->param.mfg_tx_frame2.stbc;
+		handle->rf_data->tx_frame_data[13] =
+			misc->param.mfg_tx_frame2.NumPkt;
+		handle->rf_data->tx_frame_data[14] =
+			misc->param.mfg_tx_frame2.MaxPE;
+		handle->rf_data->tx_frame_data[15] =
+			misc->param.mfg_tx_frame2.BeamChange;
+		handle->rf_data->tx_frame_data[16] =
+			misc->param.mfg_tx_frame2.Dcm;
+		handle->rf_data->tx_frame_data[17] =
+			misc->param.mfg_tx_frame2.Doppler;
+		handle->rf_data->tx_frame_data[18] =
+			misc->param.mfg_tx_frame2.MidP;
+		handle->rf_data->tx_frame_data[19] =
+			misc->param.mfg_tx_frame2.QNum;
+		for (i = 0; i < ETH_ALEN; i++) {
+			handle->rf_data->bssid[i] =
+				misc->param.mfg_tx_frame2.bssid[i];
+		}
+		break;
+	case MFG_CMD_CONFIG_MAC_HE_TB_TX:
+		handle->rf_data->he_tb_tx[0] = misc->param.mfg_he_power.enable;
+		handle->rf_data->he_tb_tx[1] = misc->param.mfg_he_power.qnum;
+		handle->rf_data->he_tb_tx[2] = misc->param.mfg_he_power.aid;
+		handle->rf_data->he_tb_tx[3] =
+			misc->param.mfg_he_power.axq_mu_timer;
+		handle->rf_data->he_tb_tx[4] =
+			misc->param.mfg_he_power.tx_power;
+		break;
+	}
+done:
+	if (err || ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif /* RF_TEST_MODE */
diff --git a/wlan_sd8987/mlinux/moal_main.c b/wlan_sd8987/mlinux/moal_main.c
new file mode 100755
index 0000000..3785300
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_main.c
@@ -0,0 +1,10679 @@
+/** @file moal_main.c
+ *
+ * @brief This file contains the major functions in WLAN
+ * driver.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#ifdef USB
+#include "moal_usb.h"
+#endif
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif
+#ifdef PCIE
+#include "moal_pcie.h"
+#endif
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#include "moal_cfg80211_util.h"
+#endif
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+#include "moal_sta_cfg80211.h"
+#endif
+#endif
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+#include "moal_uap_cfg80211.h"
+#endif
+#endif
+#include "moal_eth_ioctl.h"
+
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <net/dsfield.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/addrconf.h>
+#endif
+
+/********************************************************
+		 Global Variables
+ ********************************************************/
+/** the pointer of new fwdump fname for each dump**/
+static char *fwdump_fname;
+/** Semaphore for add/remove card */
+struct semaphore AddRemoveCardSem;
+/**
+ * The global variable of a pointer to moal_handle
+ * structure variable
+ **/
+moal_handle *m_handle[MAX_MLAN_ADAPTER];
+static int reg_work;
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+#ifdef SD8801
+static struct _card_info card_info_SD8801 = {
+	.embedded_supp = 0,
+	.drcs = 0,
+	.go_noa = 0,
+	.v14_fw_api = 1,
+	.v16_fw_api = 0,
+	.v17_fw_api = 0,
+	.pmic = 0,
+	.cal_data_cfg = 0,
+	.low_power_enable = 1,
+	.rx_rate_max = 76,
+	.histogram_table_num = 1,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.fw_name = SD8801_DEFAULT_WLAN_FW_NAME,
+	.fw_name_wlan = SD8801_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = 0,
+	.dump_fw_ctrl_reg = 0x63,
+	.dump_fw_start_reg = 0x64,
+	.dump_fw_end_reg = 0x6A,
+	.dump_fw_host_ready = 0xee,
+	.dump_reg.reg_table = {0x28, 0x30, 0x34, 0x38, 0x3c},
+	.dump_reg.reg_table_size = 5,
+	.scratch_reg = 0x60,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x64,
+	.fw_reset_val = 0,
+	.slew_rate_reg = 0x8000231C,
+	.slew_rate_bit_offset = 14,
+#endif
+	.per_pkt_cfg_support = 0,
+};
+#endif
+#ifdef SD8887
+static struct _card_info card_info_SD8887 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 0,
+	.pmic = 0,
+	.cal_data_cfg = 1,
+	.low_power_enable = 1,
+	.rx_rate_max = 196,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.rev_id_reg = 0xc8,
+	.fw_name = SD8887_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD8887_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V2,
+	.dump_fw_ctrl_reg = 0xa2,
+	.dump_fw_start_reg = 0xa3,
+	.dump_fw_end_reg = 0xaa,
+	.dump_fw_host_ready = 0xee,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0x90,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0B6,
+	.fw_reset_val = 1,
+	.slew_rate_reg = 0x80002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 0,
+};
+#endif
+
+#ifdef SD8897
+static struct _card_info card_info_SD8897 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 0,
+	.pmic = 0,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 196,
+	.histogram_table_num = 1,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0xbc,
+	.fw_name = SD8897_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD8897_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V2,
+	.dump_fw_ctrl_reg = 0xe2,
+	.dump_fw_start_reg = 0xe3,
+	.dump_fw_end_reg = 0xea,
+	.dump_fw_host_ready = 0xee,
+	.dump_reg.reg_table = {0x4C, 0x50, 0x54, 0x55, 0x58, 0x59, 0x5c, 0x5d},
+	.dump_reg.reg_table_size = 8,
+	.scratch_reg = 0xc0,
+	.func1_reg_start = 0x04,
+	.func1_reg_end = 0x0b,
+	.fw_reset_reg = 0x0E8,
+	.fw_reset_val = 1,
+	.slew_rate_reg = 0x80002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 0,
+};
+#endif
+
+#ifdef PCIE8897
+static struct _card_info card_info_PCIE8897 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 0,
+	.pmic = 0,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 196,
+	.histogram_table_num = 1,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0x0c58,
+	.fw_name = PCIE8897_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = PCIE8897_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 0,
+};
+#endif
+
+#ifdef USB8897
+static struct _card_info card_info_USB8897 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 0,
+	.pmic = 0,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 196,
+	.histogram_table_num = 1,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.fw_name = USB8897_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = USB8897_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 0,
+};
+#endif
+
+#ifdef SD8977
+static struct _card_info card_info_SD8977 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 0,
+	.rx_rate_max = 76,
+	.histogram_table_num = 1,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.rev_id_reg = 0xc8,
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.fw_name = SD8977_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD8977_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x80002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef SD8978
+static struct _card_info card_info_SD8978 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 0,
+	.rx_rate_max = 76,
+	.histogram_table_num = 1,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.rev_id_reg = 0xc8,
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.fw_name = SD8978_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD8978_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x80002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef SD8997
+static struct _card_info card_info_SD8997 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 0,
+	.rx_rate_max = 196,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0xc8,
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.fw_name = SD8997_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD8997_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x80002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef SD9098
+static struct _card_info card_info_SD9098 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0xc8,
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.fw_name = SD9098_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD9098_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x90002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef SD9097
+static struct _card_info card_info_SD9097 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0xc8,
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.fw_name = SD9097_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD9097_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x90002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef SD9177
+static struct _card_info card_info_SD9177 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0xc8,
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.fw_name = SD9177_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD9177_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x90002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef PCIE8997
+static struct _card_info card_info_PCIE8997 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 0,
+	.rx_rate_max = 196,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0x8,
+	.host_strap_reg = 0x0cd0,
+	.magic_reg = 0x0cd4,
+	.fw_name = PCIE8997_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = PCIE8997_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef PCIE9097
+static struct _card_info card_info_PCIE9097 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0x8,
+	.host_strap_reg = 0x1c70,
+	.magic_reg = 0x1c74,
+	.fw_name = PCIE9097_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = PCIE9097_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef PCIE9098
+static struct _card_info card_info_PCIE9098 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.histogram_table_num = 3,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.rev_id_reg = 0x8,
+	.host_strap_reg = 0x1c70,
+	.magic_reg = 0x1c74,
+	.fw_name = PCIE9098_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = PCIE9098_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef USB8801
+static struct _card_info card_info_USB8801 = {
+	.embedded_supp = 0,
+	.drcs = 0,
+	.go_noa = 0,
+	.v14_fw_api = 1,
+	.v16_fw_api = 0,
+	.v17_fw_api = 0,
+	.pmic = 0,
+	.cal_data_cfg = 0,
+	.low_power_enable = 1,
+	.rx_rate_max = 76,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.histogram_table_num = 1,
+	.fw_name = USB8801_DEFAULT_WLAN_FW_NAME,
+	.fw_name_wlan = USB8801_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 0,
+};
+#endif
+
+#ifdef USB8978
+static struct _card_info card_info_USB8978 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 0,
+	.rx_rate_max = 76,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.histogram_table_num = 1,
+	.fw_name = USB8978_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = USB8978_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef USB8997
+static struct _card_info card_info_USB8997 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 0,
+	.rx_rate_max = 196,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.histogram_table_num = 3,
+	.fw_name = USB8997_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = USB8997_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef USB9098
+static struct _card_info card_info_USB9098 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.histogram_table_num = 3,
+	.fw_name = USB9098_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = USB9098_DEFAULT_WLAN_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+#ifdef USB9097
+static struct _card_info card_info_USB9097 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 1,
+	.v16_fw_api = 1,
+	.v17_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 0,
+	.low_power_enable = 0,
+	.rx_rate_max = 412,
+	.feature_control = FEATURE_CTRL_DEFAULT,
+	.histogram_table_num = 3,
+	.fw_name = USBUSB9097_COMBO_V1_FW_NAME,
+	.fw_name_wlan = USB9097_WLAN_V1_FW_NAME,
+	.per_pkt_cfg_support = 1,
+};
+#endif
+#ifdef SD8987
+static struct _card_info card_info_SD8987 = {
+	.embedded_supp = 1,
+	.drcs = 1,
+	.go_noa = 0,
+	.v16_fw_api = 1,
+	.pmic = 1,
+	.cal_data_cfg = 1,
+	.low_power_enable = 1,
+	.rx_rate_max = 196,
+	.feature_control = FEATURE_CTRL_DEFAULT & (~FEATURE_CTRL_STREAM_2X2),
+	.host_strap_reg = 0xf4,
+	.magic_reg = 0xf0,
+	.histogram_table_num = 3,
+	.fw_name = SD8987_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SD8987_DEFAULT_WLAN_FW_NAME,
+#ifdef SDIO
+	.dump_fw_info = DUMP_FW_SDIO_V3,
+	.dump_fw_ctrl_reg = 0xf9,
+	.dump_fw_start_reg = 0xf1,
+	.dump_fw_end_reg = 0xf8,
+	.dump_fw_host_ready = 0xcc,
+	.dump_reg.reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, 0x61, 0x62, 0x64,
+			       0x65, 0x66, 0x68, 0x69, 0x6a},
+	.dump_reg.reg_table_size = 13,
+	.scratch_reg = 0xe8,
+	.func1_reg_start = 0x10,
+	.func1_reg_end = 0x17,
+	.fw_reset_reg = 0x0EE,
+	.fw_reset_val = 0x99,
+	.slew_rate_reg = 0x80002328,
+	.slew_rate_bit_offset = 12,
+#endif
+	.per_pkt_cfg_support = 1,
+};
+#endif
+
+/** Driver version */
+char driver_version[] = INTF_CARDTYPE KERN_VERSION "--" MLAN_RELEASE_VERSION
+	"-GPL" "-(" "FP" FPNUM ")"
+#ifdef DEBUG_LEVEL2
+	"-dbg"
+#endif
+	" ";
+
+/** woal_callbacks */
+static mlan_callbacks woal_callbacks = {
+	.moal_get_fw_data = moal_get_fw_data,
+	.moal_get_vdll_data = moal_get_vdll_data,
+	.moal_get_hw_spec_complete = moal_get_hw_spec_complete,
+	.moal_init_fw_complete = moal_init_fw_complete,
+	.moal_shutdown_fw_complete = moal_shutdown_fw_complete,
+	.moal_send_packet_complete = moal_send_packet_complete,
+	.moal_recv_packet = moal_recv_packet,
+	.moal_recv_amsdu_packet = moal_recv_amsdu_packet,
+	.moal_recv_event = moal_recv_event,
+	.moal_ioctl_complete = moal_ioctl_complete,
+	.moal_alloc_mlan_buffer = moal_alloc_mlan_buffer,
+	.moal_free_mlan_buffer = moal_free_mlan_buffer,
+#ifdef USB
+	.moal_recv_complete = moal_recv_complete,
+	.moal_write_data_async = moal_write_data_async,
+#endif /* USB */
+
+#if defined(SDIO) || defined(PCIE)
+	.moal_write_reg = moal_write_reg,
+	.moal_read_reg = moal_read_reg,
+#endif /* SDIO || PCIE */
+	.moal_write_data_sync = moal_write_data_sync,
+	.moal_read_data_sync = moal_read_data_sync,
+	.moal_malloc = moal_malloc,
+	.moal_mfree = moal_mfree,
+	.moal_vmalloc = moal_vmalloc,
+	.moal_vfree = moal_vfree,
+#ifdef PCIE
+	.moal_malloc_consistent = moal_malloc_consistent,
+	.moal_mfree_consistent = moal_mfree_consistent,
+	.moal_map_memory = moal_map_memory,
+	.moal_unmap_memory = moal_unmap_memory,
+#endif /* PCIE */
+	.moal_memset = moal_memset,
+	.moal_memcpy = moal_memcpy,
+	.moal_memcpy_ext = moal_memcpy_ext,
+	.moal_memmove = moal_memmove,
+	.moal_memcmp = moal_memcmp,
+	.moal_udelay = moal_udelay,
+	.moal_usleep_range = moal_usleep_range,
+	.moal_get_system_time = moal_get_system_time,
+	.moal_get_boot_ktime = moal_get_boot_ktime,
+	.moal_init_timer = moal_init_timer,
+	.moal_free_timer = moal_free_timer,
+	.moal_start_timer = moal_start_timer,
+	.moal_stop_timer = moal_stop_timer,
+	.moal_init_lock = moal_init_lock,
+	.moal_free_lock = moal_free_lock,
+	.moal_spin_lock = moal_spin_lock,
+	.moal_spin_unlock = moal_spin_unlock,
+	.moal_print = moal_print,
+	.moal_print_netintf = moal_print_netintf,
+	.moal_assert = moal_assert,
+	.moal_hist_data_add = moal_hist_data_add,
+	.moal_updata_peer_signal = moal_updata_peer_signal,
+	.moal_do_div = moal_do_div,
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	.moal_wait_hostcmd_complete = moal_wait_hostcmd_complete,
+	.moal_notify_hostcmd_complete = moal_notify_hostcmd_complete,
+#endif
+	.moal_tp_accounting = moal_tp_accounting,
+	.moal_tp_accounting_rx_param = moal_tp_accounting_rx_param,
+	.moal_amsdu_tp_accounting = moal_amsdu_tp_accounting,
+};
+
+int woal_open(struct net_device *dev);
+int woal_close(struct net_device *dev);
+int woal_set_mac_address(struct net_device *dev, void *addr);
+void woal_tx_timeout(struct net_device *dev
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+		     , unsigned int txqueue
+#endif
+	);
+struct net_device_stats *woal_get_stats(struct net_device *dev);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      struct net_device *sb_dev);
+#else
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      struct net_device *sb_dev,
+		      select_queue_fallback_t fallback);
+#endif
+#else
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      void *accel_priv, select_queue_fallback_t fallback);
+#endif
+#else
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb,
+		      void *accel_priv);
+#endif
+#else
+u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb);
+#endif
+#endif
+
+static moal_handle *reset_handle;
+/** Hang workqueue */
+static struct workqueue_struct *hang_workqueue;
+/** Hang work */
+static struct work_struct hang_work;
+/** register workqueue */
+static struct workqueue_struct *register_workqueue;
+/** register work */
+static struct work_struct register_work;
+
+/**
+ *  @brief This function send fw dump event to kernel
+ *
+ *  @param priv       Pointer to structure moal_private
+ *
+ *  @return        N/A
+ */
+void
+woal_send_fw_dump_complete_event(moal_private *priv)
+{
+	int cfg80211_wext = priv->phandle->params.cfg80211_wext;
+#ifdef STA_WEXT
+	if (IS_STA_WEXT(cfg80211_wext))
+		woal_send_iwevcustom_event(priv, CUS_EVT_FW_DUMP_DONE);
+#endif
+#ifdef STA_CFG80211
+	if (IS_STA_CFG80211(cfg80211_wext))
+		woal_cfg80211_vendor_event_fw_dump(priv);
+#endif
+	woal_broadcast_event(priv, CUS_EVT_FW_DUMP_DONE,
+			     strlen(CUS_EVT_FW_DUMP_DONE));
+
+	return;
+}
+
+/**
+ *  @brief This function process FW hang
+ *
+ *  @param handle       Pointer to structure moal_handle
+ *
+ *  @return        N/A
+ */
+static void
+woal_hang_work_queue(struct work_struct *work)
+{
+	int i;
+	moal_private *priv;
+	int cfg80211_wext = 0;
+
+	ENTER();
+	if (!reset_handle) {
+		LEAVE();
+		return;
+	}
+
+    mlan_ioctl(reset_handle->pmlan_adapter, NULL);
+	cfg80211_wext = reset_handle->params.cfg80211_wext;
+	//stop pending scan
+#ifdef STA_CFG80211
+	if (IS_STA_CFG80211(cfg80211_wext) && reset_handle->scan_request) {
+		moal_private *scan_priv = reset_handle->scan_priv;
+		cancel_delayed_work_sync(&reset_handle->scan_timeout_work);
+	/** some supplicant can not handle SCAN abort event */
+		if (scan_priv->bss_type == MLAN_BSS_TYPE_STA)
+			woal_cfg80211_scan_done(reset_handle->scan_request,
+						MTRUE);
+		else
+			woal_cfg80211_scan_done(reset_handle->scan_request,
+						MFALSE);
+		reset_handle->scan_request = NULL;
+		reset_handle->scan_priv = NULL;
+		reset_handle->scan_pending_on_block = MFALSE;
+		MOAL_REL_SEMAPHORE(&reset_handle->async_sem);
+	}
+#endif
+
+	for (i = 0; i < reset_handle->priv_num; i++) {
+		if (reset_handle->priv[i]) {
+			priv = reset_handle->priv[i];
+			woal_stop_queue(priv->netdev);
+			if (netif_carrier_ok(priv->netdev))
+				netif_carrier_off(priv->netdev);
+			priv->media_connected = MFALSE;
+			//disconnect
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+			if (IS_STA_CFG80211(cfg80211_wext) &&
+			    priv->wdev->current_bss) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+				if (priv->host_mlme)
+					woal_host_mlme_disconnect(priv,
+								  MLAN_REASON_DEAUTH_LEAVING,
+								  NULL);
+				else
+#endif
+					cfg80211_disconnected(priv->netdev, 0,
+							      NULL, 0,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+							      true,
+#endif
+							      GFP_KERNEL);
+			}
+#endif
+#endif
+			//stop bgscan
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			if (IS_STA_CFG80211(cfg80211_wext) &&
+			    priv->sched_scanning) {
+				priv->bg_scan_start = MFALSE;
+				priv->bg_scan_reported = MFALSE;
+				cfg80211_sched_scan_stopped(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+							    ,
+							    priv->bg_scan_reqid
+#endif
+					);
+				priv->sched_scanning = MFALSE;
+			}
+#endif
+#endif
+		}
+	}
+	woal_flush_workqueue(reset_handle);
+
+	priv = woal_get_priv(reset_handle, MLAN_BSS_ROLE_ANY);
+	if (priv) {
+		woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG,
+				     strlen(CUS_EVT_DRIVER_HANG));
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
+			woal_cfg80211_vendor_event(priv, event_hang,
+						   CUS_EVT_DRIVER_HANG,
+						   strlen(CUS_EVT_DRIVER_HANG));
+#endif
+#endif
+	}
+	reset_handle = NULL;
+	LEAVE();
+}
+
+/**
+ *  @brief This function process FW hang
+ *
+ *  @param handle       Pointer to structure moal_handle
+ *
+ *  @return        N/A
+ */
+void
+woal_process_hang(moal_handle *handle)
+{
+	ENTER();
+	if (reset_handle == NULL) {
+		PRINTM(MMSG, "Start to process hanging\n");
+		reset_handle = handle;
+		queue_work(hang_workqueue, &hang_work);
+#ifdef ANDROID_KERNEL
+#define WAKE_LOCK_HANG 5000
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+		__pm_wakeup_event(&reset_handle->ws, WAKE_LOCK_HANG);
+#else
+		wake_lock_timeout(&reset_handle->wake_lock,
+				  msecs_to_jiffies(WAKE_LOCK_HANG));
+#endif
+#endif
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Check if any interface is active
+ *
+ *  @param handle        A pointer to moal_handle
+ *
+ *
+ *  @return              MTRUE/MFALSE;
+ */
+t_u8
+woal_is_any_interface_active(moal_handle *handle)
+{
+	int i;
+	for (i = 0; i < handle->priv_num; i++) {
+		if (!handle->priv[i])
+			continue;
+#ifdef STA_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
+			if (handle->priv[i]->media_connected == MTRUE)
+				return MTRUE;
+		}
+#endif
+#ifdef UAP_SUPPORT
+		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+			if (handle->priv[i]->bss_started == MTRUE)
+				return MTRUE;
+		}
+#endif
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief This function handle the net interface ipaddr change event
+ *
+ *  @param nb      pointer to the notifier_block
+ *  @param event   event type
+ *  @param ptr     pointer to event struct
+ *
+ *  @return        NOTIFY_DONE or NOTIFY_OK
+ */
+static int
+woal_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr)
+{
+	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+	struct net_device *ndev;
+	moal_private *priv;
+
+	int ret = NOTIFY_OK;
+#ifdef STA_CFG80211
+	char rssi_low[11];
+#endif
+	ENTER();
+
+	ndev = ifa->ifa_dev->dev;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	if (!ndev || ndev->netdev_ops->ndo_open != woal_open)
+#else
+	if (!ndev || ndev->open != woal_open)
+#endif
+	{
+		PRINTM(MIOCTL, "IP changes not for us, ignore. ndev[%p]\n",
+		       ndev);
+		if (ndev)
+			PRINTM(MIOCTL, "changes on %s\n", ndev->name);
+		ret = NOTIFY_DONE;
+		goto done;
+	}
+	priv = (moal_private *)netdev_priv(ndev);
+	if (priv->bss_type != MLAN_BSS_TYPE_STA
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		) {
+		PRINTM(MIOCTL, "Bss type [%d] is not STA/P2P, ignore\n",
+		       (int)priv->bss_type);
+		ret = NOTIFY_DONE;
+		goto done;
+	}
+
+	switch (event) {
+	case NETDEV_UP:
+		PRINTM(MIOCTL, "[%s]: New ip addr: 0x%08x\n", ndev->name,
+		       ifa->ifa_address);
+		/* Save the IP addr now */
+		moal_memcpy_ext(priv->phandle, priv->ip_addr, &ifa->ifa_address,
+				sizeof(ifa->ifa_address),
+				sizeof(priv->ip_addr));
+		priv->ip_addr_type = IPADDR_TYPE_IPV4;
+#ifdef STA_CFG80211
+		if (!moal_extflg_isset(priv->phandle, EXT_HW_TEST) &&
+		    priv->roaming_enabled) {
+			snprintf(rssi_low, sizeof(rssi_low), "%d",
+				 priv->rssi_low);
+			woal_set_rssi_low_threshold(priv, rssi_low,
+						    MOAL_IOCTL_WAIT);
+		}
+#endif
+		break;
+	case NETDEV_DOWN:
+		PRINTM(MIOCTL, "[%s]: Ip addr removed.\n", ndev->name);
+		priv->ip_addr_type = IPADDR_TYPE_NONE;
+		memset(priv->ip_addr, 0, sizeof(priv->ip_addr));
+		break;
+	default:
+		PRINTM(MIOCTL, "[%s]: Ignore event: %u\n", ndev->name,
+		       (unsigned int)event);
+		ret = NOTIFY_DONE;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+/**
+ *  @brief This function handle the net interface ipv6 address change event
+ *
+ *  @param nb      pointer to the notifier_block
+ *  @param event   event type
+ *  @param ptr     pointer to event struct
+ *
+ *  @return        NOTIFY_DONE or NOTIFY_OK
+ */
+static int
+woal_inet6_netdeive_event(struct notifier_block *nb,
+			  unsigned long event, void *ptr)
+{
+	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+	struct net_device *ndev = ifa->idev->dev;
+	moal_private *priv;
+	int ret = NOTIFY_OK;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	if (!ndev || ndev->netdev_ops->ndo_open != woal_open)
+#else
+	if (!ndev || ndev->open != woal_open)
+#endif
+	{
+		PRINTM(MIOCTL, "IPV6 changes not for us, ignore. ndev[%p]\n",
+		       ndev);
+		if (ndev)
+			PRINTM(MIOCTL, "changes on %s\n", ndev->name);
+		ret = NOTIFY_DONE;
+		goto done;
+	}
+	priv = (moal_private *)netdev_priv(ndev);
+	if (!priv) {
+		PRINTM(MERROR, "Invalid private structure\n");
+		goto done;
+	}
+	if (priv->bss_type != MLAN_BSS_TYPE_STA
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		) {
+		PRINTM(MIOCTL, "Bss type [%d] is not STA/P2P, ignore\n",
+		       (int)priv->bss_type);
+		ret = NOTIFY_DONE;
+		goto done;
+	}
+
+	switch (event) {
+	case NETDEV_UP:
+		PRINTM(MIOCTL, "[%s]: New ipv6 addr\n", ndev->name);
+		moal_memcpy_ext(priv->phandle, priv->ipv6_addr,
+				(t_u8 *)&ifa->addr, sizeof(priv->ipv6_addr),
+				sizeof(priv->ipv6_addr));
+		priv->ipv6_addr_configured = MTRUE;
+		break;
+	case NETDEV_DOWN:
+		PRINTM(MIOCTL, "[%s]: Ipv6 addr removed.\n", ndev->name);
+		memset(priv->ipv6_addr, 0, sizeof(priv->ipv6_addr));
+		priv->ipv6_addr_configured = MFALSE;
+		break;
+	default:
+		PRINTM(MIOCTL, "[%s]: Ignore event: %u\n", ndev->name,
+		       (unsigned int)event);
+		ret = NOTIFY_DONE;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function validates a SSID as being able to be printed
+ *
+ *  @param pssid   SSID structure to validate
+ *
+ *  @return        MTRUE or MFALSE
+ */
+BOOLEAN
+woal_ssid_valid(mlan_802_11_ssid *pssid)
+{
+#ifdef ASCII_SSID_CHECK
+	unsigned int ssid_idx;
+
+	ENTER();
+
+	for (ssid_idx = 0; ssid_idx < pssid->ssid_len; ssid_idx++) {
+		if ((pssid->ssid[ssid_idx] < 0x20) ||
+		    (pssid->ssid[ssid_idx] > 0x7e)) {
+			LEAVE();
+			return MFALSE;
+		}
+	}
+	LEAVE();
+#endif
+	return MTRUE;
+}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+/**
+ *  @brief Remain on Channel timeout function
+ *
+ *  @param context  A pointer to context
+ *  @return         N/A
+ */
+void
+woal_remain_timer_func(void *context)
+{
+	moal_handle *handle = (moal_handle *)context;
+	moal_private *priv = handle->priv[handle->remain_bss_index];
+
+	ENTER();
+
+	PRINTM(MEVENT, "remain_timer fired.\n");
+	if (handle->cookie) {
+		cfg80211_remain_on_channel_expired(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+							  priv->netdev,
+#else
+							  priv->wdev,
+#endif
+							  handle->cookie,
+							  &handle->chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+							  handle->channel_type,
+#endif
+							  GFP_ATOMIC);
+		handle->cookie = 0;
+	}
+	handle->is_remain_timer_set = MFALSE;
+
+	LEAVE();
+	return;
+}
+#endif
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+/**
+ *  @brief GO timeout function
+ *
+ *  @param context  A pointer to context
+ *  @return         N/A
+ */
+void
+woal_go_timer_func(void *context)
+{
+	moal_handle *handle = (moal_handle *)context;
+
+	ENTER();
+
+	PRINTM(MEVENT, "go_timer fired.\n");
+	handle->is_go_timer_set = MFALSE;
+
+	LEAVE();
+	return;
+}
+
+#endif
+#endif
+
+/**
+ *  @brief check if we already connect to the AP.
+ *  @param priv         A pointer to moal_private structure
+ *  @param ssid_bssid   A pointer to mlan_ssid_bssid structure
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+int
+woal_is_connected(moal_private *priv, mlan_ssid_bssid *ssid_bssid)
+{
+	mlan_bss_info bss_info;
+	int ret = MFALSE;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	ENTER();
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info))
+		goto done;
+	if (bss_info.media_connected) {
+		if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) {
+			if (ssid_bssid->ssid.ssid_len) {	/* compare ssid and
+								   bssid */
+				if ((ssid_bssid->ssid.ssid_len ==
+				     bss_info.ssid.ssid_len) &&
+				    !memcmp(ssid_bssid->ssid.ssid,
+					    bss_info.ssid.ssid,
+					    bss_info.ssid.ssid_len) &&
+				    !memcmp(ssid_bssid->bssid, bss_info.bssid,
+					    MLAN_MAC_ADDR_LENGTH))
+					ret = MTRUE;
+			} else {	/* compare bssid */
+				if (!memcmp(ssid_bssid->bssid, bss_info.bssid,
+					    MLAN_MAC_ADDR_LENGTH)) {
+					moal_memcpy_ext(priv->phandle,
+							&ssid_bssid->ssid,
+							&bss_info.ssid,
+							sizeof(bss_info.ssid),
+							sizeof(ssid_bssid->
+							       ssid));
+					ret = MTRUE;
+				}
+			}
+		} else {	/* compare ssid */
+			if (ssid_bssid->ssid.ssid_len &&
+			    (ssid_bssid->ssid.ssid_len ==
+			     bss_info.ssid.ssid_len) &&
+			    !memcmp(ssid_bssid->ssid.ssid, bss_info.ssid.ssid,
+				    bss_info.ssid.ssid_len)) {
+				moal_memcpy_ext(priv->phandle,
+						&ssid_bssid->bssid,
+						&bss_info.bssid,
+						MLAN_MAC_ADDR_LENGTH,
+						sizeof(ssid_bssid->bssid));
+				ret = MTRUE;
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Look up specific IE in a buf
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ * @param id              Element id to lookup
+ *
+ * @return                Pointer of the specific IE -- success, NULL -- fail
+ */
+const t_u8 *
+woal_parse_ie_tlv(const t_u8 *ie, int len, t_u8 id)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	int length;
+
+	/* IE format:
+	 * |   u8  |   id   |
+	 * |   u8  |   len  |
+	 * |   var |   data |
+	 */
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		if ((*pos == id) && (length + 2) <= left_len)
+			return pos;
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+
+	return NULL;
+}
+
+/**
+ * @brief Look up specific IE in Extension IE
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ * @param ext_id         Extended Element id to lookup
+ *
+ * @return                Pointer of the specific Extended IE -- success, NULL
+ * -- fail
+ */
+const t_u8 *
+woal_parse_ext_ie_tlv(const t_u8 *ie, int len, t_u8 ext_id)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	int length;
+
+	/* Extension IE format:
+	 * |   u8  |   id   |
+	 * |   u8  |   len  |
+	 * |   u8  |   ext_id |
+	 * |   var |   data |
+	 */
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		if ((*pos == EXTENSION) && (length + 2) <= left_len) {
+			if (*(pos + 2) == ext_id)
+				return pos;
+		}
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+	return NULL;
+}
+
+/**
+ *  @brief Get mode
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option   Wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ *
+ *  @return              Wireless mode
+ */
+t_u32
+woal_get_mode(moal_private *priv, t_u8 wait_option)
+{
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u32 mode = 0;
+
+	ENTER();
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+	mode = priv->w_stats.status;
+#endif
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MODE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		switch (bss->param.bss_mode) {
+		case MLAN_BSS_MODE_INFRA:
+			mode = MW_MODE_INFRA;
+			break;
+		case MLAN_BSS_MODE_IBSS:
+			mode = MW_MODE_ADHOC;
+			break;
+		default:
+			mode = MW_MODE_AUTO;
+			break;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return mode;
+}
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief This function update the default firmware name
+ *
+ *  @param handle           A pointer to moal_handle structure
+ *
+ *  @return        N/A
+ */
+void
+woal_update_firmware_name(moal_handle *handle)
+{
+	if (handle->params.fw_name) {
+		handle->drv_mode.fw_name = handle->params.fw_name;
+	} else {
+		if (!moal_extflg_isset(handle, EXT_FW_SERIAL)
+		    || handle->fw_reload || handle->params.fw_reload) {
+			handle->drv_mode.fw_name =
+				handle->card_info->fw_name_wlan;
+		} else
+			handle->drv_mode.fw_name = handle->card_info->fw_name;
+
+	}
+}
+
+/**
+ *  @brief This function dynamically populates the driver mode table
+ *
+ *  @param handle           A pointer to moal_handle structure
+ *  @param drv_mode_local   Driver mode
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_update_drv_tbl(moal_handle *handle, int drv_mode_local)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	unsigned int intf_num = 0;
+	int i = 0, j = 0;
+	mlan_bss_attr *bss_tbl = NULL;
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	int last_wfd_index = 0;
+	int max_vir_bss = handle->params.max_vir_bss;
+#endif
+#endif
+#ifdef STA_SUPPORT
+	int max_sta_bss = handle->params.max_sta_bss;
+#endif
+#ifdef UAP_SUPPORT
+	int max_uap_bss = handle->params.max_uap_bss;
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	int max_wfd_bss = handle->params.max_wfd_bss;
+#endif
+
+	ENTER();
+
+	/* Calculate number of interfaces */
+#ifdef STA_SUPPORT
+	if (drv_mode_local & DRV_MODE_STA) {
+		if ((max_sta_bss < 1) || (max_sta_bss > MAX_STA_BSS)) {
+			PRINTM(MWARN,
+			       "Unsupported max_sta_bss (%d), setting to default\n",
+			       max_sta_bss);
+			max_sta_bss = DEF_STA_BSS;
+		}
+		intf_num += max_sta_bss;
+		handle->params.max_sta_bss = max_sta_bss;
+	}
+#endif /* STA_SUPPORT */
+
+#ifdef UAP_SUPPORT
+	if (drv_mode_local & DRV_MODE_UAP) {
+		if ((max_uap_bss < 1) || (max_uap_bss > MAX_UAP_BSS)) {
+			PRINTM(MWARN,
+			       "Unsupported max_uap_bss (%d), setting to default\n",
+			       max_uap_bss);
+			max_uap_bss = DEF_UAP_BSS;
+		}
+		intf_num += max_uap_bss;
+		handle->params.max_uap_bss = max_uap_bss;
+	}
+#endif /* UAP_SUPPORT */
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (drv_mode_local & DRV_MODE_WIFIDIRECT) {
+		if ((max_wfd_bss < 1) || (max_wfd_bss > MAX_WIFIDIRECT_BSS)) {
+			PRINTM(MWARN,
+			       "Unsupported max_wfd_bss (%d), setting to default\n",
+			       max_wfd_bss);
+			max_wfd_bss = DEF_WIFIDIRECT_BSS;
+		}
+		intf_num += max_wfd_bss;
+		handle->params.max_wfd_bss = max_wfd_bss;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		intf_num += max_vir_bss;
+#endif
+	}
+#endif /* WIFI_DIRECT_SUPPORT */
+
+	/* Create BSS attribute table */
+	if ((intf_num == 0) || (intf_num > MLAN_MAX_BSS_NUM)) {
+		PRINTM(MERROR, "Unsupported number of BSS %d\n", intf_num);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	} else {
+		/* Create new table */
+		bss_tbl = kmalloc(sizeof(mlan_bss_attr) * intf_num, GFP_KERNEL);
+		if (!bss_tbl) {
+			PRINTM(MERROR,
+			       "Could not create BSS attribute table\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Populate BSS attribute table */
+#ifdef STA_SUPPORT
+	if (drv_mode_local & DRV_MODE_STA) {
+		for (j = 0; j < max_sta_bss; j++) {
+			if (i >= (int)intf_num)
+				break;
+			bss_tbl[i].bss_type = MLAN_BSS_TYPE_STA;
+			bss_tbl[i].frame_type = MLAN_DATA_FRAME_TYPE_ETH_II;
+			bss_tbl[i].active = MTRUE;
+			bss_tbl[i].bss_priority = 0;
+			bss_tbl[i].bss_num = j;
+			bss_tbl[i].bss_virtual = MFALSE;
+			i++;
+		}
+	}
+#endif /* STA_SUPPORT */
+
+#ifdef UAP_SUPPORT
+	if (drv_mode_local & DRV_MODE_UAP) {
+		for (j = 0; j < max_uap_bss; j++) {
+			if (i >= (int)intf_num)
+				break;
+			bss_tbl[i].bss_type = MLAN_BSS_TYPE_UAP;
+			bss_tbl[i].frame_type = MLAN_DATA_FRAME_TYPE_ETH_II;
+			bss_tbl[i].active = MTRUE;
+			bss_tbl[i].bss_priority = 0;
+			bss_tbl[i].bss_num = j;
+			bss_tbl[i].bss_virtual = MFALSE;
+			i++;
+		}
+	}
+#endif /* UAP_SUPPORT */
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (drv_mode_local & DRV_MODE_WIFIDIRECT) {
+		for (j = 0; j < max_wfd_bss; j++) {
+			if (i >= (int)intf_num)
+				break;
+			bss_tbl[i].bss_type = MLAN_BSS_TYPE_WIFIDIRECT;
+			bss_tbl[i].frame_type = MLAN_DATA_FRAME_TYPE_ETH_II;
+			bss_tbl[i].active = MTRUE;
+			bss_tbl[i].bss_priority = 0;
+			bss_tbl[i].bss_num = j;
+			bss_tbl[i].bss_virtual = MFALSE;
+			i++;
+		}
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+		last_wfd_index = j;
+#endif
+	}
+#endif /* WIFI_DIRECT_SUPPORT */
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	/** append virtual interface at the end of table */
+	for (j = 0; j < max_vir_bss; j++) {
+		if (i >= (int)intf_num)
+			break;
+		bss_tbl[i].bss_type = MLAN_BSS_TYPE_WIFIDIRECT;
+		bss_tbl[i].frame_type = MLAN_DATA_FRAME_TYPE_ETH_II;
+		bss_tbl[i].active = MTRUE;
+		bss_tbl[i].bss_priority = 0;
+		bss_tbl[i].bss_num = j + last_wfd_index;
+		bss_tbl[i].bss_virtual = MTRUE;
+		i++;
+	}
+#endif
+#endif
+
+	/* Clear existing table, if any */
+	kfree(handle->drv_mode.bss_attr);
+	handle->drv_mode.bss_attr = NULL;
+
+	/* Create moal_drv_mode entry */
+	handle->drv_mode.drv_mode = handle->params.drv_mode;
+	handle->drv_mode.intf_num = intf_num;
+	handle->drv_mode.bss_attr = bss_tbl;
+
+	/* update default firmware name */
+	woal_update_firmware_name(handle);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes software
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_init_sw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	unsigned int i;
+	mlan_device device;
+	t_void *pmlan;
+	int cfg80211_wext = handle->params.cfg80211_wext;
+
+	ENTER();
+
+	/* Initialize moal_handle structure */
+	handle->hardware_status = HardwareStatusInitializing;
+	handle->main_state = MOAL_STATE_IDLE;
+
+#ifdef STA_SUPPORT
+	if ((handle->params.drv_mode & DRV_MODE_STA)
+#ifdef STA_WEXT
+	    && !IS_STA_WEXT(cfg80211_wext)
+#endif
+#ifdef STA_CFG80211
+	    && !IS_STA_CFG80211(cfg80211_wext)
+#endif
+#ifdef MFG_CMD_SUPPORT
+	    && !handle->params.mfg_mode
+#endif
+		) {
+		PRINTM(MERROR,
+		       "STA without WEXT or CFG80211 bit definition!\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+#endif /* STA_SUPPORT */
+
+#if defined(STA_CFG80211) && defined(STA_SUPPORT)
+	if (IS_STA_CFG80211(cfg80211_wext))
+		cfg80211_wext |= STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#endif
+
+#if defined(UAP_CFG80211) && defined(UAP_SUPPORT)
+	if (IS_UAP_CFG80211(cfg80211_wext))
+		cfg80211_wext |= STA_CFG80211_MASK | UAP_CFG80211_MASK;
+#endif
+	handle->params.cfg80211_wext = cfg80211_wext;
+	moal_memcpy_ext(handle, handle->driver_version, driver_version,
+			strlen(driver_version), MLAN_MAX_VER_STR_LEN - 1);
+
+	if (woal_update_drv_tbl(handle, handle->params.drv_mode) !=
+	    MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Could not update driver mode table\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/** user config file */
+	init_waitqueue_head(&handle->init_user_conf_wait_q);
+
+	/* PnP and power profile */
+	handle->surprise_removed = MFALSE;
+	init_waitqueue_head(&handle->init_wait_q);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	spin_lock_init(&handle->queue_lock);
+#endif
+	spin_lock_init(&handle->driver_lock);
+	spin_lock_init(&handle->ioctl_lock);
+	spin_lock_init(&handle->scan_req_lock);
+
+	handle->is_suspended = MFALSE;
+	handle->hs_activated = MFALSE;
+	handle->hs_auto_arp = MTRUE;
+	handle->suspend_fail = MFALSE;
+	handle->hs_skip_count = 0;
+	handle->hs_force_count = 0;
+#ifdef SDIO
+	if (IS_SD(handle->card_type)) {
+#ifdef SDIO_SUSPEND_RESUME
+		handle->suspend_notify_req = MFALSE;
+#endif
+		handle->cmd52_func = 0;
+		handle->cmd52_reg = 0;
+		handle->cmd52_val = 0;
+	}
+#endif
+
+	if (handle->params.scan_chan_gap &&
+	    (handle->params.scan_chan_gap <= MRVDRV_MAX_SCAN_CHAN_GAP_TIME))
+		handle->scan_chan_gap = handle->params.scan_chan_gap;
+	else
+		handle->scan_chan_gap = DEF_SCAN_CHAN_GAP;
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#ifdef WIFI_DIRECT_SUPPORT
+	handle->miracast_scan_time = DEF_MIRACAST_SCAN_TIME;
+#define DEF_NOA_DURATION 0
+#define DEF_NOA_INTERVAL 100
+	handle->noa_duration = DEF_NOA_DURATION;
+	handle->noa_interval = DEF_NOA_INTERVAL;
+#endif
+#endif
+
+#ifdef STA_CFG80211
+	handle->scan_timeout = SCAN_TIMEOUT_25S;
+#endif
+	if (IS_USB(handle->card_type))
+		init_waitqueue_head(&handle->suspend_wait_q);
+	init_waitqueue_head(&handle->hs_activate_wait_q);
+
+	/* Initialize measurement wait queue */
+	handle->meas_wait_q_woken = MFALSE;
+	handle->meas_start_jiffies = 0;
+	handle->cac_period = MFALSE;
+	handle->delay_bss_start = MFALSE;
+	init_waitqueue_head(&handle->meas_wait_q);
+#if defined(UAP_SUPPORT)
+	handle->chsw_wait_q_woken = MFALSE;
+	init_waitqueue_head(&handle->chsw_wait_q);
+#endif
+
+	handle->cac_period_jiffies = 0;
+	handle->usr_nop_period_sec = 0;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	memset(&handle->dfs_channel, 0, sizeof(struct cfg80211_chan_def));
+	woal_initialize_timer(&handle->cac_timer, woal_cac_timer_func, handle);
+	handle->is_cac_timer_set = MFALSE;
+	handle->cac_bss_index = 0xff;
+#endif
+#endif
+
+#ifdef REASSOCIATION
+	MOAL_INIT_SEMAPHORE(&handle->reassoc_sem);
+	handle->reassoc_on = 0;
+
+	/* Initialize the timer for the reassociation */
+	woal_initialize_timer(&handle->reassoc_timer, woal_reassoc_timer_func,
+			      handle);
+
+	handle->is_reassoc_timer_set = MFALSE;
+#endif /* REASSOCIATION */
+
+	/* Initialize the timer for the FW dump */
+	woal_initialize_timer(&handle->fw_dump_timer, woal_fw_dump_timer_func,
+			      handle);
+	handle->is_fw_dump_timer_set = MFALSE;
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	/* Initialize the timer for GO timeout */
+	woal_initialize_timer(&handle->go_timer, woal_go_timer_func, handle);
+
+	handle->is_go_timer_set = MFALSE;
+#endif
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	handle->remain_on_channel = MFALSE;
+
+	/* Initialize the timer for remain on channel */
+	woal_initialize_timer(&handle->remain_timer, woal_remain_timer_func,
+			      handle);
+
+	handle->is_remain_timer_set = MFALSE;
+#endif
+#endif
+
+	/* Register to MLAN */
+	memset(&device, 0, sizeof(mlan_device));
+	device.pmoal_handle = handle;
+	device.card_type = handle->card_type;
+	device.card_rev = handle->card_rev;
+#ifdef USB
+	if (IS_USB(handle->card_type)) {
+		struct usb_card_rec *cardp = handle->card;
+		device.tx_cmd_ep = cardp->tx_cmd_ep;
+		device.rx_cmd_ep = cardp->rx_cmd_ep;
+		device.tx_data_ep = cardp->tx_data_ep;
+		device.rx_data_ep = cardp->rx_data_ep;
+	}
+#endif
+#ifdef MFG_CMD_SUPPORT
+	device.mfg_mode = (t_u32)handle->params.mfg_mode;
+#endif
+#ifdef DEBUG_LEVEL1
+	device.drvdbg = drvdbg;
+#endif
+	device.fixed_beacon_buffer =
+		(t_u32)moal_extflg_isset(handle, EXT_FIX_BCN_BUF);
+	device.auto_ds = (t_u32)handle->params.auto_ds;
+	device.ext_scan = (t_u8)handle->params.ext_scan;
+	device.ps_mode = (t_u32)handle->params.ps_mode;
+	device.passive_to_active_scan = (t_u8)handle->params.p2a_scan;
+	device.max_tx_buf = (t_u32)handle->params.max_tx_buf;
+#if defined(STA_SUPPORT)
+	device.cfg_11d = (t_u32)handle->params.cfg_11d;
+#endif
+	device.indrstcfg = (t_u32)handle->params.indrstcfg;
+#ifdef PCIE
+	if (IS_PCIE(handle->card_type))
+		device.ring_size = handle->params.ring_size;
+#endif
+#ifdef SDIO
+	if (IS_SD(handle->card_type)) {
+		device.sdio_rx_aggr_enable =
+			moal_extflg_isset(handle, EXT_SDIO_RX_AGGR);
+		device.int_mode = (t_u32)moal_extflg_isset(handle, EXT_INTMODE);
+		device.gpio_pin = (t_u32)handle->params.gpiopin;
+#ifdef SDIO_MMC
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)
+		device.max_segs = ((struct sdio_mmc_card *)handle->card)
+			->func->card->host->max_segs;
+		device.max_seg_size = ((struct sdio_mmc_card *)handle->card)
+			->func->card->host->max_seg_size;
+#endif
+		PRINTM(MMSG, "SDIO: max_segs=%d max_seg_size=%d\n",
+		       device.max_segs, device.max_seg_size);
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+		device.mpa_tx_cfg = MLAN_INIT_PARA_ENABLED;
+		device.mpa_rx_cfg = MLAN_INIT_PARA_ENABLED;
+#else
+		device.mpa_tx_cfg = MLAN_INIT_PARA_DISABLED;
+		device.mpa_rx_cfg = MLAN_INIT_PARA_DISABLED;
+#endif
+#else
+		device.mpa_tx_cfg = MLAN_INIT_PARA_ENABLED;
+		device.mpa_rx_cfg = MLAN_INIT_PARA_ENABLED;
+#endif /* SDIO_MMC */
+	}
+#endif /* SDIO */
+	device.feature_control = handle->card_info->feature_control;
+	handle->feature_control = device.feature_control;
+
+	if (handle->params.rx_work == MLAN_INIT_PARA_ENABLED)
+		device.rx_work = MTRUE;
+	else if (handle->params.rx_work == MLAN_INIT_PARA_DISABLED)
+		device.rx_work = MFALSE;
+	else {
+		if (num_possible_cpus() > 1)
+			device.rx_work = MTRUE;
+		else
+			device.rx_work = MFALSE;
+	}
+	PRINTM(MMSG, "rx_work=%d cpu_num=%d\n", device.rx_work,
+	       num_possible_cpus());
+	if (moal_extflg_isset(handle, EXT_NAPI))
+		device.rx_work = MTRUE;
+
+	device.dev_cap_mask = handle->params.dev_cap_mask;
+
+	device.multi_dtim = handle->params.multi_dtim;
+
+	device.inact_tmo = handle->params.inact_tmo;
+#ifdef UAP_SUPPORT
+	device.uap_max_sta = handle->params.uap_max_sta;
+#endif
+	device.hs_wake_interval = handle->params.hs_wake_interval;
+	device.indication_gpio = handle->params.indication_gpio;
+	device.hs_mimo_switch = moal_extflg_isset(handle, EXT_HS_MIMO_SWITCH);
+
+	device.dfs53cfg = handle->params.dfs53cfg;
+
+	for (i = 0; i < handle->drv_mode.intf_num; i++) {
+		device.bss_attr[i].bss_type =
+			handle->drv_mode.bss_attr[i].bss_type;
+		device.bss_attr[i].frame_type =
+			handle->drv_mode.bss_attr[i].frame_type;
+		device.bss_attr[i].active = handle->drv_mode.bss_attr[i].active;
+		device.bss_attr[i].bss_priority =
+			handle->drv_mode.bss_attr[i].bss_priority;
+		device.bss_attr[i].bss_num =
+			handle->drv_mode.bss_attr[i].bss_num;
+		device.bss_attr[i].bss_virtual =
+			handle->drv_mode.bss_attr[i].bss_virtual;
+	}
+	moal_memcpy_ext(handle, &device.callbacks, &woal_callbacks,
+			sizeof(mlan_callbacks), sizeof(mlan_callbacks));
+	if (!handle->params.amsdu_deaggr)
+		device.callbacks.moal_recv_amsdu_packet = NULL;
+	device.drv_mode = handle->params.drv_mode;
+	if (MLAN_STATUS_SUCCESS == mlan_register(&device, &pmlan))
+		handle->pmlan_adapter = pmlan;
+	else
+		ret = MLAN_STATUS_FAILURE;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function frees the structure of moal_handle
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         N/A
+ */
+void
+woal_free_moal_handle(moal_handle *handle)
+{
+	moal_handle *ref_handle = NULL;
+
+	ENTER();
+	if (!handle) {
+		PRINTM(MERROR, "The handle is NULL\n");
+		LEAVE();
+		return;
+	}
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (handle->wiphy) {
+		wiphy_unregister(handle->wiphy);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+		woal_cfg80211_free_iftype_data(handle->wiphy);
+#endif
+		wiphy_free(handle->wiphy);
+		handle->wiphy = NULL;
+	}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+	if ((handle->nl_sk) && ((handle->nl_sk)->sk_socket)) {
+		sock_release((handle->nl_sk)->sk_socket);
+		handle->nl_sk = NULL;
+	}
+#else
+	netlink_kernel_release(handle->nl_sk);
+#endif
+
+	if (handle->pmlan_adapter) {
+		mlan_unregister(handle->pmlan_adapter);
+		handle->pmlan_adapter = NULL;
+	}
+
+	/* Free BSS attribute table */
+	kfree(handle->drv_mode.bss_attr);
+	handle->drv_mode.bss_attr = NULL;
+	PRINTM(MINFO, "Free Adapter\n");
+	if (atomic_read(&handle->lock_count) ||
+	    atomic_read(&handle->malloc_count) ||
+	    atomic_read(&handle->mbufalloc_count)) {
+		PRINTM(MERROR,
+		       "mlan has memory leak: lock_count=%d, malloc_count=%d, mbufalloc_count=%d\n",
+		       atomic_read(&handle->lock_count),
+		       atomic_read(&handle->malloc_count),
+		       atomic_read(&handle->mbufalloc_count));
+	}
+#ifdef PCIE
+	if (IS_PCIE(handle->card_type) &&
+	    atomic_read(&handle->malloc_cons_count)) {
+		PRINTM(MERROR, "mlan has memory leak: malloc_cons_count=%d\n",
+		       atomic_read(&handle->malloc_cons_count));
+	}
+#endif
+
+	/* Free allocated memory for fwdump filename */
+	kfree(handle->fwdump_fname);
+	if (fwdump_fname) {
+		kfree(fwdump_fname);
+		fwdump_fname = NULL;
+	}
+	/* Free module params */
+	woal_free_module_param(handle);
+	/** clear pref_mac to avoid later crash */
+	if (handle->pref_mac) {
+		ref_handle = (moal_handle *)handle->pref_mac;
+		if (ref_handle->pref_mac && (ref_handle->pref_mac == handle))
+			ref_handle->pref_mac = NULL;
+	}
+	/* Free the moal handle itself */
+	kfree(handle);
+	LEAVE();
+}
+
+/**
+ *    @brief WOAL get one line data from ASCII format data
+ *
+ *    @param data         Source data
+ *    @param size         Source data length
+ *    @param line_pos     Destination data
+ *    @return             routnine status
+ */
+static t_size
+parse_cfg_get_line(t_u8 *data, t_size size, t_u8 *line_pos)
+{
+	t_u8 *src, *dest;
+	static t_s32 pos;
+
+	ENTER();
+
+	if (pos >= (t_s32)size) {	/* reach the end */
+		pos = 0;	/* Reset position for rfkill */
+		LEAVE();
+		return -1;
+	}
+	memset(line_pos, 0, MAX_LINE_LEN);
+	src = data + pos;
+	dest = line_pos;
+
+	while ((dest - line_pos < MAX_LINE_LEN - 1) && pos < (t_s32)size &&
+	       *src != '\x0A' && *src != '\0') {
+		if (*src != ' ' && *src != '\t')	/* parse space */
+			*dest++ = *src++;
+		else
+			src++;
+		pos++;
+	}
+	/* parse new line */
+	pos++;
+	*dest = '\0';
+	LEAVE();
+	return strlen(line_pos);
+}
+
+/**
+ *  @brief Process register access request
+ *  @param type_string     String format Register type
+ *  @param offset_string   String format Register offset
+ *  @param value_string    String format Pointer to value
+ *  @return                MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_process_regrdwr(moal_handle *handle, t_u8 *type_string,
+		     t_u8 *offset_string, t_u8 *value_string)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	int type, offset, value;
+	pmlan_ioctl_req ioctl_req = NULL;
+	mlan_ds_reg_mem *reg = NULL;
+
+	ENTER();
+
+	/* Alloc ioctl_req */
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+
+	if (ioctl_req == NULL) {
+		PRINTM(MERROR, "Can't alloc memory\n");
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_atoi(&type, type_string))
+		goto done;
+	if (MLAN_STATUS_SUCCESS != woal_atoi(&offset, offset_string))
+		goto done;
+	if (MLAN_STATUS_SUCCESS != woal_atoi(&value, value_string))
+		goto done;
+
+	ioctl_req->req_id = MLAN_IOCTL_REG_MEM;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	reg = (mlan_ds_reg_mem *)ioctl_req->pbuf;
+	reg->sub_command = MLAN_OID_REG_RW;
+	if (type < 5) {
+		reg->param.reg_rw.type = type;
+	} else {
+		PRINTM(MERROR, "Unsupported Type\n");
+		goto done;
+	}
+	reg->param.reg_rw.offset = offset;
+	reg->param.reg_rw.value = value;
+
+	/* request ioctl for STA */
+	ret = woal_request_ioctl(handle->priv[0], ioctl_req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	PRINTM(MINFO, "Register type: %d, offset: 0x%x, value: 0x%x\n", type,
+	       offset, value);
+	ret = MLAN_STATUS_SUCCESS;
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(SDIO)
+/**
+ * @brief Read/Write registers value
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param action      get / set action
+ * @param type   type of register
+ * @param offset   offset of register
+ * @param value   value of registere
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_getset_regrdwr(moal_private *priv, t_u32 action, t_u32 type,
+		    t_u32 offset, t_u32 *value)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg_mem = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg_mem = (mlan_ds_reg_mem *)req->pbuf;
+	reg_mem->sub_command = MLAN_OID_REG_RW;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+	req->action = action;
+
+	reg_mem->param.reg_rw.type = type;
+	reg_mem->param.reg_rw.offset = offset;
+	if (req->action == MLAN_ACT_SET)
+		reg_mem->param.reg_rw.value = *value;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	*value = reg_mem->param.reg_rw.value;
+	PRINTM(MINFO, "woal_getset_regrdwr value=%x\n", *value);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief set slew rate mode
+ *
+ *    @param handle       MOAL handle
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_set_sdio_slew_rate(moal_handle *handle)
+{
+	t_u32 value = 0;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	t_u32 new_value = 0;
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv)
+		return MLAN_STATUS_FAILURE;
+
+	if ((handle->card_info->slew_rate_reg != 0) &&
+	    (handle->params.slew_rate > 3 || handle->params.slew_rate < 0))
+		return MLAN_STATUS_FAILURE;
+
+	ret = woal_getset_regrdwr(priv, MLAN_ACT_GET, MLAN_REG_MAC,
+				  handle->card_info->slew_rate_reg, &value);
+	if (ret < 0) {
+		PRINTM(MERROR, "woal_getset_regrdwr get REG_MAC failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	new_value = value & ~(0x3 << handle->card_info->slew_rate_bit_offset);
+	new_value |= (t_u32)handle->params.slew_rate
+		<< handle->card_info->slew_rate_bit_offset;
+
+	if (value != new_value) {
+		PRINTM(MMSG, "Set REG 0x%8x: 0x%x slew_rate=%d\n",
+		       handle->card_info->slew_rate_reg, new_value,
+		       handle->params.slew_rate);
+		ret = woal_getset_regrdwr(priv, MLAN_ACT_SET, MLAN_REG_MAC,
+					  handle->card_info->slew_rate_reg,
+					  &new_value);
+		if (ret < 0) {
+			PRINTM(MERROR,
+			       "woal_getset_regrdwr get REG_MAC failed\n");
+			ret = MLAN_STATUS_FAILURE;
+		}
+	}
+done:
+	return ret;
+}
+#endif /* SDIO */
+
+#ifdef UAP_SUPPORT
+/**
+ *    @brief set uap operation contrl value
+ *
+ *    @param handle       MOAL handle
+ *    @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_set_uap_operation_ctrl(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	int uap_oper_ctrl;
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_UAP);
+	if (!priv) {
+		PRINTM(MERROR,
+		       "woal_set_uap_operation_ctrl failed, no uap interface\n");
+		LEAVE();
+		return ret;
+	}
+	uap_oper_ctrl = handle->params.uap_oper_ctrl;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_OPER_CTRL;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	bss->param.ap_oper_ctrl.ctrl_value =
+		(t_u16)((uap_oper_ctrl & 0xffff0000) >> 16);
+	bss->param.ap_oper_ctrl.chan_opt = (t_u16)(uap_oper_ctrl & 0xffff);
+	PRINTM(MMSG, "Uap oper_ctrl=0x%x chan_opt=0x%x\n",
+	       bss->param.ap_oper_ctrl.ctrl_value,
+	       bss->param.ap_oper_ctrl.chan_opt);
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *    @brief WOAL parse ASCII format data to MAC address
+ *
+ *    @param handle       MOAL handle
+ *    @param data         Source data
+ *    @param size         data length
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_process_init_cfg(moal_handle *handle, t_u8 *data, t_size size)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *pos;
+	t_u8 *intf_s, *intf_e;
+	t_u8 s[MAX_LINE_LEN];	/* 1 line data */
+	t_size line_len;
+	t_u8 index = 0;
+	t_u32 i;
+	t_u8 bss_mac_addr[MAX_MAC_ADDR_LEN];
+	t_u8 bss_mac_name[MAX_PARAM_LEN];
+	t_u8 type[MAX_PARAM_LEN];
+	t_u8 offset[MAX_PARAM_LEN];
+	t_u8 value[MAX_PARAM_LEN];
+
+	ENTER();
+
+	while ((int)(line_len = parse_cfg_get_line(data, size, s)) != -1) {
+		pos = s;
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+
+		if (*pos == '#' || (*pos == '\r' && *(pos + 1) == '\n') ||
+		    *pos == '\n' || *pos == '\0')
+			continue;	/* Needn't process this line */
+
+		/* Process MAC addr */
+		if (strncmp(pos, "mac_addr", 8) == 0) {
+			intf_s = strchr(pos, '=');
+			if (intf_s != NULL)
+				intf_e = strchr(intf_s, ':');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				strncpy(bss_mac_addr, intf_e + 1,
+					MAX_MAC_ADDR_LEN - 1);
+				bss_mac_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
+				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
+					PRINTM(MERROR,
+					       "Too long interface name %d\n",
+					       __LINE__);
+					goto done;
+				}
+				strncpy(bss_mac_name, intf_s + 1,
+					intf_e - intf_s - 1);
+				bss_mac_name[intf_e - intf_s - 1] = '\0';
+				for (i = 0; i < handle->priv_num; i++) {
+					if (strcmp(bss_mac_name, handle->priv[i]
+						   ->netdev->name) == 0) {
+						memset(handle->priv[i]
+						       ->current_addr,
+						       0, ETH_ALEN);
+						PRINTM(MINFO,
+						       "Interface name: %s mac: %s\n",
+						       bss_mac_name,
+						       bss_mac_addr);
+						woal_mac2u8(handle->priv[i]
+							    ->current_addr,
+							    bss_mac_addr);
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+						if (handle->priv[i]->bss_type ==
+						    MLAN_BSS_TYPE_WIFIDIRECT) {
+							handle->priv[i]
+								->
+								current_addr[0]
+								|= 0x02;
+							PRINTM(MCMND,
+							       "Set WFD device addr: "
+							       MACSTR "\n",
+							       MAC2STR(handle->
+								       priv[i]
+								       ->
+								       current_addr));
+						}
+#endif
+#endif
+#endif
+						/* Set WLAN MAC addresses */
+						if (MLAN_STATUS_SUCCESS !=
+						    woal_request_set_mac_address
+						    (handle->priv[i],
+						     MOAL_IOCTL_WAIT)) {
+							PRINTM(MERROR,
+							       "Set MAC address failed\n");
+							goto done;
+						}
+						moal_memcpy_ext(handle,
+								handle->priv[i]
+								->netdev->
+								dev_addr,
+								handle->priv[i]
+								->current_addr,
+								ETH_ALEN,
+								ETH_ALEN);
+						index++;	/* Mark found one
+								   interface matching
+								 */
+					}
+				}
+			} else {
+				PRINTM(MERROR, "Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+		}
+		/* Process REG value */
+		else if (strncmp(pos, "wlan_reg", 8) == 0) {
+			intf_s = strchr(pos, '=');
+			if (intf_s != NULL)
+				intf_e = strchr(intf_s, ',');
+			else
+				intf_e = NULL;
+			if (intf_s != NULL && intf_e != NULL) {
+				/* Copy type */
+				strncpy(type, intf_s + 1, 1);
+				type[1] = '\0';
+			} else {
+				PRINTM(MERROR, "Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			intf_e = strchr(intf_s, ',');
+			if (intf_e != NULL) {
+				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
+					PRINTM(MERROR,
+					       "Regsier offset is too long %d\n",
+					       __LINE__);
+					goto done;
+				}
+				/* Copy offset */
+				strncpy(offset, intf_s, intf_e - intf_s);
+				offset[intf_e - intf_s] = '\0';
+			} else {
+				PRINTM(MERROR, "Wrong config file format %d\n",
+				       __LINE__);
+				goto done;
+			}
+			intf_s = intf_e + 1;
+			if ((strlen(intf_s) >= MAX_PARAM_LEN)) {
+				PRINTM(MERROR, "Regsier value is too long %d\n",
+				       __LINE__);
+				goto done;
+			}
+			/* Copy value */
+			memcpy(value, intf_s,
+			       MIN((MAX_PARAM_LEN - 1), strlen(intf_s)));
+
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_process_regrdwr(handle, type, offset, value)) {
+				PRINTM(MERROR, "Access Reg failed\n");
+				goto done;
+			}
+			PRINTM(MINFO, "Reg type: %s, offset: %s, value: %s\n",
+			       type, offset, value);
+		}
+	}
+
+	if (index == 0)
+		PRINTM(MINFO, "Can't find any matching MAC Address");
+	ret = MLAN_STATUS_SUCCESS;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *    @brief WOAL parse ASCII format raw data to hex format
+ *
+ *    @param handle       MOAL handle
+ *    @param data         Source data
+ *    @param size         data length
+ *    @param wait_option  wait option
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_process_hostcmd_cfg(moal_handle *handle, t_u8 *data,
+			 t_size size, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 *pos = data;
+	t_u8 *intf_s, *intf_e;
+	t_u8 *buf = NULL;
+	t_u8 *ptr = NULL;
+	t_u32 cmd_len = 0;
+	t_u8 start_raw = MFALSE;
+	gfp_t flag;
+
+#define CMD_STR "MRVL_CMDhostcmd"
+#define CMD_BUF_LEN 2048
+
+	ENTER();
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	buf = kzalloc(CMD_BUF_LEN, flag);
+	if (!buf) {
+		PRINTM(MERROR, "Could not allocate buffer space!\n");
+		goto done;
+	}
+	ptr = buf;
+	strcpy(ptr, CMD_STR);
+	ptr = buf + strlen(CMD_STR) + sizeof(t_u32);
+	while ((pos - data) < size) {
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos == '#') {	/* Line comment */
+			while (*pos != '\n')
+				pos++;
+			pos++;
+		}
+		if ((*pos == '\r' && *(pos + 1) == '\n') || *pos == '\n' ||
+		    *pos == '\0') {
+			pos++;
+			continue;	/* Needn't process this line */
+		}
+
+		if (*pos == '}') {
+			cmd_len = *((t_u16 *)(buf + strlen(CMD_STR) +
+					      sizeof(t_u32) + sizeof(t_u16)));
+			moal_memcpy_ext(handle, buf + strlen(CMD_STR), &cmd_len,
+					sizeof(t_u32),
+					CMD_BUF_LEN - strlen(CMD_STR));
+
+			/* fire the hostcommand from here */
+			woal_priv_hostcmd(handle->priv[0], buf, CMD_BUF_LEN,
+					  wait_option);
+			memset(buf + strlen(CMD_STR), 0,
+			       CMD_BUF_LEN - strlen(CMD_STR));
+			ptr = buf + strlen(CMD_STR) + sizeof(t_u32);
+			start_raw = MFALSE;
+			pos++;
+			continue;
+		}
+
+		if (start_raw == MFALSE) {
+			intf_s = strchr(pos, '=');
+			if (intf_s)
+				intf_e = strchr(intf_s, '{');
+			else
+				intf_e = NULL;
+
+			if (intf_s && intf_e) {
+				start_raw = MTRUE;
+				pos = intf_e + 1;
+				continue;
+			}
+		}
+
+		if (start_raw) {
+			/* Raw data block exists */
+			while (*pos != '\n') {
+				if ((*pos <= 'f' && *pos >= 'a') ||
+				    (*pos <= 'F' && *pos >= 'A') ||
+				    (*pos <= '9' && *pos >= '0')) {
+					*ptr++ = woal_atox(pos);
+					pos += 2;
+				} else
+					pos++;
+			}
+		}
+	}
+
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+#define INIT_CFG_DATA 0x00
+#define INIT_HOSTCMD_CFG_DATA 0x02
+#define COUNTRY_POWER_TABLE 0x04
+#define BAND_STEER_CFG_DATA 0x08
+
+/**
+ * @brief Request init conf firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware  A pointer to firmware image
+ * @param context   A pointer to moal_handle structure
+ *
+ * @return          N/A
+ */
+static void
+woal_request_init_user_conf_callback(const struct firmware *firmware,
+				     void *context)
+{
+	moal_handle *handle;
+
+	ENTER();
+
+	handle = (moal_handle *)context;
+	if (!handle) {
+		LEAVE();
+		return;
+	}
+	if (firmware)
+		handle->user_data = firmware;
+	else
+		PRINTM(MERROR, "User init config request firmware failed\n");
+
+	handle->init_user_conf_wait_flag = MTRUE;
+	wake_up_interruptible(&handle->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Request init conf firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware  A pointer to firmware image
+ * @param context   A pointer to moal_handle structure
+ *
+ * @return          N/A
+ */
+static void
+woal_request_init_dpd_conf_callback(const struct firmware *firmware,
+				    void *context)
+{
+	moal_handle *handle;
+
+	ENTER();
+
+	handle = (moal_handle *)context;
+	if (!handle) {
+		LEAVE();
+		return;
+	}
+	if (firmware && handle)
+		handle->dpd_data = firmware;
+	else
+		PRINTM(MERROR, "User init cfg data request firmware failed\n");
+
+	handle->init_user_conf_wait_flag = MTRUE;
+	wake_up_interruptible(&handle->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Request init conf firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware  A pointer to firmware image
+ * @param context   A pointer to moal_handle structure
+ *
+ * @return          N/A
+ */
+static void
+woal_request_vdll_fw_callback(const struct firmware *firmware, void *context)
+{
+	moal_handle *handle;
+
+	ENTER();
+
+	handle = (moal_handle *)context;
+	if (!handle) {
+		LEAVE();
+		return;
+	}
+	if (firmware && handle)
+		handle->firmware = firmware;
+	else
+		PRINTM(MERROR, "VDLL: Request firmware failed\n");
+
+	handle->init_user_conf_wait_flag = MTRUE;
+	wake_up_interruptible(&handle->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Request firmware image for VDLL
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_vdll_req_fw(moal_handle *handle)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 req_fw_nowait = moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT);
+	char *vdll_fw = handle->drv_mode.fw_name;
+
+	ENTER();
+	if (vdll_fw) {
+		PRINTM(MMSG, "VDLL: Request firmware: %s\n", vdll_fw);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, vdll_fw,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_vdll_fw_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, vdll_fw,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_vdll_fw_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, vdll_fw,
+			      handle->hotplug_device, handle,
+			      woal_request_vdll_fw_callback)) < 0) {
+#else
+			if ((request_firmware_nowait(THIS_MODULE, vdll_fw,
+						     handle->hotplug_device,
+						     handle,
+						     woal_request_vdll_fw_callback))
+			    < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "VDLL: request_firmware_nowait() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			if ((request_firmware(&handle->firmware, vdll_fw,
+					      handle->hotplug_device)) < 0) {
+				PRINTM(MERROR,
+				       "VDLL: request_firmware() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request init conf firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware  A pointer to firmware image
+ * @param context   A pointer to moal_handle structure
+ *
+ * @return          N/A
+ */
+static void
+woal_request_init_txpwr_conf_callback(const struct firmware *firmware,
+				      void *context)
+{
+	moal_handle *handle;
+
+	ENTER();
+
+	handle = (moal_handle *)context;
+	if (!handle) {
+		LEAVE();
+		return;
+	}
+	if (firmware && handle)
+		handle->txpwr_data = firmware;
+	else
+		PRINTM(MERROR, "User init cfg data request firmware failed\n");
+
+	handle->init_user_conf_wait_flag = MTRUE;
+	wake_up_interruptible(&handle->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Request init conf firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware  A pointer to firmware image
+ * @param context   A pointer to moal_handle structure
+ *
+ * @return          N/A
+ */
+static void
+woal_request_init_cfg_data_callback(const struct firmware *firmware,
+				    void *context)
+{
+	moal_handle *handle;
+
+	ENTER();
+
+	handle = (moal_handle *)context;
+	if (!handle) {
+		LEAVE();
+		return;
+	}
+	if (firmware && handle)
+		handle->init_cfg_data = firmware;
+	else
+		PRINTM(MERROR, "User init cfg data request firmware failed\n");
+
+	handle->init_user_conf_wait_flag = MTRUE;
+	wake_up_interruptible(&handle->init_user_conf_wait_q);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief WOAL set user defined init data and param
+ *
+ *    @param handle       MOAL handle structure
+ *    @param type         type argument
+ *    @param wait_option  wait option
+ *    @param country_txpwrlimit Configure Tx Power Limit
+ *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static t_u32
+woal_set_user_init_data(moal_handle *handle, int type,
+			t_u8 wait_option, char *country_txpwrlimit)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *cfg_data = NULL;
+	t_size len;
+	t_u8 req_fw_nowait = moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT);
+	char *init_cfg = handle->params.init_cfg;
+	char *init_hostcmd_cfg = handle->params.init_hostcmd_cfg;
+	char *band_steer_cfg = handle->params.band_steer_cfg;
+
+	ENTER();
+
+	if (type == INIT_CFG_DATA) {
+		PRINTM(MMSG, "Request firmware: %s\n", init_cfg);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, init_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_cfg_data_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, init_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_cfg_data_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, init_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_cfg_data_callback)) < 0) {
+#else
+			if ((request_firmware_nowait(THIS_MODULE, init_cfg,
+						     handle->hotplug_device,
+						     handle,
+						     woal_request_init_cfg_data_callback))
+			    < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "Init config file request_firmware_nowait() failed\n");
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			if ((request_firmware(&handle->init_cfg_data, init_cfg,
+					      handle->hotplug_device)) < 0) {
+				PRINTM(MERROR,
+				       "Init config file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	} else if (type == COUNTRY_POWER_TABLE) {
+		if (country_txpwrlimit == NULL) {
+			PRINTM(MERROR,
+			       "The parameter 'country_txpwrlimit' is NULL\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(MMSG, "Request firmware: %s\n", country_txpwrlimit);
+		/* 'country_txpwrlimit' holds the value of Configured Tx Power
+		 * Limit */
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, country_txpwrlimit,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG,
+			      country_txpwrlimit, handle->hotplug_device,
+			      GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG,
+			      country_txpwrlimit, handle->hotplug_device,
+			      handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+			if ((request_firmware_nowait
+			     (THIS_MODULE, country_txpwrlimit,
+			      handle->hotplug_device, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "country txpwrlimit config file request_firmware_nowait() failed\n");
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			int status = request_firmware_direct(&handle->user_data,
+							     country_txpwrlimit,
+							     handle->
+							     hotplug_device);
+#else
+			int status = request_firmware(&handle->user_data,
+						      country_txpwrlimit,
+						      handle->hotplug_device);
+#endif
+			/* File does not exist, skip download */
+			if (status == -ENOENT) {
+				ret = MLAN_STATUS_FILE_ERR;
+				PRINTM(MIOCTL,
+				       "Country power table file does not exist\n");
+				goto done;
+			} else if (status) {
+				PRINTM(MERROR,
+				       "country txpwrlimit config file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	} else if (type == INIT_HOSTCMD_CFG_DATA) {
+		PRINTM(MMSG, "Request firmware: %s\n", init_hostcmd_cfg);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, init_hostcmd_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, init_hostcmd_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, init_hostcmd_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+			if ((request_firmware_nowait
+			     (THIS_MODULE, init_hostcmd_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "Init hostcmd config file request_firmware_nowait() failed\n");
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			if ((request_firmware(&handle->user_data,
+					      init_hostcmd_cfg,
+					      handle->hotplug_device)) < 0) {
+				PRINTM(MERROR,
+				       "Init hostcmd config file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	}
+	if (type == BAND_STEER_CFG_DATA) {
+		PRINTM(MMSG, "Request firmware: %s\n", band_steer_cfg);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, band_steer_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, band_steer_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, band_steer_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+			if ((request_firmware_nowait
+			     (THIS_MODULE, band_steer_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "band_steer_cfg request_firmware_nowait() failed\n");
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			if ((request_firmware(&handle->user_data,
+					      band_steer_cfg,
+					      handle->hotplug_device)) < 0) {
+				PRINTM(MERROR,
+				       "band_steer_cfg file request_firmware() failed\n");
+				goto done;
+			}
+		}
+	}
+	if (handle->user_data) {
+		cfg_data = (t_u8 *)(handle->user_data)->data;
+		len = (handle->user_data)->size;
+		if (type == INIT_HOSTCMD_CFG_DATA || type == BAND_STEER_CFG_DATA
+		    || type == COUNTRY_POWER_TABLE) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_process_hostcmd_cfg(handle, cfg_data, len,
+						     wait_option)) {
+				PRINTM(MERROR,
+				       "Can't process hostcmd config file\n");
+				goto done;
+			}
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	} else if (type == INIT_CFG_DATA && handle->init_cfg_data) {
+		PRINTM(MIOCTL, "Load init_cfg success\n");
+		ret = MLAN_STATUS_SUCCESS;
+	}
+done:
+	if (handle->user_data) {
+		release_firmware(handle->user_data);
+		handle->user_data = NULL;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+static int woal_netdevice_event(struct notifier_block *nb, unsigned long event,
+				void *ptr);
+
+#ifdef UAP_SUPPORT
+/**
+ *  @brief Configure WACP Mode
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ *                          otherwise fail
+ */
+mlan_status
+woal_set_wacp_mode(moal_private *priv, t_u8 wait_option)
+{
+	//moal_private      *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg_misc->sub_command = MLAN_OID_MISC_WACP_MODE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	pcfg_misc->param.wacp_mode = priv->phandle->params.wacp_mode;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+#endif
+
+/**
+ *  @brief Configure aggrctrl
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ *                          otherwise fail
+ */
+mlan_status
+woal_init_aggr_ctrl(moal_handle *handle, t_u8 wait_option)
+{
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg_misc->sub_command = MLAN_OID_MISC_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	req->action = MLAN_ACT_SET;
+	pcfg_misc->param.aggr_params.tx.enable = MTRUE;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ * @brief Add interfaces DPC
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_add_card_dpc(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int i;
+	char str_buf[MLAN_MAX_VER_STR_LEN];
+	ENTER();
+
+#if defined(USB)
+	if (IS_USB(handle->card_type) && handle->boot_state == USB_FW_DNLD) {
+		/* Return now */
+		LEAVE();
+		return ret;
+	}
+#endif /* USB_NEW_FW_DNLD */
+
+#ifdef CONFIG_PROC_FS
+	/* Initialize proc fs */
+	woal_proc_init(handle);
+#endif /* CONFIG_PROC_FS */
+
+	/* Add interfaces */
+	for (i = 0; i < handle->drv_mode.intf_num; i++) {
+		if (handle->drv_mode.bss_attr[i].bss_virtual)
+			continue;
+		if (!woal_add_interface(handle, handle->priv_num,
+					handle->drv_mode.bss_attr[i].
+					bss_type)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto err;
+		}
+	}
+	woal_get_version(handle, str_buf, sizeof(str_buf) - 1);
+	PRINTM(MMSG, "wlan: version = %s\n", str_buf);
+
+	handle->woal_notifier.notifier_call = woal_netdevice_event;
+	if (register_inetaddr_notifier(&handle->woal_notifier)) {
+		PRINTM(MFATAL,
+		       "Error registering register_inetaddr_notifier\n");
+		goto err;
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (handle->params.mfg_mode == MLAN_INIT_PARA_ENABLED)
+		goto done;
+#endif
+
+	if (handle->params.init_cfg && handle->init_cfg_data) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_process_init_cfg(handle,
+					  (t_u8 *)(handle->init_cfg_data)->data,
+					  (handle->init_cfg_data)->size)) {
+			PRINTM(MERROR, "Can't process init config file\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto err;
+		}
+	}
+
+	if (moal_extflg_isset(handle, EXT_AGGR_CTRL)) {
+		/* Enable aggregation in FW */
+		if (woal_init_aggr_ctrl(handle, MOAL_IOCTL_WAIT)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto err;
+		}
+	}
+#ifdef USB
+	if (handle->params.usb_aggr == 1) {
+		/* Enable USB aggregation in FW */
+		if (woal_usb_aggr_init(handle)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto err;
+		}
+	}
+#endif
+	/* Add low power mode check */
+	if (moal_extflg_isset(handle, EXT_LOW_PW_MODE) &&
+	    handle->card_info->low_power_enable &&
+	    woal_set_low_pwr_mode(handle, MOAL_IOCTL_WAIT)) {
+		/* Proceed with Warning */
+		PRINTM(MERROR, "Unable to set Low Power Mode\n");
+	}
+#if defined(SDIO)
+	if (IS_SD(handle->card_type))
+		woal_set_sdio_slew_rate(handle);
+#endif
+
+	if (moal_extflg_isset(handle, EXT_PMIC) && handle->card_info->pmic) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_pmic_configure(handle, MOAL_IOCTL_WAIT)) {
+			PRINTM(MFATAL, "Failed to configure PMIC\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto err;
+		}
+	}
+
+	if (handle->params.antcfg) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_user_antcfg(handle, MOAL_IOCTL_WAIT)) {
+			PRINTM(MFATAL, "Set user antcfg data failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto err;
+		}
+	}
+#ifdef UAP_SUPPORT
+	if (handle->params.uap_oper_ctrl)
+		woal_set_uap_operation_ctrl(handle);
+#endif
+
+#if IS_ENABLED(CONFIG_IPV6)
+	handle->woal_inet6_notifier.notifier_call = woal_inet6_netdeive_event;
+	if (register_inet6addr_notifier(&handle->woal_inet6_notifier)) {
+		PRINTM(MFATAL,
+		       "Error registering register_inet6addr_notifier\n");
+		goto err;
+	}
+#endif
+
+#ifdef MFG_CMD_SUPPORT
+done:
+#endif
+err:
+	if (handle->params.init_cfg && handle->init_cfg_data) {
+		release_firmware(handle->init_cfg_data);
+		handle->init_cfg_data = NULL;
+	}
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to add interface\n");
+		unregister_inetaddr_notifier(&handle->woal_notifier);
+#if IS_ENABLED(CONFIG_IPV6)
+		unregister_inet6addr_notifier(&handle->woal_inet6_notifier);
+#endif
+
+		for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, handle->priv_num); i++)
+			woal_remove_interface(handle, i);
+		handle->priv_num = 0;
+#ifdef CONFIG_PROC_FS
+		woal_proc_exit(handle);
+#endif
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request dpd data
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_req_dpd_data(moal_handle *handle, mlan_init_param *param)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 req_fw_nowait = moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT);
+	char *dpd_data_cfg = handle->params.dpd_data_cfg;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (dpd_data_cfg && strncmp(dpd_data_cfg, "none", strlen("none"))) {
+		PRINTM(MMSG, "Request firmware: %s\n", dpd_data_cfg);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, dpd_data_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_dpd_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, dpd_data_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_dpd_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, dpd_data_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_dpd_conf_callback)) < 0) {
+#else
+			if ((request_firmware_nowait(THIS_MODULE, dpd_data_cfg,
+						     handle->hotplug_device,
+						     handle,
+						     woal_request_init_dpd_conf_callback))
+			    < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "DPD data request_firmware_nowait() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			status = request_firmware(&handle->dpd_data,
+						  dpd_data_cfg,
+						  handle->hotplug_device);
+			if (status < 0 && status != -ENOENT) {
+				PRINTM(MERROR,
+				       "DPD data request_firmware() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		if (handle->dpd_data) {
+			param->pdpd_data_buf = (t_u8 *)handle->dpd_data->data;
+			param->dpd_data_len = handle->dpd_data->size;
+		} else {
+			param->dpd_data_len = UNKNOW_DPD_LENGTH;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request TX Power data
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_req_txpwr_data(moal_handle *handle, mlan_init_param *param)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 req_fw_nowait = moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT);
+	char *txpwrlimit_cfg = handle->params.txpwrlimit_cfg;
+
+	ENTER();
+
+	if (txpwrlimit_cfg && strncmp(txpwrlimit_cfg, "none", strlen("none"))) {
+		PRINTM(MMSG, "Download txpwrlimit_cfg=%s\n",
+		       handle->params.txpwrlimit_cfg);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, txpwrlimit_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_txpwr_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, txpwrlimit_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_txpwr_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, txpwrlimit_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_txpwr_conf_callback)) < 0) {
+#else
+			if ((request_firmware_nowait
+			     (THIS_MODULE, txpwrlimit_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_txpwr_conf_callback)) < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "Region txpwrlimit cfg data "
+				       "request_firmware_nowait() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			if ((request_firmware(&handle->txpwr_data,
+					      txpwrlimit_cfg,
+					      handle->hotplug_device)) < 0) {
+				PRINTM(MERROR, "Region txpwrlimit cfg data "
+				       "request_firmware() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+		if (handle->txpwr_data) {
+			param->ptxpwr_data_buf =
+				(t_u8 *)handle->txpwr_data->data;
+			param->txpwr_data_len = handle->txpwr_data->size;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request Cal data
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_req_cal_data(moal_handle *handle, mlan_init_param *param)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	t_u8 req_fw_nowait = moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT);
+	char *cal_data_cfg = handle->params.cal_data_cfg;
+
+	ENTER();
+	/** Cal data request */
+	if (cal_data_cfg && strncmp(cal_data_cfg, "none", strlen("none"))) {
+		PRINTM(MMSG, "Request firmware: %s\n", cal_data_cfg);
+		if (req_fw_nowait) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_UEVENT, cal_data_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, cal_data_cfg,
+			      handle->hotplug_device, GFP_KERNEL, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+			if ((request_firmware_nowait
+			     (THIS_MODULE, FW_ACTION_HOTPLUG, cal_data_cfg,
+			      handle->hotplug_device, handle,
+			      woal_request_init_user_conf_callback)) < 0) {
+#else
+			if ((request_firmware_nowait(THIS_MODULE, cal_data_cfg,
+						     handle->hotplug_device,
+						     handle,
+						     woal_request_init_user_conf_callback))
+			    < 0) {
+#endif
+#endif
+#endif
+				PRINTM(MERROR,
+				       "Cal data request_firmware_nowait() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+			handle->init_user_conf_wait_flag = MFALSE;
+			wait_event_interruptible(handle->init_user_conf_wait_q,
+						 handle->
+						 init_user_conf_wait_flag);
+		} else {
+			if ((request_firmware(&handle->user_data, cal_data_cfg,
+					      handle->hotplug_device)) < 0) {
+				PRINTM(MERROR,
+				       "Cal data request_firmware() failed\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		}
+	} else if (!cal_data_cfg && handle->card_info->cal_data_cfg) {
+		PRINTM(MERROR,
+		       "Please add cal_data_cfg for 8887/8977/8997/8987/8978\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (handle->user_data) {
+		param->pcal_data_buf = (t_u8 *)handle->user_data->data;
+		param->cal_data_len = handle->user_data->size;
+	}
+done:
+	return ret;
+}
+
+#if defined(USB)
+/**
+ * @brief Download and Initialize firmware DPC
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_reset_usb_dev(moal_handle *handle)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct usb_device *udev = ((struct usb_card_rec *)(handle->card))->udev;
+	int usbRstDev_ret = 0;
+
+	ENTER();
+
+	/* Return now */
+	PRINTM(MMSG, "WLAN FW is downloaded\n");
+
+	/* Reset USB device to get re-enumeration */
+	if (udev) {
+#define USB_WAIT_FW_READY (500)
+		mdelay(USB_WAIT_FW_READY);
+		usbRstDev_ret = usb_reset_device(udev);
+		if ((usbRstDev_ret == 0) || (usbRstDev_ret == -ENODEV) ||	/* expected
+										   since
+										   chip
+										   re-enumerates
+										 */
+		    (usbRstDev_ret == -EINVAL)) {	/* expected if USB FW detaches
+							   first */
+			PRINTM(MMSG, "usb_reset_device() successful.\n");
+		} else {
+			PRINTM(MERROR,
+			       "usb_reset_device() failed with error code =%d\n",
+			       usbRstDev_ret);
+			ret = MLAN_STATUS_FAILURE;
+		}
+	} else {
+		PRINTM(MERROR, "ERR: No handle to call usb_reset_device()!\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Download and Initialize firmware DPC
+ *
+ * @param handle    A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_init_fw_dpc(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_fw_image fw;
+	mlan_init_param param;
+
+	ENTER();
+
+	if (handle->firmware) {
+		memset(&fw, 0, sizeof(mlan_fw_image));
+		fw.pfw_buf = (t_u8 *)handle->firmware->data;
+		fw.fw_len = handle->firmware->size;
+		if (handle->params.fw_reload == FW_RELOAD_SDIO_INBAND_RESET)
+			fw.fw_reload = handle->params.fw_reload;
+		else
+			fw.fw_reload = 0;
+		wifi_status = 0;
+		ret = mlan_dnld_fw(handle->pmlan_adapter, &fw);
+		if (ret == MLAN_STATUS_FAILURE) {
+			wifi_status = 1;
+			PRINTM(MERROR,
+			       "WLAN: Fail download FW with nowwait: %u\n",
+			       moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT));
+			if (handle->ops.reg_dbg)
+				handle->ops.reg_dbg(handle);
+			goto done;
+		}
+		wifi_status = 0;
+
+#if defined(USB)
+		if (handle->boot_state == USB_FW_DNLD) {
+			if (!IS_USB8997(handle->card_type) &&
+			    !IS_USB9098(handle->card_type) &&
+			    !IS_USB9097(handle->card_type) &&
+			    !IS_USB8978(handle->card_type))
+				ret = woal_reset_usb_dev(handle);
+			goto done;
+		}
+#endif /* USB_NEW_FW_DNLD */
+		PRINTM(MMSG, "WLAN FW is active\n");
+		if (!handle->fw_reload)
+			handle->driver_status = MFALSE;
+	}
+
+	moal_get_boot_ktime(handle, &handle->on_time);
+	PRINTM(MMSG, "on_time is %llu\n", handle->on_time);
+
+	/** data request */
+	memset(&param, 0, sizeof(mlan_init_param));
+
+	ret = woal_req_dpd_data(handle, &param);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	ret = woal_req_txpwr_data(handle, &param);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	ret = woal_req_cal_data(handle, &param);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	handle->hardware_status = HardwareStatusFwReady;
+#ifdef USB
+	if (IS_USB(handle->card_type) && !handle->fw_reload) {
+		if (handle->skip_fw_dnld != MTRUE) {
+			ret = woal_usb_rx_init(handle);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = woal_usb_tx_init(handle);
+		}
+		if (ret != MLAN_STATUS_SUCCESS)
+			goto done;
+	}
+#endif /* USB */
+	ret = mlan_set_init_param(handle->pmlan_adapter, &param);
+	if (handle->fw_reload) {
+		LEAVE();
+		return ret;
+	}
+	handle->init_wait_q_woken = MFALSE;
+	ret = mlan_init_fw(handle->pmlan_adapter);
+	if (ret == MLAN_STATUS_FAILURE) {
+		wifi_status = 2;
+		goto done;
+	} else if (ret == MLAN_STATUS_SUCCESS) {
+		handle->hardware_status = HardwareStatusReady;
+		goto done;
+	}
+	/* Wait for mlan_init to complete */
+	wait_event_timeout(handle->init_wait_q, handle->init_wait_q_woken,
+			   10 * HZ);
+	if (handle->hardware_status != HardwareStatusReady) {
+		woal_moal_debug_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+				     handle, MTRUE);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	ret = MLAN_STATUS_SUCCESS;
+done:
+	if (handle->dpd_data) {
+		release_firmware(handle->dpd_data);
+		handle->dpd_data = NULL;
+	}
+	if (handle->txpwr_data) {
+		release_firmware(handle->txpwr_data);
+		handle->txpwr_data = NULL;
+	}
+	if (handle->user_data) {
+		release_firmware(handle->user_data);
+		handle->user_data = NULL;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request firmware DPC
+ *
+ * @param handle    A pointer to moal_handle structure
+ * @param firmware  A pointer to firmware image
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_request_fw_dpc(moal_handle *handle, const struct firmware *firmware)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	wifi_timeval tstamp;
+	ENTER();
+
+	if (!firmware) {
+		woal_get_monotonic_time(&tstamp);
+		if (tstamp.time_sec >
+		    (handle->req_fw_time.time_sec + REQUEST_FW_TIMEOUT)) {
+			PRINTM(MERROR,
+			       "No firmware image found. Skipping download\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		PRINTM(MERROR,
+		       "request_firmware_nowait failed for %s. Retrying..\n",
+		       handle->drv_mode.fw_name);
+		woal_sched_timeout(MOAL_TIMER_1S);
+		woal_request_fw(handle);
+		LEAVE();
+		return ret;
+	}
+	handle->firmware = firmware;
+
+	ret = woal_init_fw_dpc(handle);
+	if (ret)
+		goto done;
+	ret = woal_add_card_dpc(handle);
+	if (ret)
+		goto done;
+
+done:
+	/* We should hold the semaphore until callback finishes execution */
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request firmware callback
+ *        This function is invoked by request_firmware_nowait system call
+ *
+ * @param firmware  A pointer to firmware image
+ * @param context   A pointer to moal_handle structure
+ *
+ * @return          N/A
+ */
+static void
+woal_request_fw_callback(const struct firmware *firmware, void *context)
+{
+	moal_handle *handle;
+
+	ENTER();
+
+	handle = (moal_handle *)context;
+	handle->firmware = firmware;
+	woal_request_fw_dpc((moal_handle *)context, firmware);
+	if (firmware) {
+		release_firmware(firmware);
+		handle->firmware = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief   Download firmware using helper
+ *
+ * @param handle  A pointer to moal_handle structure
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_request_fw(moal_handle *handle)
+{
+	int err;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u8 req_fw_nowait = moal_extflg_isset(handle, EXT_REQ_FW_NOWAIT);
+
+	ENTER();
+
+	PRINTM(MMSG, "Request firmware: %s\n", handle->drv_mode.fw_name);
+
+	if (req_fw_nowait && !handle->fw_reload) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)
+		err = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
+					      handle->drv_mode.fw_name,
+					      handle->hotplug_device,
+					      GFP_KERNEL, handle,
+					      woal_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+		err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      handle->drv_mode.fw_name,
+					      handle->hotplug_device,
+					      GFP_KERNEL, handle,
+					      woal_request_fw_callback);
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)
+		err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					      handle->drv_mode.fw_name,
+					      handle->hotplug_device, handle,
+					      woal_request_fw_callback);
+#else
+		err = request_firmware_nowait(THIS_MODULE,
+					      handle->drv_mode.fw_name,
+					      handle->hotplug_device, handle,
+					      woal_request_fw_callback);
+#endif
+#endif
+#endif
+		if (err < 0) {
+			PRINTM(MFATAL,
+			       "WLAN: request_firmware_nowait() failed, error code = %d\n",
+			       err);
+			ret = MLAN_STATUS_FAILURE;
+		}
+	} else {
+		err = request_firmware(&handle->firmware,
+				       handle->drv_mode.fw_name,
+				       handle->hotplug_device);
+		if (err < 0) {
+			PRINTM(MFATAL,
+			       "WLAN: request_firmware() failed, error code = %d\n",
+			       err);
+			ret = MLAN_STATUS_FAILURE;
+		} else {
+			if (handle->fw_reload)
+				ret = woal_init_fw_dpc(handle);
+			else
+				ret = woal_request_fw_dpc(handle,
+							  handle->firmware);
+			release_firmware(handle->firmware);
+			handle->firmware = NULL;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initializes firmware
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_init_fw(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+#ifdef USB
+	if (IS_USB(handle->card_type)) {
+		if (MFALSE || (handle->skip_fw_dnld == MTRUE)
+#if defined(USB)
+		    || (handle->boot_state == USB_FW_READY)
+#endif /* USB_NEW_FW_DNLD */
+			) {
+			PRINTM(MMSG, "WLAN FW is active\n");
+			/* Set it to NULL to skip downloading firmware to card
+			 */
+			handle->firmware = NULL;
+			ret = woal_init_fw_dpc(handle);
+			if (ret)
+				goto done;
+			ret = woal_add_card_dpc(handle);
+			if (ret)
+				goto done;
+			/* Release semaphore if download is not required */
+			MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+done:
+			LEAVE();
+			return ret;
+		}
+	}
+#endif /* USB */
+
+	woal_get_monotonic_time(&handle->req_fw_time);
+	ret = woal_request_fw(handle);
+	if (ret == MLAN_STATUS_FAILURE) {
+		PRINTM(MFATAL, "woal_request_fw failed\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function will fill in the mlan_buffer
+ *
+ *  @param pmbuf   A pointer to mlan_buffer
+ *  @param skb     A pointer to struct sk_buff
+ *
+ *  @return        N/A
+ */
+void
+woal_fill_mlan_buffer(moal_private *priv, mlan_buffer *pmbuf,
+		      struct sk_buff *skb)
+{
+	wifi_timeval tstamp;
+	struct ethhdr *eth;
+	t_u8 tid = 0;
+	dot11_txcontrol *txcontrol;
+	t_u8 tx_ctrl_flag = MFALSE;
+	int i = 0;
+	ENTER();
+	/*
+	 * skb->priority values from 256->263 are magic values to
+	 * directly indicate a specific 802.1d priority.  This is used
+	 * to allow 802.1d priority to be passed directly in from VLAN
+	 * tags, etc.
+	 */
+	if (IS_SKB_MAGIC_VLAN(skb)) {
+		tid = GET_VLAN_PRIO(skb);
+	} else {
+		eth = (struct ethhdr *)skb->data;
+
+		switch (eth->h_proto) {
+		case __constant_htons(ETH_P_IP):
+			tid = priv->dscp_map[SKB_TOS(skb) >> DSCP_OFFSET];
+			if (tid == 0xFF)
+				tid = (IPTOS_PREC(SKB_TOS(skb)) >>
+				       IPTOS_OFFSET);
+			PRINTM(MDAT_D,
+			       "packet type ETH_P_IP: dscp[%x], map[%x], tid=%d\n",
+			       SKB_TOS(skb) >> DSCP_OFFSET,
+			       priv->dscp_map[SKB_TOS(skb) >> DSCP_OFFSET],
+			       tid);
+			break;
+		case __constant_htons(ETH_P_IPV6):
+			tid = SKB_TIDV6(skb);
+			PRINTM(MDAT_D,
+			       "packet type ETH_P_IPV6: %04x, tid=%#x prio=%#x\n",
+			       eth->h_proto, tid, skb->priority);
+			break;
+		case __constant_htons(ETH_P_ARP):
+			tid = 0;
+			PRINTM(MDATA, "ARP packet %04x\n", eth->h_proto);
+			break;
+		default:
+			tid = 0;
+			if (priv->tx_protocols.protocol_num) {
+				for (i = 0; i < priv->tx_protocols.protocol_num;
+				     i++) {
+					if (eth->h_proto ==
+					    __constant_htons(priv->tx_protocols.
+							     protocols[i]))
+						tx_ctrl_flag = MTRUE;
+				}
+			}
+			if (tx_ctrl_flag) {
+				txcontrol = (dot11_txcontrol
+					     *) (skb->data +
+						 sizeof(struct ethhdr));
+				pmbuf->u.tx_info.data_rate =
+					txcontrol->datarate;
+				pmbuf->u.tx_info.channel = txcontrol->channel;
+				pmbuf->u.tx_info.bw = txcontrol->bw;
+				pmbuf->u.tx_info.tx_power.val =
+					txcontrol->power;
+				pmbuf->u.tx_info.retry_limit =
+					txcontrol->retry_limit;
+				tid = txcontrol->priority;
+				memmove(skb->data + sizeof(dot11_txcontrol),
+					skb->data, sizeof(struct ethhdr));
+				skb_pull(skb, sizeof(dot11_txcontrol));
+				pmbuf->flags |= MLAN_BUF_FLAG_TX_CTRL;
+			}
+			break;
+		}
+	}
+
+	skb->priority = tid;
+
+	/* Record the current time the packet was queued; used to determine
+	 *   the amount of time the packet was queued in the driver before it
+	 *   was sent to the firmware.  The delay is then sent along with the
+	 *   packet to the firmware for aggregate delay calculation for stats
+	 *   and MSDU lifetime expiry.
+	 */
+	woal_get_monotonic_time(&tstamp);
+	skb->tstamp = ktime_get_real();
+
+	pmbuf->pdesc = skb;
+	pmbuf->pbuf = skb->head + sizeof(mlan_buffer);
+#ifdef PCIE
+	if (IS_PCIE(priv->phandle->card_type)) {
+		pmbuf->buf_pa = 0;
+	}
+#endif
+	pmbuf->data_offset = skb->data - (skb->head + sizeof(mlan_buffer));
+	pmbuf->data_len = skb->len;
+	pmbuf->priority = skb->priority;
+	pmbuf->buf_type = 0;
+	pmbuf->in_ts_sec = tstamp.time_sec;
+	pmbuf->in_ts_usec = tstamp.time_usec;
+
+	LEAVE();
+	return;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+static struct device_type wlan_type = {
+	.name = "wlan",
+};
+#endif
+
+#ifdef STA_SUPPORT
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+/** Network device handlers */
+const struct net_device_ops woal_netdev_ops = {
+	.ndo_open = woal_open,
+	.ndo_start_xmit = woal_hard_start_xmit,
+	.ndo_stop = woal_close,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+	.ndo_siocdevprivate = woal_do_ioctl,
+#else
+	.ndo_do_ioctl = woal_do_ioctl,
+#endif
+	.ndo_set_mac_address = woal_set_mac_address,
+	.ndo_tx_timeout = woal_tx_timeout,
+	.ndo_get_stats = woal_get_stats,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.ndo_set_rx_mode = woal_set_multicast_list,
+#else
+	.ndo_set_multicast_list = woal_set_multicast_list,
+#endif
+	.ndo_select_queue = woal_select_queue,
+	.ndo_validate_addr = eth_validate_addr,
+};
+#endif
+
+/**
+ *  @brief This function initializes the private structure
+ *          and dev structure for station mode
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param priv     A pointer to moal_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+woal_init_sta_dev(struct net_device *dev, moal_private *priv)
+{
+	ENTER();
+
+	/* Setup the OS Interface to our functions */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
+	dev->open = woal_open;
+	dev->hard_start_xmit = woal_hard_start_xmit;
+	dev->stop = woal_close;
+	dev->do_ioctl = woal_do_ioctl;
+	dev->set_mac_address = woal_set_mac_address;
+	dev->tx_timeout = woal_tx_timeout;
+	dev->get_stats = woal_get_stats;
+	dev->set_multicast_list = woal_set_multicast_list;
+#else
+	dev->netdev_ops = &woal_netdev_ops;
+#endif
+	dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+	dev->needed_headroom += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
+		priv->extra_tx_head_len;
+#else
+	dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
+		priv->extra_tx_head_len;
+#endif
+#ifdef STA_WEXT
+	if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
+#if WIRELESS_EXT < 21
+		dev->get_wireless_stats = woal_get_wireless_stats;
+#endif
+		dev->wireless_handlers =
+			(struct iw_handler_def *)&woal_handler_def;
+	}
+#endif
+	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+
+#ifdef STA_CFG80211
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext))
+		init_waitqueue_head(&priv->ft_wait_q);
+#endif
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif /* STA_SUPPORT */
+
+#ifdef UAP_SUPPORT
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+/** Network device handlers */
+const struct net_device_ops woal_uap_netdev_ops = {
+	.ndo_open = woal_open,
+	.ndo_start_xmit = woal_hard_start_xmit,
+	.ndo_stop = woal_close,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+	.ndo_siocdevprivate = woal_uap_do_ioctl,
+#else
+	.ndo_do_ioctl = woal_uap_do_ioctl,
+#endif
+	.ndo_set_mac_address = woal_set_mac_address,
+	.ndo_tx_timeout = woal_tx_timeout,
+	.ndo_get_stats = woal_get_stats,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.ndo_set_rx_mode = woal_uap_set_multicast_list,
+#else
+	.ndo_set_multicast_list = woal_uap_set_multicast_list,
+#endif
+	.ndo_select_queue = woal_select_queue,
+	.ndo_validate_addr = eth_validate_addr,
+};
+#endif
+
+/**
+ *  @brief This function initializes the private structure
+ *          and dev structure for uap mode
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param priv     A pointer to moal_private structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+woal_init_uap_dev(struct net_device *dev, moal_private *priv)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Setup the OS Interface to our functions */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
+	dev->open = woal_open;
+	dev->hard_start_xmit = woal_hard_start_xmit;
+	dev->stop = woal_close;
+	dev->set_mac_address = woal_set_mac_address;
+	dev->tx_timeout = woal_tx_timeout;
+	dev->get_stats = woal_get_stats;
+	dev->do_ioctl = woal_uap_do_ioctl;
+	dev->set_multicast_list = woal_uap_set_multicast_list;
+#else
+	dev->netdev_ops = &woal_uap_netdev_ops;
+#endif
+	dev->watchdog_timeo = MRVDRV_DEFAULT_UAP_WATCHDOG_TIMEOUT;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+	dev->needed_headroom += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
+		priv->extra_tx_head_len;
+#else
+	dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
+		priv->extra_tx_head_len;
+#endif
+#ifdef UAP_WEXT
+	if (IS_UAP_WEXT(priv->phandle->params.cfg80211_wext)) {
+#if WIRELESS_EXT < 21
+		dev->get_wireless_stats = woal_get_uap_wireless_stats;
+#endif
+		dev->wireless_handlers =
+			(struct iw_handler_def *)&woal_uap_handler_def;
+	}
+#endif /* UAP_WEXT */
+	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+
+	LEAVE();
+	return status;
+}
+#endif /* UAP_SUPPORT */
+
+/**
+ * @brief This function adds a new interface. It will
+ *      allocate, initialize and register the device.
+ *
+ *  @param handle    A pointer to moal_handle structure
+ *  @param bss_index BSS index number
+ *  @param bss_type  BSS type
+ *
+ *  @return          A pointer to the new priv structure
+ */
+moal_private *
+woal_add_interface(moal_handle *handle, t_u8 bss_index, t_u8 bss_type)
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = NULL;
+	char name[256];
+	int i = 0;
+#ifdef STA_CFG80211
+	char sched_scan_str[256];
+#endif
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	char csa_str[256];
+#endif
+#endif
+	ENTER();
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#define MAX_WMM_QUEUE 4
+	/* Allocate an Ethernet device */
+	dev = alloc_etherdev_mq(sizeof(moal_private), MAX_WMM_QUEUE);
+#else
+	dev = alloc_etherdev(sizeof(moal_private));
+#endif
+	if (!dev) {
+		PRINTM(MFATAL, "Init virtual ethernet device failed\n");
+		goto error;
+	}
+	/* Allocate device name */
+#ifdef STA_SUPPORT
+	memset(name, 0, sizeof(name));
+	if (handle->params.sta_name)
+		snprintf(name, sizeof(name), "%s%%d", handle->params.sta_name);
+	else if (handle->second_mac)
+		snprintf(name, sizeof(name), "m%s", default_mlan_name);
+	else
+		snprintf(name, sizeof(name), "%s", default_mlan_name);
+
+	if ((bss_type == MLAN_BSS_TYPE_STA) && (dev_alloc_name(dev, name) < 0)) {
+		PRINTM(MERROR, "Could not allocate mlan device name\n");
+		goto error;
+	}
+#endif
+#ifdef UAP_SUPPORT
+	memset(name, 0, sizeof(name));
+	if (handle->params.uap_name)
+		snprintf(name, sizeof(name), "%s%%d", handle->params.uap_name);
+	else if (handle->second_mac)
+		snprintf(name, sizeof(name), "m%s", default_uap_name);
+	else
+		snprintf(name, sizeof(name), "%s", default_uap_name);
+	if ((bss_type == MLAN_BSS_TYPE_UAP) && (dev_alloc_name(dev, name) < 0)) {
+		PRINTM(MERROR, "Could not allocate uap device name\n");
+		goto error;
+	}
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+	memset(name, 0, sizeof(name));
+	if (handle->params.wfd_name)
+		snprintf(name, sizeof(name), "%s%%d", handle->params.wfd_name);
+	else if (handle->second_mac)
+		snprintf(name, sizeof(name), "m%s", default_wfd_name);
+	else
+		snprintf(name, sizeof(name), "%s", default_wfd_name);
+	if ((bss_type == MLAN_BSS_TYPE_WIFIDIRECT) &&
+	    (dev_alloc_name(dev, name) < 0)) {
+		PRINTM(MERROR, "Could not allocate wifidirect device name\n");
+		goto error;
+	}
+#endif
+	priv = (moal_private *)netdev_priv(dev);
+	/* Save the priv to handle */
+	handle->priv[bss_index] = priv;
+
+	/* Use the same handle structure */
+	priv->phandle = handle;
+	priv->netdev = dev;
+	priv->bss_index = bss_index;
+	priv->bss_type = bss_type;
+	priv->extra_tx_head_len = 0;
+	if (bss_type == MLAN_BSS_TYPE_STA) {
+		priv->bss_role = MLAN_BSS_ROLE_STA;
+	} else if (bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->bss_role = MLAN_BSS_ROLE_UAP;
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+	else if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+		priv->bss_role = MLAN_BSS_ROLE_STA;
+#endif
+
+	INIT_LIST_HEAD(&priv->tcp_sess_queue);
+	spin_lock_init(&priv->tcp_sess_lock);
+#ifdef STA_SUPPORT
+	INIT_LIST_HEAD(&priv->tdls_list);
+	spin_lock_init(&priv->tdls_lock);
+#endif
+
+	INIT_LIST_HEAD(&priv->tx_stat_queue);
+	spin_lock_init(&priv->tx_stat_lock);
+
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+	spin_lock_init(&priv->connect_lock);
+#endif
+#endif
+
+#ifdef STA_SUPPORT
+	INIT_LIST_HEAD(&priv->pmksa_cache_list);
+	if (bss_type == MLAN_BSS_TYPE_STA) {
+		init_waitqueue_head(&priv->okc_wait_q);
+		spin_lock_init(&priv->pmksa_list_lock);
+		priv->okc_roaming_ie = NULL;
+		priv->okc_ie_len = 0;
+	}
+#endif
+#if defined(DRV_EMBEDDED_AUTHENTICATOR)
+	init_waitqueue_head(&priv->hostcmd_wait_q);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	SET_MODULE_OWNER(dev);
+#endif
+#ifdef STA_SUPPORT
+	if (bss_type == MLAN_BSS_TYPE_STA
+#ifdef WIFI_DIRECT_SUPPORT
+	    || bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		)
+		woal_init_sta_dev(dev, priv);
+#endif
+#ifdef UAP_SUPPORT
+	if (bss_type == MLAN_BSS_TYPE_UAP) {
+		if (MLAN_STATUS_SUCCESS != woal_init_uap_dev(dev, priv))
+			goto error;
+	}
+#endif
+	if (!handle->priv_num
+#ifdef MFG_CMD_SUPPORT
+	    && (handle->params.mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		) {
+		if (handle->params.init_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle, INIT_CFG_DATA,
+						    MOAL_IOCTL_WAIT, NULL)) {
+				PRINTM(MFATAL,
+				       "Set user init data and param failed\n");
+				goto error;
+			}
+		}
+		if (handle->params.init_hostcmd_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(handle,
+						    INIT_HOSTCMD_CFG_DATA,
+						    MOAL_IOCTL_WAIT, NULL)) {
+				PRINTM(MFATAL,
+				       "Set user init hostcmd data and param failed\n");
+				goto error;
+			}
+		}
+	}
+#ifdef MFG_CMD_SUPPORT
+	if (handle->params.mfg_mode != MLAN_INIT_PARA_ENABLED) {
+#endif
+		if (bss_type == MLAN_BSS_TYPE_UAP &&
+		    priv->phandle->params.band_steer_cfg) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_user_init_data(priv->phandle,
+						    BAND_STEER_CFG_DATA,
+						    MOAL_IOCTL_WAIT, NULL)) {
+				PRINTM(MFATAL,
+				       "Set band steering configure param failed\n");
+			}
+		}
+#ifdef MFG_CMD_SUPPORT
+	}
+#endif
+
+	handle->priv_num++;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	if (!priv->phandle->wiphy &&
+	    IS_STA_OR_UAP_CFG80211(handle->params.cfg80211_wext)) {
+		if (woal_register_cfg80211(priv)) {
+			PRINTM(MERROR, "Cannot register with cfg80211\n");
+			goto error;
+		}
+	}
+#endif
+
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+	if ((priv->bss_role == MLAN_BSS_ROLE_STA) &&
+	    IS_STA_CFG80211(handle->params.cfg80211_wext)) {
+		if (bss_type == MLAN_BSS_TYPE_STA
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+		    || bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+#endif
+			)
+			/* Register cfg80211 for STA or Wifi direct */
+			if (woal_register_sta_cfg80211(dev, bss_type)) {
+				PRINTM(MERROR,
+				       "Cannot register STA with cfg80211\n");
+				goto error;
+			}
+	}
+	strcpy(sched_scan_str, "SCHED_SCAN");
+	strcat(sched_scan_str, name);
+	priv->sched_scan_workqueue =
+		alloc_workqueue(sched_scan_str,
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+	if (!priv->sched_scan_workqueue) {
+		PRINTM(MERROR, "cannot alloc sched_scan workqueue \n");
+		goto error;
+	}
+	INIT_DELAYED_WORK(&priv->sched_scan_work, woal_sched_scan_work_queue);
+
+#endif /* STA_SUPPORT */
+#endif /* STA_CFG80211 */
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+	if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
+	    IS_UAP_CFG80211(handle->params.cfg80211_wext)
+		) {
+		/* Register cfg80211 for UAP */
+		if (woal_register_uap_cfg80211(dev, bss_type)) {
+			PRINTM(MERROR, "Cannot register UAP with cfg80211\n");
+			goto error;
+		}
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	strcpy(csa_str, "CSA");
+	strcat(csa_str, name);
+	priv->csa_workqueue =
+		alloc_workqueue(csa_str,
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+	if (!priv->csa_workqueue) {
+		PRINTM(MERROR, "cannot alloc csa workqueue \n");
+		goto error;
+	}
+	INIT_DELAYED_WORK(&priv->csa_work, woal_csa_work_queue);
+#endif
+#endif
+#endif /*UAP_CFG80211 */
+
+	/* Create workqueue for main process */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+	priv->mclist_workqueue =
+		alloc_workqueue("MCLIST_WORK_QUEUE",
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+	priv->mclist_workqueue = create_workqueue("MCLIST_WORK_QUEUE");
+#endif
+	if (!priv->mclist_workqueue) {
+		PRINTM(MERROR, "cannot alloc mclist workqueue \n");
+		goto error;
+	}
+	MLAN_INIT_WORK(&priv->mclist_work, woal_mclist_work_queue);
+
+
+	/* Initialize priv structure */
+	woal_init_priv(priv, MOAL_IOCTL_WAIT);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	SET_NETDEV_DEV(dev, handle->hotplug_device);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+	SET_NETDEV_DEVTYPE(dev, &wlan_type);
+#endif
+
+	/* Register network device */
+	if (register_netdev(dev)) {
+		PRINTM(MERROR, "Cannot register virtual network device\n");
+		goto error;
+	}
+	netif_carrier_off(dev);
+	woal_stop_queue(dev);
+
+	PRINTM(MINFO, "%s: NXP 802.11 Adapter\n", dev->name);
+
+	if (bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+#if defined(SD8887) || defined(SD8987)
+		mlan_fw_info fw_info;
+		memset(&fw_info, 0, sizeof(mlan_fw_info));
+		woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+		if (MFALSE
+#ifdef SD8887
+		    || IS_SD8887(handle->card_type)
+#endif
+#ifdef SD8987
+		    || IS_SD8987(handle->card_type)
+#endif
+			) {
+			if ((fw_info.antinfo & ANT_DIVERSITY_2G)&&
+			    (fw_info.antinfo & ANT_DIVERSITY_5G))
+				handle->card_info->histogram_table_num = 4;
+		}
+#endif
+
+		for (i = 0; i < handle->card_info->histogram_table_num; i++) {
+			priv->hist_data[i] =
+				kmalloc(sizeof(hgm_data) +
+					handle->card_info->rx_rate_max *
+					sizeof(atomic_t), GFP_KERNEL);
+			if (!(priv->hist_data[i])) {
+				PRINTM(MERROR,
+				       "kmalloc priv->hist_data[%d] failed\n",
+				       i);
+				goto error;
+			}
+		}
+		woal_hist_data_reset(priv);
+	}
+#ifdef CONFIG_PROC_FS
+	woal_create_proc_entry(priv);
+	woal_debug_entry(priv);
+#endif /* CONFIG_PROC_FS */
+
+	LEAVE();
+	return priv;
+error:
+	handle->priv_num = bss_index;
+	/* Unregister wiphy device and free */
+	if (priv) {
+		if (priv->mclist_workqueue) {
+			flush_workqueue(priv->mclist_workqueue);
+			destroy_workqueue(priv->mclist_workqueue);
+			priv->mclist_workqueue = NULL;
+		}
+#ifdef STA_CFG80211
+		if (priv->sched_scan_workqueue) {
+			destroy_workqueue(priv->sched_scan_workqueue);
+			priv->sched_scan_workqueue = NULL;
+		}
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (priv->wdev &&
+		    IS_STA_OR_UAP_CFG80211(handle->params.cfg80211_wext))
+			priv->wdev = NULL;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		if (priv->csa_workqueue) {
+			destroy_workqueue(priv->csa_workqueue);
+			priv->csa_workqueue = NULL;
+		}
+#endif
+#endif
+#endif
+	}
+	if (dev && dev->reg_state == NETREG_REGISTERED)
+		unregister_netdev(dev);
+	if (dev)
+		free_netdev(dev);
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function removes an interface.
+ *
+ *  @param handle       A pointer to the moal_handle structure
+ *  @param bss_index    BSS index number
+ *
+ *  @return             N/A
+ */
+void
+woal_remove_interface(moal_handle *handle, t_u8 bss_index)
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = handle->priv[bss_index];
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+	union iwreq_data wrqu;
+#endif
+	int i = 0;
+
+	ENTER();
+
+	if (!priv || !priv->netdev)
+		goto error;
+	dev = priv->netdev;
+
+	if (priv->media_connected == MTRUE) {
+		priv->media_connected = MFALSE;
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+		if (IS_STA_OR_UAP_WEXT(handle->params.cfg80211_wext) &&
+		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+			memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu,
+					    NULL);
+		}
+#endif
+	}
+	woal_flush_tcp_sess_queue(priv);
+
+	woal_flush_tx_stat_queue(priv);
+
+#ifdef STA_CFG80211
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#endif
+
+#ifdef STA_CFG80211
+	if (priv->bss_type == MLAN_BSS_TYPE_STA &&
+	    IS_STA_CFG80211(handle->params.cfg80211_wext)) {
+		woal_flush_pmksa_list(priv);
+		if (priv->okc_roaming_ie) {
+			kfree(priv->okc_roaming_ie);
+			priv->okc_roaming_ie = NULL;
+			priv->okc_ie_len = 0;
+		}
+	}
+#endif
+
+	if (priv->bss_type == MLAN_BSS_TYPE_STA ||
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		for (i = 0; i < handle->card_info->histogram_table_num; i++) {
+			kfree(priv->hist_data[i]);
+			priv->hist_data[i] = NULL;
+		}
+	}
+#ifdef CONFIG_PROC_FS
+	/* Remove proc debug */
+	woal_debug_remove(priv);
+	woal_proc_remove(priv);
+#endif /* CONFIG_PROC_FS */
+	/* Last reference is our one */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+	PRINTM(MINFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
+#else
+	PRINTM(MINFO, "refcnt = %d\n", netdev_refcnt_read(dev));
+#endif
+
+	PRINTM(MINFO, "netdev_finish_unregister: %s\n", dev->name);
+
+	if (dev->reg_state == NETREG_REGISTERED)
+		unregister_netdev(dev);
+
+	if (priv->mclist_workqueue) {
+		flush_workqueue(priv->mclist_workqueue);
+		destroy_workqueue(priv->mclist_workqueue);
+		priv->mclist_workqueue = NULL;
+	}
+#ifdef STA_CFG80211
+	if (priv->sched_scan_workqueue) {
+		destroy_workqueue(priv->sched_scan_workqueue);
+		priv->sched_scan_workqueue = NULL;
+	}
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/* Unregister wiphy device and free */
+	if (priv->wdev && IS_STA_OR_UAP_CFG80211(handle->params.cfg80211_wext))
+		priv->wdev = NULL;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	if (priv->csa_workqueue) {
+		flush_workqueue(priv->csa_workqueue);
+		destroy_workqueue(priv->csa_workqueue);
+		priv->csa_workqueue = NULL;
+	}
+#endif
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA ||
+	    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+		woal_deinit_wifi_hal(priv);
+#endif
+
+	/* Clear the priv in handle */
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 8, 13)
+	if (IS_STA_OR_UAP_CFG80211(handle->params.cfg80211_wext))
+		priv->phandle->wiphy->extended_capabilities = NULL;
+#endif
+#endif
+	priv->phandle->priv[priv->bss_index] = NULL;
+	priv->phandle = NULL;
+	priv->netdev = NULL;
+	free_netdev(dev);
+error:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Configure pmic in firmware
+ *
+ *  @param handle    A pointer to moal_handle
+ *  @param wait_option  Wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ *                          otherwise fail
+ */
+mlan_status
+woal_pmic_configure(moal_handle *handle, t_u8 wait_option)
+{
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_PMIC_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Configure antcfg
+ *
+ *  @param handle    A pointer to moal_handle
+ *  @param wait_option  Wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ *                          otherwise fail
+ */
+mlan_status
+woal_set_user_antcfg(moal_handle *handle, t_u8 wait_option)
+{
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_status status;
+	int antcfg;
+
+	ENTER();
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	antcfg = handle->params.antcfg;
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	req->action = MLAN_ACT_SET;
+
+	if (handle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+		if (IS_CARD9098(handle->card_type) ||
+		    IS_CARD9097(handle->card_type)) {
+			radio->param.ant_cfg.tx_antenna =
+				radio->param.ant_cfg.rx_antenna = antcfg;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+			woal_cfg80211_notify_antcfg(priv, priv->phandle->wiphy,
+						    radio);
+#endif
+		} else {
+			radio->param.ant_cfg.tx_antenna =
+				(antcfg & 0x0030) >> 4;
+			radio->param.ant_cfg.rx_antenna = antcfg & 0x0003;
+		}
+	} else
+		radio->param.ant_cfg_1x1.antenna = antcfg;
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Configure MLAN for low power mode
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ *                          otherwise fail
+ */
+mlan_status
+woal_set_low_pwr_mode(moal_handle *handle, t_u8 wait_option)
+{
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_LOW_PWR_MODE;
+	misc->param.low_pwr_mode = moal_extflg_isset(handle, EXT_LOW_PW_MODE);
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+done:
+	kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Send FW shutdown command to MLAN
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wait_option  Wait option
+ *
+ *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ *                          otherwise fail
+ */
+mlan_status
+woal_shutdown_fw(moal_private *priv, t_u8 wait_option)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_INIT_SHUTDOWN;
+	misc->param.func_init_shutdown = MLAN_FUNC_SHUTDOWN;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	/* add 100 ms delay to avoid back to back init/shutdown */
+	mdelay(100);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Return hex value of a give character
+ *
+ *  @param chr      Character to be converted
+ *
+ *  @return         The converted character if chr is a valid hex, else 0
+ */
+int
+woal_hexval(char chr)
+{
+	if (chr >= '0' && chr <= '9')
+		return chr - '0';
+	if (chr >= 'A' && chr <= 'F')
+		return chr - 'A' + 10;
+	if (chr >= 'a' && chr <= 'f')
+		return chr - 'a' + 10;
+
+	return 0;
+}
+
+#ifdef STA_SUPPORT
+#endif
+
+/**
+ *  @brief This function flush event queue
+ *
+ *  @param priv      A pointer to moal_private structure
+ *
+ *  @return          N/A
+ */
+static void
+woal_flush_evt_queue(moal_handle *handle)
+{
+	struct woal_event *evt = NULL, *tmp_node;
+	unsigned long flags;
+	spin_lock_irqsave(&handle->evt_lock, flags);
+	list_for_each_entry_safe(evt, tmp_node, &handle->evt_queue, link) {
+		list_del(&evt->link);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		kfree(evt);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+	}
+	INIT_LIST_HEAD(&handle->evt_queue);
+	spin_unlock_irqrestore(&handle->evt_lock, flags);
+}
+
+/**
+ *  @brief This function flush all works in the queue
+ *
+ *  @param handle    A pointer to moal_handle
+ *
+ *  @return        N/A
+ */
+void
+woal_flush_workqueue(moal_handle *handle)
+{
+	ENTER();
+
+	/* Terminate main workqueue */
+	if (handle->workqueue)
+		flush_workqueue(handle->workqueue);
+	if (handle->rx_workqueue)
+		flush_workqueue(handle->rx_workqueue);
+	if (handle->evt_workqueue)
+		flush_workqueue(handle->evt_workqueue);
+	if (handle->tx_workqueue)
+		flush_workqueue(handle->tx_workqueue);
+	LEAVE();
+}
+
+/**
+ *  @brief This function cancel all works in the queue
+ *  and destroy the main workqueue.
+ *
+ *  @param handle    A pointer to moal_handle
+ *
+ *  @return        N/A
+ */
+void
+woal_terminate_workqueue(moal_handle *handle)
+{
+	ENTER();
+
+	/* Terminate main workqueue */
+	if (handle->workqueue) {
+		flush_workqueue(handle->workqueue);
+		destroy_workqueue(handle->workqueue);
+		handle->workqueue = NULL;
+	}
+	if (handle->rx_workqueue) {
+		flush_workqueue(handle->rx_workqueue);
+		destroy_workqueue(handle->rx_workqueue);
+		handle->rx_workqueue = NULL;
+	}
+	if (handle->evt_workqueue) {
+		woal_flush_evt_queue(handle);
+		flush_workqueue(handle->evt_workqueue);
+		destroy_workqueue(handle->evt_workqueue);
+		handle->evt_workqueue = NULL;
+	}
+	if (handle->tx_workqueue) {
+		flush_workqueue(handle->tx_workqueue);
+		destroy_workqueue(handle->tx_workqueue);
+		handle->tx_workqueue = NULL;
+	}
+	LEAVE();
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+
+/**
+ *  @brief This function opens the network device
+ *
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        0 --success, otherwise fail
+ */
+int
+woal_open(struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+#if defined(USB)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+	struct usb_interface *intf =
+		((struct usb_card_rec *)priv->phandle->card)->intf;
+#else
+	// struct usb_device *udev = ((struct usb_card_rec *)(priv->phandle->card))->udev;
+#endif /* < 2.6.34 */
+#endif /* USB_SUSPEND_RESUME */
+	t_u8 carrier_on = MFALSE;
+
+	ENTER();
+
+	if (priv->phandle->surprise_removed == MTRUE) {
+		PRINTM(MERROR,
+		       "open is not allowed in surprise remove state.\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#if defined(USB)
+	if (IS_USB(priv->phandle->card_type)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+		/* Error enabling PM on interface */
+		if (usb_autopm_get_interface(intf)) {
+			LEAVE();
+			return -EIO;
+		}
+#else
+		// atomic_set(&udev->dev.power.usage_count, 1);
+#endif /* < 2.6.34 */
+	}
+#endif /* USB_SUSPEND_RESUME */
+
+#if defined(USB) || defined(SYSKT)
+	/* On some systems the device open handler will be called before HW
+	   ready.
+	   Use the following flag check and wait function to work around
+	   the issue. */
+	if (MTRUE
+#ifdef SDIO
+	    && !IS_SD(priv->phandle->card_type)
+#endif
+#ifdef PCIE
+	    && !IS_PCIE(priv->phandle->card_type)
+#endif
+		) {
+		int i = 0;
+
+		while ((priv->phandle->hardware_status !=
+			HardwareStatusReady) &&
+		       (i < MAX_WAIT_DEVICE_READY_COUNT)) {
+			i++;
+			woal_sched_timeout(100);
+		}
+		if (i >= MAX_WAIT_DEVICE_READY_COUNT) {
+			PRINTM(MFATAL,
+			       "HW not ready, wlan_open() return failure\n");
+			LEAVE();
+			return -EFAULT;
+		}
+	}
+#endif /* USB || SYSKT || SYSKT_MULTI */
+	if (!MODULE_GET) {
+		LEAVE();
+		return -EFAULT;
+	}
+#ifdef UAP_SUPPORT
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
+	    (priv->media_connected))
+		carrier_on = MTRUE;
+#endif
+#ifdef STA_SUPPORT
+	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
+	    (priv->media_connected || priv->is_adhoc_link_sensed))
+		carrier_on = MTRUE;
+#endif
+
+	if (carrier_on == MTRUE) {
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_wake_queue(priv->netdev);
+	} else {
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+	}
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief This function closes the network device
+ *
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        0
+ */
+int
+woal_close(struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+#if defined(USB)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+	struct usb_interface *intf =
+		((struct usb_card_rec *)priv->phandle->card)->intf;
+#else
+	// struct usb_device *udev = ((struct usb_card_rec *)(priv->phandle->card))->udev;
+#endif /* < 2.6.34 */
+#endif /* USB_SUSPEND_RESUME */
+#ifdef STA_CFG80211
+	int cfg80211_wext = priv->phandle->params.cfg80211_wext;
+#endif
+	ENTER();
+
+	woal_flush_tx_stat_queue(priv);
+
+#ifdef STA_SUPPORT
+#ifdef STA_CFG80211
+	if (IS_STA_CFG80211(cfg80211_wext) &&
+	    (priv->bss_type == MLAN_BSS_TYPE_STA))
+		woal_clear_conn_params(priv);
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+	if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev->current_bss) {
+		priv->cfg_disconnect = MTRUE;
+		cfg80211_disconnected(priv->netdev, 0, NULL, 0,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+				      true,
+#endif
+				      GFP_KERNEL);
+	}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (IS_STA_CFG80211(cfg80211_wext) && priv->sched_scanning) {
+		woal_stop_bg_scan(priv, MOAL_IOCTL_WAIT);
+		priv->bg_scan_start = MFALSE;
+		priv->bg_scan_reported = MFALSE;
+		cfg80211_sched_scan_stopped(priv->wdev->wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+					    , priv->bg_scan_reqid
+#endif
+			);
+		priv->sched_scanning = MFALSE;
+	}
+#endif
+#endif
+#endif
+	if (!priv->bss_virtual)
+		woal_stop_queue(priv->netdev);
+	MODULE_PUT;
+#if defined(USB)
+	if (IS_USB(priv->phandle->card_type)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+		usb_autopm_put_interface(intf);
+#else
+		// atomic_set(&udev->dev.power.usage_count, 0);
+#endif /* < 2.6.34 */
+	}
+#endif /* USB_SUSPEND_RESUME */
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief This function sets the MAC address to firmware.
+ *
+ *  @param dev     A pointer to mlan_private structure
+ *  @param addr    MAC address to set
+ *
+ *  @return        0 --success, otherwise fail
+ */
+int
+woal_set_mac_address(struct net_device *dev, void *addr)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct sockaddr *phw_addr = (struct sockaddr *)addr;
+	t_u8 prev_addr[ETH_ALEN];
+
+	ENTER();
+
+	if (priv->phandle->surprise_removed == MTRUE) {
+		PRINTM(MERROR,
+		       "Set mac address is not allowed in surprise remove state.\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	moal_memcpy_ext(priv->phandle, prev_addr, priv->current_addr, ETH_ALEN,
+			ETH_ALEN);
+	memset(priv->current_addr, 0, ETH_ALEN);
+	/* dev->dev_addr is 6 bytes */
+	HEXDUMP("dev->dev_addr:", dev->dev_addr, ETH_ALEN);
+
+	HEXDUMP("addr:", (t_u8 *)phw_addr->sa_data, ETH_ALEN);
+	moal_memcpy_ext(priv->phandle, priv->current_addr, phw_addr->sa_data,
+			ETH_ALEN, ETH_ALEN);
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		priv->current_addr[0] |= 0x02;
+		PRINTM(MCMND, "Set WFD device addr: " MACSTR "\n",
+		       MAC2STR(priv->current_addr));
+	}
+#endif
+#endif
+#endif
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_request_set_mac_address(priv, MOAL_IOCTL_WAIT)) {
+		PRINTM(MERROR, "Set MAC address failed\n");
+		/* For failure restore the MAC address */
+		moal_memcpy_ext(priv->phandle, priv->current_addr, prev_addr,
+				ETH_ALEN, ETH_ALEN);
+		ret = -EFAULT;
+		goto done;
+	}
+	HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
+	moal_memcpy_ext(priv->phandle, dev->dev_addr, priv->current_addr,
+			ETH_ALEN, ETH_ALEN);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Check driver status
+ *
+ *  @param handle   A pointer to moal_handle
+ *
+ *  @return         MTRUE/MFALSE
+ */
+t_u8
+woal_check_driver_status(moal_handle *handle)
+{
+	moal_private *priv = NULL;
+	wifi_timeval t;
+	int i = 0;
+	mlan_debug_info *info = &(handle->debug_info);
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv || woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info)) {
+		PRINTM(MERROR,
+		       "Could not retrieve debug information from MLAN\n");
+		LEAVE();
+		return MTRUE;
+	}
+#define MOAL_CMD_TIMEOUT_MAX 9
+#define MOAL_CMD_TIMEOUT 20
+	woal_get_monotonic_time(&t);
+	if (info->dnld_cmd_in_secs && info->pending_cmd &&
+	    (t.time_sec > (info->dnld_cmd_in_secs + MOAL_CMD_TIMEOUT_MAX))) {
+		if (t.time_sec > (info->dnld_cmd_in_secs + MOAL_CMD_TIMEOUT) &&
+		    !info->num_cmd_timeout) {
+			PRINTM(MERROR, "Ignore invalid time, wait=%d\n",
+			       (int)(t.time_sec - info->dnld_cmd_in_secs));
+		} else {
+			PRINTM(MERROR, "Timeout cmd id = 0x%x wait=%d\n",
+			       info->pending_cmd,
+			       (int)(t.time_sec - info->dnld_cmd_in_secs));
+			LEAVE();
+			return MTRUE;
+		}
+	}
+	if (info->num_cmd_timeout) {
+		PRINTM(MERROR, "num_cmd_timeout = %d\n", info->num_cmd_timeout);
+		PRINTM(MERROR, "Timeout cmd id = 0x%x, act = 0x%x\n",
+		       info->timeout_cmd_id, info->timeout_cmd_act);
+		LEAVE();
+		return MTRUE;
+	}
+	if (info->num_cmd_host_to_card_failure) {
+		PRINTM(MERROR, "num_cmd_host_to_card_failure = %d\n",
+		       info->num_cmd_host_to_card_failure);
+		LEAVE();
+		return MTRUE;
+	}
+	if (info->num_no_cmd_node) {
+		PRINTM(MERROR, "num_no_cmd_node = %d\n", info->num_no_cmd_node);
+		LEAVE();
+		return MTRUE;
+	}
+	for (i = 0; i < handle->priv_num; i++) {
+		priv = handle->priv[i];
+		if (priv) {
+			if (priv->num_tx_timeout >= NUM_TX_TIMEOUT_THRESHOLD) {
+				PRINTM(MERROR, "num_tx_timeout = %d\n",
+				       priv->num_tx_timeout);
+				LEAVE();
+				return MTRUE;
+			}
+		}
+	}
+	if (info->pm_wakeup_card_req && info->pm_wakeup_fw_try) {
+#define MAX_WAIT_TIME 3
+		if (t.time_sec > (info->pm_wakeup_in_secs + MAX_WAIT_TIME)) {
+			PRINTM(MERROR,
+			       "wakeup_dev_req=%d wakeup_tries=%d wait=%d\n",
+			       info->pm_wakeup_card_req, info->pm_wakeup_fw_try,
+			       (int)(t.time_sec - info->pm_wakeup_in_secs));
+			LEAVE();
+			return MTRUE;
+		}
+	}
+	if (info->fw_hang_report) {
+		PRINTM(MERROR, "fw_hang_report = %d\n", info->fw_hang_report);
+		LEAVE();
+		return MTRUE;
+	}
+
+	if (priv && priv->phandle->driver_status) {
+		LEAVE();
+		return MTRUE;
+	}
+
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief Display MLAN debug information
+ *
+ *  @param priv     A pointer to moal_private
+ *
+ *  @return         N/A
+ */
+void
+woal_mlan_debug_info(moal_private *priv)
+{
+	int i;
+#ifdef SDIO
+	int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+	char str[512] = { 0 };
+	char *s;
+	mlan_debug_info *info = NULL;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or priv->phandle is null\n");
+		LEAVE();
+		return;
+	}
+
+	info = &(priv->phandle->debug_info);
+
+	if (woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info)) {
+		PRINTM(MERROR,
+		       "Could not retrieve debug information from MLAN\n");
+		LEAVE();
+		return;
+	}
+	PRINTM(MERROR, "------------mlan_debug_info-------------\n");
+	PRINTM(MERROR, "mlan_processing =%d\n", info->mlan_processing);
+	PRINTM(MERROR, "main_lock_flag =%d\n", info->main_lock_flag);
+	PRINTM(MERROR, "main_process_cnt =%d\n", info->main_process_cnt);
+	PRINTM(MERROR, "delay_task_flag =%d\n", info->delay_task_flag);
+	PRINTM(MERROR, "mlan_rx_processing =%d\n", info->mlan_rx_processing);
+	PRINTM(MERROR, "rx_pkts_queued=%d\n", info->rx_pkts_queued);
+	PRINTM(MERROR, "tx_pkts_queued=%d\n", info->tx_pkts_queued);
+	PRINTM(MERROR, "fw_hang_report = %d\n", info->fw_hang_report);
+	PRINTM(MERROR, "num_cmd_timeout = %d\n", info->num_cmd_timeout);
+	PRINTM(MERROR, "Timeout cmd id = 0x%x, act = 0x%x\n",
+	       info->timeout_cmd_id, info->timeout_cmd_act);
+
+	PRINTM(MERROR, "last_cmd_index = %d\n", info->last_cmd_index);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_cmd_id[i]);
+	PRINTM(MERROR, "last_cmd_id = %s\n", str);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_cmd_act[i]);
+	PRINTM(MERROR, "last_cmd_act = %s\n", str);
+	PRINTM(MERROR, "last_cmd_resp_index = %d\n", info->last_cmd_resp_index);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_cmd_resp_id[i]);
+	PRINTM(MERROR, "last_cmd_resp_id = %s\n", str);
+	PRINTM(MERROR, "last_event_index = %d\n", info->last_event_index);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_event[i]);
+	PRINTM(MERROR, "last_event = %s", str);
+
+	PRINTM(MERROR, "num_data_h2c_failure = %d\n",
+	       info->num_tx_host_to_card_failure);
+	PRINTM(MERROR, "num_cmd_h2c_failure = %d\n",
+	       info->num_cmd_host_to_card_failure);
+	PRINTM(MERROR, "num_alloc_buffer_failure = %d\n",
+	       info->num_alloc_buffer_failure);
+	PRINTM(MERROR, "num_pkt_dropped = %d\n", info->num_pkt_dropped);
+
+#ifdef SDIO
+	if (IS_SD(priv->phandle->card_type)) {
+		PRINTM(MERROR, "num_data_c2h_failure = %d\n",
+		       info->num_rx_card_to_host_failure);
+		PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n",
+		       info->num_cmdevt_card_to_host_failure);
+		PRINTM(MERROR, "num_int_read_failure = %d\n",
+		       info->num_int_read_failure);
+		PRINTM(MERROR, "last_int_status = %d\n", info->last_int_status);
+
+		PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+		       (unsigned int)info->mp_rd_bitmap, info->curr_rd_port);
+		PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+		       (unsigned int)info->mp_wr_bitmap, info->curr_wr_port);
+		PRINTM(MERROR, "mp_data_port_mask=0x%x\n",
+		       info->mp_data_port_mask);
+		PRINTM(MERROR,
+		       "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n",
+		       info->last_recv_rd_bitmap, info->mp_invalid_update);
+		mp_aggr_pkt_limit = info->mp_aggr_pkt_limit;
+		PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index = %d\n",
+		       info->last_recv_wr_bitmap, info->last_mp_index);
+		for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
+			for (s = str, j = 0; j < mp_aggr_pkt_limit; j++)
+				s += sprintf(s, "0x%02x ",
+					     info->last_mp_wr_info
+					     [i * mp_aggr_pkt_limit + j]);
+
+			PRINTM(MERROR,
+			       "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n%s\n",
+			       info->last_mp_wr_bitmap[i],
+			       info->last_mp_wr_ports[i],
+			       info->last_mp_wr_len[i],
+			       info->last_curr_wr_port[i], str);
+		}
+	}
+#endif
+#ifdef PCIE
+	if (IS_PCIE(priv->phandle->card_type)) {
+		PRINTM(MERROR, "txbd_rdptr=0x%x txbd_wrptr=0x%x\n",
+		       info->txbd_rdptr, info->txbd_wrptr);
+		PRINTM(MERROR, "rxbd_rdptr=0x%x rxbd_wrptr=0x%x\n",
+		       info->rxbd_rdptr, info->rxbd_wrptr);
+		PRINTM(MERROR, "eventbd_rdptr=0x%x event_wrptr=0x%x\n",
+		       info->eventbd_rdptr, info->eventbd_wrptr);
+		PRINTM(MERROR, "last_wr_index:%d\n",
+		       info->txbd_wrptr & (info->txrx_bd_size - 1));
+		PRINTM(MERROR, "TxRx BD size:%d\n", info->txrx_bd_size);
+	}
+#endif
+	PRINTM(MERROR, "num_event_deauth = %d\n", info->num_event_deauth);
+	PRINTM(MERROR, "num_event_disassoc = %d\n", info->num_event_disassoc);
+	PRINTM(MERROR, "num_event_link_lost = %d\n", info->num_event_link_lost);
+	PRINTM(MERROR, "num_cmd_deauth = %d\n", info->num_cmd_deauth);
+	PRINTM(MERROR, "num_cmd_assoc_success = %d\n",
+	       info->num_cmd_assoc_success);
+	PRINTM(MERROR, "num_cmd_assoc_failure = %d\n",
+	       info->num_cmd_assoc_failure);
+	PRINTM(MERROR, "num_cons_assoc_failure = %d\n",
+	       info->num_cons_assoc_failure);
+	PRINTM(MERROR, "cmd_resp_received = %d\n", info->cmd_resp_received);
+	PRINTM(MERROR, "event_received = %d\n", info->event_received);
+
+	PRINTM(MERROR, "max_tx_buf_size = %d\n", info->max_tx_buf_size);
+	PRINTM(MERROR, "tx_buf_size = %d\n", info->tx_buf_size);
+	PRINTM(MERROR, "curr_tx_buf_size = %d\n", info->curr_tx_buf_size);
+	PRINTM(MERROR, "bypass_pkt_count=%d\n", info->bypass_pkt_count);
+
+	PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", info->data_sent,
+	       info->cmd_sent);
+	PRINTM(MERROR, "data_sent_cnt=%u\n", info->data_sent_cnt);
+
+	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", info->ps_mode,
+	       info->ps_state);
+	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d wakeup_timeout=%d\n",
+	       info->pm_wakeup_card_req, info->pm_wakeup_fw_try,
+	       info->pm_wakeup_timeout);
+	PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n",
+	       info->is_hs_configured, info->hs_activated);
+	PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n", info->pps_uapsd_mode,
+	       info->sleep_pd);
+	PRINTM(MERROR, "tx_lock_flag = %d\n", info->tx_lock_flag);
+	PRINTM(MERROR, "port_open = %d\n", info->port_open);
+	PRINTM(MERROR, "scan_processing = %d\n", info->scan_processing);
+	for (i = 0; i < (int)info->ralist_num; i++) {
+		PRINTM(MERROR,
+		       "ralist ra: %02x:%02x:%02x:%02x:%02x:%02x tid=%d pkts=%d pause=%d\n",
+		       info->ralist[i].ra[0], info->ralist[i].ra[1],
+		       info->ralist[i].ra[2], info->ralist[i].ra[3],
+		       info->ralist[i].ra[4], info->ralist[i].ra[5],
+		       info->ralist[i].tid, info->ralist[i].total_pkts,
+		       info->ralist[i].tx_pause);
+	}
+
+#ifdef PCIE
+	if (IS_PCIE(priv->phandle->card_type)) {
+		PRINTM(MERROR, "txbd: rdptr=0x%x wrptr=0x%x\n",
+		       info->txbd_rdptr, info->txbd_wrptr);
+		PRINTM(MERROR, "rxbd: rdptr=0x%x wrptr=0x%x\n",
+		       info->rxbd_rdptr, info->rxbd_wrptr);
+		PRINTM(MERROR, "eventbd: rdptr=0x%x wrptr=0x%x\n",
+		       info->eventbd_rdptr, info->eventbd_wrptr);
+	}
+#endif
+	PRINTM(MERROR, "------------mlan_debug_info End-------------\n");
+	LEAVE();
+}
+
+/**
+ *  @brief This function handle the shutdown timeout issue
+ *
+ *  @param handle   Pointer to structure moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_ioctl_timeout(moal_handle *handle)
+{
+	moal_private *priv = NULL;
+
+	ENTER();
+
+	PRINTM(MMSG, "woal_ioctl_timout.\n");
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (priv) {
+		woal_mlan_debug_info(priv);
+		woal_moal_debug_info(priv, NULL, MFALSE);
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function handles the timeout of packet
+ *          transmission
+ *
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        N/A
+ */
+void
+woal_tx_timeout(struct net_device *dev
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+		, unsigned int txqueue
+#endif
+	)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u8 auto_fw_dump = MFALSE;
+	ENTER();
+
+	priv->num_tx_timeout++;
+	PRINTM(MERROR, "%lu : %s (bss=%d): Tx timeout (%d)\n", jiffies,
+	       dev->name, priv->bss_index, priv->num_tx_timeout);
+	woal_set_trans_start(dev);
+
+	if (priv->num_tx_timeout == NUM_TX_TIMEOUT_THRESHOLD) {
+		if (drvdbg & MFW_D)
+			auto_fw_dump = MTRUE;
+		woal_mlan_debug_info(priv);
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		priv->phandle->driver_status = MTRUE;
+		if (!auto_fw_dump && !priv->phandle->fw_dump)
+			woal_process_hang(priv->phandle);
+
+		wifi_status = 3;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function returns the network statistics
+ *
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        A pointer to net_device_stats structure
+ */
+struct net_device_stats *
+woal_get_stats(struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	return &priv->stats;
+}
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+/**
+ *  @brief This function handles wmm queue select
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @param skb     A pointer to sk_buff structure
+ *
+ *  @return        tx_queue index (0-3)
+ */
+u16
+woal_select_queue(struct net_device *dev, struct sk_buff *skb
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
+		  , struct net_device *sb_dev
+#else
+		  , void *accel_priv
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) &&                          \
+	LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
+		  , select_queue_fallback_t fallback
+#endif
+#endif
+	)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct ethhdr *eth = NULL;
+	t_u8 tid = 0;
+	t_u8 index = 0;
+
+	ENTER();
+	if (priv->phandle->surprise_removed == MTRUE) {
+		LEAVE();
+		return index;
+	}
+	/*
+	 * skb->priority values from 256->263 are magic values to
+	 * directly indicate a specific 802.1d priority.  This is used
+	 * to allow 802.1d priority to be passed directly in from VLAN
+	 * tags, etc.
+	 */
+	if (IS_SKB_MAGIC_VLAN(skb)) {
+		tid = GET_VLAN_PRIO(skb);
+	} else {
+		eth = (struct ethhdr *)skb->data;
+		switch (eth->h_proto) {
+		case __constant_htons(ETH_P_IP):
+			tid = priv->dscp_map[SKB_TOS(skb) >> DSCP_OFFSET];
+			if (tid == 0xFF)
+				tid = (IPTOS_PREC(SKB_TOS(skb)) >>
+				       IPTOS_OFFSET);
+			break;
+		case __constant_htons(ETH_P_IPV6):
+			tid = SKB_TIDV6(skb);
+			break;
+		case __constant_htons(ETH_P_ARP):
+		default:
+			break;
+		}
+	}
+
+	index = mlan_select_wmm_queue(priv->phandle->pmlan_adapter,
+				      priv->bss_index, tid);
+	PRINTM(MDATA, "select queue: tid=%d, index=%d\n", tid, index);
+	LEAVE();
+	return index;
+}
+#endif
+
+/**
+ *  @brief This function flush tx status queue
+ *
+ *  @param priv      A pointer to moal_private structure
+ *
+ *  @return          N/A
+ */
+void
+woal_flush_tx_stat_queue(moal_private *priv)
+{
+	struct tx_status_info *tx_info = NULL, *tmp_node;
+	unsigned long flags;
+	struct sk_buff *skb = NULL;
+	spin_lock_irqsave(&priv->tx_stat_lock, flags);
+	list_for_each_entry_safe(tx_info, tmp_node, &priv->tx_stat_queue, link) {
+		list_del(&tx_info->link);
+		spin_unlock_irqrestore(&priv->tx_stat_lock, flags);
+		skb = (struct sk_buff *)tx_info->tx_skb;
+		if (tx_info->tx_cookie) {
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+			cfg80211_mgmt_tx_status(priv->netdev,
+						tx_info->tx_cookie, skb->data,
+						skb->len, true, GFP_ATOMIC);
+#else
+			cfg80211_mgmt_tx_status(priv->wdev, tx_info->tx_cookie,
+						skb->data, skb->len, true,
+						GFP_ATOMIC);
+#endif
+#endif
+#endif
+		}
+		dev_kfree_skb_any(skb);
+		kfree(tx_info);
+		spin_lock_irqsave(&priv->tx_stat_lock, flags);
+	}
+	INIT_LIST_HEAD(&priv->tx_stat_queue);
+	spin_unlock_irqrestore(&priv->tx_stat_lock, flags);
+	spin_lock_bh(&(priv->tx_q.lock));
+	__skb_queue_purge(&priv->tx_q);
+	spin_unlock_bh(&(priv->tx_q.lock));
+}
+
+/**
+ *  @brief This function gets tx info from tx_stat_queue
+ *
+ *  @param priv      	A pointer to moal_private structure
+ *  @param tx_seq_num   tx seq number
+ *
+ *  @return          A pointer to the tcp tx_status_info structure, if found.
+ *                   Otherwise, null
+ */
+struct tx_status_info *
+woal_get_tx_info(moal_private *priv, t_u8 tx_seq_num)
+{
+	struct tx_status_info *tx_info = NULL;
+	ENTER();
+
+	list_for_each_entry(tx_info, &priv->tx_stat_queue, link) {
+		if (tx_info->tx_seq_num == tx_seq_num) {
+			LEAVE();
+			return tx_info;
+		}
+	}
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function remove tx info from queue
+ *
+ *  @param priv      		A pointer to moal_private structure
+ *  @param tx_seq_num           tx seq number
+ *
+ *  @return	         N/A
+ */
+void
+woal_remove_tx_info(moal_private *priv, t_u8 tx_seq_num)
+{
+	struct tx_status_info *tx_info, *tmp = NULL;
+	unsigned long flags;
+	ENTER();
+
+	spin_lock_irqsave(&priv->tx_stat_lock, flags);
+	list_for_each_entry_safe(tx_info, tmp, &priv->tx_stat_queue, link) {
+		if (tx_info->tx_seq_num == tx_seq_num) {
+			list_del(&tx_info->link);
+			dev_kfree_skb_any((struct sk_buff *)tx_info->tx_skb);
+			kfree(tx_info);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&priv->tx_stat_lock, flags);
+
+	LEAVE();
+}
+
+#ifdef STA_CFG80211
+/**
+ *  @brief This function flush tcp session queue
+ *
+ *  @param priv      A pointer to moal_private structure
+ *
+ *  @return          N/A
+ */
+void
+woal_flush_tdls_list(moal_private *priv)
+{
+	struct tdls_peer *peer = NULL, *tmp_node;
+	unsigned long flags;
+	spin_lock_irqsave(&priv->tdls_lock, flags);
+	list_for_each_entry_safe(peer, tmp_node, &priv->tdls_list, link) {
+		list_del(&peer->link);
+		kfree(peer);
+	}
+	INIT_LIST_HEAD(&priv->tdls_list);
+	spin_unlock_irqrestore(&priv->tdls_lock, flags);
+	priv->tdls_check_tx = MFALSE;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ *  @brief  check the tx packet for tdls auto set up
+ *
+ *  @param priv      A pointer to moal_private structure
+ *  @param skb       A pointer to skb buffer.
+ *
+ *  @return          N/A
+ */
+static void
+woal_tdls_check_tx(moal_private *priv, struct sk_buff *skb)
+{
+	struct tdls_peer *peer = NULL;
+	unsigned long flags;
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	ENTER();
+	moal_memcpy_ext(priv->phandle, ra, skb->data, MLAN_MAC_ADDR_LENGTH,
+			sizeof(ra));
+	spin_lock_irqsave(&priv->tdls_lock, flags);
+	list_for_each_entry(peer, &priv->tdls_list, link) {
+		if (!memcmp(peer->peer_addr, ra, ETH_ALEN)) {
+			if (peer->rssi &&
+			    (peer->rssi <= TDLS_RSSI_HIGH_THRESHOLD)) {
+				if ((peer->link_status == TDLS_NOT_SETUP) &&
+				    (peer->num_failure <
+				     TDLS_MAX_FAILURE_COUNT)) {
+					peer->link_status =
+						TDLS_SETUP_INPROGRESS;
+					PRINTM(MMSG,
+					       "Wlan: Set up TDLS link,peer="
+					       MACSTR " rssi=%d\n",
+					       MAC2STR(peer->peer_addr),
+					       -peer->rssi);
+					cfg80211_tdls_oper_request(priv->netdev,
+								   peer->
+								   peer_addr,
+								   NL80211_TDLS_SETUP,
+								   0,
+								   GFP_ATOMIC);
+					priv->tdls_check_tx = MFALSE;
+				}
+			}
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&priv->tdls_lock, flags);
+	LEAVE();
+}
+#endif
+#endif
+
+/**
+ *  @brief This function flush tcp session queue
+ *
+ *  @param priv      A pointer to moal_private structure
+ *
+ *  @return          N/A
+ */
+void
+woal_flush_tcp_sess_queue(moal_private *priv)
+{
+	struct tcp_sess *tcp_sess = NULL, *tmp_node;
+	unsigned long flags;
+	struct sk_buff *skb;
+	spin_lock_irqsave(&priv->tcp_sess_lock, flags);
+	list_for_each_entry_safe(tcp_sess, tmp_node, &priv->tcp_sess_queue,
+				 link) {
+		list_del(&tcp_sess->link);
+		if (tcp_sess->is_timer_set)
+			woal_cancel_timer(&tcp_sess->ack_timer);
+		skb = (struct sk_buff *)tcp_sess->ack_skb;
+		if (skb)
+			dev_kfree_skb_any(skb);
+		kfree(tcp_sess);
+	}
+	INIT_LIST_HEAD(&priv->tcp_sess_queue);
+	priv->tcp_ack_drop_cnt = 0;
+	priv->tcp_ack_cnt = 0;
+	spin_unlock_irqrestore(&priv->tcp_sess_lock, flags);
+}
+
+/**
+ *  @brief This function gets tcp session from the tcp session queue
+ *
+ *  @param priv      A pointer to moal_private structure
+ *  @param src_ip    IP address of the device
+ *  @param src_port  TCP port of the device
+ *  @param dst_ip    IP address of the client
+ *  @param dst_port  TCP port of the client
+ *
+ *  @return          A pointer to the tcp session data structure, if found.
+ *                   Otherwise, null
+ */
+static inline struct tcp_sess *
+woal_get_tcp_sess(moal_private *priv,
+		  t_u32 src_ip, t_u16 src_port, t_u32 dst_ip, t_u16 dst_port)
+{
+	struct tcp_sess *tcp_sess = NULL;
+	ENTER();
+
+	list_for_each_entry(tcp_sess, &priv->tcp_sess_queue, link) {
+		if ((tcp_sess->src_ip_addr == src_ip) &&
+		    (tcp_sess->src_tcp_port == src_port) &&
+		    (tcp_sess->dst_ip_addr == dst_ip) &&
+		    (tcp_sess->dst_tcp_port == dst_port)) {
+			LEAVE();
+			return tcp_sess;
+		}
+	}
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function send the holding tcp ack packet
+ *  re-assoc thread.
+ *
+ *  @param context  A pointer to context
+ *  @return         N/A
+ */
+static void
+woal_tcp_ack_timer_func(void *context)
+{
+	struct tcp_sess *tcp_session = (struct tcp_sess *)context;
+	moal_private *priv = (moal_private *)tcp_session->priv;
+	unsigned long flags;
+	mlan_buffer *pmbuf;
+	struct sk_buff *skb;
+	mlan_status status;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	t_u32 index = 0;
+#endif
+	ENTER();
+	spin_lock_irqsave(&priv->tcp_sess_lock, flags);
+	tcp_session->is_timer_set = MFALSE;
+	skb = (struct sk_buff *)tcp_session->ack_skb;
+	pmbuf = (mlan_buffer *)tcp_session->pmbuf;
+	tcp_session->ack_skb = NULL;
+	tcp_session->pmbuf = NULL;
+	spin_unlock_irqrestore(&priv->tcp_sess_lock, flags);
+	if (skb && pmbuf) {
+		status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+		switch (status) {
+		case MLAN_STATUS_PENDING:
+			atomic_inc(&priv->phandle->tx_pending);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+			index = skb_get_queue_mapping(skb);
+			atomic_inc(&priv->wmm_tx_pending[index]);
+			if (atomic_read(&priv->wmm_tx_pending[index]) >=
+			    MAX_TX_PENDING) {
+				struct netdev_queue *txq =
+					netdev_get_tx_queue(priv->netdev,
+							    index);
+				netif_tx_stop_queue(txq);
+				moal_tp_accounting_rx_param((t_void *)priv->
+							    phandle, 8, 0);
+				PRINTM(MINFO, "Stop Kernel Queue : %d\n",
+				       index);
+			}
+#else
+			if (atomic_read(&priv->phandle->tx_pending) >=
+			    MAX_TX_PENDING)
+				woal_stop_queue(priv->netdev);
+#endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
+			queue_work(priv->phandle->workqueue,
+				   &priv->phandle->main_work);
+			break;
+		case MLAN_STATUS_SUCCESS:
+			priv->stats.tx_packets++;
+			priv->stats.tx_bytes += skb->len;
+			dev_kfree_skb_any(skb);
+			break;
+		case MLAN_STATUS_FAILURE:
+		default:
+			priv->stats.tx_dropped++;
+			dev_kfree_skb_any(skb);
+			break;
+		}
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function send the tcp ack
+ *
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param tcp_session  A pointer to tcp_session
+ *  @return         N/A
+ */
+static void
+woal_send_tcp_ack(moal_private *priv, struct tcp_sess *tcp_session)
+{
+	mlan_status status;
+	struct sk_buff *skb = (struct sk_buff *)tcp_session->ack_skb;
+	mlan_buffer *pmbuf = (mlan_buffer *)tcp_session->pmbuf;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	t_u32 index = 0;
+#endif
+	ENTER();
+	if (tcp_session->is_timer_set) {
+		woal_cancel_timer(&tcp_session->ack_timer);
+		tcp_session->is_timer_set = MFALSE;
+	}
+	tcp_session->ack_skb = NULL;
+	tcp_session->pmbuf = NULL;
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+		index = skb_get_queue_mapping(skb);
+		atomic_inc(&priv->wmm_tx_pending[index]);
+		if (atomic_read(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
+			struct netdev_queue *txq =
+				netdev_get_tx_queue(priv->netdev, index);
+			netif_tx_stop_queue(txq);
+			moal_tp_accounting_rx_param((t_void *)priv->phandle, 8,
+						    0);
+			PRINTM(MINFO, "Stop Kernel Queue : %d\n", index);
+		}
+#else
+		if (atomic_read(&priv->phandle->tx_pending) >= MAX_TX_PENDING)
+			woal_stop_queue(priv->netdev);
+#endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len;
+		dev_kfree_skb_any(skb);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		priv->stats.tx_dropped++;
+		dev_kfree_skb_any(skb);
+		break;
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief This function get the tcp ack session node
+ *
+ *  @param priv      A pointer to moal_private structure
+ *  @param pmbuf     A pointer to mlan_buffer associated with a skb
+ *
+ *  @return          1, if it's dropped; 0, if not dropped
+ */
+static int
+woal_process_tcp_ack(moal_private *priv, mlan_buffer *pmbuf)
+{
+	int ret = 0;
+	unsigned long flags;
+	struct tcp_sess *tcp_session;
+	struct ethhdr *ethh = NULL;
+	struct iphdr *iph = NULL;
+	struct tcphdr *tcph = NULL;
+	t_u32 ack_seq;
+	struct sk_buff *skb;
+
+	ENTER();
+
+	/** check the tcp packet */
+	ethh = (struct ethhdr *)(pmbuf->pbuf + pmbuf->data_offset);
+	if (ntohs(ethh->h_proto) != ETH_P_IP) {
+		LEAVE();
+		return 0;
+	}
+	iph = (struct iphdr *)((t_u8 *)ethh + sizeof(struct ethhdr));
+	if (iph->protocol != IPPROTO_TCP) {
+		LEAVE();
+		return 0;
+	}
+	tcph = (struct tcphdr *)((t_u8 *)iph + iph->ihl * 4);
+
+	if (*((t_u8 *)tcph + 13) == 0x10) {
+		/* Only replace ACK */
+		if (ntohs(iph->tot_len) > (iph->ihl + tcph->doff) * 4) {
+			priv->tcp_ack_payload++;
+			/* Don't drop ACK with payload */
+			/* TODO: should we delete previous TCP session */
+			LEAVE();
+			return ret;
+		}
+		priv->tcp_ack_cnt++;
+		spin_lock_irqsave(&priv->tcp_sess_lock, flags);
+		tcp_session =
+			woal_get_tcp_sess(priv, (__force t_u32)iph->saddr,
+					  (__force t_u16)tcph->source,
+					  (__force t_u32)iph->daddr,
+					  (__force t_u16)tcph->dest);
+		if (!tcp_session) {
+			tcp_session =
+				kmalloc(sizeof(struct tcp_sess), GFP_ATOMIC);
+			if (!tcp_session) {
+				PRINTM(MERROR, "Fail to allocate tcp_sess.\n");
+				spin_unlock_irqrestore(&priv->tcp_sess_lock,
+						       flags);
+				goto done;
+			}
+			tcp_session->ack_skb = pmbuf->pdesc;
+			tcp_session->pmbuf = pmbuf;
+			pmbuf->flags |= MLAN_BUF_FLAG_TCP_ACK;
+			tcp_session->src_ip_addr = (__force t_u32)iph->saddr;
+			tcp_session->dst_ip_addr = (__force t_u32)iph->daddr;
+			tcp_session->src_tcp_port = (__force t_u32)tcph->source;
+			tcp_session->dst_tcp_port = (__force t_u32)tcph->dest;
+			tcp_session->ack_seq = ntohl(tcph->ack_seq);
+			tcp_session->priv = (void *)priv;
+			skb = (struct sk_buff *)pmbuf->pdesc;
+			skb->cb[0] = 0;
+			/* Initialize the timer for tcp ack */
+			woal_initialize_timer(&tcp_session->ack_timer,
+					      woal_tcp_ack_timer_func,
+					      tcp_session);
+			tcp_session->is_timer_set = MTRUE;
+			woal_mod_timer(&tcp_session->ack_timer, MOAL_TIMER_1MS);
+			list_add_tail(&tcp_session->link,
+				      &priv->tcp_sess_queue);
+			spin_unlock_irqrestore(&priv->tcp_sess_lock, flags);
+			ret = HOLD_TCP_ACK;
+			LEAVE();
+			return ret;
+		} else if (!tcp_session->ack_skb) {
+			tcp_session->ack_skb = pmbuf->pdesc;
+			tcp_session->pmbuf = pmbuf;
+			pmbuf->flags |= MLAN_BUF_FLAG_TCP_ACK;
+			tcp_session->ack_seq = ntohl(tcph->ack_seq);
+			tcp_session->priv = (void *)priv;
+			skb = (struct sk_buff *)pmbuf->pdesc;
+			skb->cb[0] = 0;
+			tcp_session->is_timer_set = MTRUE;
+			woal_mod_timer(&tcp_session->ack_timer, MOAL_TIMER_1MS);
+			spin_unlock_irqrestore(&priv->tcp_sess_lock, flags);
+			ret = HOLD_TCP_ACK;
+			LEAVE();
+			return ret;
+		}
+		ack_seq = ntohl(tcph->ack_seq);
+		skb = (struct sk_buff *)tcp_session->ack_skb;
+		if (likely(ack_seq > tcp_session->ack_seq) &&
+		    (skb->len == pmbuf->data_len)) {
+			moal_memcpy_ext(priv->phandle, skb->data,
+					pmbuf->pbuf + pmbuf->data_offset,
+					pmbuf->data_len, skb->len);
+			tcp_session->ack_seq = ack_seq;
+			ret = DROP_TCP_ACK;
+			skb->cb[0]++;
+			if (skb->cb[0] >= priv->tcp_ack_max_hold)
+				woal_send_tcp_ack(priv, tcp_session);
+			spin_unlock_irqrestore(&priv->tcp_sess_lock, flags);
+			skb = (struct sk_buff *)pmbuf->pdesc;
+			dev_kfree_skb_any(skb);
+			priv->tcp_ack_drop_cnt++;
+		} else {
+			pmbuf->flags |= MLAN_BUF_FLAG_TCP_ACK;
+			spin_unlock_irqrestore(&priv->tcp_sess_lock, flags);
+			LEAVE();
+			return ret;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles packet transmission
+ *
+ *  @param skb     A pointer to sk_buff structure
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        0 --success
+ */
+static int
+woal_start_xmit(moal_private *priv, struct sk_buff *skb)
+{
+	mlan_buffer *pmbuf = NULL;
+	mlan_status status;
+	struct sk_buff *new_skb = NULL;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	t_u32 index = 0;
+#endif
+	int ret = 0;
+
+	ENTER();
+
+	priv->num_tx_timeout = 0;
+	if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
+		PRINTM(MERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
+		       ETH_FRAME_LEN);
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		goto done;
+	}
+	//kernel crash with cloned skb without copy
+	//2 AGO case
+	//uap0  <-->muap0 bridge
+	if (moal_extflg_isset(priv->phandle, EXT_TX_SKB_CLONE) ||
+	    skb->cloned ||
+	    (skb_headroom(skb) <
+	     (MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
+	      priv->extra_tx_head_len))) {
+		PRINTM(MINFO,
+		       "Tx: skb cloned %d skb headroom %d tx_skb_clone=%d \n",
+		       skb->cloned, skb_headroom(skb),
+		       moal_extflg_isset(priv->phandle, EXT_TX_SKB_CLONE));
+		/* Insufficient skb headroom - allocate a new skb */
+		new_skb =
+			skb_realloc_headroom(skb,
+					     MLAN_MIN_DATA_HEADER_LEN +
+					     sizeof(mlan_buffer) +
+					     priv->extra_tx_head_len);
+		moal_tp_accounting_rx_param((t_void *)priv->phandle, 7, 0);
+		if (unlikely(!new_skb)) {
+			PRINTM(MERROR, "Tx: Cannot allocate skb\n");
+			dev_kfree_skb_any(skb);
+			priv->stats.tx_dropped++;
+			goto done;
+		}
+		if (new_skb != skb)
+			dev_kfree_skb_any(skb);
+		skb = new_skb;
+
+		PRINTM(MINFO, "new skb headroom %d\n", skb_headroom(skb));
+	}
+	pmbuf = (mlan_buffer *)skb->head;
+	memset((t_u8 *)pmbuf, 0, sizeof(mlan_buffer));
+	pmbuf->bss_index = priv->bss_index;
+	woal_fill_mlan_buffer(priv, pmbuf, skb);
+
+	if (priv->enable_tcp_ack_enh == MTRUE) {
+		ret = woal_process_tcp_ack(priv, pmbuf);
+		if (ret)
+			goto done;
+	}
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (priv->enable_auto_tdls && priv->tdls_check_tx)
+		woal_tdls_check_tx(priv, skb);
+#endif
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	index = skb_get_queue_mapping(skb);
+#endif
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		if (is_zero_timeval(priv->phandle->tx_time_start)) {
+			priv->phandle->tx_time_start.time_sec =
+				pmbuf->in_ts_sec;
+			priv->phandle->tx_time_start.time_usec =
+				pmbuf->in_ts_usec;
+			PRINTM(MINFO, "%s : start_timeval=%d:%d \n", __func__,
+			       priv->phandle->tx_time_start.time_sec,
+			       priv->phandle->tx_time_start.time_usec);
+		}
+		atomic_inc(&priv->phandle->tx_pending);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+		atomic_inc(&priv->wmm_tx_pending[index]);
+		if (atomic_read(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
+			struct netdev_queue *txq =
+				netdev_get_tx_queue(priv->netdev, index);
+			netif_tx_stop_queue(txq);
+			moal_tp_accounting_rx_param((t_void *)priv->phandle, 8,
+						    0);
+			PRINTM(MINFO, "Stop Kernel Queue : %d\n", index);
+		}
+#else
+		if (atomic_read(&priv->phandle->tx_pending) >= MAX_TX_PENDING)
+			woal_stop_queue(priv->netdev);
+#endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
+
+		if (!mlan_is_main_process_running(priv->phandle->pmlan_adapter))
+			 queue_work(priv->phandle->workqueue,
+				    &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len;
+		dev_kfree_skb_any(skb);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		priv->stats.tx_dropped++;
+		dev_kfree_skb_any(skb);
+		break;
+	}
+done:
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief This function handles packet transmission
+ *
+ *  @param skb     A pointer to sk_buff structure
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        0 --success
+ */
+netdev_tx_t
+woal_hard_start_xmit(struct sk_buff * skb, struct net_device * dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	ENTER();
+	PRINTM(MDATA, "%lu : %s (bss=%d): Data <= kernel\n", jiffies, dev->name,
+	       priv->bss_index);
+
+	/* Collect TP statistics */
+	if (priv->phandle->tp_acnt.on)
+		moal_tp_accounting(priv->phandle, skb, 1);
+	/* Drop Tx packets at drop point 1 */
+	if (priv->phandle->tp_acnt.drop_point == 1) {
+		dev_kfree_skb_any(skb);
+		LEAVE();
+		return 0;
+	}
+	if (priv->phandle->surprise_removed == MTRUE) {
+		dev_kfree_skb_any(skb);
+		priv->stats.tx_dropped++;
+		goto done;
+	}
+	if (moal_extflg_isset(priv->phandle, EXT_TX_WORK)) {
+
+		spin_lock_bh(&(priv->tx_q.lock));
+		__skb_queue_tail(&(priv->tx_q), skb);
+		spin_unlock_bh(&(priv->tx_q.lock));
+
+		queue_work(priv->phandle->tx_workqueue,
+			   &priv->phandle->tx_work);
+		goto done;
+	}
+	woal_start_xmit(priv, skb);
+done:
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Convert ascii string to Hex integer
+ *
+ *  @param d        A pointer to integer buf
+ *  @param s        A pointer to ascii string
+ *  @param dlen     The byte number of ascii string in hex
+ *
+ *  @return         Number of integer
+ */
+int
+woal_ascii2hex(t_u8 *d, char *s, t_u32 dlen)
+{
+	unsigned int i;
+	t_u8 n;
+
+	ENTER();
+
+	memset(d, 0x00, dlen);
+
+	for (i = 0; i < dlen * 2; i++) {
+		if ((s[i] >= 48) && (s[i] <= 57))
+			n = s[i] - 48;
+		else if ((s[i] >= 65) && (s[i] <= 70))
+			n = s[i] - 55;
+		else if ((s[i] >= 97) && (s[i] <= 102))
+			n = s[i] - 87;
+		else
+			break;
+		if (!(i % 2))
+			n = n * 16;
+		d[i / 2] += n;
+	}
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Return integer value of a given ascii string
+ *
+ *  @param data    Converted data to be returned
+ *  @param a       String to be converted
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_atoi(int *data, char *a)
+{
+	int i, val = 0, len;
+	int mul = 1;
+
+	ENTER();
+
+	len = strlen(a);
+	if (len > 2) {
+		if (!strncmp(a, "0x", 2)) {
+			a = a + 2;
+			len -= 2;
+			*data = woal_atox(a);
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	}
+	for (i = 0; i < len; i++) {
+		if (isdigit(a[i])) {
+			val = val * 10 + (a[i] - '0');
+		} else {
+			if ((i == 0) && (a[i] == '-')) {
+				mul = -1;
+			} else {
+				PRINTM(MERROR, "Invalid char %c in string %s\n",
+				       a[i], a);
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+		}
+	}
+	*data = (mul * val);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Return hex value of a given ascii string
+ *
+ *  @param a        String to be converted to ascii
+ *
+ *  @return         The converted character if a is a valid hex, else 0
+ */
+int
+woal_atox(char *a)
+{
+	int i = 0;
+
+	ENTER();
+
+	while (isxdigit(*a))
+		i = i * 16 + woal_hexval(*a++);
+
+	LEAVE();
+	return i;
+}
+
+/**
+ *  @brief Extension of strsep lib command. This function will also take care
+ *      escape character
+ *
+ *  @param s         A pointer to array of chars to process
+ *  @param delim     The delimiter character to end the string
+ *  @param esc       The escape character to ignore for delimiter
+ *
+ *  @return          Pointer to the separated string if delim found, else NULL
+ */
+char *
+woal_strsep(char **s, char delim, char esc)
+{
+	char *se = *s, *sb;
+
+	ENTER();
+
+	if (!(*s) || (*se == '\0')) {
+		LEAVE();
+		return NULL;
+	}
+
+	for (sb = *s; *sb != '\0'; ++sb) {
+		if (*sb == esc && *(sb + 1) == esc) {
+			/*
+			 * We get a esc + esc seq then keep the one esc
+			 * and chop off the other esc character
+			 */
+			memmove(sb, sb + 1, strlen(sb));
+			continue;
+		}
+		if (*sb == esc && *(sb + 1) == delim) {
+			/*
+			 * We get a delim + esc seq then keep the delim
+			 * and chop off the esc character
+			 */
+			memmove(sb, sb + 1, strlen(sb));
+			continue;
+		}
+		if (*sb == delim)
+			break;
+	}
+
+	if (*sb == '\0')
+		sb = NULL;
+	else
+		*sb++ = '\0';
+
+	*s = sb;
+
+	LEAVE();
+	return se;
+}
+
+/**
+ *  @brief Convert mac address from string to t_u8 buffer.
+ *
+ *  @param mac_addr The buffer to store the mac address in.
+ *  @param buf      The source of mac address which is a string.
+ *
+ *  @return         N/A
+ */
+void
+woal_mac2u8(t_u8 *mac_addr, char *buf)
+{
+	char *begin, *end, *mac_buff;
+	int i;
+
+	ENTER();
+
+	if (!buf) {
+		LEAVE();
+		return;
+	}
+
+	mac_buff = kzalloc(strlen(buf) + 1, GFP_KERNEL);
+	if (!mac_buff) {
+		LEAVE();
+		return;
+	}
+	moal_memcpy_ext(NULL, mac_buff, buf, strlen(buf), strlen(buf) + 1);
+
+	begin = mac_buff;
+	for (i = 0; i < ETH_ALEN; ++i) {
+		end = woal_strsep(&begin, ':', '/');
+		if (end)
+			mac_addr[i] = woal_atox(end);
+	}
+
+	kfree(mac_buff);
+	LEAVE();
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief This function sets multicast addresses to firmware
+ *
+ *  @param dev     A pointer to net_device structure
+ *
+ *  @return        N/A
+ */
+void
+woal_set_multicast_list(struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	ENTER();
+	queue_work(priv->mclist_workqueue, &priv->mclist_work);
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief This function initializes the private structure
+ *          and set default value to the member of moal_private.
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *
+ *  @return                 N/A
+ */
+void
+woal_init_priv(moal_private *priv, t_u8 wait_option)
+{
+
+	ENTER();
+#ifdef STA_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		priv->current_key_index = 0;
+		priv->rate_index = AUTO_RATE;
+		priv->is_adhoc_link_sensed = MFALSE;
+		priv->scan_type = MLAN_SCAN_TYPE_ACTIVE;
+		priv->bg_scan_start = MFALSE;
+		priv->bg_scan_reported = MFALSE;
+		priv->sched_scanning = MFALSE;
+#ifdef STA_CFG80211
+		priv->roaming_enabled = MFALSE;
+		priv->roaming_required = MFALSE;
+#endif
+
+		memset(&priv->nick_name, 0, sizeof(priv->nick_name));
+		priv->num_tx_timeout = 0;
+		priv->rx_filter = 0;
+
+#ifdef REASSOCIATION
+		priv->reassoc_on = MFALSE;
+		priv->set_asynced_essid_flag = MFALSE;
+#endif
+#ifdef STA_CFG80211
+		memset(&priv->sme_current, 0,
+		       sizeof(struct cfg80211_connect_params));
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		woal_init_wifi_hal(priv);
+#endif
+	}
+#endif /* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		priv->bss_started = MFALSE;
+		priv->uap_host_based = MFALSE;
+		priv->skip_cac = MFALSE;
+
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		memset(&priv->chan, 0, sizeof(struct cfg80211_chan_def));
+		memset(&priv->csa_chan, 0, sizeof(struct cfg80211_chan_def));
+		priv->uap_tx_blocked = MFALSE;
+		memset(&priv->beacon_after, 0,
+		       sizeof(struct cfg80211_beacon_data));
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		woal_init_wifi_hal(priv);
+#endif
+#endif
+
+	}
+#endif
+
+	skb_queue_head_init(&priv->tx_q);
+	memset(&priv->tx_protocols, 0, sizeof(dot11_protocol));
+	memset(&priv->rx_protocols, 0, sizeof(dot11_protocol));
+	priv->media_connected = MFALSE;
+
+	memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	priv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->beacon_wps_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->assocresp_qos_map_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->beacon_vendor_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
+	priv->mgmt_subtype_mask = 0;
+	priv->cfg_disconnect = MFALSE;
+	priv->cfg_connect = MFALSE;
+#endif
+#ifdef STA_SUPPORT
+#endif
+
+	priv->enable_tcp_ack_enh = MTRUE;
+	priv->tcp_ack_drop_cnt = 0;
+	priv->tcp_ack_cnt = 0;
+	priv->tcp_ack_payload = 0;
+	priv->tcp_ack_max_hold = TCP_ACK_MAX_HOLD;
+
+	priv->enable_auto_tdls = MFALSE;
+	priv->tdls_check_tx = MFALSE;
+
+	priv->gtk_data_ready = MFALSE;
+	memset(&priv->gtk_rekey_data, 0, sizeof(mlan_ds_misc_gtk_rekey_data));
+
+	woal_request_get_fw_info(priv, wait_option, NULL);
+
+	/* Set MAC address from the insmod command line */
+	if (priv->phandle->set_mac_addr) {
+		memset(priv->current_addr, 0, ETH_ALEN);
+		moal_memcpy_ext(priv->phandle, priv->current_addr,
+				priv->phandle->mac_addr, ETH_ALEN, ETH_ALEN);
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+#ifdef MFG_CMD_SUPPORT
+	if (priv->phandle->params.mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+			if (priv->bss_virtual) {
+				if (priv->pa_netdev) {
+					moal_memcpy_ext(priv->phandle,
+							priv->current_addr,
+							priv->pa_netdev->
+							dev_addr, ETH_ALEN,
+							ETH_ALEN);
+					priv->current_addr[4] ^= 0x80;
+					if (priv->phandle->second_mac)
+						priv->current_addr[5] ^= 0x80;
+					PRINTM(MCMND,
+					       "Set WFD interface addr: " MACSTR
+					       "\n",
+					       MAC2STR(priv->current_addr));
+				}
+			} else {
+				priv->current_addr[0] |= 0x02;
+				PRINTM(MCMND,
+				       "Set WFD device addr: " MACSTR "\n",
+				       MAC2STR(priv->current_addr));
+			}
+		}
+#endif
+#endif
+#endif
+
+	/* Set MAC address for UAPx/MLANx/WFDx/OCBx and let them
+	 * different with each other */
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
+#endif
+	{
+		priv->current_addr[4] += priv->bss_index;
+		PRINTM(MCMND, "Set %s interface addr: " MACSTR "\n",
+		       priv->netdev->name, MAC2STR(priv->current_addr));
+	}
+
+	woal_request_set_mac_address(priv, MOAL_IOCTL_WAIT);
+	moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
+			priv->current_addr, ETH_ALEN, ETH_ALEN);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	priv->host_mlme = 0;
+	priv->auth_flag = 0;
+	priv->auth_alg = 0xFFFF;
+#endif
+
+#ifdef UAP_SUPPORT
+	priv->trans_chan = 0;
+	priv->user_cac_period_msec = 0;
+	priv->chan_under_nop = MFALSE;
+#endif
+	LEAVE();
+}
+
+/**
+ *  @brief Reset all interfaces if all_intf flag is TRUE,
+ *          otherwise specified interface only
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option   Wait option
+ *  @param all_intf      TRUE  : all interfaces
+ *                       FALSE : current interface only
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int
+woal_reset_intf(moal_private *priv, t_u8 wait_option, int all_intf)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	int intf_num;
+	moal_handle *handle = NULL;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle = priv->phandle;
+
+	if (handle->rf_test_mode)
+		woal_process_rf_test_mode(handle, MFG_CMD_UNSET_TEST_MODE);
+#ifdef STA_SUPPORT
+	woal_cancel_scan(priv, wait_option);
+#endif
+
+	/* Stop queue and detach device */
+	if (!all_intf) {
+		woal_stop_queue(priv->netdev);
+		netif_device_detach(priv->netdev);
+	} else {
+		for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+			woal_stop_queue(handle->priv[intf_num]->netdev);
+			netif_device_detach(handle->priv[intf_num]->netdev);
+		}
+	}
+
+	/* Get BSS info */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, wait_option, &bss_info);
+
+	/* Cancel host sleep */
+	if (bss_info.is_hs_configured) {
+		if (MLAN_STATUS_SUCCESS != woal_cancel_hs(priv, wait_option)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	/* Disconnect from network */
+	if (!all_intf) {
+		/* Disconnect specified interface only */
+		if ((priv->media_connected == MTRUE)
+#ifdef UAP_SUPPORT
+		    || (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
+#endif
+			) {
+			woal_disconnect(priv, wait_option, NULL,
+					DEF_DEAUTH_REASON_CODE);
+			priv->media_connected = MFALSE;
+		}
+	} else {
+		/* Disconnect all interfaces */
+		for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+			if (handle->priv[intf_num]->media_connected == MTRUE
+#ifdef UAP_SUPPORT
+			    || (GET_BSS_ROLE(handle->priv[intf_num]) ==
+				MLAN_BSS_ROLE_UAP)
+#endif
+				) {
+				woal_disconnect(handle->priv[intf_num],
+						wait_option, NULL,
+						DEF_DEAUTH_REASON_CODE);
+				handle->priv[intf_num]->media_connected =
+					MFALSE;
+			}
+		}
+	}
+
+#ifdef REASSOCIATION
+	/* Reset the reassoc timer and status */
+	if (!all_intf) {
+		handle->reassoc_on &= ~MBIT(priv->bss_index);
+		priv->reassoc_on = MFALSE;
+		priv->set_asynced_essid_flag = MFALSE;
+	} else {
+		handle->reassoc_on = 0;
+		for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+			handle->priv[intf_num]->reassoc_on = MFALSE;
+			handle->priv[intf_num]->set_asynced_essid_flag = MFALSE;
+		}
+	}
+	if (!handle->reassoc_on && handle->is_reassoc_timer_set) {
+		woal_cancel_timer(&handle->reassoc_timer);
+		handle->is_reassoc_timer_set = MFALSE;
+	}
+#endif /* REASSOCIATION */
+
+	if (handle->is_fw_dump_timer_set) {
+		woal_cancel_timer(&handle->fw_dump_timer);
+		handle->is_fw_dump_timer_set = MFALSE;
+	}
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	if (handle->is_go_timer_set) {
+		woal_cancel_timer(&handle->go_timer);
+		handle->is_go_timer_set = MFALSE;
+	}
+#endif
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	if (handle->is_remain_timer_set) {
+		woal_cancel_timer(&handle->remain_timer);
+		woal_remain_timer_func(handle);
+	}
+#endif
+#endif
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function return the point to structure moal_private
+ *
+ *  @param handle       Pointer to structure moal_handle
+ *  @param bss_index    BSS index number
+ *
+ *  @return             moal_private pointer or NULL
+ */
+moal_private *
+woal_bss_index_to_priv(moal_handle *handle, t_u8 bss_index)
+{
+	int i;
+
+	ENTER();
+	if (!handle) {
+		LEAVE();
+		return NULL;
+	}
+	for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
+		if (handle->priv[i] &&
+		    (handle->priv[i]->bss_index == bss_index)) {
+			LEAVE();
+			return handle->priv[i];
+		}
+	}
+
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function alloc mlan_buffer.
+ *  @param handle  A pointer to moal_handle structure
+ *  @param size	   buffer size to allocate
+ *
+ *  @return        mlan_buffer pointer or NULL
+ */
+pmlan_buffer
+woal_alloc_mlan_buffer(moal_handle *handle, int size)
+{
+	mlan_buffer *pmbuf = NULL;
+	struct sk_buff *skb;
+	gfp_t flag;
+
+	ENTER();
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	if (size <= 0) {
+		PRINTM(MERROR, "Buffer size must be positive\n");
+		LEAVE();
+		return NULL;
+	}
+
+	skb = __dev_alloc_skb(size + sizeof(mlan_buffer), flag);
+	if (!skb) {
+		PRINTM(MERROR, "%s: No free skb\n", __func__);
+		LEAVE();
+		return NULL;
+	}
+	skb_reserve(skb, sizeof(mlan_buffer));
+	pmbuf = (mlan_buffer *)skb->head;
+	memset((u8 *)pmbuf, 0, sizeof(mlan_buffer));
+	pmbuf->pdesc = (t_void *)skb;
+	pmbuf->pbuf = (t_u8 *)skb->data;
+	atomic_inc(&handle->mbufalloc_count);
+	LEAVE();
+	return pmbuf;
+}
+
+/**
+ *  @brief This function alloc mlan_ioctl_req.
+ *
+ *  @param size	   buffer size to allocate
+ *
+ *  @return        mlan_ioctl_req pointer or NULL
+ */
+pmlan_ioctl_req
+woal_alloc_mlan_ioctl_req(int size)
+{
+	mlan_ioctl_req *req = NULL;
+	gfp_t flag;
+
+	ENTER();
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	req = kzalloc((sizeof(mlan_ioctl_req) + size + sizeof(int) +
+		       sizeof(wait_queue)), flag);
+	if (!req) {
+		PRINTM(MERROR, "%s: Fail to alloc ioctl buffer\n", __func__);
+		LEAVE();
+		return NULL;
+	}
+	req->pbuf = (t_u8 *)req + sizeof(mlan_ioctl_req) + sizeof(wait_queue);
+	req->buf_len = (t_u32)size;
+	req->reserved_1 = (t_ptr)((t_u8 *)req + sizeof(mlan_ioctl_req));
+
+	LEAVE();
+	return req;
+}
+
+/**
+ *  @brief This function frees mlan_buffer.
+ *  @param handle  A pointer to moal_handle structure
+ *  @param pmbuf   Pointer to mlan_buffer
+ *
+ *  @return        N/A
+ */
+void
+woal_free_mlan_buffer(moal_handle *handle, pmlan_buffer pmbuf)
+{
+	ENTER();
+	if (!pmbuf) {
+		LEAVE();
+		return;
+	}
+	if (pmbuf->pdesc)
+		dev_kfree_skb_any((struct sk_buff *)pmbuf->pdesc);
+	else
+		PRINTM(MERROR, "free mlan buffer without pdesc\n");
+	atomic_dec(&handle->mbufalloc_count);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function get card info from card type
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static int
+woal_get_card_info(moal_handle *phandle)
+{
+	int ret = 0;
+
+	ENTER();
+
+	switch (phandle->card_type) {
+#ifdef SD8801
+	case CARD_TYPE_SD8801:
+		phandle->card_info = &card_info_SD8801;
+		break;
+#endif
+#ifdef SD8887
+	case CARD_TYPE_SD8887:
+		phandle->card_info = &card_info_SD8887;
+		break;
+#endif
+#if defined(SD8897)
+	case CARD_TYPE_SD8897:
+		phandle->card_info = &card_info_SD8897;
+		break;
+#endif
+#if defined(PCIE8897)
+	case CARD_TYPE_PCIE8897:
+		phandle->card_info = &card_info_PCIE8897;
+		break;
+#endif
+#if defined(USB8897)
+	case CARD_TYPE_USB8897:
+		phandle->card_info = &card_info_USB8897;
+		break;
+#endif
+#ifdef SD8977
+	case CARD_TYPE_SD8977:
+		phandle->card_info = &card_info_SD8977;
+		break;
+#endif
+#ifdef SD8978
+	case CARD_TYPE_SD8978:
+		phandle->card_info = &card_info_SD8978;
+		break;
+#endif
+#ifdef SD8997
+	case CARD_TYPE_SD8997:
+		phandle->card_info = &card_info_SD8997;
+		break;
+#endif
+#ifdef SD9098
+	case CARD_TYPE_SD9098:
+		phandle->card_info = &card_info_SD9098;
+		break;
+#endif
+#ifdef SD9097
+	case CARD_TYPE_SD9097:
+		phandle->card_info = &card_info_SD9097;
+		break;
+#endif
+#ifdef SD9177
+	case CARD_TYPE_SD9177:
+		phandle->card_info = &card_info_SD9177;
+		phandle->event_fw_dump = MFALSE;
+		break;
+#endif
+#ifdef PCIE8997
+	case CARD_TYPE_PCIE8997:
+		phandle->card_info = &card_info_PCIE8997;
+		break;
+#endif
+#ifdef PCIE9097
+	case CARD_TYPE_PCIE9097:
+		phandle->card_info = &card_info_PCIE9097;
+		break;
+#endif
+#ifdef PCIE9098
+	case CARD_TYPE_PCIE9098:
+		phandle->card_info = &card_info_PCIE9098;
+		phandle->event_fw_dump = MTRUE;
+		break;
+#endif
+#ifdef USB8801
+	case CARD_TYPE_USB8801:
+		phandle->card_info = &card_info_USB8801;
+		break;
+#endif
+#ifdef USB8997
+	case CARD_TYPE_USB8997:
+		phandle->card_info = &card_info_USB8997;
+		break;
+#endif
+#ifdef USB8978
+	case CARD_TYPE_USB8978:
+		phandle->card_info = &card_info_USB8978;
+		break;
+#endif
+#ifdef USB9098
+	case CARD_TYPE_USB9098:
+		phandle->card_info = &card_info_USB9098;
+		break;
+#endif
+#ifdef USB9097
+	case CARD_TYPE_USB9097:
+		phandle->card_info = &card_info_USB9097;
+		break;
+#endif
+#ifdef SD8987
+	case CARD_TYPE_SD8987:
+		phandle->card_info = &card_info_SD8987;
+		break;
+#endif
+	default:
+		PRINTM(MERROR,
+		       "woal_get_card_info can't get right card type \n");
+		ret = -1;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef STA_SUPPORT
+#endif /* STA_SUPPORT */
+
+/**
+ *  @brief This function handles events generated by firmware
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param payload  A pointer to payload buffer
+ *  @param len      Length of the payload
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_broadcast_event(moal_private *priv, t_u8 *payload, t_u32 len)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	struct nlmsghdr *nlh = NULL;
+	moal_handle *handle = priv->phandle;
+	struct net_device *netdev = priv->netdev;
+	struct sock *sk = handle->nl_sk;
+
+	ENTER();
+
+	/* interface name to be prepended to event */
+	if ((len + IFNAMSIZ) > NL_MAX_PAYLOAD
+#ifdef WIFI_DIRECT_SUPPORT
+	    * 2
+#endif
+		) {
+		PRINTM(MERROR, "event size is too big, len=%d\n", (int)len);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (sk) {
+		/* Allocate skb */
+#ifdef WIFI_DIRECT_SUPPORT
+		if ((len + IFNAMSIZ) > NL_MAX_PAYLOAD) {
+			skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD * 2),
+					GFP_ATOMIC);
+			if (!skb) {
+				PRINTM(MERROR,
+				       "Could not allocate skb for netlink\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		} else {
+#endif
+			skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD),
+					GFP_ATOMIC);
+			if (!skb) {
+				PRINTM(MERROR,
+				       "Could not allocate skb for netlink\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+#ifdef WIFI_DIRECT_SUPPORT
+		}
+#endif
+		memset(skb->data, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
+
+		nlh = (struct nlmsghdr *)skb->data;
+		nlh->nlmsg_len = NLMSG_SPACE(len + IFNAMSIZ);
+
+		/* From kernel */
+		nlh->nlmsg_pid = 0;
+		nlh->nlmsg_flags = 0;
+
+		/* Data */
+		skb_put(skb, nlh->nlmsg_len);
+		moal_memcpy_ext(handle, NLMSG_DATA(nlh), netdev->name, IFNAMSIZ,
+				nlh->nlmsg_len - NLMSG_LENGTH(0));
+		moal_memcpy_ext(handle, ((t_u8 *)(NLMSG_DATA(nlh))) + IFNAMSIZ,
+				payload, len,
+				nlh->nlmsg_len - NLMSG_LENGTH(IFNAMSIZ));
+
+		/* From Kernel */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
+		NETLINK_CB(skb).pid = 0;
+#else
+		NETLINK_CB(skb).portid = 0;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+		/* Multicast message */
+		NETLINK_CB(skb).dst_pid = 0;
+#endif
+
+		/* Multicast group number */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+		NETLINK_CB(skb).dst_groups = NL_MULTICAST_GROUP;
+#else
+		NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP;
+#endif
+
+		/* Send message */
+		ret = netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP,
+					GFP_ATOMIC);
+		if (ret) {
+			PRINTM(MWARN, "netlink_broadcast failed: ret=%d\n",
+			       ret);
+			goto done;
+		}
+
+		ret = MLAN_STATUS_SUCCESS;
+	} else {
+		PRINTM(MERROR,
+		       "Could not send event through NETLINK. Link down.\n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef REASSOCIATION
+/**
+ *  @brief This function handles re-association. it is triggered
+ *  by re-assoc timer.
+ *
+ *  @param data    A pointer to wlan_thread structure
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+woal_reassociation_thread(void *data)
+{
+	moal_thread *pmoal_thread = data;
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)pmoal_thread->handle;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+	wait_queue_t wait;
+#else
+	wait_queue_entry_t wait;
+#endif
+	int i;
+	BOOLEAN reassoc_timer_req;
+	mlan_802_11_ssid req_ssid;
+	mlan_ssid_bssid ssid_bssid;
+	mlan_status status;
+	mlan_bss_info bss_info;
+	t_u32 timer_val = MOAL_TIMER_10S;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	ENTER();
+
+	woal_activate_thread(pmoal_thread);
+	init_waitqueue_entry(&wait, current);
+
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		add_wait_queue(&pmoal_thread->wait_q, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		schedule();
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&pmoal_thread->wait_q, &wait);
+#if defined(USB)
+		if (IS_USB(handle->card_type)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
+			try_to_freeze(0);	/* Argument is not used by the kernel
+						 */
+#else
+			try_to_freeze();
+#endif
+		}
+#endif
+
+		/* Cancel re-association timer */
+		if (handle->is_reassoc_timer_set == MTRUE) {
+			woal_cancel_timer(&handle->reassoc_timer);
+			handle->is_reassoc_timer_set = MFALSE;
+		}
+
+		if (handle->surprise_removed)
+			break;
+		if (kthread_should_stop())
+			break;
+
+		if (handle->hardware_status != HardwareStatusReady) {
+			PRINTM(MINFO,
+			       "Reassoc: Hardware status is not correct\n");
+			continue;
+		}
+
+		PRINTM(MEVENT, "Reassoc: Thread waking up...\n");
+		reassoc_timer_req = MFALSE;
+#ifdef STA_CFG80211
+		for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM) &&
+		     (priv = handle->priv[i]); i++) {
+			if (priv->roaming_required) {
+				priv->roaming_required = MFALSE;
+				PRINTM(MEVENT, "Try to roaming......\n");
+				woal_start_roaming(priv);
+				break;
+			}
+		}
+#endif
+
+		for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM) &&
+		     (priv = handle->priv[i]); i++) {
+			if (priv->reassoc_required == MFALSE) {
+				priv->set_asynced_essid_flag = MFALSE;
+				continue;
+			}
+
+			memset(&bss_info, 0x00, sizeof(bss_info));
+
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_get_bss_info(priv, MOAL_IOCTL_WAIT,
+					      &bss_info)) {
+				PRINTM(MINFO, "Ressoc: Fail to get bss info\n");
+				priv->reassoc_required = MFALSE;
+				priv->set_asynced_essid_flag = MFALSE;
+				continue;
+			}
+
+			if (bss_info.bss_mode != MLAN_BSS_MODE_INFRA ||
+			    priv->media_connected != MFALSE) {
+				PRINTM(MINFO,
+				       "Reassoc: ad-hoc mode or media connected\n");
+				priv->reassoc_required = MFALSE;
+				priv->set_asynced_essid_flag = MFALSE;
+				continue;
+			}
+			/** avoid on going scan from other thread */
+			if (handle->scan_pending_on_block) {
+				reassoc_timer_req = MTRUE;
+				break;
+			}
+
+			/* The semaphore is used to avoid reassociation
+			   thread and wlan_set_scan/wlan_set_essid
+			   interrupting each other. Reassociation should
+			   be disabled completely by application if
+			   wlan_set_user_scan_ioctl/wlan_set_wap is
+			   used.
+			 */
+			if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+				PRINTM(MERROR,
+				       "Acquire semaphore error, reassociation thread\n");
+				reassoc_timer_req = MTRUE;
+				break;
+			}
+
+			PRINTM(MINFO, "Reassoc: Required ESSID: %s\n",
+			       priv->prev_ssid_bssid.ssid.ssid);
+			PRINTM(MINFO, "Reassoc: Performing Active Scan\n");
+
+			memset(&req_ssid, 0x00, sizeof(mlan_802_11_ssid));
+			moal_memcpy_ext(priv->phandle, &req_ssid,
+					&priv->prev_ssid_bssid.ssid,
+					sizeof(mlan_802_11_ssid),
+					sizeof(mlan_802_11_ssid));
+
+			/* Do specific SSID scanning */
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_request_scan(priv, MOAL_IOCTL_WAIT,
+					      &req_ssid)) {
+				PRINTM(MERROR,
+				       "Reassoc: Fail to do specific scan\n");
+				reassoc_timer_req = MTRUE;
+				MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+				break;
+			}
+
+			if (handle->surprise_removed) {
+				MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+				break;
+			}
+
+			memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+			if (priv->set_asynced_essid_flag == MTRUE) {
+				if (priv->assoc_with_mac &&
+				    memcmp(priv->prev_ssid_bssid.bssid,
+					   zero_mac, MLAN_MAC_ADDR_LENGTH)) {
+					/* Search AP by BSSID & SSID */
+					PRINTM(MINFO,
+					       "Reassoc: Search AP by BSSID & SSID\n");
+					moal_memcpy_ext(priv->phandle,
+							&ssid_bssid.bssid,
+							&priv->prev_ssid_bssid.
+							bssid,
+							MLAN_MAC_ADDR_LENGTH,
+							sizeof
+							(mlan_802_11_mac_addr));
+				} else {
+					/* Search AP by ESSID for asynced essid
+					 * setting */
+					PRINTM(MINFO,
+					       "Set asynced essid: Search AP by ESSID\n");
+				}
+
+				moal_memcpy_ext(priv->phandle, &ssid_bssid.ssid,
+						&priv->prev_ssid_bssid.ssid,
+						sizeof(mlan_802_11_ssid),
+						sizeof(mlan_802_11_ssid));
+			} else {
+				/* Search AP by BSSID first */
+				PRINTM(MINFO,
+				       "Reassoc: Search AP by BSSID first\n");
+				moal_memcpy_ext(priv->phandle,
+						&ssid_bssid.bssid,
+						&priv->prev_ssid_bssid.bssid,
+						MLAN_MAC_ADDR_LENGTH,
+						sizeof(mlan_802_11_mac_addr));
+			}
+
+			status = woal_find_best_network(priv, MOAL_IOCTL_WAIT,
+							&ssid_bssid);
+#ifdef STA_WEXT
+			if (status == MLAN_STATUS_SUCCESS) {
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_11d_check_ap_channel(priv,
+							      MOAL_IOCTL_WAIT,
+							      &ssid_bssid)) {
+					PRINTM(MERROR,
+					       "Reassoc: The AP's channel is invalid for current region\n");
+					status = MLAN_STATUS_FAILURE;
+				}
+			}
+#endif
+			/** The find AP without ssid, we need re-search
+			 */
+			if (status == MLAN_STATUS_SUCCESS &&
+			    !ssid_bssid.ssid.ssid_len) {
+				PRINTM(MINFO,
+				       "Reassoc: Skip AP without ssid\n");
+				status = MLAN_STATUS_FAILURE;
+			}
+
+			if (priv->set_asynced_essid_flag != MTRUE &&
+			    MLAN_STATUS_SUCCESS != status) {
+				PRINTM(MINFO,
+				       "Reassoc: AP not found in scan list\n");
+				PRINTM(MINFO, "Reassoc: Search AP by SSID\n");
+				/* Search AP by SSID */
+				memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+				moal_memcpy_ext(priv->phandle, &ssid_bssid.ssid,
+						&priv->prev_ssid_bssid.ssid,
+						sizeof(mlan_802_11_ssid),
+						sizeof(mlan_802_11_ssid));
+				status = woal_find_best_network(priv,
+								MOAL_IOCTL_WAIT,
+								&ssid_bssid);
+#ifdef STA_WEXT
+				if (status == MLAN_STATUS_SUCCESS) {
+					if (MLAN_STATUS_SUCCESS !=
+					    woal_11d_check_ap_channel(priv,
+								      MOAL_IOCTL_WAIT,
+								      &ssid_bssid))
+					{
+						PRINTM(MERROR,
+						       "Reassoc: The AP's channel is invalid for current region\n");
+						status = MLAN_STATUS_FAILURE;
+					}
+				}
+#endif
+			}
+
+			if (status == MLAN_STATUS_SUCCESS) {
+				/* set the wep key */
+				if (bss_info.wep_status)
+					woal_enable_wep_key(priv,
+							    MOAL_IOCTL_WAIT);
+				/* Zero SSID implies use BSSID to
+				 * connect */
+				memset(&ssid_bssid.ssid, 0,
+				       sizeof(mlan_802_11_ssid));
+				status = woal_bss_start(priv, MOAL_IOCTL_WAIT,
+							&ssid_bssid);
+			}
+
+			if (priv->media_connected == MFALSE)
+				reassoc_timer_req = MTRUE;
+			else {
+				mlan_ds_rate *rate = NULL;
+				mlan_ioctl_req *req = NULL;
+
+				reassoc_timer_req = MFALSE;
+				if (priv->set_asynced_essid_flag == MTRUE) {
+					memset(&bss_info, 0, sizeof(bss_info));
+					if (MLAN_STATUS_SUCCESS !=
+					    woal_get_bss_info(priv,
+							      MOAL_IOCTL_WAIT,
+							      &bss_info)) {
+						PRINTM(MINFO,
+						       "Set asynced essid: Fail to get bss info after assoc\n");
+					} else {
+						moal_memcpy_ext(priv->phandle,
+								&priv->
+								prev_ssid_bssid.
+								ssid,
+								&bss_info.ssid,
+								sizeof
+								(mlan_802_11_ssid),
+								sizeof
+								(mlan_802_11_ssid));
+						moal_memcpy_ext(priv->phandle,
+								&priv->
+								prev_ssid_bssid.
+								bssid,
+								&bss_info.bssid,
+								MLAN_MAC_ADDR_LENGTH,
+								sizeof(priv->
+								       prev_ssid_bssid.
+								       bssid));
+					}
+					priv->set_asynced_essid_flag = MFALSE;
+				}
+				if (priv->rate_index != AUTO_RATE) {
+					req = woal_alloc_mlan_ioctl_req(sizeof
+									(mlan_ds_rate));
+
+					if (req == NULL) {
+						LEAVE();
+						return MLAN_STATUS_FAILURE;
+					}
+
+					rate = (mlan_ds_rate *)req->pbuf;
+					rate->param.rate_cfg.rate_type =
+						MLAN_RATE_INDEX;
+					rate->sub_command = MLAN_OID_RATE_CFG;
+					req->req_id = MLAN_IOCTL_RATE;
+
+					req->action = MLAN_ACT_SET;
+
+					rate->param.rate_cfg.rate =
+						priv->rate_index;
+
+					status = woal_request_ioctl(priv, req,
+								    MOAL_IOCTL_WAIT);
+					if (status != MLAN_STATUS_SUCCESS) {
+						if (status !=
+						    MLAN_STATUS_PENDING)
+							kfree(req);
+						LEAVE();
+						return MLAN_STATUS_FAILURE;
+					}
+					kfree(req);
+				}
+			}
+
+			MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+		}
+
+		if (handle->surprise_removed)
+			break;
+
+		if (reassoc_timer_req == MTRUE) {
+			handle->is_reassoc_timer_set = MTRUE;
+			if (priv && (priv->set_asynced_essid_flag == MTRUE)) {
+				PRINTM(MERROR,
+				       "Set Async ESSID: No AP found or assoc failed.\n");
+				priv->set_asynced_essid_flag = MFALSE;
+			} else {
+				PRINTM(MEVENT,
+				       "Reassoc: No AP found or assoc failed. "
+				       "Restarting re-assoc Timer: %d\n",
+				       (int)timer_val);
+				woal_mod_timer(&handle->reassoc_timer,
+					       timer_val);
+			}
+		} else {
+			if (priv) {
+				priv->set_asynced_essid_flag = MFALSE;
+			}
+		}
+	}
+	woal_deactivate_thread(pmoal_thread);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function triggers re-association by waking up
+ *  re-assoc thread.
+ *
+ *  @param context  A pointer to context
+ *  @return         N/A
+ */
+void
+woal_reassoc_timer_func(void *context)
+{
+	moal_handle *handle = (moal_handle *)context;
+
+	ENTER();
+
+	PRINTM(MINFO, "reassoc_timer fired.\n");
+	handle->is_reassoc_timer_set = MFALSE;
+
+	PRINTM(MINFO, "Waking Up the Reassoc Thread\n");
+	wake_up_interruptible(&handle->reassoc_thread.wait_q);
+
+	LEAVE();
+	return;
+}
+#endif /* REASSOCIATION */
+
+/**
+ *  @brief This function triggers process hang
+ *  re-assoc thread.
+ *
+ *  @param context  A pointer to context
+ *  @return         N/A
+ */
+void
+woal_fw_dump_timer_func(void *context)
+{
+	moal_handle *handle = (moal_handle *)context;
+
+	ENTER();
+
+	PRINTM(MMSG, "fw_dump_timer fired.\n");
+	handle->is_fw_dump_timer_set = MFALSE;
+	woal_process_hang(handle);
+	LEAVE();
+	return;
+}
+
+#ifdef STA_SUPPORT
+/**
+ *  @brief update dscp mapping from assoc_resp/reassoc_resp
+ *
+ *  @param priv      Pointer to the moal_private driver data struct
+ *
+ *  @return          N/A
+ */
+void
+woal_update_dscp_mapping(moal_private *priv)
+{
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+	IEEEtypes_AssocRsp_t *passoc_rsp = NULL;
+	IEEEtypes_Header_t *qos_mapping_ie = NULL;
+	DSCP_Range_t *pdscp_range = NULL;
+	t_u8 dscp_except_num = 0;
+	DSCP_Exception_t dscp_except[MAX_DSCP_EXCEPTION_NUM];
+	int i, j;
+	ENTER();
+
+	memset(&assoc_rsp, 0, sizeof(mlan_ds_misc_assoc_rsp));
+	woal_get_assoc_rsp(priv, &assoc_rsp, MOAL_NO_WAIT);
+	passoc_rsp = (IEEEtypes_AssocRsp_t *)assoc_rsp.assoc_resp_buf;
+	memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
+	qos_mapping_ie =
+		(IEEEtypes_Header_t *)woal_parse_ie_tlv(passoc_rsp->ie_buffer,
+							assoc_rsp.
+							assoc_resp_len -
+							ASSOC_RESP_FIXED_SIZE,
+							QOS_MAPPING);
+	if (qos_mapping_ie &&
+	    (qos_mapping_ie->len >= (sizeof(DSCP_Range_t) * MAX_NUM_TID))) {
+		dscp_except_num =
+			(qos_mapping_ie->len -
+			 sizeof(DSCP_Range_t) * MAX_NUM_TID) /
+			sizeof(DSCP_Exception_t);
+		if (dscp_except_num > MAX_DSCP_EXCEPTION_NUM) {
+			PRINTM(MERROR, "dscp_except_num exceeds MAX limit\n");
+			LEAVE();
+			return;
+		}
+		moal_memcpy_ext(priv->phandle, dscp_except,
+				(t_u8 *)qos_mapping_ie +
+				sizeof(IEEEtypes_Header_t),
+				dscp_except_num *
+				sizeof(DSCP_Exception_t), sizeof(dscp_except));
+		pdscp_range =
+			(DSCP_Range_t
+			 *)((t_u8 *)qos_mapping_ie +
+			    sizeof(IEEEtypes_Header_t) +
+			    dscp_except_num * sizeof(DSCP_Exception_t));
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			PRINTM(MEVENT,
+			       "TID %d: dscp_low=%d, dscp_high=%d\n", i,
+			       pdscp_range->dscp_low_value,
+			       pdscp_range->dscp_high_value);
+			if (pdscp_range->dscp_low_value != 0xff &&
+			    pdscp_range->dscp_high_value != 0xff &&
+			    pdscp_range->dscp_high_value <= 63) {
+				for (j = pdscp_range->dscp_low_value;
+				     j <= pdscp_range->dscp_high_value; j++)
+					priv->dscp_map[j] = i;
+			}
+			pdscp_range++;
+		}
+		for (i = 0; i < dscp_except_num; i++) {
+			if ((dscp_except[i].dscp_value <= 63) &&
+			    (dscp_except[i].user_priority <= 7)) {
+				PRINTM(MEVENT,
+				       "dscp excpt: value=%d priority=%d\n",
+				       dscp_except[i].dscp_value,
+				       dscp_except[i].user_priority);
+				priv->dscp_map[dscp_except[i]
+					       .dscp_value] =
+					dscp_except[i].user_priority;
+			}
+		}
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Sends disconnect event
+ *
+ *  @param priv A pointer to moal_private struct
+ *  @param disconnect_reason  disconnect reason code
+ *  @return     N/A
+ */
+t_void
+woal_send_disconnect_to_system(moal_private *priv, t_u16 disconnect_reason)
+{
+	int custom_len = 0;
+	t_u8 event_buf[32];
+#ifdef STA_WEXT
+	union iwreq_data wrqu;
+#endif
+#ifdef STA_CFG80211
+	unsigned long flags;
+#endif
+	int cfg80211_wext = priv->phandle->params.cfg80211_wext;
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	mlan_ds_misc_gtk_rekey_data zero_gtk;
+#endif
+#endif
+#ifdef STA_CFG80211
+	t_u16 reason_code = 0;
+#endif
+	ENTER();
+	priv->media_connected = MFALSE;
+#ifdef STA_CFG80211
+	if (!disconnect_reason)
+		reason_code = MLAN_REASON_DEAUTH_LEAVING;
+	else
+		reason_code = disconnect_reason;
+#endif
+	woal_stop_queue(priv->netdev);
+	if (netif_carrier_ok(priv->netdev))
+		netif_carrier_off(priv->netdev);
+	woal_flush_tcp_sess_queue(priv);
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	priv->gtk_data_ready = MFALSE;
+	memset(&zero_gtk, 0x00, sizeof(zero_gtk));
+	if (priv->phandle->params.gtk_rekey_offload ==
+	    GTK_REKEY_OFFLOAD_ENABLE &&
+	    memcmp(&priv->gtk_rekey_data, &zero_gtk,
+		   sizeof(priv->gtk_rekey_data)) != 0) {
+		PRINTM(MCMND, "clear GTK in woal_send_disconnect_to_system\n");
+		woal_set_rekey_data(priv, NULL, MLAN_ACT_CLEAR, MOAL_NO_WAIT);
+	}
+	memset(&priv->gtk_rekey_data, 0, sizeof(mlan_ds_misc_gtk_rekey_data));
+#endif
+#endif
+
+#ifdef STA_CFG80211
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_flush_tdls_list(priv);
+#endif
+#ifdef STA_CFG80211
+	if (priv->bss_type == MLAN_BSS_TYPE_STA &&
+	    IS_STA_CFG80211(cfg80211_wext)) {
+		woal_flush_pmksa_list(priv);
+		if (priv->okc_roaming_ie) {
+			kfree(priv->okc_roaming_ie);
+			priv->okc_roaming_ie = NULL;
+			priv->okc_ie_len = 0;
+		}
+	}
+#endif
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_hist_data_reset(priv);
+
+#ifdef STA_WEXT
+	if (IS_STA_WEXT(cfg80211_wext)) {
+		memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
+		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+		wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu, NULL);
+	}
+#endif
+#ifdef STA_CFG80211
+	if (IS_STA_CFG80211(cfg80211_wext)) {
+		spin_lock_irqsave(&priv->connect_lock, flags);
+		if (!priv->cfg_disconnect && !priv->cfg_connect &&
+		    priv->wdev && priv->wdev->current_bss) {
+			PRINTM(MMSG,
+			       "wlan: Disconnected from " MACSTR
+			       ": Reason code %d\n",
+			       MAC2STR(priv->cfg_bssid), reason_code);
+			spin_unlock_irqrestore(&priv->connect_lock, flags);
+			priv->cfg_disconnect = MTRUE;
+			/* This function must be called only when
+			   disconnect issued by the FW, i.e.
+			   disconnected by AP. For IBSS mode this call
+			   is not valid */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (priv->host_mlme)
+				woal_host_mlme_disconnect(priv, reason_code,
+							  NULL);
+			else
+#endif
+				cfg80211_disconnected(priv->netdev,
+						      reason_code, NULL, 0,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+						      false,
+#endif
+						      GFP_KERNEL);
+		} else {
+			spin_unlock_irqrestore(&priv->connect_lock, flags);
+		}
+		if (!woal_is_any_interface_active(priv->phandle))
+			woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME,
+					   PASSIVE_SCAN_CHAN_TIME,
+					   SPECIFIC_SCAN_CHAN_TIME);
+		priv->ft_ie_len = 0;
+		priv->ft_pre_connect = MFALSE;
+		priv->ft_md = 0;
+		priv->ft_cap = 0;
+		memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
+	}
+#endif /* STA_CFG80211 */
+
+	memset(event_buf, 0, sizeof(event_buf));
+	custom_len = strlen(CUS_EVT_AP_CONNECTED);
+	memcpy(event_buf, CUS_EVT_AP_CONNECTED,
+	       MIN((int)(sizeof(event_buf) - 1), custom_len));
+	woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN);
+	LEAVE();
+}
+#endif /* STA_SUPPORT */
+
+#define OFFSET_SEQNUM 4
+#define OFFSET_TYPE   8
+#define DUMP_TYPE_ENDE  2
+/**
+*  @brief  This function stores the FW dumps received from events
+*
+*  @param phandle     A pointer to moal_handle
+*  @param pmevent  A pointer to mlan_event structure
+*
+*  @return         N/A
+*/
+t_void
+woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent)
+{
+	int ret = 0;
+	t_u16 seqnum;
+	t_u16 type = 0;
+	t_u8 *pos;
+
+	ENTER();
+
+	if (!phandle || !pmevent) {
+		PRINTM(MERROR, "Could not dump firmware info\n");
+		LEAVE();
+		return;
+	}
+	seqnum = woal_le16_to_cpu(*(t_u16 *)
+				  (pmevent->event_buf + OFFSET_SEQNUM));
+	type = woal_le16_to_cpu(*(t_u16 *)(pmevent->event_buf + OFFSET_TYPE));
+
+	if (seqnum == 1) {
+		if (drvdbg & MFW_D)
+			drvdbg &= ~MFW_D;
+		if (phandle->fw_dump == MFALSE) {
+			PRINTM(MMSG, "=====FW trigger dump====\n");
+			phandle->fw_dump = MTRUE;
+			phandle->is_fw_dump_timer_set = MTRUE;
+			woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
+		}
+
+		if (!phandle->fw_dump_buf) {
+			ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
+					   &phandle->fw_dump_buf);
+			if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
+				PRINTM(MERROR,
+				       "Failed to vmalloc fw dump buffer\n");
+				LEAVE();
+				return;
+			}
+		} else {
+			memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
+		}
+		phandle->fw_dump_len = 0;
+		PRINTM(MMSG, "==== Start Receive FW dump event  ====\n");
+	} else {
+		if (!phandle->fw_dump_buf || !phandle->fw_dump_len) {
+			PRINTM(MERROR,
+			       "Error! Fw dump buffer is null or dump len is zero\n");
+			LEAVE();
+			return;
+		}
+	}
+	pos = phandle->fw_dump_buf + phandle->fw_dump_len;
+	moal_memcpy_ext(phandle, pos, pmevent->event_buf + OFFSET_SEQNUM,
+			pmevent->event_len - OFFSET_SEQNUM,
+			FW_DUMP_INFO_LEN - phandle->fw_dump_len);
+	phandle->fw_dump_len += pmevent->event_len - OFFSET_SEQNUM;
+
+	PRINTM(MINFO, "fw dump event: evt_len=%d toal_len=%ld\n",
+	       pmevent->event_len, (long int)phandle->fw_dump_len);
+	if (type == DUMP_TYPE_ENDE) {
+		PRINTM(MMSG, "==== FW DUMP END: %ld bytes ====\n",
+		       (long int)phandle->fw_dump_len);
+		woal_append_end_block(phandle);
+		phandle->fw_dump = MFALSE;
+		woal_send_fw_dump_complete_event(woal_get_priv
+						 (phandle, MLAN_BSS_ROLE_ANY));
+		mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+		if (phandle->is_fw_dump_timer_set) {
+			woal_cancel_timer(&phandle->fw_dump_timer);
+			phandle->is_fw_dump_timer_set = MFALSE;
+		}
+#ifdef USB
+		if (IS_USB(phandle->card_type))
+			phandle->driver_status = MTRUE;
+#endif
+		woal_process_hang(phandle);
+	}
+
+	LEAVE();
+	return;
+}
+
+#define DRV_INFO_SIZE 0x60000
+#define DRV_INFO_PER_INTF 0x11000
+#define ROW_SIZE_16 16
+#define ROW_SIZE_32 32
+
+/**
+ *  @brief This function dump hex to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buf       A pointer to buffer to dump
+ *  @param len       lengh of buf
+ *  @param ascii     Whether add ascii at the end
+ *  @param save_buf  Buffer which is saved to
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_save_hex_dump(int rowsize, const void *buf, size_t len,
+		   bool ascii, t_u8 *save_buf)
+{
+	const u8 *ptr = buf;
+	int i, linelen, remaining = len;
+	unsigned char linebuf[ROW_SIZE_32 * 3 + 2 + ROW_SIZE_32 + 1];
+	char *pos = (char *)save_buf;
+
+	if (rowsize != ROW_SIZE_16 && rowsize != ROW_SIZE_32)
+		rowsize = ROW_SIZE_16;
+
+	for (i = 0; i < (int)len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, 1,
+				   linebuf, sizeof(linebuf), false);
+
+		pos += sprintf(pos, "%s\n", linebuf);
+	}
+
+	return pos - (char *)save_buf;
+}
+
+/**
+ *  @brief This function save moal_priv's debug log
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buf       A pointer buffer saving log
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_priv_drv_info(moal_handle *handle, t_u8 *buf)
+{
+	char *ptr = (char *)buf;
+	int index;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	int i = 0;
+#endif
+	moal_private *priv;
+
+	ENTER();
+	if (!handle || !buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+	for (index = 0; index < MIN(handle->priv_num, MLAN_MAX_BSS_NUM);
+	     index++) {
+		priv = handle->priv[index];
+		if (priv) {
+			ptr += sprintf(ptr, "[Interface : %s]\n",
+				       priv->proc_entry_name);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+			ptr += sprintf(ptr, "wmm_tx_pending[0] = %d\n",
+				       atomic_read(&priv->wmm_tx_pending[0]));
+			ptr += sprintf(ptr, "wmm_tx_pending[1] = %d\n",
+				       atomic_read(&priv->wmm_tx_pending[1]));
+			ptr += sprintf(ptr, "wmm_tx_pending[2] = %d\n",
+				       atomic_read(&priv->wmm_tx_pending[2]));
+			ptr += sprintf(ptr, "wmm_tx_pending[3] = %d\n",
+				       atomic_read(&priv->wmm_tx_pending[3]));
+#endif
+			ptr += sprintf(ptr, "Media state = \"%s\"\n",
+				       ((priv->media_connected == MFALSE) ?
+					"Disconnected" : "Connected"));
+			ptr += sprintf(ptr, "carrier %s\n",
+				       ((netif_carrier_ok(priv->netdev)) ?
+					"on" : "off"));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+			for (i = 0; i < (int)(priv->netdev->num_tx_queues); i++) {
+				ptr += sprintf(ptr, "tx queue %d: %s\n", i,
+					       ((netif_tx_queue_stopped
+						 (netdev_get_tx_queue
+						  (priv->netdev,
+						   i))) ? "stopped" :
+						"started"));
+			}
+#else
+			ptr += sprintf(ptr, "tx queue %s\n",
+				       ((netif_queue_stopped(priv->netdev)) ?
+					"stopped" : "started"));
+#endif
+			ptr += sprintf(ptr, "%s: num_tx_timeout = %d\n",
+				       priv->netdev->name,
+				       priv->num_tx_timeout);
+		}
+	}
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @brief This function save moal_handle's info
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buf       A pointer buffer saving log
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_moal_drv_info(moal_handle *phandle, t_u8 *buf)
+{
+	char *ptr;
+#ifdef USB
+	struct usb_card_rec *cardp = NULL;
+#endif
+	char str_buf[MLAN_MAX_VER_STR_LEN];
+
+	ENTER();
+	if (!phandle || !buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+#ifdef USB
+	if (IS_USB(phandle->card_type))
+		cardp = (struct usb_card_rec *)phandle->card;
+#endif
+	ptr = (char *)buf;
+	ptr += sprintf(ptr, "------------moal_debug_info-------------\n");
+	woal_get_version(phandle, str_buf, sizeof(str_buf) - 1);
+	ptr += sprintf(ptr, "Driver version = %s\n", str_buf);
+	ptr += sprintf(ptr, "main_state = %d\n", phandle->main_state);
+#ifdef USB
+	if (IS_USB(phandle->card_type)) {
+		ptr += sprintf(ptr, "tx_cmd_urb_pending = %d\n",
+			       atomic_read(&cardp->tx_cmd_urb_pending));
+		ptr += sprintf(ptr, "tx_data_urb_pending = %d\n",
+			       atomic_read(&cardp->tx_data_urb_pending));
+#ifdef USB_CMD_DATA_EP
+		ptr += sprintf(ptr, "rx_cmd_urb_pending = %d\n",
+			       atomic_read(&cardp->rx_cmd_urb_pending));
+#endif
+		ptr += sprintf(ptr, "rx_data_urb_pending = %d\n",
+			       atomic_read(&cardp->rx_data_urb_pending));
+	}
+#endif
+	ptr += sprintf(ptr, "ioctl_pending = %d\n",
+		       atomic_read(&phandle->ioctl_pending));
+	ptr += sprintf(ptr, "tx_pending = %d\n",
+		       atomic_read(&phandle->tx_pending));
+	ptr += sprintf(ptr, "rx_pending = %d\n",
+		       atomic_read(&phandle->rx_pending));
+	ptr += sprintf(ptr, "lock_count = %d\n",
+		       atomic_read(&phandle->lock_count));
+	ptr += sprintf(ptr, "malloc_count = %d\n",
+		       atomic_read(&phandle->malloc_count));
+	ptr += sprintf(ptr, "mbufalloc_count = %d\n",
+		       atomic_read(&phandle->mbufalloc_count));
+#ifdef PCIE
+	if (IS_PCIE(phandle->card_type)) {
+		ptr += sprintf(ptr, "malloc_cons_count = %d\n",
+			       atomic_read(&phandle->malloc_cons_count));
+	}
+#endif
+	ptr += sprintf(ptr, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	ptr += sprintf(ptr, "hs_force_count = %u\n", phandle->hs_force_count);
+
+	ptr += woal_dump_priv_drv_info(phandle, ptr);
+	ptr += sprintf(ptr, "------------moal_debug_info End-------------\n");
+
+	if (phandle->ops.dump_reg_info)
+		ptr += phandle->ops.dump_reg_info(phandle, ptr);
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @brief This function save mlan's info
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buf       A pointer buffer saving log
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_mlan_drv_info(moal_private *priv, t_u8 *buf)
+{
+	char *ptr = (char *)buf;
+	int i;
+#ifdef SDIO
+	int j;
+	t_u8 mp_aggr_pkt_limit = 0;
+#endif
+	char str[11 * DBG_CMD_NUM + 1] = { 0 };
+	char *s;
+	mlan_debug_info *info = NULL;
+
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or priv->phandle is null\n");
+		LEAVE();
+		return 0;
+	}
+	info = &(priv->phandle->debug_info);
+	if (woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info)) {
+		PRINTM(MERROR,
+		       "Could not retrieve debug information from MLAN\n");
+		LEAVE();
+		return 0;
+	}
+	ptr += sprintf(ptr, "------------mlan_debug_info-------------\n");
+	ptr += sprintf(ptr, "mlan_processing =%d\n", info->mlan_processing);
+	ptr += sprintf(ptr, "main_lock_flag =%d\n", info->main_lock_flag);
+	ptr += sprintf(ptr, "main_process_cnt =%d\n", info->main_process_cnt);
+	ptr += sprintf(ptr, "delay_task_flag =%d\n", info->delay_task_flag);
+	ptr += sprintf(ptr, "mlan_rx_processing =%d\n",
+		       info->mlan_rx_processing);
+	ptr += sprintf(ptr, "rx_pkts_queued =%d\n", info->rx_pkts_queued);
+	ptr += sprintf(ptr, "tx_pkts_queued =%d\n", info->tx_pkts_queued);
+	ptr += sprintf(ptr, "fw_hang_report = %d\n", info->fw_hang_report);
+	ptr += sprintf(ptr, "num_cmd_timeout = %d\n", info->num_cmd_timeout);
+	ptr += sprintf(ptr, "Timeout cmd id = 0x%x, act = 0x%x\n",
+		       info->timeout_cmd_id, info->timeout_cmd_act);
+	ptr += sprintf(ptr, "last_cmd_index = %d\n", info->last_cmd_index);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_cmd_id[i]);
+	ptr += sprintf(ptr, "last_cmd_id = %s\n", str);
+
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_cmd_act[i]);
+
+	ptr += sprintf(ptr, "last_cmd_act = %s\n", str);
+	ptr += sprintf(ptr, "last_cmd_resp_index = %d\n",
+		       info->last_cmd_resp_index);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_cmd_resp_id[i]);
+
+	ptr += sprintf(ptr, "last_cmd_resp_id = %s\n", str);
+	ptr += sprintf(ptr, "last_event_index = %d\n", info->last_event_index);
+	for (s = str, i = 0; i < DBG_CMD_NUM; i++)
+		s += sprintf(s, "0x%x ", info->last_event[i]);
+
+	ptr += sprintf(ptr, "last_event = %s\n", str);
+	ptr += sprintf(ptr, "num_data_h2c_failure = %d\n",
+		       info->num_tx_host_to_card_failure);
+	ptr += sprintf(ptr, "num_cmd_h2c_failure = %d\n",
+		       info->num_cmd_host_to_card_failure);
+	ptr += sprintf(ptr, "num_alloc_buffer_failure = %d\n",
+		       info->num_alloc_buffer_failure);
+	ptr += sprintf(ptr, "num_pkt_dropped = %d\n", info->num_pkt_dropped);
+#ifdef SDIO
+	if (IS_SD(priv->phandle->card_type)) {
+		ptr += sprintf(ptr, "num_data_c2h_failure = %d\n",
+			       info->num_rx_card_to_host_failure);
+		ptr += sprintf(ptr, "num_cmdevt_c2h_failure = %d\n",
+			       info->num_cmdevt_card_to_host_failure);
+		ptr += sprintf(ptr, "num_int_read_failure = %d\n",
+			       info->num_int_read_failure);
+		ptr += sprintf(ptr, "last_int_status = %d\n",
+			       info->last_int_status);
+		ptr += sprintf(ptr,
+			       "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
+			       (unsigned int)info->mp_rd_bitmap,
+			       info->curr_rd_port);
+		ptr += sprintf(ptr,
+			       "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
+			       (unsigned int)info->mp_wr_bitmap,
+			       info->curr_wr_port);
+		ptr += sprintf(ptr, "mp_data_port_mask=0x%x\n",
+			       info->mp_data_port_mask);
+		ptr += sprintf(ptr,
+			       "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n",
+			       info->last_recv_rd_bitmap,
+			       info->mp_invalid_update);
+		mp_aggr_pkt_limit = info->mp_aggr_pkt_limit;
+		ptr += sprintf(ptr,
+			       "last_recv_wr_bitmap=0x%x last_mp_index = %d\n",
+			       info->last_recv_wr_bitmap, info->last_mp_index);
+		for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
+			for (s = str, j = 0; j < mp_aggr_pkt_limit; j++)
+				s += sprintf(s, "0x%02x ",
+					     info->last_mp_wr_info
+					     [i * mp_aggr_pkt_limit + j]);
+
+			ptr += sprintf(ptr,
+				       "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n%s\n",
+				       info->last_mp_wr_bitmap[i],
+				       info->last_mp_wr_ports[i],
+				       info->last_mp_wr_len[i],
+				       info->last_curr_wr_port[i], str);
+		}
+	}
+#endif
+#ifdef PCIE
+	if (IS_PCIE(priv->phandle->card_type)) {
+		ptr += sprintf(ptr, "txbd_rdptr=0x%x txbd_wrptr=0x%x\n",
+			       info->txbd_rdptr, info->txbd_wrptr);
+		ptr += sprintf(ptr, "rxbd_rdptr=0x%x rxbd_wrptr=0x%x\n",
+			       info->rxbd_rdptr, info->rxbd_wrptr);
+		ptr += sprintf(ptr,
+			       "eventbd_rdptr=0x%x event_wrptr=0x%x\n",
+			       info->eventbd_rdptr, info->eventbd_wrptr);
+		ptr += sprintf(ptr, "last_wr_index:%d\n",
+			       info->txbd_wrptr & (info->txrx_bd_size - 1));
+		ptr += sprintf(ptr, "TxRx BD size:%d\n", info->txrx_bd_size);
+	}
+#endif
+	ptr += sprintf(ptr, "num_event_deauth = %d\n", info->num_event_deauth);
+	ptr += sprintf(ptr, "num_event_disassoc = %d\n",
+		       info->num_event_disassoc);
+	ptr += sprintf(ptr, "num_event_link_lost = %d\n",
+		       info->num_event_link_lost);
+	ptr += sprintf(ptr, "num_cmd_deauth = %d\n", info->num_cmd_deauth);
+	ptr += sprintf(ptr, "num_cmd_assoc_success = %d\n",
+		       info->num_cmd_assoc_success);
+	ptr += sprintf(ptr, "num_cmd_assoc_failure = %d\n",
+		       info->num_cmd_assoc_failure);
+	ptr += sprintf(ptr, "num_cons_assoc_failure = %d\n",
+		       info->num_cons_assoc_failure);
+	ptr += sprintf(ptr, "cmd_resp_received = %d\n",
+		       info->cmd_resp_received);
+	ptr += sprintf(ptr, "event_received = %d\n", info->event_received);
+	ptr += sprintf(ptr, "max_tx_buf_size = %d\n", info->max_tx_buf_size);
+	ptr += sprintf(ptr, "tx_buf_size = %d\n", info->tx_buf_size);
+	ptr += sprintf(ptr, "curr_tx_buf_size = %d\n", info->curr_tx_buf_size);
+	ptr += sprintf(ptr, "bypass_pkt_count=%d\n", info->bypass_pkt_count);
+
+	ptr += sprintf(ptr, "data_sent=%d cmd_sent=%d\n",
+		       info->data_sent, info->cmd_sent);
+	ptr += sprintf(ptr, "data_sent_cnt=%u\n", info->data_sent_cnt);
+	ptr += sprintf(ptr, "ps_mode=%d ps_state=%d\n", info->ps_mode,
+		       info->ps_state);
+	ptr += sprintf(ptr,
+		       "wakeup_dev_req=%d wakeup_tries=%d pm_wakeup_timeout=%d\n",
+		       info->pm_wakeup_card_req, info->pm_wakeup_fw_try,
+		       info->pm_wakeup_timeout);
+	ptr += sprintf(ptr, "hs_configured=%d hs_activated=%d\n",
+		       info->is_hs_configured, info->hs_activated);
+	ptr += sprintf(ptr, "pps_uapsd_mode=%d sleep_pd=%d\n",
+		       info->pps_uapsd_mode, info->sleep_pd);
+	ptr += sprintf(ptr, "tx_lock_flag = %d\n", info->tx_lock_flag);
+	ptr += sprintf(ptr, "port_open = %d\n", info->port_open);
+	ptr += sprintf(ptr, "scan_processing = %d\n", info->scan_processing);
+
+#ifdef PCIE
+	if (IS_PCIE(priv->phandle->card_type)) {
+		ptr += sprintf(ptr, "txbd: rdptr=0x%x wrptr=0x%x\n",
+			       info->txbd_rdptr, info->txbd_wrptr);
+		ptr += sprintf(ptr, "rxbd: rdptr=0x%x wrptr=0x%x\n",
+			       info->rxbd_rdptr, info->rxbd_wrptr);
+		ptr += sprintf(ptr, "eventbd: rdptr=0x%x wrptr=0x%x\n",
+			       info->eventbd_rdptr, info->eventbd_wrptr);
+		ptr += sprintf(ptr, "TXBD Ring:\n");
+		ptr += woal_save_hex_dump(ROW_SIZE_16,
+					  info->txbd_ring_vbase,
+					  info->txbd_ring_size, MTRUE, ptr);
+		ptr += sprintf(ptr, "RXBD Ring:\n");
+		ptr += woal_save_hex_dump(ROW_SIZE_16,
+					  info->rxbd_ring_vbase,
+					  info->rxbd_ring_size, MTRUE, ptr);
+		ptr += sprintf(ptr, "EVTBD Ring:\n");
+		ptr += woal_save_hex_dump(ROW_SIZE_16,
+					  info->evtbd_ring_vbase,
+					  info->evtbd_ring_size, MTRUE, ptr);
+	}
+#endif
+	ptr += sprintf(ptr, "------------mlan_debug_info End-------------\n");
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @brief This function dump moal hex to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buf       A pointer to buffer
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_moal_hex(moal_handle *phandle, t_u8 *buf)
+{
+	char *ptr = (char *)buf;
+	int i;
+	ENTER();
+
+	if (!phandle || !buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+
+	ptr += sprintf(ptr, "<--moal_handle-->\n");
+	ptr += sprintf(ptr, "moal_handle=%p, size=%ld(0x%lx)\n",
+		       phandle, (long int)sizeof(*phandle),
+		       (long unsigned int)sizeof(*phandle));
+	ptr += woal_save_hex_dump(ROW_SIZE_16, phandle,
+				  sizeof(*phandle), MTRUE, ptr);
+	ptr += sprintf(ptr, "<--moal_handle End-->\n");
+
+	for (i = 0; i < phandle->priv_num; i++) {
+		if (!phandle->priv[i])
+			continue;
+		ptr += sprintf(ptr, "<--moal_private(%d) %s-->\n", i,
+			       phandle->priv[i]->netdev->name);
+		ptr += sprintf(ptr, "moal_private=%p, size=%ld(0x%lx)\n",
+			       phandle->priv[i],
+			       (long int)sizeof(*(phandle->priv[i])),
+			       (long unsigned int)sizeof(*(phandle->priv[i])));
+		ptr += woal_save_hex_dump(ROW_SIZE_16, phandle->priv[i],
+					  sizeof(*(phandle->priv[i])),
+					  MTRUE, ptr);
+		ptr += sprintf(ptr, "<--moal_private(%d) End-->\n", i);
+	}
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @brief This function dump mlan hex to file
+ *
+ *  @param priv   A pointer to moal_private structure
+ *  @param buf       A pointer to buffer
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_dump_mlan_hex(moal_private *priv, t_u8 *buf)
+{
+	char *ptr = (char *)buf;
+	int i;
+	mlan_debug_info *info = NULL;
+
+	ENTER();
+
+	if (!buf || !priv || !priv->phandle) {
+		PRINTM(MERROR, "buf priv or priv->phandle is null\n");
+		LEAVE();
+		return 0;
+	}
+	info = &(priv->phandle->debug_info);
+	if (woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info)) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+
+	ptr += sprintf(ptr, "<--mlan_adapter-->\n");
+	ptr += sprintf(ptr, "mlan_adapter=%p, size=%d(0x%x)\n",
+		       info->mlan_adapter, info->mlan_adapter_size,
+		       info->mlan_adapter_size);
+	ptr += woal_save_hex_dump(ROW_SIZE_16, info->mlan_adapter,
+				  info->mlan_adapter_size, MTRUE, ptr);
+	ptr += sprintf(ptr, "<--mlan_adapter End-->\n");
+#ifdef SDIO
+	if (IS_SD(priv->phandle->card_type) && info->mpa_buf &&
+	    info->mpa_buf_size) {
+		ptr += sprintf(ptr, "<--mlan_mpa_buf-->\n");
+		ptr += sprintf(ptr, "mlan_mpa_buf=%p, size=%d(0x%x)\n",
+			       info->mpa_buf, info->mpa_buf_size,
+			       info->mpa_buf_size);
+		ptr += woal_save_hex_dump(ROW_SIZE_16, info->mpa_buf,
+					  info->mpa_buf_size, MTRUE, ptr);
+		ptr += sprintf(ptr, "<--mlan_mpa_buf End-->\n");
+	}
+#endif
+	for (i = 0; i < info->mlan_priv_num; i++) {
+		ptr += sprintf(ptr, "<--mlan_private(%d)-->\n", i);
+		ptr += sprintf(ptr, "mlan_private=%p, size=%d(0x%x)\n",
+			       info->mlan_priv[i],
+			       info->mlan_priv_size[i],
+			       info->mlan_priv_size[i]);
+		ptr += woal_save_hex_dump(ROW_SIZE_16,
+					  info->mlan_priv[i],
+					  info->mlan_priv_size[i], MTRUE, ptr);
+		ptr += sprintf(ptr, "<--mlan_private(%d) End-->\n", i);
+	}
+
+	LEAVE();
+	return ptr - (char *)buf;
+}
+
+/**
+ *  @brief This function dump drv info to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param dump_len  A point to hold the len of drv info memory
+ *
+ *  @return         A pointer to drv_info memory
+ */
+t_u8 *
+woal_dump_drv_info(moal_handle *phandle, t_u32 *dump_len)
+{
+	t_u8 *drv_buf = NULL;
+	t_u32 len = 0;
+	t_u32 total_len = 0;
+	t_u32 drv_info_size = DRV_INFO_SIZE;
+	int ret;
+	if (phandle->priv_num > 3)
+		drv_info_size += (phandle->priv_num - 3) * DRV_INFO_PER_INTF;
+	PRINTM(MERROR, "=== START DRIVER INFO DUMP===");
+	ret = moal_vmalloc(phandle, drv_info_size, &drv_buf);
+	if ((ret != MLAN_STATUS_SUCCESS) || !drv_buf) {
+		PRINTM(MERROR, "Error: vmalloc drv buffer failed!\n");
+		goto done;
+	}
+
+	len = woal_dump_moal_drv_info(phandle, drv_buf);
+	total_len += len;
+	len = woal_dump_mlan_drv_info(woal_get_priv(phandle,
+						    MLAN_BSS_ROLE_ANY),
+				      drv_buf + total_len);
+	total_len += len;
+	len = woal_dump_moal_hex(phandle, drv_buf + total_len);
+	total_len += len;
+	len = woal_dump_mlan_hex(woal_get_priv(phandle,
+					       MLAN_BSS_ROLE_ANY),
+				 drv_buf + total_len);
+	total_len += len;
+
+	PRINTM(MERROR, "Drv info total bytes = %ld (0x%lx)\n",
+	       (long int)total_len, (long unsigned int)total_len);
+	PRINTM(MERROR, "=== DRIVER INFO DUMP END===");
+	*dump_len = total_len;
+done:
+	return drv_buf;
+}
+
+/**
+ *  @brief This function adds header and copy the src data to buf
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param src     A ponter to source buffer
+ *  @param len     Length of raw data
+ *  @param type   Dump type
+ *
+ *  return Total len of buf
+ */
+int
+woal_save_dump_info_to_buf(moal_handle *phandle, t_u8 *src,
+			   t_u32 len, t_u32 type)
+{
+	mem_dump_header header;
+	t_u32 left_len = 0;
+	t_u32 len_to_copy = 0;
+	int total_len = 0;
+	t_u8 *dest = NULL;
+	int count = 0;
+	int pad = 0;
+	dest = phandle->fw_dump_buf + phandle->fw_dump_len;
+
+	left_len = len;
+	while (left_len) {
+		header.type = type;
+		if (left_len < 1024)
+			len_to_copy = left_len;
+		else
+			len_to_copy = 1024;
+		header.len = (t_u16)(len_to_copy + sizeof(t_u32));
+		header.start_addr = count * 1024;
+		moal_memcpy_ext(phandle, dest, &header, sizeof(mem_dump_header),
+				FW_DUMP_INFO_LEN - phandle->fw_dump_len);
+		dest += sizeof(mem_dump_header);
+		moal_memcpy_ext(phandle, dest, src, len_to_copy,
+				FW_DUMP_INFO_LEN -
+				phandle->fw_dump_len - sizeof(mem_dump_header));
+		dest += len_to_copy;
+		src += len_to_copy;
+		left_len -= len_to_copy;
+		// 8 bytes align
+		pad = (header.len & 7) ? (8 - (header.len & 7)) : 0;
+		dest += pad;
+		total_len += pad + len_to_copy + sizeof(mem_dump_header);
+		count++;
+	}
+	phandle->fw_dump_len += total_len;
+	PRINTM(MMSG, "type=%d, len=%d  block=%d  total=%d\n", type, len,
+	       count, total_len);
+	return total_len;
+}
+
+/**
+ *  @brief This function append end block to dump file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  return N/A
+ */
+void
+woal_append_end_block(moal_handle *phandle)
+{
+	mem_dump_header header;
+	t_u8 *pos = phandle->fw_dump_buf + phandle->fw_dump_len;
+	ENTER();
+	memset(&header, 0, sizeof(header));
+	header.type = FW_DUMP_TYPE_ENDED;
+	header.len = 0;
+	moal_memcpy_ext(phandle, pos, &header, sizeof(mem_dump_header),
+			FW_DUMP_INFO_LEN - phandle->fw_dump_len);
+	phandle->fw_dump_len += sizeof(mem_dump_header);
+	PRINTM(MMSG, "fw dump total length is %ld\n",
+	       (long int)phandle->fw_dump_len);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function displays extra MOAL debug information
+ *
+ *  @param priv     A pointer to moal_private
+ *  @param handle   A pointer to moal_handle
+ *  @param flag     Indicates whether register read can be done directly
+ *
+ *  @return         N/A
+ */
+void
+woal_moal_debug_info(moal_private *priv, moal_handle *handle, u8 flag)
+{
+	moal_handle *phandle = NULL;
+#ifdef USB
+	struct usb_card_rec *cardp = NULL;
+#endif
+	char buf[MLAN_MAX_VER_STR_LEN];
+	int i = 0;
+
+	ENTER();
+
+	if (!priv) {
+		if (handle) {
+			phandle = handle;
+		} else {
+			PRINTM(MERROR,
+			       "Could not retrieve debug information from MOAL\n");
+			LEAVE();
+			return;
+		}
+	} else {
+		phandle = priv->phandle;
+	}
+#ifdef USB
+	if (IS_USB(phandle->card_type)) {
+		cardp = (struct usb_card_rec *)phandle->card;
+		PRINTM(MERROR, "tx_cmd_urb_pending = %d\n",
+		       atomic_read(&cardp->tx_cmd_urb_pending));
+		PRINTM(MERROR, "tx_data_urb_pending = %d\n",
+		       atomic_read(&cardp->tx_data_urb_pending));
+#ifdef USB_CMD_DATA_EP
+		PRINTM(MERROR, "rx_cmd_urb_pending = %d\n",
+		       atomic_read(&cardp->rx_cmd_urb_pending));
+#endif
+		PRINTM(MERROR, "rx_data_urb_pending = %d\n",
+		       atomic_read(&cardp->rx_data_urb_pending));
+	}
+#endif
+
+	woal_get_version(phandle, buf, sizeof(buf) - 1);
+	PRINTM(MERROR, "Driver version = %s\n", buf);
+	PRINTM(MERROR, "main_state = %d\n", phandle->main_state);
+	PRINTM(MERROR, "ioctl_pending = %d\n",
+	       atomic_read(&phandle->ioctl_pending));
+	PRINTM(MERROR, "tx_pending = %d\n", atomic_read(&phandle->tx_pending));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	if (priv) {
+		PRINTM(MERROR, "wmm_tx_pending[0] = %d\n",
+		       atomic_read(&priv->wmm_tx_pending[0]));
+		PRINTM(MERROR, "wmm_tx_pending[1] = %d\n",
+		       atomic_read(&priv->wmm_tx_pending[1]));
+		PRINTM(MERROR, "wmm_tx_pending[2] = %d\n",
+		       atomic_read(&priv->wmm_tx_pending[2]));
+		PRINTM(MERROR, "wmm_tx_pending[3] = %d\n",
+		       atomic_read(&priv->wmm_tx_pending[3]));
+	}
+#endif
+	PRINTM(MERROR, "rx_pending = %d\n", atomic_read(&phandle->rx_pending));
+	PRINTM(MERROR, "lock_count = %d\n", atomic_read(&phandle->lock_count));
+	PRINTM(MERROR, "malloc_count = %d\n",
+	       atomic_read(&phandle->malloc_count));
+	PRINTM(MERROR, "mbufalloc_count = %d\n",
+	       atomic_read(&phandle->mbufalloc_count));
+#ifdef PCIE
+	if (IS_PCIE(phandle->card_type)) {
+		PRINTM(MERROR, "malloc_cons_count = %d\n",
+		       atomic_read(&phandle->malloc_cons_count));
+	}
+#endif
+	PRINTM(MERROR, "hs_skip_count = %u\n", phandle->hs_skip_count);
+	PRINTM(MERROR, "hs_force_count = %u\n", phandle->hs_force_count);
+
+	if (priv && priv->netdev) {
+		PRINTM(MERROR, "Media state = \"%s\"\n",
+		       ((priv->media_connected == MFALSE) ?
+			"Disconnected" : "Connected"));
+		PRINTM(MERROR, "carrier %s\n",
+		       ((netif_carrier_ok(priv->netdev)) ? "on" : "off"));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+		for (i = 0; i < (int)(priv->netdev->num_tx_queues); i++) {
+			PRINTM(MERROR, "tx queue %d: %s\n", i,
+			       ((netif_tx_queue_stopped
+				 (netdev_get_tx_queue(priv->netdev, i))) ?
+				"stopped" : "started"));
+		}
+#else
+		PRINTM(MERROR, "tx queue %s\n",
+		       ((netif_queue_stopped(priv->netdev)) ? "stopped" :
+			"started"));
+#endif
+	}
+
+	for (i = 0; i < phandle->priv_num; i++) {
+		priv = phandle->priv[i];
+		if (priv && priv->netdev)
+			PRINTM(MERROR, "%s: num_tx_timeout = %d\n",
+			       priv->netdev->name, priv->num_tx_timeout);
+	}
+
+	if (phandle->is_suspended == MTRUE) {
+		LEAVE();
+		return;
+	}
+#ifdef PCIE
+	if (IS_PCIE(phandle->card_type)) {
+		if (phandle->ops.reg_dbg && (drvdbg & (MREG_D | MFW_D))) {
+			if (!phandle->event_fw_dump)
+				phandle->ops.reg_dbg(phandle);
+		}
+	}
+#endif
+#ifdef SDIO
+	if (IS_SD(phandle->card_type)) {
+		if (flag &&
+		    ((phandle->main_state == MOAL_END_MAIN_PROCESS) ||
+		     (phandle->main_state == MOAL_STATE_IDLE))) {
+			if (phandle->ops.reg_dbg && (drvdbg & (MREG_D | MFW_D))) {
+				if (!phandle->event_fw_dump)
+					phandle->ops.reg_dbg(phandle);
+			}
+		} else {
+			if (drvdbg & (MREG_D | MFW_D)) {
+				if (!phandle->event_fw_dump) {
+					phandle->reg_dbg = MTRUE;
+					queue_work(phandle->workqueue,
+						   &phandle->main_work);
+				}
+			}
+		}
+	}
+#endif
+#ifdef DEBUG_LEVEL1
+	if (drvdbg & MFW_D) {
+		drvdbg &= ~MFW_D;
+		phandle->fw_dbg = MTRUE;
+		queue_work(phandle->workqueue, &phandle->main_work);
+	}
+#endif
+	LEAVE();
+	return;
+}
+
+/**
+ *    @brief Download power table to firmware for a specific country
+ *
+ *    @param priv         A pointer to moal_private
+ *    @param country      ISO 3166-1 alpha-2 country code
+ *
+ *    @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_request_country_power_table(moal_private *priv, char *country)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = NULL;
+	char country_name[128];
+	char file_path[256];
+	char *last_slash = NULL;
+	char *fw_name = NULL;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "Priv or handle is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (!country) {
+		PRINTM(MERROR, "Country is null\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle = priv->phandle;
+	memset(country_name, 0, sizeof(country_name));
+	if (handle->params.hw_name)
+		sprintf(country_name, "%s_txpower_XX.bin",
+			handle->params.hw_name);
+	else
+		memcpy(country_name, "txpower_XX.bin",
+		       strlen("txpower_XX.bin"));
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (handle->params.cntry_txpwr == CNTRY_RGPOWER_MODE) {
+		memset(country_name, 0, sizeof(country_name));
+		if (handle->params.hw_name)
+			sprintf(country_name, "%s_rgpower_XX.bin",
+				handle->params.hw_name);
+		else
+			memcpy(country_name, "rgpower_XX.bin",
+			       strlen("rgpower_XX.bin"));
+	}
+#endif
+#endif
+
+	/* Replace XX with ISO 3166-1 alpha-2 country code */
+	memcpy(strstr(country_name, "XX"), country, COUNTRY_CODE_LEN - 1);
+	fw_name = handle->params.fw_name;
+	memset(file_path, 0, sizeof(file_path));
+	/* file_path should be Null terminated */
+	if (fw_name) {
+		strncpy(file_path, fw_name, sizeof(file_path) - 1);
+		last_slash = strrchr(file_path, '/');
+		if (last_slash)
+			memset(last_slash + 1, 0,
+			       sizeof(file_path) - 1 -
+			       (last_slash - file_path));
+		else
+			memset(file_path, 0, sizeof(file_path));
+	} else {
+		memcpy(file_path, "nxp/",
+		       MIN((sizeof(file_path) - 1), strlen("nxp/")));
+	}
+
+	if ((strlen(file_path) + strlen(country_name)) <
+	    (sizeof(file_path) - 1))
+		strncpy(file_path + strlen(file_path), country_name,
+			sizeof(file_path) - strlen(file_path));
+	else {
+		PRINTM(MERROR,
+		       "file path buffer too small, fail to dnld power table\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	PRINTM(MMSG, "Trying download country_power_tble: %s\n", file_path);
+	ret = woal_set_user_init_data(handle, COUNTRY_POWER_TABLE,
+				      MOAL_IOCTL_WAIT, file_path);
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	/* Try download WW rgpowertable */
+	if ((handle->params.cntry_txpwr == CNTRY_RGPOWER_MODE)
+	    && (ret == MLAN_STATUS_FILE_ERR)) {
+		memset(country_name, 0, sizeof(country_name));
+		if (handle->params.hw_name)
+			sprintf(country_name, "%s_rgpower_WW.bin",
+				handle->params.hw_name);
+		else
+			memcpy(country_name, "rgpower_WW.bin",
+			       strlen("rgpower_WW.bin"));
+		last_slash = strrchr(file_path, '/');
+		if (last_slash)
+			memset(last_slash + 1, 0,
+			       sizeof(file_path) - 1 -
+			       (last_slash - file_path));
+		else
+			memset(file_path, 0, sizeof(file_path));
+		strncpy(file_path + strlen(file_path), country_name,
+			strlen(country_name));
+		PRINTM(MMSG,
+		       "Trying again download country_power_tble: %s\n",
+		       file_path);
+		ret = woal_set_user_init_data(handle,
+					      COUNTRY_POWER_TABLE,
+					      MOAL_IOCTL_WAIT, file_path);
+		if (!ret) {
+			handle->country_code[0] = '0';
+			handle->country_code[1] = '0';
+		}
+	}
+#endif
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief napi polling call back function.
+ *
+ *  @param napi     A pointer to napi_struct
+ *  @param budget   the limit of packets driver should poll
+ *
+ *  @return       packets received
+ */
+static int
+woal_netdev_poll_rx(struct napi_struct *napi, int budget)
+{
+	moal_handle *handle = container_of(napi, moal_handle, napi_rx);
+	t_u8 recv = budget;
+
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		napi_complete(napi);
+		LEAVE();
+		return 0;
+	}
+	mlan_rx_process(handle->pmlan_adapter, &recv);
+	if (recv < budget)
+		napi_complete(napi);
+	LEAVE();
+	return recv;
+}
+
+/**
+ *  @brief This workqueue function handles set multicast_list
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+t_void
+woal_mclist_work_queue(struct work_struct *work)
+{
+	moal_private *priv = container_of(work, moal_private, mclist_work);
+	woal_request_set_multicast_list(priv, priv->netdev);
+}
+#ifdef STA_CFG80211
+/**
+ *  @brief This workqueue function handles woal scan timeout  work
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+t_void woal_scan_timeout_handler(struct work_struct *work)
+{
+    struct delayed_work *delayed_work = to_delayed_work(work);
+	moal_handle *handle = container_of(delayed_work, moal_handle, scan_timeout_work);
+    unsigned long flags;
+	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	t_u8  auto_fw_dump = MFALSE;
+
+    ENTER();   
+    
+	if (IS_STA_CFG80211(handle->params.cfg80211_wext)) {
+		if (handle->scan_request && handle->fake_scan_complete) {
+			PRINTM(MMSG, "wlan: Send fake scan result\n");
+			if(priv)
+				woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT);
+			spin_lock_irqsave(&handle->scan_req_lock, flags);
+			woal_cfg80211_scan_done(handle->scan_request, MFALSE);
+			handle->scan_request = NULL;
+			spin_unlock_irqrestore(&priv->phandle->scan_req_lock, flags);
+		}
+		else if(handle->scan_request){
+			PRINTM(MMSG,"wlan: scan timeout!\n");
+			if(drvdbg & MFW_D)
+				auto_fw_dump = MTRUE;
+			if(priv){
+				woal_mlan_debug_info(priv);
+				woal_moal_debug_info(priv, NULL, MFALSE);
+#ifdef DEBUG_LOG
+#ifdef DEBUG_LEVEL1
+				woal_set_get_log_config(priv, "lock", NULL, MOAL_SMEM_WRITE);
+#endif
+#endif
+			}
+			handle->driver_status = MTRUE;
+			if(!auto_fw_dump && !handle->fw_dump)
+				woal_process_hang(priv->phandle);
+			wifi_status = 3;
+        }
+    }
+
+    LEAVE();
+}
+#endif
+
+/**
+ *  @brief This workqueue function handles woal event queue
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+t_void
+woal_evt_work_queue(struct work_struct *work)
+{
+	moal_handle *handle = container_of(work, moal_handle, evt_work);
+	struct woal_event *evt;
+	unsigned long flags;
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	moal_private *priv;
+#endif
+#endif
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+	spin_lock_irqsave(&handle->evt_lock, flags);
+	while (!list_empty(&handle->evt_queue)) {
+		evt = list_first_entry(&handle->evt_queue,
+				       struct woal_event, link);
+		list_del(&evt->link);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		switch (evt->type) {
+		case WOAL_EVENT_CHAN_SWITCH:
+#if defined(UAP_SUPPORT) || defined(STA_SUPPORT)
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+			woal_cfg80211_notify_channel((moal_private *)evt->priv,
+						     &evt->chan_info);
+#endif
+#endif
+#endif
+			break;
+		case WOAL_EVENT_RX_MGMT_PKT:
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+			priv = evt->priv;
+			mutex_lock(&priv->wdev->mtx);
+			cfg80211_rx_mlme_mgmt(priv->netdev,
+					      evt->evt.event_buf,
+					      evt->evt.event_len);
+			mutex_unlock(&priv->wdev->mtx);
+#endif
+#endif
+			break;
+		case WOAL_EVENT_BGSCAN_STOP:
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			woal_cfg80211_notify_sched_scan_stop((moal_private *)
+							     evt->priv);
+#endif
+#endif
+			break;
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		case WOAL_EVENT_DEAUTH:
+			priv = evt->priv;
+			woal_host_mlme_disconnect(evt->priv, evt->reason_code,
+						  priv->cfg_bssid);
+			break;
+
+		case WOAL_EVENT_ASSOC_RESP:
+			woal_host_mlme_process_assoc_resp((moal_private *)evt->
+							  priv,
+							  &evt->assoc_resp);
+			break;
+#endif
+#endif
+#ifdef UAP_CFG80211
+#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
+		case WOAL_EVENT_CANCEL_CHANRPT:
+			woal_process_cancel_chanrpt_event((moal_private *)evt->
+							  priv);
+			break;
+#endif
+#endif
+		}
+		kfree(evt);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+	}
+	spin_unlock_irqrestore(&handle->evt_lock, flags);
+	LEAVE();
+}
+
+/**
+ *  @brief This workqueue function handles rx_process
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+t_void
+woal_rx_work_queue(struct work_struct *work)
+{
+	moal_handle *handle = container_of(work, moal_handle, rx_work);
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 14, 6)
+	moal_private *priv;
+#endif
+#endif
+#endif
+	wifi_timeval start_timeval;
+	wifi_timeval end_timeval;
+
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+
+	woal_get_monotonic_time(&start_timeval);
+	mlan_rx_process(handle->pmlan_adapter, NULL);
+
+	woal_get_monotonic_time(&end_timeval);
+	handle->rx_time += (t_u64)(timeval_to_usec(end_timeval) -
+				   timeval_to_usec(start_timeval));
+	PRINTM(MINFO,
+	       "%s : start_timeval=%d:%d end_timeval=%d:%d inter=%llu rx_time=%llu\n",
+	       __func__, start_timeval.time_sec,
+	       start_timeval.time_usec, end_timeval.time_sec,
+	       end_timeval.time_usec,
+	       (t_u64)(timeval_to_usec(end_timeval) -
+		       timeval_to_usec(start_timeval)), handle->rx_time);
+	LEAVE();
+}
+
+/**
+ *  @brief This function dequeue pkt from list
+ *
+ *  @param list    A pointer to struct sk_buff_head
+ *
+ *  @return        skb buffer
+ */
+
+struct sk_buff *
+woal_skb_dequeue_spinlock(struct sk_buff_head *list)
+{
+	struct sk_buff *result;
+
+	spin_lock_bh(&list->lock);
+	result = __skb_dequeue(list);
+	spin_unlock_bh(&list->lock);
+	return result;
+}
+
+/**
+ *  @brief This workqueue function handles rx_work_process
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+t_void
+woal_tx_work_handler(struct work_struct *work)
+{
+	moal_handle *handle = container_of(work, moal_handle, tx_work);
+	moal_private *priv = NULL;
+	int i = 0;
+	struct sk_buff *skb = NULL;
+
+	ENTER();
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		priv = handle->priv[i];
+		while ((skb = woal_skb_dequeue_spinlock(&priv->tx_q)) != NULL) {
+			woal_start_xmit(priv, skb);
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This workqueue function handles main_process
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+t_void
+woal_main_work_queue(struct work_struct *work)
+{
+	moal_handle *handle = container_of(work, moal_handle, main_work);
+#ifdef USB
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	struct sched_param sp = {.sched_priority = wq_sched_prio };
+#endif
+
+	ENTER();
+
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+	if (handle->reg_dbg == MTRUE) {
+		handle->reg_dbg = MFALSE;
+		if (handle->ops.reg_dbg)
+			handle->ops.reg_dbg(handle);
+	}
+	if (handle->fw_dbg == MTRUE) {
+		handle->fw_dbg = MFALSE;
+		handle->ops.dump_fw_info(handle);
+		LEAVE();
+		return;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+	/* Change the priority and scheduling policy of main work queue
+	 */
+	if ((handle->params.wq_sched_prio != current->rt_priority) ||
+	    (handle->params.wq_sched_policy != current->policy)) {
+		PRINTM(MMSG,
+		       "Set work queue priority %d and scheduling policy %d\n",
+		       handle->params.wq_sched_prio,
+		       handle->params.wq_sched_policy);
+		sched_setscheduler(current,
+				   handle->params.wq_sched_policy, &sp);
+	}
+#endif
+
+	handle->main_state = MOAL_ENTER_WORK_QUEUE;
+#ifdef USB
+	/* WAR for no free skb issue */
+	if (IS_USB(handle->card_type) &&
+	    !atomic_read(&handle->rx_pending) &&
+	    atomic_read(&cardp->rx_data_urb_pending) < MVUSB_RX_DATA_URB) {
+		PRINTM(MWARN, "Try to resubmit Rx data URBs\n");
+		woal_usb_submit_rx_data_urbs(handle);
+	}
+#endif
+	handle->main_state = MOAL_START_MAIN_PROCESS;
+	/* Call MLAN main process */
+	mlan_main_process(handle->pmlan_adapter);
+	handle->main_state = MOAL_END_MAIN_PROCESS;
+
+	LEAVE();
+}
+
+#ifdef IMX_SUPPORT
+/**
+ *  @brief This function allocates the interrupt line to wakeup
+ *         the host, and initializes the device for wakeup
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *
+ *  @return        N/A
+ */
+void
+woal_regist_oob_wakeup_irq(moal_handle *handle)
+{
+	int ret;
+	struct device *dev = handle->hotplug_device;
+	struct device_node *node;
+
+	ENTER();
+
+	node = of_find_compatible_node(NULL, NULL, "nxp,wifi-wake-host");
+	if (!node)
+		goto err_exit;
+
+	handle->irq_oob_wakeup = irq_of_parse_and_map(node, 0);
+	if (!handle->irq_oob_wakeup) {
+		dev_dbg(dev, "fail to parse irq_oob_wakeup from device tree\n");
+		goto err_exit;
+	}
+
+	ret = devm_request_irq(dev, handle->irq_oob_wakeup,
+			       woal_oob_wakeup_irq_handler,
+			       IRQF_TRIGGER_LOW | IRQF_SHARED,
+			       "wifi_oob_wakeup", handle);
+	if (ret) {
+		dev_err(dev, "Failed to request irq_oob_wakeup %d (%d)\n",
+			handle->irq_oob_wakeup, ret);
+		goto err_exit;
+	}
+
+	disable_irq(handle->irq_oob_wakeup);
+
+	LEAVE();
+	return;
+
+err_exit:
+	handle->irq_oob_wakeup = -1;
+}
+
+/**
+ *  @brief This function frees the wakeup interrupt line
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *
+ *  @return        N/A
+ */
+void
+woal_unregist_oob_wakeup_irq(moal_handle *handle)
+{
+	struct device *dev = handle->hotplug_device;
+
+	ENTER();
+	if (handle->irq_oob_wakeup >= 0) {
+		devm_free_irq(dev, handle->irq_oob_wakeup, handle);
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief This function disables power management wakeup
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *
+ *  @return        N/A
+ */
+void
+woal_disable_oob_wakeup_irq(moal_handle *handle)
+{
+	ENTER();
+
+	if (handle->irq_oob_wakeup >= 0) {
+		if (handle->wake_by_wifi)
+			disable_irq_wake(handle->irq_oob_wakeup);
+		else {
+			disable_irq_wake(handle->irq_oob_wakeup);
+			disable_irq(handle->irq_oob_wakeup);
+		}
+
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function enables power management wakeup
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *
+ *  @return        N/A
+ */
+void
+woal_enable_oob_wakeup_irq(moal_handle *handle)
+{
+	ENTER();
+
+	/* Enable platform specific wakeup interrupt */
+	if (handle->irq_oob_wakeup >= 0) {
+		handle->wake_by_wifi = false;
+		enable_irq(handle->irq_oob_wakeup);
+		enable_irq_wake(handle->irq_oob_wakeup);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function will be called when the wakeup IRQ occurs
+ *
+ *  @param irq     Wakeup interrupt line
+ *  @param priv    A void pointer to store moal_handle structure pointer
+ *
+ *  @return        Returns status of interrupt handler.
+ */
+irqreturn_t
+woal_oob_wakeup_irq_handler(int irq, void *priv)
+{
+	moal_handle *handle = priv;
+	struct device *dev = handle->hotplug_device;
+
+	ENTER();
+
+	dev_dbg(dev, "%s: OOB wakeup by wifi", __func__);
+	handle->wake_by_wifi = true;
+	disable_irq_nosync(irq);
+
+	/* Notify PM core we are wakeup source */
+	pm_wakeup_event(dev, 0);
+	pm_system_wakeup();
+
+	LEAVE();
+	return IRQ_HANDLED;
+}
+#endif /* IMX_SUPPORT */
+
+/**
+ * @brief This function adds the card. it will probe the
+ *      card, allocate the mlan_private and initialize the device.
+ *
+ *  @param card    A pointer to card
+ *  @param dev     A pointer to device structure
+ *  @param if_ops  A pointer to interface ops
+ *  @param card_type card type id
+ *
+ *  @return        A pointer to moal_handle structure
+ */
+moal_handle *
+woal_add_card(void *card, struct device *dev,
+	      moal_if_ops * if_ops, t_u16 card_type)
+{
+	moal_handle *handle = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int netlink_num = NETLINK_NXP;
+	int index = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct netlink_kernel_cfg cfg = {
+		.groups = NL_MULTICAST_GROUP,
+	};
+#endif
+
+	ENTER();
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
+		goto exit_sem_err;
+
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == NULL)
+			break;
+	}
+	if (index >= MAX_MLAN_ADAPTER)
+		goto err_handle;
+
+	/* Allocate buffer for moal_handle */
+	handle = kzalloc(sizeof(moal_handle), GFP_KERNEL);
+	if (!handle) {
+		PRINTM(MERROR, "Allocate buffer for moal_handle failed!\n");
+		goto err_handle;
+	}
+
+	/* Init moal_handle */
+	handle->card = card;
+
+	/* Save the handle */
+	m_handle[index] = handle;
+	handle->handle_idx = index;
+
+	handle->hotplug_device = dev;
+	handle->card_type = card_type;
+	/* Attach moal handle ops */
+	PRINTM(MMSG,
+	       "Attach moal handle ops, card interface type: 0x%x\n",
+	       handle->card_type);
+	moal_memcpy_ext(handle, &handle->ops, if_ops, sizeof(*if_ops),
+			sizeof(handle->ops));
+	handle->second_mac = handle->ops.is_second_mac(handle);
+	if (handle->second_mac) {
+		if ((index >= 1) && m_handle[index - 1]) {
+			handle->pref_mac = (void *)m_handle[index - 1];
+			m_handle[index - 1]->pref_mac = (void *)handle;
+		}
+	}
+
+	/* Init module parameters */
+	woal_init_module_param(handle);
+#ifdef IMX_SUPPORT
+#ifdef SDIO
+	if (IS_SD(handle->card_type)) {
+		moal_extflg_set(handle, EXT_TX_WORK);
+		moal_extflg_set(handle, EXT_TX_SKB_CLONE);
+	}
+#endif
+#endif
+
+	if (handle->params.mac_addr
+#ifdef MFG_CMD_SUPPORT
+	    && handle->params.mfg_mode != MLAN_INIT_PARA_ENABLED
+#endif
+		) {
+		t_u8 temp[20];
+		t_u8 len = strlen(handle->params.mac_addr) + 1;
+		if (len < sizeof(temp)) {
+			moal_memcpy_ext(handle, temp,
+					handle->params.mac_addr, len,
+					sizeof(temp));
+			handle->set_mac_addr = 1;
+			/* note: the following function overwrites the
+			 * temp buffer */
+			woal_mac2u8(handle->mac_addr, temp);
+		}
+	}
+
+	/* Get card info */
+	woal_get_card_info(handle);
+	/** Get card revision */
+	handle->ops.get_fw_name(handle);
+#ifdef STA_SUPPORT
+	handle->scan_pending_on_block = MFALSE;
+	MOAL_INIT_SEMAPHORE(&handle->async_sem);
+#endif
+
+#if defined(USB)
+	if (IS_USB(handle->card_type))
+		handle->boot_state = ((struct usb_card_rec *)card)->boot_state;
+#endif /* USB_NEW_FW_DNLD */
+	/* Init SW */
+	if (MLAN_STATUS_SUCCESS != woal_init_sw(handle)) {
+		PRINTM(MFATAL, "Software Init Failed\n");
+		goto err_kmalloc;
+	}
+
+	do {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+		handle->nl_sk = netlink_kernel_create(netlink_num, NULL);
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+		handle->nl_sk =
+			netlink_kernel_create(netlink_num, NL_MULTICAST_GROUP,
+					      NULL, THIS_MODULE);
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+		handle->nl_sk =
+			netlink_kernel_create(netlink_num, NL_MULTICAST_GROUP,
+					      NULL, NULL, THIS_MODULE);
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+		handle->nl_sk = netlink_kernel_create(&init_net, netlink_num,
+						      NL_MULTICAST_GROUP, NULL,
+						      NULL, THIS_MODULE);
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
+		handle->nl_sk = netlink_kernel_create(&init_net, netlink_num,
+						      THIS_MODULE, &cfg);
+#else
+		handle->nl_sk =
+			netlink_kernel_create(&init_net, netlink_num, &cfg);
+#endif
+#endif
+#endif
+#endif
+#endif
+		if (handle->nl_sk) {
+			PRINTM(MINFO, "Netlink number = %d\n", netlink_num);
+			handle->netlink_num = netlink_num;
+			break;
+		}
+		netlink_num--;
+	} while (netlink_num > 0);
+
+	if (handle->nl_sk == NULL) {
+		PRINTM(MERROR,
+		       "Could not initialize netlink event passing mechanism!\n");
+		goto err_kmalloc;
+	}
+
+	/* Create workqueue for main process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+	/* For kernel less than 2.6.14 name can not be
+	 * greater than 10 characters */
+	handle->workqueue = create_workqueue("MOAL_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+	handle->workqueue =
+		alloc_workqueue("MOAL_WORK_QUEUE",
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+	handle->workqueue = create_workqueue("MOAL_WORK_QUEUE");
+#endif
+#endif
+	if (!handle->workqueue)
+		goto err_kmalloc;
+
+	MLAN_INIT_WORK(&handle->main_work, woal_main_work_queue);
+
+	/* Create workqueue for event process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+	/* For kernel less than 2.6.14 name can not be
+	 * greater than 10 characters */
+	handle->evt_workqueue = create_workqueue("MOAL_EVT_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+	handle->evt_workqueue =
+		alloc_workqueue("MOAL_EVT_WORK_QUEUE",
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+	handle->evt_workqueue = create_workqueue("MOAL_EVT_WORK_QUEUE");
+#endif
+#endif
+	if (!handle->evt_workqueue) {
+		woal_terminate_workqueue(handle);
+		goto err_kmalloc;
+	}
+
+	MLAN_INIT_WORK(&handle->evt_work, woal_evt_work_queue);
+	INIT_LIST_HEAD(&handle->evt_queue);
+	spin_lock_init(&handle->evt_lock);
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	MLAN_INIT_WORK(&handle->regulatory_work, woal_regulatory_work_queue);
+#endif
+#endif
+
+#ifdef STA_CFG80211
+	INIT_DELAYED_WORK(&handle->scan_timeout_work,
+		woal_scan_timeout_handler);
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	MLAN_INIT_WORK(&handle->host_mlme_work, woal_host_mlme_work_queue);
+#endif
+#endif
+
+	if (!moal_extflg_isset(handle, EXT_NAPI)) {
+		/* Create workqueue for rx process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+		/* For kernel less than 2.6.14 name can not be
+		 * greater than 10 characters */
+		handle->rx_workqueue = create_workqueue("MOAL_RX_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+		handle->rx_workqueue =
+			alloc_workqueue("MOAL_RX_WORK_QUEUE",
+					WQ_HIGHPRI | WQ_MEM_RECLAIM |
+					WQ_UNBOUND, 1);
+#else
+		handle->rx_workqueue = create_workqueue("MOAL_RX_WORK_QUEUE");
+#endif
+#endif
+		if (!handle->rx_workqueue) {
+			woal_terminate_workqueue(handle);
+			goto err_kmalloc;
+		}
+		MLAN_INIT_WORK(&handle->rx_work, woal_rx_work_queue);
+	}
+#define NAPI_BUDGET 64
+	if (moal_extflg_isset(handle, EXT_NAPI)) {
+		init_dummy_netdev(&handle->napi_dev);
+		netif_napi_add(&handle->napi_dev, &handle->napi_rx,
+			       woal_netdev_poll_rx, NAPI_BUDGET);
+		napi_enable(&handle->napi_rx);
+	}
+
+	if (moal_extflg_isset(handle, EXT_TX_WORK)) {
+		/* Create workqueue for tx process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+		handle->tx_workqueue = create_workqueue("MOAL_TX_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+		handle->tx_workqueue = alloc_workqueue("MOAL_TX_WORK_QUEUE",
+						       WQ_HIGHPRI |
+						       WQ_MEM_RECLAIM |
+						       WQ_UNBOUND, 1);
+#else
+		handle->tx_workqueue = create_workqueue("MOAL_TX_WORK_QUEUE");
+#endif
+#endif
+		if (!handle->tx_workqueue) {
+			woal_terminate_workqueue(handle);
+			goto err_kmalloc;
+		}
+		MLAN_INIT_WORK(&handle->tx_work, woal_tx_work_handler);
+	}
+
+#ifdef REASSOCIATION
+	PRINTM(MINFO, "Starting re-association thread...\n");
+	handle->reassoc_thread.handle = handle;
+	woal_create_thread(woal_reassociation_thread,
+			   &handle->reassoc_thread, "woal_reassoc_service");
+
+	while (!handle->reassoc_thread.pid)
+		woal_sched_timeout(2);
+#endif /* REASSOCIATION */
+
+	/* Register the device. Fill up the private data structure with
+	 * relevant information from the card and request for the
+	 * required IRQ.
+	 */
+	if (handle->ops.register_dev(handle) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "Failed to register wlan device!\n");
+		goto err_registerdev;
+	}
+	woal_update_firmware_name(handle);
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+	wakeup_source_init(&handle->ws, "mwlan");
+#else
+	wake_lock_init(&handle->wake_lock, WAKE_LOCK_SUSPEND, "mwlan");
+#endif
+#endif
+
+	/* Init FW and HW */
+	if (MLAN_STATUS_SUCCESS != woal_init_fw(handle)) {
+		PRINTM(MFATAL, "Firmware Init Failed\n");
+		goto err_init_fw;
+	}
+	device_init_wakeup(dev, true);
+#ifdef SD8887
+	if (IS_SD8887(handle->card_type)) {
+		union {
+			t_u32 l;
+			t_u8 c[4];
+		} ver;
+		ver.l = handle->fw_release_number;
+		if (ver.c[1] == 75) {
+			handle->card_info->embedded_supp = 0;
+			PRINTM(MMSG,
+			       "Disable EMBEDED Supplicant for SD8887-FP75\n");
+		}
+	}
+#endif
+	LEAVE();
+	return handle;
+
+err_init_fw:
+	if ((handle->hardware_status == HardwareStatusFwReady) ||
+	    (handle->hardware_status == HardwareStatusReady)) {
+		PRINTM(MINFO, "shutdown mlan\n");
+		handle->init_wait_q_woken = MFALSE;
+		status = mlan_shutdown_fw(handle->pmlan_adapter);
+		if (status == MLAN_STATUS_PENDING)
+			wait_event_interruptible(handle->init_wait_q,
+						 handle->init_wait_q_woken);
+	}
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+	wakeup_source_trash(&handle->ws);
+#else
+	wake_lock_destroy(&handle->wake_lock);
+#endif
+#endif
+	/* Unregister device */
+	PRINTM(MINFO, "unregister device\n");
+	handle->ops.unregister_dev(handle);
+err_registerdev:
+	handle->surprise_removed = MTRUE;
+#ifdef REASSOCIATION
+	if (handle->reassoc_thread.pid)
+		wake_up_interruptible(&handle->reassoc_thread.wait_q);
+	/* waiting for main thread quit */
+	while (handle->reassoc_thread.pid)
+		woal_sched_timeout(2);
+#endif /* REASSOCIATION */
+	if (moal_extflg_isset(handle, EXT_NAPI))
+		netif_napi_del(&handle->napi_rx);
+	woal_terminate_workqueue(handle);
+err_kmalloc:
+	woal_free_moal_handle(handle);
+	if (index < MAX_MLAN_ADAPTER)
+		m_handle[index] = NULL;
+err_handle:
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+exit_sem_err:
+	LEAVE();
+	return NULL;
+}
+
+/**
+ *  @brief This function removes the card.
+ *
+ *  @param card    A pointer to card
+ *
+ *  @return        MLAN_STATUS_SUCCESS
+ */
+mlan_status
+woal_remove_card(void *card)
+{
+	moal_handle *handle = NULL;
+	moal_private *priv = NULL;
+	mlan_status status;
+	int i;
+	int index = 0;
+
+	ENTER();
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
+		goto exit_sem_err;
+	/* Find the correct handle */
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] && (m_handle[index]->card == card)) {
+			handle = m_handle[index];
+			break;
+		}
+	}
+	if (!handle)
+		goto exit_remove;
+	device_init_wakeup(handle->hotplug_device, false);
+#ifdef MFG_CMD_SUPPORT
+	if (handle->params.mfg_mode == MLAN_INIT_PARA_ENABLED
+#if defined(USB)
+	    && handle->boot_state == USB_FW_READY
+#endif
+		) {
+		if (handle->params.fw_name) {
+			kfree(handle->params.fw_name);
+			handle->params.fw_name = NULL;
+		}
+	}
+#endif
+	if (handle->rf_test_mode)
+		woal_process_rf_test_mode(handle, MFG_CMD_UNSET_TEST_MODE);
+	handle->surprise_removed = MTRUE;
+
+	woal_flush_workqueue(handle);
+
+	if (moal_extflg_isset(handle, EXT_NAPI)) {
+		napi_disable(&handle->napi_rx);
+		netif_napi_del(&handle->napi_rx);
+	}
+
+	/* Stop data */
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		priv = handle->priv[i];
+		if (priv) {
+			if (priv->netdev) {
+				woal_stop_queue(priv->netdev);
+				if (netif_carrier_ok(priv->netdev))
+					netif_carrier_off(priv->netdev);
+			}
+		}
+	}
+	if ((handle->hardware_status == HardwareStatusFwReady) ||
+	    (handle->hardware_status == HardwareStatusReady)) {
+		/* Shutdown firmware */
+		PRINTM(MIOCTL, "mlan_shutdown_fw.....\n");
+		handle->init_wait_q_woken = MFALSE;
+
+		status = mlan_shutdown_fw(handle->pmlan_adapter);
+		if (status == MLAN_STATUS_PENDING)
+			wait_event_interruptible(handle->init_wait_q,
+						 handle->init_wait_q_woken);
+		PRINTM(MIOCTL, "mlan_shutdown_fw done!\n");
+	}
+	/* Unregister mlan */
+	if (handle->pmlan_adapter) {
+		mlan_unregister(handle->pmlan_adapter);
+		handle->pmlan_adapter = NULL;
+	}
+	if (atomic_read(&handle->rx_pending) ||
+	    atomic_read(&handle->tx_pending) ||
+	    atomic_read(&handle->ioctl_pending)) {
+		PRINTM(MERROR,
+		       "ERR: rx_pending=%d,tx_pending=%d,ioctl_pending=%d\n",
+		       atomic_read(&handle->rx_pending),
+		       atomic_read(&handle->tx_pending),
+		       atomic_read(&handle->ioctl_pending));
+	}
+	unregister_inetaddr_notifier(&handle->woal_notifier);
+#if IS_ENABLED(CONFIG_IPV6)
+	unregister_inet6addr_notifier(&handle->woal_inet6_notifier);
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	if (handle->is_remain_timer_set) {
+		woal_cancel_timer(&handle->remain_timer);
+		woal_remain_timer_func(handle);
+	}
+#endif
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	if (handle->is_go_timer_set) {
+		woal_cancel_timer(&handle->go_timer);
+		handle->is_go_timer_set = MFALSE;
+	}
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	/* Remove virtual interface */
+	woal_remove_virtual_interface(handle);
+#endif
+#endif
+#endif
+	if (handle->tp_acnt.on) {
+		handle->tp_acnt.on = 0;
+		handle->tp_acnt.drop_point = 0;
+		if (handle->is_tp_acnt_timer_set) {
+			woal_cancel_timer(&handle->tp_acnt.timer);
+			handle->is_tp_acnt_timer_set = MFALSE;
+		}
+	}
+
+	/* Remove interface */
+	for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, handle->priv_num); i++)
+		woal_remove_interface(handle, i);
+
+	woal_terminate_workqueue(handle);
+
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	if (handle->is_cac_timer_set) {
+		woal_cancel_timer(&handle->cac_timer);
+		handle->is_cac_timer_set = MFALSE;
+	}
+#endif
+#endif
+#ifdef REASSOCIATION
+	PRINTM(MINFO, "Free reassoc_timer\n");
+	if (handle->is_reassoc_timer_set) {
+		woal_cancel_timer(&handle->reassoc_timer);
+		handle->is_reassoc_timer_set = MFALSE;
+	}
+	if (handle->reassoc_thread.pid)
+		wake_up_interruptible(&handle->reassoc_thread.wait_q);
+
+	/* waiting for main thread quit */
+	while (handle->reassoc_thread.pid)
+		woal_sched_timeout(2);
+#endif /* REASSOCIATION */
+
+	PRINTM(MINFO, "Free FW dump timer\n");
+	if (handle->is_fw_dump_timer_set) {
+		woal_cancel_timer(&handle->fw_dump_timer);
+		handle->is_fw_dump_timer_set = MFALSE;
+	}
+#ifdef CONFIG_PROC_FS
+	woal_proc_exit(handle);
+#endif
+	/* Unregister device */
+	PRINTM(MINFO, "unregister device\n");
+	handle->ops.unregister_dev(handle);
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+	wakeup_source_trash(&handle->ws);
+#else
+	wake_lock_destroy(&handle->wake_lock);
+#endif
+#endif
+	/* Free adapter structure */
+	PRINTM(MINFO, "Free Adapter\n");
+	woal_free_moal_handle(handle);
+
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == handle) {
+			m_handle[index] = NULL;
+			break;
+		}
+	}
+exit_remove:
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+exit_sem_err:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef CONFIG_PROC_FS
+/**
+ *  @brief This function switch the drv_mode
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param mode     new drv_mode to switch.
+ *
+ *  @return        MLAN_STATUS_SUCCESS /MLAN_STATUS_FAILURE
+ * /MLAN_STATUS_PENDING
+ */
+mlan_status
+woal_switch_drv_mode(moal_handle *handle, t_u32 mode)
+{
+	unsigned int i;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+
+	ENTER();
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
+		goto exit_sem_err;
+
+	if (woal_update_drv_tbl(handle, mode) != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Could not update driver mode table!\n");
+		status = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+
+	/* Reset all interfaces */
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE);
+
+	status = woal_shutdown_fw(priv, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "func shutdown failed!\n");
+		goto exit;
+	}
+#ifdef USB
+	handle->skip_fw_dnld = MTRUE;
+#endif
+
+	/* Shutdown firmware */
+	PRINTM(MIOCTL, "mlan_shutdown_fw.....\n");
+	handle->init_wait_q_woken = MFALSE;
+	status = mlan_shutdown_fw(handle->pmlan_adapter);
+	if (status == MLAN_STATUS_PENDING)
+		wait_event_interruptible(handle->init_wait_q,
+					 handle->init_wait_q_woken);
+	PRINTM(MIOCTL, "mlan_shutdown_fw done!\n");
+	/* Unregister mlan */
+	if (handle->pmlan_adapter) {
+		mlan_unregister(handle->pmlan_adapter);
+		handle->pmlan_adapter = NULL;
+	}
+	if (atomic_read(&handle->rx_pending) ||
+	    atomic_read(&handle->tx_pending) ||
+	    atomic_read(&handle->ioctl_pending)) {
+		PRINTM(MERROR,
+		       "ERR: rx_pending=%d,tx_pending=%d,ioctl_pending=%d\n",
+		       atomic_read(&handle->rx_pending),
+		       atomic_read(&handle->tx_pending),
+		       atomic_read(&handle->ioctl_pending));
+	}
+
+	unregister_inetaddr_notifier(&handle->woal_notifier);
+#if IS_ENABLED(CONFIG_IPV6)
+	unregister_inet6addr_notifier(&handle->woal_inet6_notifier);
+#endif
+
+	/* Remove interface */
+	for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, handle->priv_num); i++)
+		woal_remove_interface(handle, i);
+
+	if (atomic_read(&handle->lock_count) ||
+	    atomic_read(&handle->malloc_count) ||
+	    atomic_read(&handle->mbufalloc_count)) {
+		PRINTM(MERROR,
+		       "mlan has memory leak: lock_count=%d, malloc_count=%d, mbufalloc_count=%d\n",
+		       atomic_read(&handle->lock_count),
+		       atomic_read(&handle->malloc_count),
+		       atomic_read(&handle->mbufalloc_count));
+	}
+#ifdef PCIE
+	if (IS_PCIE(handle->card_type) &&
+	    atomic_read(&handle->malloc_cons_count)) {
+		PRINTM(MERROR,
+		       "mlan has memory leak: malloc_cons_count=%d\n",
+		       atomic_read(&handle->malloc_cons_count));
+	}
+#endif
+
+	handle->priv_num = 0;
+	handle->params.drv_mode = mode;
+	/* Init SW */
+	if (woal_init_sw(handle)) {
+		PRINTM(MFATAL, "Software Init Failed\n");
+		goto exit;
+	}
+	/* Init FW and HW */
+	if (woal_init_fw(handle)) {
+		PRINTM(MFATAL, "Firmware Init Failed\n");
+		goto exit;
+	}
+	LEAVE();
+	return status;
+exit:
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+exit_sem_err:
+	LEAVE();
+	return status;
+}
+#endif
+
+#ifdef SDIO_MMC
+#define FW_POLL_TRIES 100
+
+/**
+ *  @brief This function reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param mode     FW_RELOAD_SDIO_INBAND_RESET or FW_RELOAD_SDIO_HW_RESET
+ *
+ *  @return        0--success, otherwise failure
+ */
+static int
+woal_reset_and_reload_fw(moal_handle *handle, t_u8 mode)
+{
+	int ret = 0, tries = 0;
+	t_u32 value = 1;
+	t_u32 reset_reg = handle->card_info->fw_reset_reg;
+	t_u8 reset_val = handle->card_info->fw_reset_val;
+
+	ENTER();
+	if (mode == FW_RELOAD_SDIO_HW_RESET) {
+		PRINTM(MCMND, "woal_sdio_reset_fw...\n");
+		woal_sdio_reset_hw(handle);
+		goto reload_fw;
+	}
+	if (!IS_SD9098(handle->card_type) &&
+	    !IS_SD9097(handle->card_type) && !IS_SD9177(handle->card_type)) {
+		mlan_pm_wakeup_card(handle->pmlan_adapter, MTRUE);
+		/** wait SOC fully wake up */
+		for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+			ret = handle->ops.write_reg(handle, reset_reg, 0xba);
+			if (ret == MLAN_STATUS_SUCCESS) {
+				handle->ops.read_reg(handle, reset_reg, &value);
+				if (value == 0xba) {
+					PRINTM(MMSG, "FW wake up\n");
+					break;
+				}
+			}
+			udelay(1000);
+		}
+	}
+	/* Write register to notify FW */
+	if (handle->ops.write_reg(handle, reset_reg, reset_val) !=
+	    MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to write register.\n");
+		ret = -EFAULT;
+		goto done;
+	}
+#if defined(SD9098) || defined(SD9097) || defined(SD9177)
+	if (IS_SD9098(handle->card_type) ||
+	    IS_SD9097(handle->card_type) || IS_SD9177(handle->card_type))
+		handle->ops.write_reg(handle, 0x00, 0x10);
+#endif
+	/* Poll register around 100 ms */
+	for (tries = 0; tries < FW_POLL_TRIES; ++tries) {
+		handle->ops.read_reg(handle, reset_reg, &value);
+		if (value == 0)
+			/* FW is ready */
+			break;
+		udelay(1000);
+	}
+
+	if (value) {
+		PRINTM(MERROR,
+		       "Failed to poll FW reset register %X=0x%x\n",
+		       reset_reg, value);
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!IS_SD9098(handle->card_type) &&
+	    !IS_SD9097(handle->card_type) && !IS_SD9177(handle->card_type))
+		mlan_pm_wakeup_card(handle->pmlan_adapter, MFALSE);
+reload_fw:
+	/* Download FW */
+	ret = woal_request_fw(handle);
+	if (ret) {
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MMSG, "FW Reload successfully.");
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function reload fw
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return        0--success, otherwise failure
+ */
+static int
+woal_reload_fw(moal_handle *handle)
+{
+	int ret = 0;
+	ENTER();
+	/* Download FW */
+	ret = woal_request_fw(handle);
+	if (ret) {
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MMSG, "FW Reload successfully.");
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handle the pre_reset
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return        NULL;
+ */
+static void
+woal_pre_reset(moal_handle *handle)
+{
+	int intf_num;
+	t_u8 driver_status = handle->driver_status;
+	t_u8 i;
+	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	mlan_debug_info *info = &(handle->debug_info);
+	int ioctl_pending = 0;
+
+	ENTER();
+	if (!driver_status && priv)
+		woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+	handle->driver_status = MTRUE;
+
+	if (!driver_status)
+		woal_sched_timeout_uninterruptible(MOAL_TIMER_1S);
+
+	//wait for IOCTL return
+	if (!driver_status && priv) {
+		for (i = 0; i < 5; i++) {
+			woal_get_debug_info(priv, MOAL_IOCTL_WAIT, info);
+			ioctl_pending = atomic_read(&handle->ioctl_pending);
+			if (!info->pending_cmd && !ioctl_pending) {
+				PRINTM(MCMND,
+				       "fw_reload: No pending command and IOCTL\n");
+				break;
+			}
+			woal_sched_timeout_uninterruptible(MOAL_TIMER_1S);
+		}
+	}
+	/** detach network interface */
+	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+		if (handle->priv[intf_num]) {
+			woal_stop_queue(handle->priv[intf_num]->netdev);
+			netif_device_detach(handle->priv[intf_num]->netdev);
+		}
+	}
+    /** mask host interrupt from firmware */
+	mlan_disable_host_int(handle->pmlan_adapter);
+	/** cancel all pending commands */
+	mlan_ioctl(handle->pmlan_adapter, NULL);
+	woal_flush_workqueue(handle);
+
+	handle->fw_reload = MTRUE;
+	woal_update_firmware_name(handle);
+#ifdef USB
+	if (IS_USB(handle->card_type))
+		woal_kill_urbs(handle);
+#endif
+	LEAVE();
+}
+
+/**
+ *  @brief This function handle pose_reset
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return        NULL;
+ */
+static void
+woal_post_reset(moal_handle *handle)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int intf_num;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	t_u8 country_code[COUNTRY_CODE_LEN];
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+	t_u8 bss_role = MLAN_BSS_ROLE_STA;
+#endif
+#endif
+#endif /* WIFI_DIRECT_SUPPORT */
+
+	ENTER();
+	/** un-block IOCTL */
+	handle->fw_reload = MFALSE;
+	/* Restart the firmware */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req) {
+		misc = (mlan_ds_misc_cfg *)req->pbuf;
+		misc->sub_command = MLAN_OID_MISC_WARM_RESET;
+		misc->param.fw_reload = MTRUE;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		req->action = MLAN_ACT_SET;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_request_ioctl(woal_get_priv(handle,
+						     MLAN_BSS_ROLE_ANY),
+				       req, MOAL_IOCTL_WAIT_TIMEOUT)) {
+			kfree(req);
+			goto done;
+		}
+		kfree(req);
+	}
+#ifdef DEBUG_LEVEL1
+	drvdbg = handle->params.drvdbg;
+#endif
+	handle->driver_status = MFALSE;
+	handle->hardware_status = HardwareStatusReady;
+#ifdef STA_CFG80211
+	handle->scan_timeout = SCAN_TIMEOUT_25S;
+#endif
+	/* Reset all interfaces */
+	woal_reset_intf(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+			MOAL_IOCTL_WAIT, MTRUE);
+	/* Initialize private structures */
+	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+		if (handle->priv[intf_num]) {
+			woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+			if ((handle->priv[intf_num]->bss_type ==
+			     MLAN_BSS_TYPE_WIFIDIRECT) &&
+			    (GET_BSS_ROLE(handle->priv[intf_num]) ==
+			     MLAN_BSS_ROLE_UAP)) {
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_bss_role_cfg(handle->priv[intf_num],
+						      MLAN_ACT_SET,
+						      MOAL_IOCTL_WAIT,
+						      &bss_role)) {
+					goto done;
+				}
+			}
+#endif /* STA_WEXT || UAP_WEXT */
+#endif /* STA_SUPPORT && UAP_SUPPORT */
+#endif /* WIFI_DIRECT_SUPPORT */
+		}
+	}
+
+	/* Enable interfaces */
+	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
+		if (handle->priv[intf_num]) {
+			netif_device_attach(handle->priv[intf_num]->netdev);
+			woal_start_queue(handle->priv[intf_num]->netdev);
+		}
+	}
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	if (handle->country_code[0] && handle->country_code[1]) {
+		memset(country_code, 0, sizeof(country_code));
+		if (MTRUE ==
+		    is_cfg80211_special_region_code(handle->country_code)) {
+			country_code[0] = 'W';
+			country_code[1] = 'W';
+		} else {
+			country_code[0] = handle->country_code[0];
+			country_code[1] = handle->country_code[1];
+		}
+
+		if (handle->params.cntry_txpwr && priv)
+			woal_request_country_power_table(priv, country_code);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+		if (handle->params.cntry_txpwr == CNTRY_RGPOWER_MODE)
+			queue_work(handle->evt_workqueue,
+				   &handle->regulatory_work);
+#endif
+	}
+#endif
+
+done:
+	if (handle->dpd_data) {
+		release_firmware(handle->dpd_data);
+		handle->dpd_data = NULL;
+	}
+	if (handle->txpwr_data) {
+		release_firmware(handle->txpwr_data);
+		handle->txpwr_data = NULL;
+	}
+	if (handle->user_data) {
+		release_firmware(handle->user_data);
+		handle->user_data = NULL;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function reload fw
+ *
+ *  @param phandle   A pointer to moal_handle structure
+ *  @param mode     FW reload mode
+ *
+ *  @return        0--success, otherwise failure
+ */
+void
+woal_request_fw_reload(moal_handle *phandle, t_u8 mode)
+{
+	int ret = 0;
+
+#ifdef PCIE
+	ppcie_service_card card = NULL;
+	struct pci_dev *pdev = NULL;
+#endif
+	moal_handle *handle = phandle;
+	moal_handle *ref_handle = NULL;
+
+	ENTER();
+#ifdef PCIE
+	if (mode == FW_RELOAD_PCIE_RESET) {
+		card = (pcie_service_card *)handle->card;
+		pdev = card->dev;
+		pci_reset_function(pdev);
+		LEAVE();
+		return;
+	}
+#endif
+
+	// handle-> mac0 , ref_handle->second mac
+	if (handle->pref_mac) {
+		if (phandle->second_mac) {
+			handle = (moal_handle *)handle->pref_mac;
+			ref_handle = phandle;
+		} else {
+			ref_handle = (moal_handle *)handle->pref_mac;
+		}
+	}
+
+	if (mode == FW_RELOAD_WITH_EMULATION) {
+		fw_reload = FW_RELOAD_WITH_EMULATION;
+		PRINTM(MMSG, "FW reload with re-emulation...\n");
+		LEAVE();
+		return;
+	}
+	woal_pre_reset(handle);
+	if (ref_handle)
+		woal_pre_reset(ref_handle);
+	if (mode == FW_RELOAD_NO_EMULATION) {
+		ret = woal_reload_fw(handle);
+		if (ref_handle)
+			woal_reload_fw(ref_handle);
+	}
+#ifdef SDIO_MMC
+	else if ((mode == FW_RELOAD_SDIO_INBAND_RESET ||
+		  mode == FW_RELOAD_SDIO_HW_RESET) &&
+		 IS_SD(handle->card_type)) {
+		ret = woal_reset_and_reload_fw(handle, mode);
+		if (ref_handle)
+			woal_reload_fw(ref_handle);
+	}
+#endif
+	else
+		ret = -EFAULT;
+	if (ret) {
+		PRINTM(MERROR, "FW reload fail\n");
+		goto done;
+	}
+	woal_post_reset(handle);
+	if (ref_handle)
+		woal_post_reset(ref_handle);
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function register to bus driver
+ *
+ *  @param work   a pointer to struct work_struct
+ *
+ *  @return        N/A
+ */
+static void
+woal_bus_register(struct work_struct *work)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	PRINTM(MMSG, "wlan: Register to Bus Driver...\n");
+#ifdef SDIO
+#ifdef SDIO_MMC
+	/* Register SDIO driver */
+	ret = woal_sdiommc_bus_register();
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to register sdio_mmc bus driver\n");
+		goto out;
+	}
+#else
+	ret = woal_sdio_bus_register();
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to register sdio_mmc bus driver\n");
+		goto out;
+	}
+#endif
+#endif
+#ifdef USB
+	/* Register USB driver */
+	ret = woal_usb_bus_register();
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to register usb bus driver\n");
+		goto out;
+	}
+#endif
+#ifdef PCIE
+	/* Register PCIE driver */
+	ret = woal_pcie_bus_register();
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to register pcie bus driver\n");
+		goto out;
+	}
+#endif
+	PRINTM(MMSG, "wlan: Register to Bus Driver Done\n");
+out:
+	return;
+}
+
+/**
+ *  @brief This function unregister from bus driver
+ *
+ *
+ *  @return        N/A
+ */
+static void
+woal_bus_unregister(void)
+{
+#ifdef SDIO
+#ifdef SDIO_MMC
+	/* Unregister SDIO driver */
+	woal_sdiommc_bus_unregister();
+#else
+	woal_sdio_bus_unregister();
+#endif
+#endif
+#ifdef USB
+	/* Unregister USB driver */
+	woal_usb_bus_unregister();
+#endif
+#ifdef PCIE
+	/* Unregister PCIE driver */
+	woal_pcie_bus_unregister();
+#endif
+}
+
+/**
+ *  @brief This function initializes module.
+ *
+ *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static int
+woal_init_module(void)
+{
+	int ret = (int)MLAN_STATUS_SUCCESS;
+	int index = 0;
+
+	ENTER();
+
+	PRINTM(MMSG, "wlan: Loading MWLAN driver\n");
+	/* Init the wlan_private pointer array first */
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++)
+		m_handle[index] = NULL;
+	/* Init mutex */
+	MOAL_INIT_SEMAPHORE(&AddRemoveCardSem);
+
+	if (woal_root_proc_init() != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "woal_init_module: Unable to create /proc/mwlan/ directory\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+#ifdef CONFIG_OF
+	woal_init_from_dev_tree();
+#endif
+	/* Create workqueue for hang process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+	/* For kernel less than 2.6.14 name can not be greater than 10
+	   characters */
+	hang_workqueue = create_workqueue("MOAL_HANG_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+	hang_workqueue =
+		alloc_workqueue("MOAL_HANG_WORK_QUEUE",
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+	hang_workqueue = create_workqueue("MOAL_HANG_WORK_QUEUE");
+#endif
+#endif
+	MLAN_INIT_WORK(&hang_work, woal_hang_work_queue);
+
+	if(reg_work) {
+	/* Create workqueue for hang process */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+	/* For kernel less than 2.6.14 name can not be greater than 10
+	   characters */
+		register_workqueue = create_workqueue("MOAL_REGISTER_WORKQ");
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+		register_workqueue =
+			alloc_workqueue("MOAL_REGISTER_WORK_QUEUE",
+					WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+		register_workqueue = create_workqueue("MOAL_REGISTER_WORK_QUEUE");
+#endif
+#endif
+		MLAN_INIT_WORK(&register_work, woal_bus_register);
+		queue_work(register_workqueue, &register_work);
+	}
+	else {
+		woal_bus_register(NULL);
+	}
+	PRINTM(MMSG, "wlan: Driver loaded successfully\n");
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans module
+ *
+ *  @return        N/A
+ */
+static void
+woal_cleanup_module(void)
+{
+	moal_handle *handle = NULL;
+	int index = 0;
+	int i;
+#if defined(STA_SUPPORT) && defined(STA_CFG80211)
+	unsigned long flags;
+#endif
+
+	ENTER();
+
+	PRINTM(MMSG, "wlan: Unloading MWLAN driver\n");
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
+		goto exit_sem_err;
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		handle = m_handle[index];
+		if (!handle)
+			continue;
+		if (!handle->priv_num)
+			goto exit;
+		if (MTRUE == woal_check_driver_status(handle))
+			goto exit;
+
+#ifdef USB
+#ifdef CONFIG_USB_SUSPEND
+		if (IS_USB(handle->card_type) && handle->is_suspended == MTRUE) {
+			woal_exit_usb_suspend(handle);
+		}
+#endif /* CONFIG_USB_SUSPEND */
+#endif
+
+#ifdef SDIO
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+		if (handle->is_suspended == MTRUE) {
+			woal_sdio_resume(&
+					 (((struct sdio_mmc_card *)handle->card)
+					  ->func)
+->dev);
+		}
+#endif /* MMC_PM_KEEP_POWER */
+#endif /* SDIO_SUSPEND_RESUME */
+#endif
+
+		if (handle->rf_test_mode)
+			woal_process_rf_test_mode(handle,
+						  MFG_CMD_UNSET_TEST_MODE);
+
+		for (i = 0; i < handle->priv_num; i++) {
+#ifdef STA_SUPPORT
+			if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
+				if (handle->priv[i]->media_connected == MTRUE) {
+					woal_disconnect(handle->priv[i],
+							MOAL_IOCTL_WAIT_TIMEOUT,
+							NULL,
+							DEF_DEAUTH_REASON_CODE);
+					if (handle->ioctl_timeout) {
+						woal_ioctl_timeout(handle);
+						goto exit;
+					}
+				}
+#ifdef STA_CFG80211
+				if (IS_STA_CFG80211
+				    (handle->params.cfg80211_wext) &&
+				    (handle->priv[i]->bss_type ==
+				     MLAN_BSS_TYPE_STA))
+					woal_clear_conn_params(handle->priv[i]);
+				spin_lock_irqsave(&handle->scan_req_lock,
+						  flags);
+				if (IS_STA_CFG80211
+				    (handle->params.cfg80211_wext) &&
+				    handle->scan_request) {
+					cancel_delayed_work(
+						&handle->scan_timeout_work);
+					woal_cfg80211_scan_done(handle->
+								scan_request,
+								MTRUE);
+					handle->scan_request = NULL;
+					handle->scan_priv = NULL;
+				}
+				spin_unlock_irqrestore(&handle->scan_req_lock,
+						       flags);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+				if (IS_STA_CFG80211
+				    (handle->params.cfg80211_wext) &&
+				    handle->priv[i]->sched_scanning) {
+					woal_stop_bg_scan(handle->priv[i],
+							  MOAL_IOCTL_WAIT_TIMEOUT);
+					if (handle->ioctl_timeout) {
+						woal_ioctl_timeout(handle);
+						goto exit;
+					}
+					handle->priv[i]->bg_scan_start = MFALSE;
+					handle->priv[i]
+						->bg_scan_reported = MFALSE;
+					cfg80211_sched_scan_stopped(handle->
+								    priv[i]
+								    ->wdev->
+								    wiphy
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+								    ,
+								    handle->
+								    priv[i]
+								    ->
+								    bg_scan_reqid
+#endif
+						);
+					handle->priv[i]->sched_scanning =
+						MFALSE;
+				}
+#endif
+#endif
+			}
+#endif
+#ifdef UAP_SUPPORT
+			if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
+#ifdef MFG_CMD_SUPPORT
+				if (handle->params.mfg_mode !=
+				    MLAN_INIT_PARA_ENABLED)
+#endif
+				{
+					woal_disconnect(handle->priv[i],
+							MOAL_IOCTL_WAIT_TIMEOUT,
+							NULL,
+							DEF_DEAUTH_REASON_CODE);
+					if (handle->ioctl_timeout) {
+						woal_ioctl_timeout(handle);
+						goto exit;
+					}
+				}
+			}
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+			woal_clear_all_mgmt_ies(handle->priv[i],
+						MOAL_IOCTL_WAIT_TIMEOUT);
+			if (handle->ioctl_timeout) {
+				woal_ioctl_timeout(handle);
+				goto exit;
+			}
+			woal_flush_tx_stat_queue(handle->priv[i]);
+#endif
+
+		}
+
+#ifdef MFG_CMD_SUPPORT
+		if (handle->params.mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		{
+			woal_set_deep_sleep(woal_get_priv(handle,
+							  MLAN_BSS_ROLE_ANY),
+					    MOAL_IOCTL_WAIT_TIMEOUT, MFALSE, 0);
+		}
+#ifdef MFG_CMD_SUPPORT
+		if (handle->params.mfg_mode != MLAN_INIT_PARA_ENABLED)
+#endif
+		{
+			woal_shutdown_fw(woal_get_priv(handle,
+						       MLAN_BSS_ROLE_ANY),
+					 MOAL_IOCTL_WAIT_TIMEOUT);
+			if (handle->ioctl_timeout) {
+				woal_ioctl_timeout(handle);
+				goto exit;
+			}
+		}
+	}
+
+exit:
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+exit_sem_err:
+	/* Unregister from bus */
+	woal_bus_unregister();
+	PRINTM(MMSG, "wlan: Driver unloaded\n");
+	if (hang_workqueue) {
+		flush_workqueue(hang_workqueue);
+		destroy_workqueue(hang_workqueue);
+		hang_workqueue = NULL;
+	}
+	if (reg_work && register_workqueue) {
+		flush_workqueue(register_workqueue);
+		destroy_workqueue(register_workqueue);
+		register_workqueue = NULL;
+	}
+
+	woal_root_proc_remove();
+
+	LEAVE();
+}
+
+#ifndef MODULE
+#ifdef MFG_CMD_SUPPORT
+/**
+ *  @brief This function handle the mfg_mode from kernel boot command
+ *
+ *  @param str     buffer for mfg_mode
+ *  @return        N/A
+ */
+static int __init
+mfg_mode_setup(char *str)
+{
+	int val = -1;
+	get_option(&str, &val);
+	if (val > 0)
+		mfg_mode = 1;
+	PRINTM(MMSG, "mfg_mode=%d\n", mfg_mode);
+	return 1;
+}
+
+__setup("mfg_mode=", mfg_mode_setup);
+#endif
+#endif
+
+module_init(woal_init_module);
+module_exit(woal_cleanup_module);
+
+module_param(reg_work, int, 0);
+MODULE_PARM_DESC(reg_work, "0: disable register work_queue; 1: enable register work_queue");
+
+MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_AUTHOR("NXP");
+MODULE_VERSION(MLAN_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/wlan_sd8987/mlinux/moal_main.h b/wlan_sd8987/mlinux/moal_main.h
new file mode 100755
index 0000000..f9f3639
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_main.h
@@ -0,0 +1,3479 @@
+/** @file moal_main.h
+ *
+ * @brief This file contains wlan driver specific defines etc.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#ifndef _MOAL_MAIN_H
+#define _MOAL_MAIN_H
+
+/* warnfix for FS redefination if any? */
+#ifdef FS
+#undef FS
+#endif
+
+/* Linux header files */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/param.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/irqreturn.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+#include <linux/namei.h>
+#include <linux/fs.h>
+#endif
+#include <linux/of.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <linux/config.h>
+#endif
+
+#ifdef USB
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+#include <linux/freezer.h>
+#endif
+#include <linux/usb.h>
+#endif /* USB */
+
+/* ASM files */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#include <asm/switch_to.h>
+#else
+#include <asm/system.h>
+#endif
+
+#include <linux/spinlock.h>
+
+/* Net header files */
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/inet.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
+#include <net/sock.h>
+#include <net/arp.h>
+#include <linux/rtnetlink.h>
+#include <linux/inetdevice.h>
+
+#include <linux/firmware.h>
+
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+#include <linux/pm_wakeup.h>
+#include <linux/device.h>
+#else
+#include <linux/wakelock.h>
+#endif
+#endif
+
+#include "mlan.h"
+#include "moal_shim.h"
+/* Wireless header */
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include <net/lib80211.h>
+#include <net/cfg80211.h>
+#include <net/ieee80211_radiotap.h>
+#endif
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include "moal_wext.h"
+#endif
+#ifdef STA_WEXT
+#include "moal_priv.h"
+#endif
+
+#ifdef IMX_SUPPORT
+#include <linux/of_irq.h>
+#include <linux/suspend.h>
+#endif /* IMX_SUPPORT */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+#include <linux/pm_qos.h>
+#endif
+
+#ifndef MIN
+/** Find minimum */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/** Find maximum */
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define COMPAT_VERSION_CODE KERNEL_VERSION(0, 0, 0)
+#define CFG80211_VERSION_CODE MAX(LINUX_VERSION_CODE, COMPAT_VERSION_CODE)
+
+/**
+ * Reason Code 3: STA is leaving (or has left) IBSS or ESS
+ */
+#define DEF_DEAUTH_REASON_CODE (0x3)
+
+/**
+ * 802.1 Local Experimental 1.
+ */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24)
+#define REFDATA __refdata
+#else
+#define REFDATA
+#endif
+
+/**
+ * Linux Kernels later 3.9 use CONFIG_PM_RUNTIME instead of
+ * CONFIG_USB_SUSPEND
+ * Linux Kernels later 3.19 use CONFIG_PM instead of
+ * CONFIG_PM_RUNTIME
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+#ifdef CONFIG_PM
+#ifndef CONFIG_USB_SUSPEND
+#define CONFIG_USB_SUSPEND
+#endif
+#ifndef CONFIG_PM_RUNTIME
+#define CONFIG_PM_RUNTIME
+#endif
+#endif
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
+#ifdef CONFIG_PM_RUNTIME
+#ifndef CONFIG_USB_SUSPEND
+#define CONFIG_USB_SUSPEND
+#endif
+#endif
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
+#endif
+
+/**
+ * Linux kernel later 3.10 use strncasecmp instead of strnicmp
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+#define strnicmp strncasecmp
+#endif
+
+/**
+ * Linux kernel later 4.7 use nl80211_band instead of ieee80211_band
+ * Linux kernel later 4.7 use new macro
+ */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+#define ieee80211_band nl80211_band
+#define IEEE80211_BAND_2GHZ NL80211_BAND_2GHZ
+#define IEEE80211_BAND_5GHZ NL80211_BAND_5GHZ
+#define IEEE80211_NUM_BANDS NUM_NL80211_BANDS
+#endif
+
+/**
+ * interface name
+ */
+#define default_mlan_name "mlan%d"
+#define default_uap_name "uap%d"
+#define default_wfd_name "wfd%d"
+#define default_nan_name "nan%d"
+#define default_mpl_name "mpl%d"
+#define default_11p_name "ocb%d"
+#define mwiphy_name "mwiphy%d"
+
+/** country txpower mode */
+#define CNTRY_TXPOWER_MODE  1
+/** country rgpower mode */
+#define CNTRY_RGPOWER_MODE  2
+
+/** Define BOOLEAN */
+typedef t_u8 BOOLEAN;
+
+#define INTF_CARDTYPE "----------%s-MXM"
+
+#define KERN_VERSION "5X"
+
+#define V14 "14"
+#define V15 "15"
+#define V16 "16"
+#define V17 "17"
+#define V18 "18"
+
+/** Chip Magic Value */
+#define CHIP_MAGIC_VALUE 0x24
+/** card type SD_UART */
+#define CARD_TYPE_SD_UART 0
+/** card type SD_SD */
+#define CARD_TYPE_SD_SD 1
+/** card type PCIE_PCIE */
+#define CARD_TYPE_PCIE_PCIE 2
+/** card type PCIE_UART */
+#define CARD_TYPE_PCIE_UART 3
+/** card type USB_UART */
+#define CARD_TYPE_USB_UART 4
+/** card type USB_USB */
+#define CARD_TYPE_USB_USB 6
+/** card type PCIE_USB */
+#define CARD_TYPE_PCIE_USB 7
+
+/** Driver version */
+extern char driver_version[];
+
+extern struct semaphore AddRemoveCardSem;
+extern int wifi_status;
+extern int max_tx_buf;
+extern int pcie_int_mode;
+
+#ifdef STA_SUPPORT
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+extern const struct net_device_ops woal_netdev_ops;
+#endif
+#endif
+
+#ifdef UAP_SUPPORT
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+extern const struct net_device_ops woal_uap_netdev_ops;
+#endif
+#endif
+
+/** Global veriable for usb independent reset */
+extern int fw_reload;
+
+#ifdef MFG_CMD_SUPPORT
+/** Mfg mode */
+extern int mfg_mode;
+#endif
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int fw_region;
+#endif
+#endif
+
+#if defined(USB)
+extern int skip_fwdnld;
+#endif
+#if defined(SDIO) || defined(PCIE)
+typedef enum {
+	RDWR_STATUS_SUCCESS = 0,
+	RDWR_STATUS_FAILURE = 1,
+	RDWR_STATUS_DONE = 2
+} rdwr_status;
+#endif
+/** Private structure for MOAL */
+typedef struct _moal_private moal_private, *pmoal_private;
+/** Handle data structure for MOAL  */
+typedef struct _moal_handle moal_handle, *pmoal_handle;
+
+/** Hardware status codes */
+typedef enum _MOAL_HARDWARE_STATUS {
+	HardwareStatusReady,
+	HardwareStatusInitializing,
+	HardwareStatusFwReady,
+	HardwareStatusReset,
+	HardwareStatusClosing,
+	HardwareStatusNotReady
+} MOAL_HARDWARE_STATUS;
+
+/** fw cap info 11p */
+#define FW_CAPINFO_80211P MBIT(24)
+/** fw cap info disable nan */
+#define FW_CAPINFO_DISABLE_NAN MBIT(29)
+/** fw cap info BGA */
+#define FW_CAPINFO_80211BGA (MBIT(8) | MBIT(9) | MBIT(10))
+
+/** moal_wait_option */
+enum { MOAL_NO_WAIT, MOAL_IOCTL_WAIT, MOAL_IOCTL_WAIT_TIMEOUT };
+
+/** moal_main_state */
+enum { MOAL_STATE_IDLE,
+	MOAL_RECV_INT,
+	MOAL_ENTER_WORK_QUEUE,
+	MOAL_START_MAIN_PROCESS,
+	MOAL_END_MAIN_PROCESS
+};
+
+/** HostCmd_Header */
+typedef struct _HostCmd_Header {
+	/** Command */
+	t_u16 command;
+	/** Size */
+	t_u16 size;
+} HostCmd_Header;
+
+/*
+ * OS timer specific
+ */
+
+/** Timer structure */
+typedef struct _moal_drv_timer {
+	/** Timer list */
+	struct timer_list tl;
+	/** Timer function */
+	void (*timer_function) (void *context);
+	/** Timer function context */
+	void *function_context;
+	/** Time period */
+	t_u32 time_period;
+	/** Is timer periodic ? */
+	t_u32 timer_is_periodic;
+	/** Is timer cancelled ? */
+	t_u32 timer_is_canceled;
+} moal_drv_timer, *pmoal_drv_timer;
+
+/**
+ *  @brief Timer handler
+ *
+ *  @param fcontext	Timer context
+ *
+ *  @return		N/A
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+static inline void
+woal_timer_handler(struct timer_list *t)
+{
+	pmoal_drv_timer timer = from_timer(timer, t, tl);
+#else
+static inline void
+woal_timer_handler(unsigned long fcontext)
+{
+	pmoal_drv_timer timer = (pmoal_drv_timer)fcontext;
+#endif
+
+	timer->timer_function(timer->function_context);
+
+	if (timer->timer_is_periodic == MTRUE) {
+		mod_timer(&timer->tl,
+			  jiffies + ((timer->time_period * HZ) / 1000));
+	} else {
+		timer->timer_is_canceled = MTRUE;
+		timer->time_period = 0;
+	}
+}
+
+/**
+ *  @brief Initialize timer
+ *
+ *  @param timer		Timer structure
+ *  @param TimerFunction	Timer function
+ *  @param FunctionContext	Timer function context
+ *
+ *  @return			N/A
+ */
+static inline void
+woal_initialize_timer(pmoal_drv_timer timer,
+		      void (*TimerFunction) (void *context),
+		      void *FunctionContext)
+{
+	/* First, setup the timer to trigger the wlan_timer_handler proxy */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+	timer_setup(&timer->tl, woal_timer_handler, 0);
+#else
+	init_timer(&timer->tl);
+	timer->tl.function = woal_timer_handler;
+	timer->tl.data = (t_ptr)timer;
+#endif
+
+	/* Then tell the proxy which function to call and what to pass it */
+	timer->timer_function = TimerFunction;
+	timer->function_context = FunctionContext;
+	timer->timer_is_canceled = MTRUE;
+	timer->time_period = 0;
+	timer->timer_is_periodic = MFALSE;
+}
+
+/**
+ *  @brief Modify timer
+ *
+ *  @param timer		Timer structure
+ *  @param millisecondperiod	Time period in millisecond
+ *
+ *  @return			N/A
+ */
+static inline void
+woal_mod_timer(pmoal_drv_timer timer, t_u32 millisecondperiod)
+{
+	timer->time_period = millisecondperiod;
+	mod_timer(&timer->tl, jiffies + (millisecondperiod * HZ) / 1000);
+	timer->timer_is_canceled = MFALSE;
+}
+
+/**
+ *  @brief Cancel timer
+ *
+ *  @param timer	Timer structure
+ *
+ *  @return		N/A
+ */
+static inline void
+woal_cancel_timer(moal_drv_timer *timer)
+{
+	if (timer->timer_is_periodic || in_atomic() || irqs_disabled())
+		del_timer(&timer->tl);
+	else
+		del_timer_sync(&timer->tl);
+	timer->timer_is_canceled = MTRUE;
+	timer->time_period = 0;
+}
+
+#ifdef REASSOCIATION
+/*
+ * OS Thread Specific
+ */
+
+#include <linux/kthread.h>
+
+/** Kernel thread structure */
+typedef struct _moal_thread {
+	/** Task control structrue */
+	struct task_struct *task;
+	/** Pointer to wait_queue_head */
+	wait_queue_head_t wait_q;
+	/** PID */
+	pid_t pid;
+	/** Pointer to moal_handle */
+	void *handle;
+} moal_thread;
+
+/**
+ *  @brief Activate thread
+ *
+ *  @param thr			Thread structure
+ *  @return			N/A
+ */
+static inline void
+woal_activate_thread(moal_thread *thr)
+{
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->wait_q);
+
+	/** Record the thread pid */
+	thr->pid = current->pid;
+}
+
+/**
+ *  @brief De-activate thread
+ *
+ *  @param thr			Thread structure
+ *  @return			N/A
+ */
+static inline void
+woal_deactivate_thread(moal_thread *thr)
+{
+	/* Reset the pid */
+	thr->pid = 0;
+}
+
+/**
+ *  @brief Create and run the thread
+ *
+ *  @param threadfunc		Thread function
+ *  @param thr			Thread structure
+ *  @param name			Thread name
+ *  @return			N/A
+ */
+static inline void
+woal_create_thread(int (*threadfunc) (void *), moal_thread *thr, char *name)
+{
+	/* Create and run the thread */
+	thr->task = kthread_run(threadfunc, thr, "%s", name);
+}
+#endif /* REASSOCIATION */
+
+/* The following macros are neccessary to retain compatibility
+ * around the workqueue chenges happened in kernels >= 2.6.20:
+ * - INIT_WORK changed to take 2 arguments and let the work function
+ *   get its own data through the container_of macro
+ * - delayed works have been split from normal works to save some
+ *   memory usage in struct work_struct
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+/** Work_queue work initialization */
+#define MLAN_INIT_WORK(_work, _fun)                                            \
+	INIT_WORK(_work, ((void (*)(void *))_fun), _work)
+/** Work_queue delayed work initialization */
+#define MLAN_INIT_DELAYED_WORK(_work, _fun)                                    \
+	INIT_WORK(_work, ((void (*)(void *))_fun), _work)
+/** Work_queue container parameter */
+#define MLAN_DELAYED_CONTAINER_OF(_ptr, _type, _m) container_of(_ptr, _type, _m)
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) */
+/** Work_queue work initialization */
+#define MLAN_INIT_WORK INIT_WORK
+/** Work_queue delayed work initialization */
+#define MLAN_INIT_DELAYED_WORK INIT_DELAYED_WORK
+/** Work_queue container parameter */
+#define MLAN_DELAYED_CONTAINER_OF(_ptr, _type, _m)                             \
+	container_of(_ptr, _type, _m.work)
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) */
+
+/**
+ *  @brief Schedule timeout
+ *
+ *  @param millisec	Timeout duration in milli second
+ *
+ *  @return		N/A
+ */
+static inline void
+woal_sched_timeout(t_u32 millisec)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	schedule_timeout((millisec * HZ) / 1000);
+}
+
+/**
+ *  @brief Schedule timeout uninterruptible
+ *
+ *  @param millisec	Timeout duration in milli second
+ *
+ *  @return		N/A
+ */
+static inline void
+woal_sched_timeout_uninterruptible(t_u32 millisec)
+{
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout_uninterruptible((millisec * HZ) / 1000);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#define IN6PTON_XDIGIT 0x00010000
+#define IN6PTON_DIGIT 0x00020000
+#define IN6PTON_COLON_MASK 0x00700000
+#define IN6PTON_COLON_1 0x00100000	/* single : requested */
+#define IN6PTON_COLON_2 0x00200000	/* second : requested */
+#define IN6PTON_COLON_1_2 0x00400000	/* :: requested */
+#define IN6PTON_DOT 0x00800000	/* . */
+#define IN6PTON_DELIM 0x10000000
+#define IN6PTON_NULL 0x20000000	/* first/tail */
+#define IN6PTON_UNKNOWN 0x40000000
+
+static inline int
+xdigit2bin(char c, int delim)
+{
+	if (c == delim || c == '\0')
+		return IN6PTON_DELIM;
+	if (c == ':')
+		return IN6PTON_COLON_MASK;
+	if (c == '.')
+		return IN6PTON_DOT;
+	if (c >= '0' && c <= '9')
+		return IN6PTON_XDIGIT | IN6PTON_DIGIT | (c - '0');
+	if (c >= 'a' && c <= 'f')
+		return IN6PTON_XDIGIT | (c - 'a' + 10);
+	if (c >= 'A' && c <= 'F')
+		return IN6PTON_XDIGIT | (c - 'A' + 10);
+	if (delim == -1)
+		return IN6PTON_DELIM;
+	return IN6PTON_UNKNOWN;
+}
+
+static inline int
+in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end)
+{
+	const char *s;
+	u8 *d;
+	u8 dbuf[4];
+	int ret = 0;
+	int i;
+	int w = 0;
+
+	if (srclen < 0)
+		srclen = strlen(src);
+	s = src;
+	d = dbuf;
+	i = 0;
+	while (1) {
+		int c;
+		c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
+		if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM |
+			   IN6PTON_COLON_MASK))) {
+			goto out;
+		}
+		if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
+			if (w == 0)
+				goto out;
+			*d++ = w & 0xff;
+			w = 0;
+			i++;
+			if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
+				if (i != 4)
+					goto out;
+				break;
+			}
+			goto cont;
+		}
+		w = (w * 10) + c;
+		if ((w & 0xffff) > 255)
+			goto out;
+cont:
+		if (i >= 4)
+			goto out;
+		s++;
+		srclen--;
+	}
+	ret = 1;
+	moal_memcpy_ext(NULL, dst, dbuf, sizeof(dbuf), sizeof(dbuf));
+out:
+	if (end)
+		*end = s;
+	return ret;
+}
+#endif /* < 2.6.19 */
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__((packed))
+#endif
+
+/** Get module */
+#define MODULE_GET try_module_get(THIS_MODULE)
+/** Put module */
+#define MODULE_PUT module_put(THIS_MODULE)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+/** Initialize semaphore */
+#define MOAL_INIT_SEMAPHORE(x) init_MUTEX(x)
+/** Initialize semaphore */
+#define MOAL_INIT_SEMAPHORE_LOCKED(x) init_MUTEX_LOCKED(x)
+#else
+/** Initialize semaphore */
+#define MOAL_INIT_SEMAPHORE(x) sema_init(x, 1)
+/** Initialize semaphore */
+#define MOAL_INIT_SEMAPHORE_LOCKED(x) sema_init(x, 0)
+#endif
+
+/** Acquire semaphore and with blocking */
+#define MOAL_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x)
+/** Acquire semaphore without blocking */
+#define MOAL_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x)
+/** Release semaphore */
+#define MOAL_REL_SEMAPHORE(x) up(x)
+
+/** Request FW timeout in second */
+#define REQUEST_FW_TIMEOUT 30
+
+#if defined(USB) || defined(SYSKT)
+/** Max loop count (* 100ms) for waiting device ready at init time */
+#define MAX_WAIT_DEVICE_READY_COUNT 50
+#endif
+
+/** Default watchdog timeout */
+#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (10 * HZ)
+
+#ifdef UAP_SUPPORT
+/** Default watchdog timeout
+    Increase the value to avoid kernel Tx timeout message in case
+    station in PS mode or left.
+    The default value of PS station ageout timer is 40 seconds.
+    Hence, the watchdog timer is set to a value higher than it.
+*/
+#define MRVDRV_DEFAULT_UAP_WATCHDOG_TIMEOUT (41 * HZ)
+#endif
+
+/* IOCTL Timeout */
+#define MOAL_IOCTL_TIMEOUT (20 * HZ)
+
+#ifdef ANDROID_KERNEL
+/** Wake lock timeout in msec */
+#define WAKE_LOCK_TIMEOUT 3000
+/** Roaming Wake lock timeout in msec */
+#define ROAMING_WAKE_LOCK_TIMEOUT 10000
+#endif
+
+/** Threshold value of number of times the Tx timeout happened */
+/* WAR For EDMAC Test */
+#define NUM_TX_TIMEOUT_THRESHOLD 10
+/** Custom event : DRIVER HANG */
+#define CUS_EVT_DRIVER_HANG "EVENT=DRIVER_HANG"
+/** Custom event : FW_DUMP */
+#define CUS_EVT_FW_DUMP "EVENT=FW_DUMP"
+
+/** TDLS connected event */
+#define CUS_EVT_TDLS_CONNECTED "EVENT=TDLS_CONNECTED"
+/** TDLS tear down event */
+#define CUS_EVT_TDLS_TEARDOWN "EVENT=TDLS_TEARDOWN"
+/** wmm info */
+#define WMM_TYPE_INFO 0
+/** wmm parameter */
+#define WMM_TYPE_PARAMETER 1
+
+/** AP connected event */
+#define CUS_EVT_AP_CONNECTED "EVENT=AP_CONNECTED"
+
+/** Custom event : BW changed */
+#define CUS_EVT_BW_CHANGED "EVENT=BW_CHANGED"
+/** Custom event : OBSS scan parameter */
+#define CUS_EVT_OBSS_SCAN_PARAM "EVENT=OBSS_SCAN_PARAM"
+
+/** Custom event : AdHoc link sensed */
+#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED"
+/** Custom event : AdHoc link lost */
+#define CUS_EVT_ADHOC_LINK_LOST "EVENT=ADHOC_LINK_LOST"
+/** Custom event : MIC failure, unicast */
+#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast"
+/** Custom event : MIC failure, multicast */
+#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast"
+/** Custom event : Beacon RSSI low */
+#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW"
+/** Custom event : Beacon SNR low */
+#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW"
+/** Custom event : Beacon RSSI high */
+#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH"
+/** Custom event : Beacon SNR high */
+#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH"
+/** Custom event : Max fail */
+#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL"
+/** Custom event : Data RSSI low */
+#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW"
+/** Custom event : Data SNR low */
+#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW"
+/** Custom event : Data RSSI high */
+#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH"
+/** Custom event : Data SNR high */
+#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH"
+/** Custom event : Link Quality */
+#define CUS_EVT_LINK_QUALITY "EVENT=LINK_QUALITY"
+/** Custom event : Port Release */
+#define CUS_EVT_PORT_RELEASE "EVENT=PORT_RELEASE"
+/** Custom event : Pre-Beacon Lost */
+#define CUS_EVT_PRE_BEACON_LOST "EVENT=PRE_BEACON_LOST"
+
+/** Custom event : Deep Sleep awake */
+#define CUS_EVT_DEEP_SLEEP_AWAKE "EVENT=DS_AWAKE"
+
+#define CUS_EVT_TOD_TOA "EVENT=TOD-TOA"
+
+/** Custom event : Host Sleep activated */
+#define CUS_EVT_HS_ACTIVATED "HS_ACTIVATED"
+/** Custom event : Host Sleep deactivated */
+#define CUS_EVT_HS_DEACTIVATED "HS_DEACTIVATED"
+/** Custom event : Host Sleep wakeup */
+#define CUS_EVT_HS_WAKEUP "HS_WAKEUP"
+
+/** Wakeup Reason */
+typedef enum {
+	NO_HSWAKEUP_REASON = 0,	// 0.unknown
+	BCAST_DATA_MATCHED,	// 1. Broadcast data matched
+	MCAST_DATA_MATCHED,	// 2. Multicast data matched
+	UCAST_DATA_MATCHED,	// 3. Unicast data matched
+	MASKTABLE_EVENT_MATCHED,	// 4. Maskable event matched
+	NON_MASKABLE_EVENT_MATCHED,	// 5. Non-maskable event matched
+	NON_MASKABLE_CONDITION_MATCHED,	// 6. Non-maskable condition matched
+	// (EAPoL rekey)
+	MAGIC_PATTERN_MATCHED,	// 7. Magic pattern matched
+	CONTROL_FRAME_MATCHED,	// 8. Control frame matched
+	MANAGEMENT_FRAME_MATCHED,	// 9. Management frame matched
+	GTK_REKEY_FAILURE,	// 10. GTK rekey failure
+	RESERVED		// Others: reserved
+} HSWakeupReason_t;
+
+/** Custom event : WEP ICV error */
+#define CUS_EVT_WEP_ICV_ERR "EVENT=WEP_ICV_ERR"
+
+/** Custom event : Channel Switch Announcment */
+#define CUS_EVT_CHANNEL_SWITCH_ANN "EVENT=CHANNEL_SWITCH_ANN"
+
+/** Custom indiciation message sent to the application layer for WMM changes */
+#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication"
+
+#define CUS_EVT_FW_DUMP_DONE "EVENT=FW_DUMP_DONE"
+
+#ifdef UAP_SUPPORT
+/** Custom event : STA connected */
+#define CUS_EVT_STA_CONNECTED "EVENT=STA_CONNECTED"
+/** Custom event : STA disconnected */
+#define CUS_EVT_STA_DISCONNECTED "EVENT=STA_DISCONNECTED"
+#endif
+#define FW_DEBUG_INFO "EVENT=FW_DEBUG_INFO"
+
+/** 10 seconds */
+#define MOAL_TIMER_10S 10000
+/** 5 seconds */
+#define MOAL_TIMER_5S 5000
+/** 1 second */
+#define MOAL_TIMER_1S 1000
+/** 1 milisecond */
+#define MOAL_TIMER_1MS 1
+/** scan timeout set to 25 seconds */
+#define SCAN_TIMEOUT_25S        25000
+
+/** passive scan time */
+#define PASSIVE_SCAN_CHAN_TIME 110
+/** active scan time */
+#define ACTIVE_SCAN_CHAN_TIME 110
+/** specific scan time */
+#define SPECIFIC_SCAN_CHAN_TIME 110
+/** passive scan time */
+#define INIT_PASSIVE_SCAN_CHAN_TIME 80
+/** active scan time */
+#define INIT_ACTIVE_SCAN_CHAN_TIME 80
+/** specific scan time */
+#define INIT_SPECIFIC_SCAN_CHAN_TIME 80
+/** specific scan time after connected */
+#define MIN_SPECIFIC_SCAN_CHAN_TIME 40
+
+/** Default value of re-assoc timer */
+#define REASSOC_TIMER_DEFAULT 500
+
+/** Netlink protocol number */
+#define NETLINK_NXP (MAX_LINKS - 1)
+/** Netlink maximum payload size */
+#define NL_MAX_PAYLOAD 1024
+/** Netlink multicast group number */
+#define NL_MULTICAST_GROUP 1
+
+#define MAX_RX_PENDING_THRHLD 50
+
+/** high rx pending packets */
+#define USB_HIGH_RX_PENDING 100
+/** low rx pending packets */
+#define USB_LOW_RX_PENDING 80
+
+/** MAX Tx Pending count */
+#define MAX_TX_PENDING 800
+
+/** LOW Tx Pending count */
+#define LOW_TX_PENDING 380
+
+/** Offset for subcommand */
+#define SUBCMD_OFFSET 4
+
+/** default scan channel gap  */
+#define DEF_SCAN_CHAN_GAP 50
+/** default scan time per channel in miracast mode */
+#define DEF_MIRACAST_SCAN_TIME 20
+/** GAP value is optional */
+#define GAP_FLAG_OPTIONAL MBIT(15)
+
+/** Macro to extract the TOS field from a skb */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+#define SKB_TOS(skb) (ip_hdr(skb)->tos)
+#else
+#define SKB_TOS(skb) (skb->nh.iph->tos)
+#endif
+#define SKB_TIDV6(skb) (ipv6_get_dsfield(ipv6_hdr(skb)))
+#define IS_SKB_MAGIC_VLAN(skb) (skb->priority >= 256 && skb->priority <= 263)
+#define GET_VLAN_PRIO(skb) (skb->priority - 256)
+
+/** Offset for TOS field in the IP header */
+#define IPTOS_OFFSET 5
+
+/** Offset for DSCP in the tos field */
+#define DSCP_OFFSET 2
+
+/** max retry count for wait_event_interupptible_xx while loop */
+#define MAX_RETRY_CNT 100
+/** wait_queue structure */
+typedef struct _wait_queue {
+	/** wait_queue_head */
+	wait_queue_head_t wait;
+	/** Wait condition */
+	BOOLEAN condition;
+	/** Start time */
+	long start_time;
+	/** Status from MLAN */
+	mlan_status status;
+	/** flag for wait_timeout */
+	t_u8 wait_timeout;
+	/** retry count */
+	t_u8 retry;
+} wait_queue, *pwait_queue;
+
+/** Auto Rate */
+#define AUTO_RATE 0xFF
+
+#define STA_WEXT_MASK MBIT(0)
+#define UAP_WEXT_MASK MBIT(1)
+#define STA_CFG80211_MASK MBIT(2)
+#define UAP_CFG80211_MASK MBIT(3)
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+/** Is STA CFG80211 enabled in module param */
+#define IS_STA_CFG80211(x) (x & STA_CFG80211_MASK)
+#endif
+#endif
+#ifdef UAP_CFG80211
+#ifdef UAP_SUPPORT
+/** Is UAP CFG80211 enabled in module param */
+#define IS_UAP_CFG80211(x) (x & UAP_CFG80211_MASK)
+#endif
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+/** Is UAP or STA CFG80211 enabled in module param */
+#define IS_STA_OR_UAP_CFG80211(x) (x & (STA_CFG80211_MASK | UAP_CFG80211_MASK))
+#endif
+
+#ifdef STA_WEXT
+/** Is STA WEXT enabled in module param */
+#define IS_STA_WEXT(x) (x & STA_WEXT_MASK)
+#endif /* STA_WEXT */
+#ifdef UAP_WEXT
+/** Is UAP WEXT enabled in module param */
+#define IS_UAP_WEXT(x) (x & UAP_WEXT_MASK)
+#endif /* UAP_WEXT */
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+/** Is UAP or STA WEXT enabled in module param */
+#define IS_STA_OR_UAP_WEXT(x) (x & (STA_WEXT_MASK | UAP_WEXT_MASK))
+#endif
+
+#ifdef STA_SUPPORT
+/** Driver mode STA bit */
+#define DRV_MODE_STA MBIT(0)
+/** Maximum STA BSS */
+#define MAX_STA_BSS 1
+/** Default STA BSS */
+#define DEF_STA_BSS 1
+#endif
+#ifdef UAP_SUPPORT
+/** Driver mode uAP bit */
+#define DRV_MODE_UAP MBIT(1)
+/** Maximum uAP BSS */
+#define MAX_UAP_BSS 1
+/** Default uAP BSS */
+#define DEF_UAP_BSS 1
+
+/** WACP Modes for uAP */
+#define WACP_MODE_DEFAULT   0
+#define WACP_MODE_1         1
+#define WACP_MODE_2         2
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+/** Driver mode WIFIDIRECT bit */
+#define DRV_MODE_WIFIDIRECT MBIT(2)
+/** Maximum WIFIDIRECT BSS */
+#define MAX_WIFIDIRECT_BSS 2
+/** Default WIFIDIRECT BSS */
+#define DEF_WIFIDIRECT_BSS 1
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#define DEF_VIRTUAL_BSS 0
+#endif
+#endif /* WIFI_DIRECT_SUPPORT */
+
+#define DRV_MODE_WLAN (MBIT(0) | MBIT(1) | MBIT(2) | MBIT(3) | MBIT(4))
+
+/**
+ * the maximum number of adapter supported
+ **/
+#define MAX_MLAN_ADAPTER 4
+
+typedef struct _moal_drv_mode {
+	/** driver mode */
+	t_u16 drv_mode;
+	/** total number of interfaces */
+	t_u16 intf_num;
+	/** attribute of bss */
+	mlan_bss_attr *bss_attr;
+	/** name of firmware image */
+	char *fw_name;
+} moal_drv_mode;
+
+extern moal_handle *m_handle[MAX_MLAN_ADAPTER];
+
+/** Indicate if handle->info's address */
+#define INFO_ADDR BIT(0)
+#define IS_INFO_ADDR(attr) (attr & INFO_ADDR)
+/** Indicate if handle's address */
+#define HANDLE_ADDR BIT(1)
+#define IS_HANDLE_ADDR(attr) (attr & HANDLE_ADDR)
+/** Indicate if card's address */
+#define CARD_ADDR BIT(2)
+#define IS_CARD_ADDR(attr) (attr & CARD_ADDR)
+/** indicate if priv's address */
+#define PRIV_ADDR BIT(3)
+#define IS_PRIV_ADDR(attr) (attr & PRIV_ADDR)
+
+/** Debug data */
+struct debug_data {
+	/** Name */
+	char name[32];
+	/** Size */
+	t_u32 size;
+	/** Address */
+	t_ptr addr;
+	/** Attribute:
+	0-7bit: start address for addr to add to, 0 means common(no specific)
+	8-15bit: interface type, 0 means common(no interface specific)
+	other: unused
+	*/
+	t_u32 attr;
+};
+
+/** Private debug data */
+struct debug_data_priv {
+	/** moal_private handle */
+	moal_private *priv;
+	/** Debug items */
+	struct debug_data *items;
+	/** numbre of item */
+	int num_of_items;
+};
+
+/** Maximum IP address buffer length */
+#define IPADDR_MAX_BUF 20
+/** IP address operation: Remove */
+#define IPADDR_OP_REMOVE 0
+
+#define TCP_ACK_MAX_HOLD    9
+#define DROP_TCP_ACK 1
+#define HOLD_TCP_ACK 2
+struct tcp_sess {
+	struct list_head link;
+	/** tcp session info */
+	t_u32 src_ip_addr;
+	t_u32 dst_ip_addr;
+	t_u16 src_tcp_port;
+	t_u16 dst_tcp_port;
+	/** tx ack packet info */
+	t_u32 ack_seq;
+	/** tcp ack buffer */
+	void *ack_skb;
+	/** priv structure */
+	void *priv;
+	/** pmbuf */
+	void *pmbuf;
+	/** timer for ack */
+	moal_drv_timer ack_timer __ATTRIB_ALIGN__;
+	/** timer is set */
+	BOOLEAN is_timer_set;
+};
+
+struct tx_status_info {
+	struct list_head link;
+	/** cookie */
+	t_u64 tx_cookie;
+	/** seq_num */
+	t_u8 tx_seq_num;
+	/** cancel remain on channel when receive tx status */
+	t_u8 cancel_remain_on_channel;
+	/**          skb */
+	void *tx_skb;
+};
+
+/** woal event type */
+enum woal_event_type {
+	WOAL_EVENT_CHAN_SWITCH,
+	WOAL_EVENT_RX_MGMT_PKT,
+	WOAL_EVENT_BGSCAN_STOP,
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	WOAL_EVENT_DEAUTH,
+	WOAL_EVENT_ASSOC_RESP,
+#endif
+#endif
+#ifdef UAP_CFG80211
+#if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
+	WOAL_EVENT_CANCEL_CHANRPT,
+#endif
+#endif
+};
+
+typedef struct _woal_evt_buf {
+	/** Event len */
+	t_u16 event_len;
+	/** Event buffer */
+	t_u8 event_buf[1024];
+} woal_evt_buf;
+
+/** woal event */
+struct woal_event {
+	/*list head */
+	struct list_head link;
+	/** type */
+	enum woal_event_type type;
+	/** priv pointer */
+	void *priv;
+	union {
+		chan_band_info chan_info;
+		woal_evt_buf evt;
+		mlan_ds_misc_assoc_rsp assoc_resp;
+		int reason_code;
+	};
+};
+
+#define MAX_NUM_ETHER_TYPE 8
+typedef struct {
+	/** number of protocols in protocol array*/
+	t_u8 protocol_num;
+	/** protocols supported */
+	t_u16 protocols[MAX_NUM_ETHER_TYPE];
+} __ATTRIB_PACK__ dot11_protocol;
+typedef struct {
+	/** Data rate in unit of 0.5Mbps */
+	t_u16 datarate;
+	/** Channel number to transmit the frame */
+	t_u8 channel;
+	/** Bandwidth to transmit the frame */
+	t_u8 bw;
+	/** Power to be used for transmission */
+	t_u8 power;
+	/** Priority of the packet to be transmitted */
+	t_u8 priority;
+	/** retry time of tx transmission*/
+	t_u8 retry_limit;
+	/** Reserved fields*/
+	t_u8 reserved[1];
+} __ATTRIB_PACK__ dot11_txcontrol;
+
+typedef struct {
+	/** Data rate of received paccket*/
+	t_u16 datarate;
+	/** Channel on which packet was received*/
+	t_u8 channel;
+	/** Rx antenna*/
+	t_u8 antenna;
+	/** RSSI */
+	t_u8 rssi;
+	/** Reserved */
+	t_u8 reserved[3];
+} __ATTRIB_PACK__ dot11_rxcontrol;
+
+#define OKC_WAIT_TARGET_PMKSA_TIMEOUT (4 * HZ / 1000)
+#define PMKID_LEN 16
+struct pmksa_entry {
+	struct list_head link;
+	u8 bssid[ETH_ALEN];
+	u8 pmkid[PMKID_LEN];
+};
+
+/** default rssi low threshold */
+#define TDLS_RSSI_LOW_THRESHOLD 55
+/** default rssi high threshold */
+#define TDLS_RSSI_HIGH_THRESHOLD 50
+/** TDLS idle time */
+#define TDLS_IDLE_TIME (10 * HZ)
+/** TDLS max failure count */
+#define TDLS_MAX_FAILURE_COUNT 4
+/** TDLS tear down reason */
+#define TDLS_TEARN_DOWN_REASON_UNSPECIFIC 26
+
+/** TDLS status */
+typedef enum _tdlsStatus_e {
+	TDLS_NOT_SETUP = 0,
+	TDLS_SETUP_INPROGRESS,
+	TDLS_SETUP_COMPLETE,
+	TDLS_SETUP_FAILURE,
+	TDLS_TEAR_DOWN,
+	TDLS_SWITCHING_CHANNEL,
+	TDLS_IN_BASE_CHANNEL,
+	TDLS_IN_OFF_CHANNEL,
+} tdlsStatus_e;
+
+/** tdls peer_info */
+struct tdls_peer {
+	struct list_head link;
+	/** MAC address information */
+	t_u8 peer_addr[ETH_ALEN];
+	/** rssi */
+	int rssi;
+	/** jiffies with rssi */
+	long rssi_jiffies;
+	/** link status */
+	tdlsStatus_e link_status;
+	/** num of set up failure */
+	t_u8 num_failure;
+};
+
+struct rf_test_mode_data {
+	/* tx antenna num */
+	t_u32 tx_antenna;
+	/* rx antenna num */
+	t_u32 rx_antenna;
+	/* radio mode */
+	t_u32 radio_mode[2];
+	/* RF band */
+	t_u32 band;
+	/* RF bandwidth */
+	t_u32 bandwidth;
+	/* RF channel */
+	t_u32 channel;
+	/* Total Rx ucast/mcast/bcast pkt count */
+	t_u32 rx_tot_pkt_count;
+	/* Rx mcast/bcast pkt count */
+	t_u32 rx_mcast_bcast_pkt_count;
+	/* Rx fcs error count */
+	t_u32 rx_pkt_fcs_err_count;
+	/* Tx power config values */
+	t_u32 tx_power_data[3];
+	/* Tx continuous config values */
+	t_u32 tx_cont_data[6];
+	/* Tx frame config values */
+	t_u32 tx_frame_data[20];
+	/* HE TB Tx values */
+	t_u32 he_tb_tx[5];
+	/* BSSID */
+	t_u8 bssid[ETH_ALEN];
+};
+
+/** Number of samples in histogram (/proc/mwlan/adapterX/mlan0/histogram).*/
+#define HIST_MAX_SAMPLES 1048576
+#define RX_RATE_MAX 196
+
+/** SRN MAX  */
+#define SNR_MAX 256
+/** NOISE FLR MAX  */
+#define NOISE_FLR_MAX 256
+/** SIG STRENTGH MAX */
+#define SIG_STRENGTH_MAX 256
+/** historgram data */
+typedef struct _hgm_data {
+	/** snr */
+	atomic_t snr[SNR_MAX];
+	/** noise flr */
+	atomic_t noise_flr[NOISE_FLR_MAX];
+	/** sig_str */
+	atomic_t sig_str[SIG_STRENGTH_MAX];
+	/** num sample */
+	atomic_t num_samples;
+	/** rx rate */
+	atomic_t rx_rate[];
+} hgm_data, *phgm_data;
+
+/** max antenna number */
+#define MAX_ANTENNA_NUM 4
+
+/* wlan_hist_proc_data */
+typedef struct _wlan_hist_proc_data {
+	/** antenna */
+	u8 ant_idx;
+	/** Private structure */
+	struct _moal_private *priv;
+} wlan_hist_proc_data;
+
+enum ring_id {
+	VERBOSE_RING_ID,
+	EVENT_RING_ID,
+	RING_ID_MAX,
+};
+
+/** Private structure for MOAL */
+struct _moal_private {
+	/** Handle structure */
+	moal_handle *phandle;
+	/** Tx timeout count */
+	t_u32 num_tx_timeout;
+	/** BSS index */
+	t_u8 bss_index;
+	/** BSS type */
+	t_u8 bss_type;
+	/** BSS role */
+	t_u8 bss_role;
+	/** bss virtual flag */
+	t_u8 bss_virtual;
+	/** MAC address information */
+	t_u8 current_addr[ETH_ALEN];
+	/** Media connection status */
+	BOOLEAN media_connected;
+    /** mclist work queue */
+	struct workqueue_struct *mclist_workqueue;
+	/** mclist work */
+	struct work_struct mclist_work;
+	/** Statistics of tcp ack tx dropped */
+	t_u32 tcp_ack_drop_cnt;
+	/** Statistics of tcp ack tx in total from kernel */
+	t_u32 tcp_ack_cnt;
+	/** Statistics of tcp ack with payload*/
+	t_u32 tcp_ack_payload;
+#ifdef UAP_SUPPORT
+	/** uAP started or not */
+	BOOLEAN bss_started;
+	/** host based uap flag */
+	BOOLEAN uap_host_based;
+    /** transition channel */
+	t_u8 trans_chan;
+	/** uAP skip CAC*/
+	BOOLEAN skip_cac;
+	/** tx block flag */
+	BOOLEAN uap_tx_blocked;
+	/** user cac period */
+	t_u32 user_cac_period_msec;
+	/** channel under nop */
+	BOOLEAN chan_under_nop;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/** current working channel */
+	struct cfg80211_chan_def chan;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	/** switch channel */
+	struct cfg80211_chan_def csa_chan;
+	/** beacon after channel switch */
+	struct cfg80211_beacon_data beacon_after;
+	/** CSA work queue */
+	struct workqueue_struct *csa_workqueue;
+	/** csa work */
+	struct delayed_work csa_work;
+#endif
+#endif
+#endif
+	/** IP addr type */
+	t_u32 ip_addr_type;
+	/** IP addr */
+	t_u8 ip_addr[IPADDR_LEN];
+	t_u8 ipv6_addr_configured;
+	t_u8 ipv6_addr[16];
+#ifdef STA_SUPPORT
+	/** scan type */
+	t_u8 scan_type;
+	/** extended capabilities */
+	ExtCap_t extended_capabilities;
+	/** bg_scan_start */
+	t_u8 bg_scan_start;
+	/** bg_scan reported */
+	t_u8 bg_scan_reported;
+	/** bg_scan config */
+	wlan_bgscan_cfg scan_cfg;
+	/** sched scaning flag */
+	t_u8 sched_scanning;
+	/** sched_scan work queue */
+	struct workqueue_struct *sched_scan_workqueue;
+	/** sched_scan work */
+	struct delayed_work sched_scan_work;
+	/** bgscan request id */
+	t_u64 bg_scan_reqid;
+#ifdef STA_CFG80211
+	/** roaming enabled flag */
+	t_u8 roaming_enabled;
+	/** roaming required flag */
+	t_u8 roaming_required;
+#endif
+#ifdef STA_CFG80211
+	/** rssi low threshold */
+	int rssi_low;
+	/** channel for connect */
+	struct ieee80211_channel conn_chan;
+	/** bssid for connect */
+	t_u8 conn_bssid[ETH_ALEN];
+	/** ssid for connect */
+	t_u8 conn_ssid[MLAN_MAX_SSID_LENGTH];
+	/** length of ssid for connect */
+	t_u8 conn_ssid_len;
+	/** key data */
+	t_u8 conn_wep_key[MAX_WEP_KEY_SIZE];
+	/** connection param */
+	struct cfg80211_connect_params sme_current;
+    /** station info */
+	struct station_info *sinfo;
+	/* associcate bss */
+	struct cfg80211_bss *assoc_bss;
+#endif
+	t_u8 wait_target_ap_pmkid;
+	wait_queue_head_t okc_wait_q __ATTRIB_ALIGN__;
+	struct list_head pmksa_cache_list;
+	spinlock_t pmksa_list_lock;
+	struct pmksa_entry *target_ap_pmksa;
+	t_u8 okc_ie_len;
+	t_u8 *okc_roaming_ie;
+#endif
+	/** Net device pointer */
+	struct net_device *netdev;
+	/** Net device statistics structure */
+	struct net_device_stats stats;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	/** Wireless device pointer */
+	struct wireless_dev *wdev;
+	/** Wireless device */
+	struct wireless_dev w_dev;
+	/** Net device pointer */
+	struct net_device *pa_netdev;
+	/** channel parameter for UAP/GO */
+	t_u16 channel;
+#ifdef UAP_SUPPORT
+	/** wep key */
+	wep_key uap_wep_key[4];
+	/** cipher */
+	t_u32 cipher;
+#endif
+	/** beacon ie index */
+	t_u16 beacon_index;
+	/** proberesp ie index */
+	t_u16 proberesp_index;
+	/** proberesp_p2p_index */
+	t_u16 proberesp_p2p_index;
+	/** assocresp ie index */
+	t_u16 assocresp_index;
+	/** assocresp qos map ie index */
+	t_u16 assocresp_qos_map_index;
+	/** probereq index for mgmt ie */
+	t_u16 probereq_index;
+	/** mgmt_subtype_mask */
+	t_u32 mgmt_subtype_mask;
+	/** beacon wps index for mgmt ie */
+	t_u16 beacon_wps_index;
+	/** beacon/proberesp vendor ie index */
+	t_u16 beacon_vendor_index;
+#endif
+#ifdef STA_CFG80211
+#ifdef STA_SUPPORT
+	/** CFG80211 association description */
+	t_u8 cfg_bssid[ETH_ALEN];
+	/** Disconnect request from CFG80211 */
+	bool cfg_disconnect;
+	/** connect request from CFG80211 */
+	bool cfg_connect;
+	/** lock for cfg connect */
+	spinlock_t connect_lock;
+	/** assoc status */
+	t_u32 assoc_status;
+	/** rssi_threshold */
+	s32 cqm_rssi_thold;
+	/** rssi_high_threshold */
+	s32 cqm_rssi_high_thold;
+	/** rssi hysteresis */
+	u32 cqm_rssi_hyst;
+	/** last rssi_low */
+	u8 last_rssi_low;
+	/** last rssi_high */
+	u8 last_rssi_high;
+	/** mrvl rssi threshold */
+	u8 mrvl_rssi_low;
+	/** last event */
+	u32 last_event;
+	/** fake scan flag */
+	u8 fake_scan_complete;
+	/**ft ie*/
+	t_u8 ft_ie[MAX_IE_SIZE];
+	/**ft ie len*/
+	t_u8 ft_ie_len;
+	/**ft ie*/
+	t_u8 pre_ft_ie[MAX_IE_SIZE];
+	/**ft ie len*/
+	t_u8 pre_ft_ie_len;
+	/**mobility domain value*/
+	t_u16 ft_md;
+	/**ft capability*/
+	t_u8 ft_cap;
+	/** set true when receive ft auth or action ft roaming */
+	t_bool ft_pre_connect;
+	/**ft roaming triggered by driver or not*/
+	t_bool ft_roaming_triggered_by_driver;
+	/**target ap mac address for Fast Transition*/
+	t_u8 target_ap_bssid[ETH_ALEN];
+	/** IOCTL wait queue for FT*/
+	wait_queue_head_t ft_wait_q __ATTRIB_ALIGN__;
+	/** ft wait condition */
+	t_bool ft_wait_condition;
+#endif				/* STA_SUPPORT */
+#endif				/* STA_CFG80211 */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/** flag for host_mlme */
+	t_u8 host_mlme;
+	/** flag for auth */
+	t_u8 auth_flag;
+	/** flag for auth algorithm */
+	t_u16 auth_alg;
+#endif
+#ifdef CONFIG_PROC_FS
+	/** Proc entry */
+	struct proc_dir_entry *proc_entry;
+	/** Proc entry name */
+	char proc_entry_name[IFNAMSIZ];
+	/** proc entry for hist */
+	struct proc_dir_entry *hist_entry;
+	/** ant_hist_proc_data */
+	wlan_hist_proc_data hist_proc[MAX_ANTENNA_NUM];
+#endif				/* CONFIG_PROC_FS */
+#ifdef STA_SUPPORT
+	/** Nickname */
+	t_u8 nick_name[16];
+	/** AdHoc link sensed flag */
+	BOOLEAN is_adhoc_link_sensed;
+	/** Current WEP key index */
+	t_u16 current_key_index;
+#ifdef REASSOCIATION
+	mlan_ssid_bssid prev_ssid_bssid;
+	/** Re-association required */
+	BOOLEAN reassoc_required;
+	/** Flag of re-association on/off */
+	BOOLEAN reassoc_on;
+	/** Set asynced essid flag */
+	BOOLEAN set_asynced_essid_flag;
+#endif				/* REASSOCIATION */
+	/** Report scan result */
+	t_u8 report_scan_result;
+	/** wpa_version */
+	t_u8 wpa_version;
+	/** key mgmt */
+	t_u8 key_mgmt;
+	/** rx_filter */
+	t_u8 rx_filter;
+#endif				/* STA_SUPPORT */
+	/** Rate index */
+	t_u16 rate_index;
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+	/** IW statistics */
+	struct iw_statistics w_stats;
+#endif
+#ifdef UAP_WEXT
+	/** Pairwise Cipher used for WPA/WPA2 mode */
+	t_u16 pairwise_cipher;
+	/** Group Cipher */
+	t_u16 group_cipher;
+	/** Protocol stored during uap wext configuratoin */
+	t_u16 uap_protocol;
+	/** Key Mgmt whether PSK or 1x */
+	t_u16 uap_key_mgmt;
+	/** Beacon IE length from hostapd */
+	t_u16 bcn_ie_len;
+	/** Beacon IE buffer from hostapd */
+	t_u8 bcn_ie_buf[MAX_IE_SIZE];
+#endif
+
+	/** dscp mapping */
+	t_u8 dscp_map[64];
+	/** MLAN debug info */
+	struct debug_data_priv items_priv;
+
+	/** tcp session queue */
+	struct list_head tcp_sess_queue;
+	/** TCP Ack enhance flag */
+	t_u8 enable_tcp_ack_enh;
+	/** TCP Ack drop count */
+	t_u8 tcp_ack_max_hold;
+	/** TCP session spin lock */
+	spinlock_t tcp_sess_lock;
+	/** tcp list */
+	struct list_head tdls_list;
+	/** tdls spin lock */
+	spinlock_t tdls_lock;
+	/** auto tdls  flag */
+	t_u8 enable_auto_tdls;
+	/** check tx packet for tdls peer */
+	t_u8 tdls_check_tx;
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	atomic_t wmm_tx_pending[4];
+#endif
+	struct sk_buff_head tx_q;
+	/** per interface extra headroom */
+	t_u16 extra_tx_head_len;
+	/** TX status spin lock */
+	spinlock_t tx_stat_lock;
+	/** tx_seq_num */
+	t_u8 tx_seq_num;
+	/** tx status queue */
+	struct list_head tx_stat_queue;
+	/** rx hgm data */
+	phgm_data hist_data[MAX_ANTENNA_NUM];
+	t_u8 random_mac[MLAN_MAC_ADDR_LENGTH];
+	BOOLEAN assoc_with_mac;
+	t_u8 gtk_data_ready;
+	mlan_ds_misc_gtk_rekey_data gtk_rekey_data;
+	dot11_protocol tx_protocols;
+	dot11_protocol rx_protocols;
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+	/** hostcmd_wait_q */
+	wait_queue_head_t hostcmd_wait_q __ATTRIB_ALIGN__;
+	/** hostcmd_wait_condition */
+	t_bool hostcmd_wait_condition;
+#endif
+	void *rings[RING_ID_MAX];
+	t_u8 pkt_fate_monitor_enable;
+	void *packet_filter;
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+	/** If |MTRUE|, suppress Wi-Fi scan requests. */
+	t_bool scan_suppressed;
+#endif  // defined(WIFI_LATENCY_MODE_SUPPORT)
+};
+
+#ifdef SDIO
+#define DUMP_FW_SDIO_V2 2
+#define DUMP_FW_SDIO_V3 3
+
+#define DUMP_REG_MAX 13
+
+typedef struct _dump_reg_t {
+	t_u8 reg_table[DUMP_REG_MAX];
+	t_u8 reg_table_size;
+} dump_reg_t;
+#endif
+
+#define FW_NAMW_MAX_LEN 64
+
+/** card info */
+typedef struct _card_info {
+	/** support embeded supp */
+	t_bool embedded_supp;
+	/** support drcs */
+	t_bool drcs;
+	/** support Go NOA*/
+	t_bool go_noa;
+	/** support V14_FW_API*/
+	t_bool v14_fw_api;
+	/** support V16_FW_API*/
+	t_bool v16_fw_api;
+	/** support V17_FW_API*/
+	t_bool v17_fw_api;
+	/** support pmic */
+	t_bool pmic;
+	/** support antcfg */
+	t_bool antcfg;
+	/** support cal_data_cfg */
+	t_bool cal_data_cfg;
+	/** support WLAN_LOW_POWER_ENABLE */
+	t_bool low_power_enable;
+	/** rx_rate_max for hist_data: 11N: 76  11AC:196 11AX: 412 */
+	t_u16 rx_rate_max;
+	t_u8 histogram_table_num;
+	/* feature_control */
+	t_u32 feature_control;
+	/* Revision id register */
+	t_u32 rev_id_reg;
+	/* host interface selection reg */
+	t_u32 host_strap_reg;
+	/* Chip Magic Register */
+	t_u32 magic_reg;
+	/* FW Name */
+	char fw_name[FW_NAMW_MAX_LEN];
+	char fw_name_wlan[FW_NAMW_MAX_LEN];
+#ifdef SDIO
+	t_u8 dump_fw_info;
+	t_u8 dump_fw_ctrl_reg;
+	t_u8 dump_fw_start_reg;
+	t_u8 dump_fw_end_reg;
+	t_u8 dump_fw_host_ready;
+	dump_reg_t dump_reg;
+	t_u8 scratch_reg;
+	t_u8 func1_reg_start;
+	t_u8 func1_reg_end;
+	t_u32 fw_reset_reg;
+	t_u8 fw_reset_val;
+	t_u32 slew_rate_reg;
+	t_u8 slew_rate_bit_offset;
+#endif
+	t_u8 per_pkt_cfg_support;
+} card_info;
+
+#define GTK_REKEY_OFFLOAD_DISABLE 0
+#define GTK_REKEY_OFFLOAD_ENABLE 1
+#define GTK_REKEY_OFFLOAD_SUSPEND 2
+
+#define MAX_KEEP_ALIVE_ID 4
+
+/** Operation data structure for MOAL bus interfaces */
+typedef struct _moal_if_ops {
+	mlan_status (*register_dev) (moal_handle *handle);
+	void (*unregister_dev) (moal_handle *handle);
+	mlan_status (*read_reg) (moal_handle *handle, t_u32 reg, t_u32 *data);
+	mlan_status (*write_reg) (moal_handle *handle, t_u32 reg, t_u32 data);
+	mlan_status (*read_data_sync) (moal_handle *handle, mlan_buffer *pmbuf,
+				       t_u32 port, t_u32 timeout);
+	mlan_status (*write_data_sync) (moal_handle *handle, mlan_buffer *pmbuf,
+					t_u32 port, t_u32 timeout);
+	mlan_status (*get_fw_name) (moal_handle *handle);
+	void (*dump_fw_info) (moal_handle *handle);
+	int (*dump_reg_info) (moal_handle *handle, t_u8 *buf);
+	void (*reg_dbg) (moal_handle *handle);
+	t_u8 (*is_second_mac) (moal_handle *handle);
+} moal_if_ops;
+
+#define WIFI_DIRECT_KERNEL_VERSION KERNEL_VERSION(2, 6, 39)
+
+/**  Extended flags */
+enum ext_mod_params {
+	EXT_HW_TEST,
+#ifdef CONFIG_OF
+	EXT_DTS_ENABLE,
+#endif
+	EXT_REQ_FW_NOWAIT,
+	EXT_FW_SERIAL,
+	EXT_PM_KEEP_POWER,
+#ifdef SDIO
+	EXT_INTMODE,
+#ifdef SDIO_SUSPEND_RESUME
+	EXT_SHUTDOWN_HS,
+#endif
+#endif
+#if defined(USB)
+	EXT_SKIP_FWDNLD,
+#endif
+	EXT_AGGR_CTRL,
+	EXT_LOW_PW_MODE,
+#ifdef SDIO
+	EXT_SDIO_RX_AGGR,
+#endif
+	EXT_PMIC,
+	EXT_DISCONNECT_ON_SUSPEND,
+	EXT_HS_MIMO_SWITCH,
+	EXT_FIX_BCN_BUF,
+	EXT_NAPI,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	EXT_DFS_OFFLOAD,
+#endif
+	EXT_DISABLE_REGD_BY_DRIVER,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	EXT_COUNTRY_IE_IGNORE,
+	EXT_BEACON_HINTS,
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	EXT_HOST_MLME,
+#endif
+#endif
+	EXT_TX_WORK,
+	EXT_RPS,
+	EXT_TX_SKB_CLONE,
+	EXT_PMQOS,
+	EXT_MAX_PARAM,
+};
+
+/** Module parameter data structure for MOAL */
+typedef struct _moal_mod_para {
+	t_u8 ext_flgs[DIV_ROUND_UP(EXT_MAX_PARAM, 8)];
+	/* BIT24 ~ BIT32 reserved */
+	t_u8 flag;
+	char *fw_name;
+	int fw_reload;
+	char *mac_addr;
+#ifdef MFG_CMD_SUPPORT
+	int mfg_mode;
+#endif				/* MFG_CMD_SUPPORT */
+	char *hw_name;
+	int drv_mode;
+#ifdef DEBUG_LEVEL1
+	int drvdbg;
+#endif
+#ifdef STA_SUPPORT
+	int max_sta_bss;
+	char *sta_name;
+#endif				/* STA_SUPPORT */
+#ifdef UAP_SUPPORT
+	int max_uap_bss;
+	char *uap_name;
+	int uap_max_sta;
+	int wacp_mode;
+#endif				/* UAP_SUPPORT */
+#ifdef WIFI_DIRECT_SUPPORT
+	int max_wfd_bss;
+	char *wfd_name;
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+	int max_vir_bss;
+#endif
+#endif				/* WIFI_DIRECT_SUPPORT */
+	int auto_ds;
+	int net_rx;
+	int amsdu_deaggr;
+	int ext_scan;
+	int ps_mode;
+	int p2a_scan;
+	/** scan chan gap */
+	int scan_chan_gap;
+	int sched_scan;
+	int max_tx_buf;
+#if defined(SDIO)
+	int gpiopin;
+#endif
+#if defined(STA_SUPPORT)
+	int cfg_11d;
+#endif
+#if defined(SDIO)
+	int slew_rate;
+#endif
+	char *dpd_data_cfg;
+	char *init_cfg;
+	char *cal_data_cfg;
+	char *txpwrlimit_cfg;
+	int cntry_txpwr;
+	char *init_hostcmd_cfg;
+	char *band_steer_cfg;
+	int cfg80211_wext;
+	int wq_sched_prio;
+	int wq_sched_policy;
+	int rx_work;
+#ifdef USB
+	int usb_aggr;
+#endif
+#ifdef PCIE
+	int pcie_int_mode;
+	int ring_size;
+#endif				/* PCIE */
+#ifdef ANDROID_KERNEL
+	int wakelock_timeout;
+#endif
+	unsigned int dev_cap_mask;
+#if defined(SD8997) || defined(PCIE8997) || defined(USB8997) || defined(SD8977) || defined(SD8987) || defined(SD9098) || defined(USB9098) || defined(PCIE9098) || defined(SD9097) || defined(USB9097) || defined(PCIE9097) || defined(SD8978) || defined(SD9177)
+	int pmic;
+#endif
+	int antcfg;
+	unsigned int uap_oper_ctrl;
+	int hs_wake_interval;
+	int indication_gpio;
+	int indrstcfg;
+#ifdef WIFI_DIRECT_SUPPORT
+	int GoAgeoutTime;
+#endif
+	int gtk_rekey_offload;
+	t_u16 multi_dtim;
+	t_u16 inact_tmo;
+	char *reg_alpha2;
+	int dfs53cfg;
+} moal_mod_para;
+
+void woal_tp_acnt_timer_func(void *context);
+void woal_set_tp_state(moal_private *priv);
+#define MAX_TP_ACCOUNT_DROP_POINT_NUM 5
+#define RX_DROP_P1	(MAX_TP_ACCOUNT_DROP_POINT_NUM)
+#define RX_DROP_P2	(MAX_TP_ACCOUNT_DROP_POINT_NUM + 1)
+#define RX_DROP_P3	(MAX_TP_ACCOUNT_DROP_POINT_NUM + 2)
+#define RX_DROP_P4	(MAX_TP_ACCOUNT_DROP_POINT_NUM + 3)
+#define RX_DROP_P5	(MAX_TP_ACCOUNT_DROP_POINT_NUM + 4)
+#define TXRX_MAX_SAMPLE 60
+#define RX_TIME_PKT  (MAX_TP_ACCOUNT_DROP_POINT_NUM + 5)
+#define TX_TIME_PKT  (MAX_TP_ACCOUNT_DROP_POINT_NUM + 6)
+
+typedef struct _moal_tp_acnt_t {
+	/* TX accounting */
+	unsigned long tx_packets[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long tx_packets_last[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long tx_packets_rate[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long tx_bytes[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long tx_bytes_last[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long tx_bytes_rate[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long tx_amsdu_cnt;
+	unsigned long tx_amsdu_cnt_last;
+	unsigned long tx_amsdu_cnt_rate;
+	unsigned long tx_amsdu_pkt_cnt;
+	unsigned long tx_amsdu_pkt_cnt_last;
+	unsigned long tx_amsdu_pkt_cnt_rate;
+	unsigned long tx_intr_cnt;
+	unsigned long tx_intr_last;
+	unsigned long tx_intr_rate;
+	unsigned long tx_pending;
+	unsigned long tx_xmit_skb_realloc_cnt;
+	unsigned long tx_stop_queue_cnt;
+	unsigned long tx_delay_driver[TXRX_MAX_SAMPLE];
+
+	/** RX accounting */
+	unsigned long rx_packets[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long rx_packets_last[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long rx_packets_rate[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long rx_bytes[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long rx_bytes_last[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long rx_bytes_rate[MAX_TP_ACCOUNT_DROP_POINT_NUM];
+	unsigned long rx_amsdu_cnt;
+	unsigned long rx_amsdu_cnt_last;
+	unsigned long rx_amsdu_cnt_rate;
+	unsigned long rx_amsdu_pkt_cnt;
+	unsigned long rx_amsdu_pkt_cnt_last;
+	unsigned long rx_amsdu_pkt_cnt_rate;
+	unsigned long rx_intr_cnt;
+	unsigned long rx_intr_last;
+	unsigned long rx_intr_rate;
+	unsigned long rx_pending;
+	unsigned long rx_paused_cnt;
+	unsigned long rx_rdptr_full_cnt;
+	unsigned long rx_delay1_driver[TXRX_MAX_SAMPLE];
+	unsigned long rx_delay2_driver[TXRX_MAX_SAMPLE];
+	unsigned long rx_delay_kernel[TXRX_MAX_SAMPLE];
+	unsigned long rx_amsdu_delay[TXRX_MAX_SAMPLE];
+	unsigned long rx_amsdu_copy_delay[TXRX_MAX_SAMPLE];
+	t_u8 rx_amsdu_index;
+	t_u8 rx_index;
+	t_u8 tx_index;
+	/* TP account mode 0-disable 1-enable */
+	unsigned int on;
+	/* drop point */
+	unsigned int drop_point;
+	/* periodic timer */
+	moal_drv_timer timer;
+} moal_tp_acnt_t;
+
+/** Handle data structure for MOAL */
+struct _moal_handle {
+	/** MLAN adapter structure */
+	t_void *pmlan_adapter;
+	/** Private pointer */
+	moal_private *priv[MLAN_MAX_BSS_NUM];
+	/** Priv number */
+	t_u8 priv_num;
+	/** Bss attr */
+	moal_drv_mode drv_mode;
+
+	/** set mac address flag */
+	t_u8 set_mac_addr;
+	/** MAC address */
+	t_u8 mac_addr[ETH_ALEN];
+#ifdef CONFIG_PROC_FS
+	/** Proc top level directory entry */
+	struct proc_dir_entry *proc_wlan;
+	/** Proc top level directory entry name */
+	char proc_wlan_name[32];
+#endif
+#ifdef USB
+	/** Firmware download skip flag */
+	t_u8 skip_fw_dnld;
+#endif				/* USB */
+	/** Firmware */
+	const struct firmware *firmware;
+	/** Firmware request start time */
+	wifi_timeval req_fw_time;
+	/** Init config file */
+	const struct firmware *init_cfg_data;
+	/** Init config file */
+	const struct firmware *user_data;
+	/** Init user configure wait queue token */
+	t_u16 init_user_conf_wait_flag;
+	/** Init user configure file wait queue */
+	wait_queue_head_t init_user_conf_wait_q __ATTRIB_ALIGN__;
+	/** dpd config file */
+	const struct firmware *dpd_data;
+	/** txpwr data file */
+	const struct firmware *txpwr_data;
+	/** Hotplug device */
+	struct device *hotplug_device;
+	/** STATUS variables */
+	MOAL_HARDWARE_STATUS hardware_status;
+	BOOLEAN fw_reload;
+	/** POWER MANAGEMENT AND PnP SUPPORT */
+	BOOLEAN surprise_removed;
+	/** Firmware release number */
+	t_u32 fw_release_number;
+	/** Firmware Hotfix version */
+	t_u8 fw_hotfix_version;
+	/** ECSA support */
+	t_u8 fw_ecsa_enable;
+	/** Getlog support */
+	t_u8 fw_getlog_enable;
+	/** Init wait queue token */
+	t_u16 init_wait_q_woken;
+	/** Init wait queue */
+	wait_queue_head_t init_wait_q __ATTRIB_ALIGN__;
+	/** Device suspend flag */
+	BOOLEAN is_suspended;
+#ifdef SDIO_SUSPEND_RESUME
+	/** suspend notify flag */
+	BOOLEAN suspend_notify_req;
+	/** hs_shutdown in process flag  */
+	BOOLEAN shutdown_hs_in_process;
+#endif
+	/** Suspend wait queue token */
+	t_u16 suspend_wait_q_woken;
+	/** Suspend wait queue */
+	wait_queue_head_t suspend_wait_q __ATTRIB_ALIGN__;
+	/** Host Sleep activated flag */
+	t_u8 hs_activated;
+	/** Host Sleep activated event wait queue token */
+	t_u16 hs_activate_wait_q_woken;
+	/** Host Sleep activated event wait queue */
+	wait_queue_head_t hs_activate_wait_q __ATTRIB_ALIGN__;
+	/** auto_arp and ipv6 offload enable/disable flag */
+	t_u8 hs_auto_arp;
+#ifdef IMX_SUPPORT
+	/** wakeup irq number */
+	int irq_oob_wakeup;
+	/** wakeup notify flag */
+	bool wake_by_wifi;
+#endif				/* IMX_SUPPORT */
+	/** Card pointer */
+	t_void *card;
+	/** Rx pending in MLAN */
+	atomic_t rx_pending;
+	/** Tx packet pending count in mlan */
+	atomic_t tx_pending;
+	/** IOCTL pending count in mlan */
+	atomic_t ioctl_pending;
+	/** lock count */
+	atomic_t lock_count;
+	/** Malloc count */
+	atomic_t malloc_count;
+	/** vmalloc count */
+	atomic_t vmalloc_count;
+	/** mlan buffer alloc count */
+	atomic_t mbufalloc_count;
+#ifdef PCIE
+	/** Malloc consistent count */
+	atomic_t malloc_cons_count;
+#endif
+	/** hs skip count */
+	t_u32 hs_skip_count;
+	/** hs force count */
+	t_u32 hs_force_count;
+	/** suspend_fail flag */
+	BOOLEAN suspend_fail;
+#ifdef REASSOCIATION
+	/** Re-association thread */
+	moal_thread reassoc_thread;
+	/** Re-association timer set flag */
+	BOOLEAN is_reassoc_timer_set;
+	/** Re-association timer */
+	moal_drv_timer reassoc_timer __ATTRIB_ALIGN__;
+	/**  */
+	struct semaphore reassoc_sem;
+	/** Bitmap for re-association on/off */
+	t_u8 reassoc_on;
+#endif				/* REASSOCIATION */
+	/** Driver workqueue */
+	struct workqueue_struct *workqueue;
+	/** main work */
+	struct work_struct main_work;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/** host_mlme_priv */
+	moal_private *host_mlme_priv;
+	/** Host Mlme Work struct**/
+	struct work_struct host_mlme_work;
+#endif
+	/** Driver workqueue */
+	struct workqueue_struct *rx_workqueue;
+	/** main work */
+	struct work_struct rx_work;
+	/** Driver event workqueue */
+	struct workqueue_struct *evt_workqueue;
+	/** event  work */
+	struct work_struct evt_work;
+	/** event spin lock */
+	spinlock_t evt_lock;
+	/** event queue */
+	struct list_head evt_queue;
+	/** tx workqueue */
+	struct workqueue_struct *tx_workqueue;
+	/** tx work */
+	struct work_struct tx_work;
+	/** remain on channel flag */
+	t_u8 remain_on_channel;
+	/** bss index for remain on channel */
+	t_u8 remain_bss_index;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+	struct wiphy *wiphy;
+	/** Country code for regulatory domain */
+	t_u8 country_code[COUNTRY_CODE_LEN];
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+    /** regulatory work */
+	struct work_struct regulatory_work;
+#endif
+	/** band */
+	enum ieee80211_band band;
+	/** first scan done flag */
+	t_u8 first_scan_done;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	/** remain_on_channel timer set flag */
+	BOOLEAN is_remain_timer_set;
+	/** remani_on_channel_timer */
+	moal_drv_timer remain_timer __ATTRIB_ALIGN__;
+	/** ieee802_11_channel */
+	struct ieee80211_channel chan;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+	/** channel type */
+	enum nl80211_channel_type channel_type;
+#endif
+	/** cookie */
+	t_u64 cookie;
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+	/** NoA duration */
+	t_u32 noa_duration;
+	/** NoA interval */
+	t_u32 noa_interval;
+	/** miracast mode */
+	t_u8 miracast_mode;
+	/** scan time in miracast mode */
+	t_u16 miracast_scan_time;
+	/** GO timer set flag */
+	BOOLEAN is_go_timer_set;
+	/** GO timer */
+	moal_drv_timer go_timer __ATTRIB_ALIGN__;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	/** cfg80211_suspend status */
+	t_u8 cfg80211_suspend;
+#endif
+#endif
+	/** FW debug flag */
+	t_u8 fw_dbg;
+	/** reg debug flag */
+	t_u8 reg_dbg;
+#ifdef SDIO
+#endif				/* SDIO */
+	/** Netlink kernel socket */
+	struct sock *nl_sk;
+	/** Netlink kernel socket number */
+	t_u32 netlink_num;
+	/** w_stats wait queue token */
+	BOOLEAN meas_wait_q_woken;
+	/** w_stats wait queue */
+	wait_queue_head_t meas_wait_q __ATTRIB_ALIGN__;
+	/** Measurement start jiffes */
+	long meas_start_jiffies;
+	/** CAC checking period flag */
+	BOOLEAN cac_period;
+	/** CAC timer jiffes */
+	long cac_timer_jiffies;
+	/** User NOP Period in sec */
+	t_u16 usr_nop_period_sec;
+	/** BSS START command delay executing flag */
+	BOOLEAN delay_bss_start;
+	/** SSID,BSSID parameter of delay executing */
+	mlan_ssid_bssid delay_ssid_bssid;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	/* CAC channel info */
+	struct cfg80211_chan_def dfs_channel;
+	/* time set flag */
+	BOOLEAN is_cac_timer_set;
+	/** cac_timer */
+	moal_drv_timer cac_timer __ATTRIB_ALIGN__;
+	/** cac bss index */
+	t_u8 cac_bss_index;
+#endif
+#endif
+#if defined(UAP_SUPPORT)
+	/** channel switch wait queue token */
+	BOOLEAN chsw_wait_q_woken;
+	/** channel switch wait queue */
+	wait_queue_head_t chsw_wait_q __ATTRIB_ALIGN__;
+#endif
+	/** cac period length, valid only when dfs testing is enabled */
+	long cac_period_jiffies;
+	/** cac restart*/
+	t_u8 cac_restart;
+	/** handle index - for multiple card supports */
+	t_u8 handle_idx;
+#if defined(USB)
+	/** Flag to indicate boot state */
+	t_u8 boot_state;
+#endif				/* USB_NEW_FW_DNLD */
+#ifdef SDIO_MMC_DEBUG
+	/** cmd53 write state */
+	u8 cmd53w;
+	/** cmd53 read state */
+	u8 cmd53r;
+#endif
+#ifdef STA_SUPPORT
+	/** Scan pending on blocked flag */
+	t_u8 scan_pending_on_block;
+	/** Scan Private pointer */
+	moal_private *scan_priv;
+	/** Async scan semaphore */
+	struct semaphore async_sem;
+	/** scan channel gap */
+	t_u16 scan_chan_gap;
+#ifdef STA_CFG80211
+	/** CFG80211 scan request description */
+	struct cfg80211_scan_request *scan_request;
+	/** fake scan flag */
+	u8 fake_scan_complete;
+	/** Scan timeout work*/
+	struct delayed_work scan_timeout_work;
+        /** scan timeout time */
+        t_u32 scan_timeout;
+#endif
+#endif
+	/** main state */
+	t_u8 main_state;
+	/** driver status */
+	t_u8 driver_status;
+	/** driver state */
+	t_u8 driver_state;
+	/** ioctl timeout */
+	t_u8 ioctl_timeout;
+	/** Pointer of fw dump buffer */
+	t_u8 *drv_dump_buf;
+	/** drv dump len */
+	t_u32 drv_dump_len;
+	/** FW dump state */
+	t_u8 fw_dump;
+    /** event fw dump */
+	t_u8 event_fw_dump;
+	/** Re-association timer set flag */
+	BOOLEAN is_fw_dump_timer_set;
+	/** Re-association timer */
+	moal_drv_timer fw_dump_timer __ATTRIB_ALIGN__;
+    /** fw dump buffer total len */
+	t_u64 fw_dump_len;
+	/** Pointer of fw dump buffer */
+	t_u8 *fw_dump_buf;
+	/** FW dump full name */
+	t_u8 firmware_dump_file[128];
+
+#ifdef SDIO
+	/** cmd52 function */
+	t_u8 cmd52_func;
+	/** cmd52 register */
+	t_u8 cmd52_reg;
+	/** cmd52 value */
+	t_u8 cmd52_val;
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	/** spinlock to stop_queue/wake_queue*/
+	spinlock_t queue_lock;
+#endif
+	/** Driver spin lock */
+	spinlock_t driver_lock;
+	/** Driver ioctl spin lock */
+	spinlock_t ioctl_lock;
+	/** lock for scan_request */
+	spinlock_t scan_req_lock;
+	/** Interface type: 1 byte,  Card type: 1 byte */
+	t_u16 card_type;
+	/** card revsion */
+	t_u8 card_rev;
+	/** card info */
+	card_info *card_info;
+	/** Card specific driver version */
+	t_s8 driver_version[MLAN_MAX_VER_STR_LEN];
+	char *fwdump_fname;
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+	struct wakeup_source ws;
+#else
+	struct wake_lock wake_lock;
+#endif
+#endif
+	t_u16 dfs_repeater_mode;
+	/* feature_control */
+	t_u32 feature_control;
+	struct notifier_block woal_notifier;
+#if IS_ENABLED(CONFIG_IPV6)
+	struct notifier_block woal_inet6_notifier;
+#endif
+	mlan_ds_misc_keep_alive keep_alive[MAX_KEEP_ALIVE_ID];
+	struct net_device napi_dev;
+	struct napi_struct napi_rx;
+	/* bus interface operations */
+	moal_if_ops ops;
+	/* module parameter data */
+	const struct firmware *param_data;
+	/* wrapped module parameters */
+	moal_mod_para params;
+	/* debug info */
+	mlan_debug_info debug_info;
+	/* block id in module param config file */
+	int blk_id;
+	/** time when FW is active, time is get from boot time, in Nanosecond */
+	t_u64 on_time;
+	/** tx time, in usecs */
+	t_u64 tx_time;
+	/** systime when tx start */
+	wifi_timeval tx_time_start;
+	/** systime when tx end */
+	wifi_timeval tx_time_end;
+	/** rx time, in usecs */
+	t_u64 rx_time;
+	/** scan time, in usecs */
+	t_u64 scan_time;
+	/** systime when scan cmd response return success */
+	wifi_timeval scan_time_start;
+	/** systime when scan event has no more event */
+	wifi_timeval scan_time_end;
+	/** seecond mac flag */
+	t_u8 second_mac;
+	/** moal handle for another mac */
+	void *pref_mac;
+	/** RF test mode status */
+	t_u8 rf_test_mode;
+	/** pointer to rf test mode data struct */
+	struct rf_test_mode_data *rf_data;
+	/** TP accounting parameters */
+	moal_tp_acnt_t tp_acnt;
+	BOOLEAN is_tp_acnt_timer_set;
+
+	t_u8 request_pm;
+#ifdef IMX_SUPPORT
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+	struct dev_pm_qos_request woal_pm_qos_req;
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
+	struct pm_qos_request woal_pm_qos_req;
+#endif
+#endif
+};
+
+/**
+ *  @brief set extended flag in bitmap
+ *
+ *  @param dev		A pointer to moal_handle structure
+ *  @param idx      extended flags id
+ *  @return			N/A
+ */
+static inline void
+moal_extflg_set(moal_handle *handle, enum ext_mod_params idx)
+{
+	t_u8 *ext_fbyte;
+	ext_fbyte = &handle->params.ext_flgs[idx / 8];
+	*ext_fbyte |= MBIT(idx % 8);
+}
+
+/**
+ *  @brief clear extended flag in bitmap
+ *
+ *  @param dev		A pointer to moal_handle structure
+ *  @param idx      extended flags id
+ *  @return			N/A
+ */
+static inline void
+moal_extflg_clear(moal_handle *handle, enum ext_mod_params idx)
+{
+	t_u8 *ext_fbyte;
+	ext_fbyte = &handle->params.ext_flgs[idx / 8];
+	*ext_fbyte &= ~MBIT(idx % 8);
+}
+
+/**
+ *  @brief check value of extended flag in bitmap
+ *
+ *  @param dev		A pointer to moal_handle structure
+ *  @param idx      extended flags id
+ *  @return			value of extended flag
+ */
+static inline t_u8
+moal_extflg_isset(moal_handle *handle, enum ext_mod_params idx)
+{
+	t_u8 ext_fbyte;
+	ext_fbyte = handle->params.ext_flgs[idx / 8];
+	return (ext_fbyte & MBIT(idx % 8)) != 0;
+}
+
+/**
+ *  @brief set trans_start for each TX queue.
+ *
+ *  @param dev		A pointer to net_device structure
+ *
+ *  @return			N/A
+ */
+static inline void
+woal_set_trans_start(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+	unsigned int i;
+	for (i = 0; i < dev->num_tx_queues; i++)
+		netdev_get_tx_queue(dev, i)->trans_start = jiffies;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
+	dev->trans_start = jiffies;
+#else
+	netif_trans_update(dev);
+#endif
+}
+
+/**
+ *  @brief Start queue
+ *
+ *  @param dev		A pointer to net_device structure
+ *
+ *  @return			N/A
+ */
+static inline void
+woal_start_queue(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
+	netif_start_queue(dev);
+#else
+	if (dev->reg_state == NETREG_REGISTERED)
+		netif_tx_wake_all_queues(dev);
+	else
+		netif_tx_start_all_queues(dev);
+#endif
+}
+
+/**
+ *  @brief Stop queue
+ *
+ *  @param dev		A pointer to net_device structure
+ *
+ *  @return			N/A
+ */
+static inline void
+woal_stop_queue(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	unsigned long flags;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	spin_lock_irqsave(&priv->phandle->queue_lock, flags);
+	woal_set_trans_start(dev);
+	if (!netif_queue_stopped(dev))
+		netif_tx_stop_all_queues(dev);
+	spin_unlock_irqrestore(&priv->phandle->queue_lock, flags);
+#else
+	woal_set_trans_start(dev);
+	if (!netif_queue_stopped(dev))
+		netif_stop_queue(dev);
+#endif
+}
+
+/**
+ *  @brief wake queue
+ *
+ *  @param dev		A pointer to net_device structure
+ *
+ *  @return			N/A
+ */
+static inline void
+woal_wake_queue(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	unsigned long flags;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	spin_lock_irqsave(&priv->phandle->queue_lock, flags);
+	if (netif_queue_stopped(dev))
+		netif_tx_wake_all_queues(dev);
+	spin_unlock_irqrestore(&priv->phandle->queue_lock, flags);
+#else
+	if (netif_queue_stopped(dev))
+		netif_wake_queue(dev);
+#endif
+}
+
+/** Debug Macro definition*/
+#ifdef DEBUG_LEVEL1
+extern t_u32 drvdbg;
+
+#define LOG_CTRL(level) (0)
+
+#ifdef DEBUG_LEVEL2
+#define PRINTM_MINFO(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MINFO)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MWARN(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MWARN)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MENTRY(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MENTRY)                                           \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#else
+#define PRINTM_MINFO(level, msg...)                                            \
+	do {                                                                   \
+	} while (0)
+#define PRINTM_MWARN(level, msg...)                                            \
+	do {                                                                   \
+	} while (0)
+#define PRINTM_MENTRY(level, msg...)                                           \
+	do {                                                                   \
+	} while (0)
+#endif /* DEBUG_LEVEL2 */
+
+#define PRINTM_MFW_D(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MFW_D)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MCMD_D(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MCMD_D)                                           \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MDAT_D(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MDAT_D)                                           \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MIF_D(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MIF_D)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+
+#define PRINTM_MIOCTL(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MIOCTL)                                           \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MINTR(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MINTR)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MEVENT(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MEVENT)                                           \
+			printk(msg);                                           \
+	} while (0)
+#define PRINTM_MCMND(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MCMND)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MDATA(level, msg...)                                            \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MDATA)                                            \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
+#define PRINTM_MERROR(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MERROR)                                           \
+			printk(KERN_ERR msg);                                  \
+	} while (0)
+#define PRINTM_MFATAL(level, msg...)                                           \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MFATAL)                                           \
+			printk(KERN_ERR msg);                                  \
+	} while (0)
+#define PRINTM_MMSG(level, msg...)                                             \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MMSG)                                             \
+			printk(KERN_ALERT msg);                                \
+	} while (0)
+
+static inline void
+woal_print(t_u32 level, char *fmt, ...)
+{
+}
+
+#define PRINTM(level, msg...) PRINTM_##level(level, msg)
+
+#else
+
+#define PRINTM(level, msg...)                                                  \
+	do {                                                                   \
+	} while (0)
+
+#endif /* DEBUG_LEVEL1 */
+
+/** Wait until a condition becomes true */
+#define MASSERT(cond)                                                          \
+	do {                                                                   \
+		if (!(cond)) {                                                 \
+			PRINTM(MFATAL, "ASSERT: %s: %i\n", __func__,           \
+			       __LINE__);                                      \
+			panic("Assert failed: Panic!");                        \
+		}                                                              \
+	} while (0)
+
+/** Log entry point for debugging */
+#define ENTER() PRINTM(MENTRY, "Enter: %s\n", __func__)
+/** Log exit point for debugging */
+#define LEAVE() PRINTM(MENTRY, "Leave: %s\n", __func__)
+
+#ifdef DEBUG_LEVEL1
+#define DBG_DUMP_BUF_LEN 64
+#define MAX_DUMP_PER_LINE 16
+
+static inline void
+hexdump(t_u32 level, char *prompt, t_u8 *buf, int len)
+{
+	int i;
+	char dbgdumpbuf[DBG_DUMP_BUF_LEN];
+	char *ptr = dbgdumpbuf;
+
+	if (drvdbg & level)
+		printk(KERN_DEBUG "%s:\n", prompt);
+	for (i = 1; i <= len; i++) {
+		ptr += snprintf(ptr, 4, "%02x ", *buf);
+		buf++;
+		if (i % MAX_DUMP_PER_LINE == 0) {
+			*ptr = 0;
+			if (drvdbg & level)
+				printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+			ptr = dbgdumpbuf;
+		}
+	}
+	if (len % MAX_DUMP_PER_LINE) {
+		*ptr = 0;
+		if (drvdbg & level)
+			printk(KERN_DEBUG "%s\n", dbgdumpbuf);
+	}
+}
+
+#define DBG_HEXDUMP_MERROR(x, y, z)                                            \
+	do {                                                                   \
+		if ((drvdbg & MERROR) || LOG_CTRL(MERROR))                     \
+			hexdump(MERROR, x, y, z);                              \
+	} while (0)
+#define DBG_HEXDUMP_MCMD_D(x, y, z)                                            \
+	do {                                                                   \
+		if ((drvdbg & MCMD_D) || LOG_CTRL(MCMD_D))                     \
+			hexdump(MCMD_D, x, y, z);                              \
+	} while (0)
+#define DBG_HEXDUMP_MDAT_D(x, y, z)                                            \
+	do {                                                                   \
+		if ((drvdbg & MDAT_D) || LOG_CTRL(MDAT_D))                     \
+			hexdump(MDAT_D, x, y, z);                              \
+	} while (0)
+#define DBG_HEXDUMP_MIF_D(x, y, z)                                             \
+	do {                                                                   \
+		if ((drvdbg & MIF_D) || LOG_CTRL(MIF_D))                       \
+			hexdump(MIF_D, x, y, z);                               \
+	} while (0)
+#define DBG_HEXDUMP_MEVT_D(x, y, z)                                            \
+	do {                                                                   \
+		if ((drvdbg & MEVT_D) || LOG_CTRL(MEVT_D))                     \
+			hexdump(MEVT_D, x, y, z);                              \
+	} while (0)
+#define DBG_HEXDUMP_MFW_D(x, y, z)                                             \
+	do {                                                                   \
+		if ((drvdbg & MFW_D) || LOG_CTRL(MFW_D))                       \
+			hexdump(MFW_D, x, y, z);                               \
+	} while (0)
+#define DBG_HEXDUMP(level, x, y, z) DBG_HEXDUMP_##level(x, y, z)
+
+#else
+/** Do nothing since debugging is not turned on */
+#define DBG_HEXDUMP(level, x, y, z)                                            \
+	do {                                                                   \
+	} while (0)
+#endif
+
+#ifdef DEBUG_LEVEL2
+#define HEXDUMP(x, y, z)                                                       \
+	do {                                                                   \
+		if ((drvdbg & MINFO) || LOG_CTRL(MINFO))                       \
+			hexdump(MINFO, x, y, z);                               \
+	} while (0)
+#else
+/** Do nothing since debugging is not turned on */
+#define HEXDUMP(x, y, z)                                                       \
+	do {                                                                   \
+	} while (0)
+#endif
+
+#ifdef BIG_ENDIAN_SUPPORT
+/** Convert from 16 bit little endian format to CPU format */
+#define woal_le16_to_cpu(x) le16_to_cpu(x)
+/** Convert from 32 bit little endian format to CPU format */
+#define woal_le32_to_cpu(x) le32_to_cpu(x)
+/** Convert from 64 bit little endian format to CPU format */
+#define woal_le64_to_cpu(x) le64_to_cpu(x)
+/** Convert to 16 bit little endian format from CPU format */
+#define woal_cpu_to_le16(x) cpu_to_le16(x)
+/** Convert to 32 bit little endian format from CPU format */
+#define woal_cpu_to_le32(x) cpu_to_le32(x)
+/** Convert to 64 bit little endian format from CPU format */
+#define woal_cpu_to_le64(x) cpu_to_le64(x)
+#else
+/** Do nothing */
+#define woal_le16_to_cpu(x) x
+/** Do nothing */
+#define woal_le32_to_cpu(x) x
+/** Do nothing */
+#define woal_le64_to_cpu(x) x
+/** Do nothing */
+#define woal_cpu_to_le16(x) x
+/** Do nothing */
+#define woal_cpu_to_le32(x) x
+/** Do nothing */
+#define woal_cpu_to_le64(x) x
+#endif
+
+/**
+ *  @brief This function returns first available priv
+ *  based on the BSS role
+ *
+ *  @param handle    A pointer to moal_handle
+ *  @param bss_role  BSS role or MLAN_BSS_ROLE_ANY
+ *
+ *  @return          Pointer to moal_private
+ */
+static inline moal_private *
+woal_get_priv(moal_handle *handle, mlan_bss_role bss_role)
+{
+	int i;
+
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i]) {
+			if (bss_role == MLAN_BSS_ROLE_ANY ||
+			    GET_BSS_ROLE(handle->priv[i]) == bss_role)
+				return handle->priv[i];
+		}
+	}
+	return NULL;
+}
+
+/**
+ *  @brief This function returns first available priv
+ *  based on the BSS type
+ *
+ *  @param handle    A pointer to moal_handle
+ *  @param bss_type  BSS type or MLAN_BSS_TYPE_ANY
+ *
+ *  @return          Pointer to moal_private
+ */
+static inline moal_private *
+woal_get_priv_bss_type(moal_handle *handle, mlan_bss_type bss_type)
+{
+	int i;
+
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i]) {
+			if (bss_type == MLAN_BSS_TYPE_ANY ||
+			    handle->priv[i]->bss_type == bss_type)
+				return handle->priv[i];
+		}
+	}
+	return NULL;
+}
+
+static inline moal_private *
+woal_get_vir_priv_bss_type(moal_handle *handle, mlan_bss_type bss_type)
+{
+	int i;
+
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i]) {
+			if (handle->priv[i]->bss_type == bss_type &&
+			    handle->priv[i]->bss_virtual)
+				return handle->priv[i];
+		}
+	}
+	return NULL;
+}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#endif
+
+static inline void
+woal_get_monotonic_time(wifi_timeval * tv)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+	struct timespec64 ts;
+#else
+	struct timespec ts;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+	ktime_get_raw_ts64(&ts);
+#else
+	getrawmonotonic(&ts);
+#endif
+	if (tv) {
+		tv->time_sec = (t_u32)ts.tv_sec;
+		tv->time_usec = (t_u32)ts.tv_nsec / 1000;
+	}
+}
+
+/* CAC Measure report default time 60 seconds */
+#define MEAS_REPORT_TIME (60 * HZ)
+
+/** Max line length allowed in init config file */
+#define MAX_LINE_LEN 256
+/** Max MAC address string length allowed */
+#define MAX_MAC_ADDR_LEN 18
+/** Max register type/offset/value etc. parameter length allowed */
+#define MAX_PARAM_LEN 12
+
+/** HostCmd_CMD_CFG_DATA for CAL data */
+#define HostCmd_CMD_CFG_DATA 0x008f
+/** HostCmd action set */
+#define HostCmd_ACT_GEN_SET 0x0001
+/** HostCmd CAL data header length */
+#define CFG_DATA_HEADER_LEN 6
+
+typedef struct _HostCmd_DS_GEN {
+	t_u16 command;
+	t_u16 size;
+	t_u16 seq_num;
+	t_u16 result;
+} HostCmd_DS_GEN;
+
+typedef struct _HostCmd_DS_802_11_CFG_DATA {
+	/** Action */
+	t_u16 action;
+	/** Type */
+	t_u16 type;
+	/** Data length */
+	t_u16 data_len;
+	/** Data */
+	t_u8 data[1];
+} __ATTRIB_PACK__ HostCmd_DS_802_11_CFG_DATA;
+
+/** combo scan header */
+#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
+/** combo scan header size */
+#define WEXT_CSCAN_HEADER_SIZE 12
+/** combo scan ssid section */
+#define WEXT_CSCAN_SSID_SECTION 'S'
+/** commbo scan channel section */
+#define WEXT_CSCAN_CHANNEL_SECTION 'C'
+/** commbo scan passive dwell section */
+#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
+/** commbo scan home dwell section */
+#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
+/** BGSCAN RSSI section */
+#define WEXT_BGSCAN_RSSI_SECTION 'R'
+/** BGSCAN SCAN INTERVAL SECTION */
+#define WEXT_BGSCAN_INTERVAL_SECTION 'T'
+/** BGSCAN REPEAT SECTION */
+#define WEXT_BGSCAN_REPEAT_SECTION 'E'
+/** Min BGSCAN interval 30 second */
+#define MIN_BGSCAN_INTERVAL 30000
+/** default repeat count */
+#define DEF_REPEAT_COUNT 6
+
+/** default rssi low threshold */
+#define DEFAULT_RSSI_LOW_THRESHOLD 70
+/** RSSI HYSTERSIS */
+#define RSSI_HYSTERESIS 6
+/** lowest rssi threshold */
+#define LOWEST_RSSI_THRESHOLD 82
+/** delta rssi */
+#define DELTA_RSSI 10
+
+/** NL80211 scan configuration header */
+#define NL80211_SCANCFG_HEADER "SCAN-CFG "
+/** NL80211 scan configuration header length */
+#define NL80211_SCANCFG_HEADER_SIZE 9
+/** NL80211 scan configuration active scan section */
+#define NL80211_SCANCFG_ACTV_DWELL_SECTION 'A'
+/** NL80211 scan configuration passive scan section */
+#define NL80211_SCANCFG_PASV_DWELL_SECTION 'P'
+/** NL80211 scan configuration specific scan section */
+#define NL80211_SCANCFG_SPCF_DWELL_SECTION 'S'
+
+/** band AUTO */
+#define WIFI_FREQUENCY_BAND_AUTO 0
+/** band 5G */
+#define WIFI_FREQUENCY_BAND_5GHZ 1
+/** band 2G */
+#define WIFI_FREQUENCY_BAND_2GHZ 2
+/** All band */
+#define WIFI_FREQUENCY_ALL_BAND 3
+
+/** Rx filter: IPV4 multicast */
+#define RX_FILTER_IPV4_MULTICAST 1
+/** Rx filter: broadcast */
+#define RX_FILTER_BROADCAST 2
+/** Rx filter: unicast */
+#define RX_FILTER_UNICAST 4
+/** Rx filter: IPV6 multicast */
+#define RX_FILTER_IPV6_MULTICAST 8
+
+/**  Convert ASCII string to hex value */
+int woal_ascii2hex(t_u8 *d, char *s, t_u32 dlen);
+/** parse ie */
+const t_u8 *woal_parse_ie_tlv(const t_u8 *ie, int len, t_u8 id);
+/** parse extension ie */
+const t_u8 *woal_parse_ext_ie_tlv(const t_u8 *ie, int len, t_u8 ext_id);
+/**  Convert mac address from string to t_u8 buffer */
+void woal_mac2u8(t_u8 *mac_addr, char *buf);
+/**  Extract token from string */
+char *woal_strsep(char **s, char delim, char esc);
+/** Return int value of a given ASCII string */
+mlan_status woal_atoi(int *data, char *a);
+/** Return hex value of a given ASCII string */
+int woal_atox(char *a);
+/** Allocate buffer */
+pmlan_buffer woal_alloc_mlan_buffer(moal_handle *handle, int size);
+/** Allocate IOCTL request buffer */
+pmlan_ioctl_req woal_alloc_mlan_ioctl_req(int size);
+/** Free buffer */
+void woal_free_mlan_buffer(moal_handle *handle, pmlan_buffer pmbuf);
+/** Get private structure of a BSS by index */
+moal_private *woal_bss_index_to_priv(moal_handle *handle, t_u8 bss_index);
+/* Functions in init module */
+/** init module parameters */
+mlan_status woal_init_module_param(moal_handle *handle);
+/** free module parameters */
+void woal_free_module_param(moal_handle *handle);
+/** init module parameters from device tree */
+void woal_init_from_dev_tree(void);
+/** initializes software */
+mlan_status woal_init_sw(moal_handle *handle);
+/** update the default firmware name */
+void woal_update_firmware_name(moal_handle *handle);
+/** cancel all works in the queue */
+void woal_terminate_workqueue(moal_handle *handle);
+void woal_flush_workqueue(moal_handle *handle);
+/** initializes firmware */
+mlan_status woal_init_fw(moal_handle *handle);
+/** frees the structure of moal_handle */
+void woal_free_moal_handle(moal_handle *handle);
+/** shutdown fw */
+mlan_status woal_shutdown_fw(moal_private *priv, t_u8 wait_option);
+/* Functions in interface module */
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
+static inline void
+wakeup_source_init(struct wakeup_source *ws, const char *name)
+{
+	ENTER();
+
+	if (ws) {
+		memset(ws, 0, sizeof(*ws));
+		ws->name = name;
+	}
+	wakeup_source_add(ws);
+
+	LEAVE();
+}
+
+static inline void
+wakeup_source_trash(struct wakeup_source *ws)
+{
+	ENTER();
+
+	if (!ws) {
+		PRINTM(MERROR, "ws is null!\n");
+		return;
+	}
+	wakeup_source_remove(ws);
+	__pm_relax(ws);
+
+	LEAVE();
+}
+#endif
+#endif
+/** Add card */
+moal_handle *woal_add_card(void *card, struct device *dev, moal_if_ops * if_ops,
+			   t_u16 card_type);
+/** Remove card */
+mlan_status woal_remove_card(void *card);
+/** broadcast event */
+mlan_status woal_broadcast_event(moal_private *priv, t_u8 *payload, t_u32 len);
+#ifdef CONFIG_PROC_FS
+/** switch driver mode */
+mlan_status woal_switch_drv_mode(moal_handle *handle, t_u32 mode);
+#endif
+
+int woal_check_media_connected(t_void *pmoal);
+/** check if any interface is up */
+t_u8 woal_is_any_interface_active(moal_handle *handle);
+/** Get version */
+void woal_get_version(moal_handle *handle, char *version, int maxlen);
+/** Get Driver Version */
+int woal_get_driver_version(moal_private *priv, struct ifreq *req);
+/** Get extended driver version */
+int woal_get_driver_verext(moal_private *priv, struct ifreq *ireq);
+/** check driver status */
+t_u8 woal_check_driver_status(moal_handle *handle);
+/** Mgmt frame forward registration */
+int woal_reg_rx_mgmt_ind(moal_private *priv, t_u16 action,
+			 t_u32 *pmgmt_subtype_mask, t_u8 wait_option);
+#ifdef DEBUG_LEVEL1
+/** Set driver debug bit masks */
+int woal_set_drvdbg(moal_private *priv, t_u32 drv_dbg);
+#endif
+
+mlan_status woal_set_get_tx_bf_cap(moal_private *priv, t_u16 action,
+				   t_u32 *tx_bf_cap);
+/** Set/Get TX beamforming configurations */
+mlan_status woal_set_get_tx_bf_cfg(moal_private *priv, t_u16 action,
+				   mlan_ds_11n_tx_bf_cfg *bf_cfg);
+/** Request MAC address setting */
+mlan_status woal_request_set_mac_address(moal_private *priv, t_u8 wait_option);
+/** Request multicast list setting */
+void woal_request_set_multicast_list(moal_private *priv,
+				     struct net_device *dev);
+/** Request IOCTL action */
+mlan_status woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req,
+			       t_u8 wait_option);
+/** Set/Get generic element */
+mlan_status woal_set_get_gen_ie(moal_private *priv, t_u32 action, t_u8 *ie,
+				int *ie_len, t_u8 wait_option);
+#ifdef CONFIG_PROC_FS
+mlan_status woal_request_soft_reset(moal_handle *handle);
+#endif
+void woal_request_fw_reload(moal_handle *phandle, t_u8 mode);
+
+/** Get debug information */
+mlan_status woal_get_debug_info(moal_private *priv, t_u8 wait_option,
+				mlan_debug_info *debug_info);
+/** Set debug information */
+mlan_status woal_set_debug_info(moal_private *priv, t_u8 wait_option,
+				mlan_debug_info *debug_info);
+/** Disconnect */
+mlan_status woal_disconnect(moal_private *priv, t_u8 wait_option, t_u8 *mac,
+			    t_u16 reason_code);
+/** associate */
+mlan_status woal_bss_start(moal_private *priv, t_u8 wait_option,
+			   mlan_ssid_bssid *ssid_bssid);
+/** Request firmware information */
+mlan_status woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
+				     mlan_fw_info *fw_info);
+/** Get channel of active intf */
+mlan_status woal_get_active_intf_channel(moal_private *priv,
+					 chan_band_info * channel);
+#ifdef STA_SUPPORT
+/** Request Exented Capability information */
+int woal_request_extcap(moal_private *priv, t_u8 *buf, t_u8 len);
+#endif
+mlan_status woal_set_get_dtim_period(moal_private *priv, t_u32 action,
+				     t_u8 wait_option, t_u8 *value);
+/** Set/get Host Sleep parameters */
+mlan_status woal_set_get_hs_params(moal_private *priv, t_u16 action,
+				   t_u8 wait_option, mlan_ds_hs_cfg *hscfg);
+/** Cancel Host Sleep configuration */
+mlan_status woal_cancel_hs(moal_private *priv, t_u8 wait_option);
+/** Enable Host Sleep configuration */
+int woal_enable_hs(moal_private *priv);
+/** hs active timeout 2 second */
+#define HS_ACTIVE_TIMEOUT (2 * HZ)
+/** Get wakeup reason */
+mlan_status woal_get_wakeup_reason(moal_private *priv,
+				   mlan_ds_hs_wakeup_reason *wakeup_reason);
+#define FW_DUMP_INFO_LEN 0x280000
+/** mem dump header */
+typedef struct {
+	/** seq number */
+	t_u16 seq_num;
+	/** resvered */
+	t_u16 reserved;
+	/** type */
+	t_u16 type;
+	/** len */
+	t_u16 len;
+	/** start addr */
+	t_u32 start_addr;
+} mem_dump_header;
+int woal_save_dump_info_to_buf(moal_handle *phandle, t_u8 *src, t_u32 len,
+			       t_u32 type);
+void woal_append_end_block(moal_handle *phandle);
+t_u8 *woal_dump_drv_info(moal_handle *phandle, t_u32 *dump_len);
+
+#define FW_DUMP_TYPE_ENDED 0x002
+#define FW_DUMP_TYPE_MEM_ITCM 0x004
+#define FW_DUMP_TYPE_MEM_DTCM 0x005
+#define FW_DUMP_TYPE_MEM_SQRAM 0x006
+#define FW_DUMP_TYPE_MEM_IRAM 0x007
+#define FW_DUMP_TYPE_REG_MAC 0x009
+#define FW_DUMP_TYPE_REG_CIU 0x00E
+#define FW_DUMP_TYPE_REG_APU 0x00F
+#define FW_DUMP_TYPE_REG_ICU 0x014
+#ifdef SDIO_MMC
+void woal_dump_firmware_info(moal_handle *phandle);
+void woal_dump_firmware_info_v2(moal_handle *phandle);
+void woal_dump_firmware_info_v3(moal_handle *phandle);
+#endif /* SDIO_MMC */
+/* Store the FW dumps received from events in a file */
+void woal_store_firmware_dump(moal_handle *phandle, pmlan_event pmevent);
+void woal_send_fw_dump_complete_event(moal_private *priv);
+
+int woal_pre_warmreset(moal_private *priv);
+int woal_warmreset(moal_private *priv);
+
+/** get deep sleep */
+int woal_get_deep_sleep(moal_private *priv, t_u32 *data);
+/** set deep sleep */
+int woal_set_deep_sleep(moal_private *priv, t_u8 wait_option,
+			BOOLEAN bdeep_sleep, t_u16 idletime);
+/** process hang */
+void woal_process_hang(moal_handle *handle);
+/** Get BSS information */
+mlan_status woal_get_bss_info(moal_private *priv, t_u8 wait_option,
+			      mlan_bss_info *bss_info);
+void woal_process_ioctl_resp(moal_private *priv, mlan_ioctl_req *req);
+char *region_code_2_string(t_u8 region_code);
+t_bool woal_is_etsi_country(t_u8 *country_code);
+t_u8 woal_is_valid_alpha2(char *alpha2);
+#ifdef STA_SUPPORT
+void woal_send_disconnect_to_system(moal_private *priv, t_u16 reason_code);
+void woal_send_mic_error_event(moal_private *priv, t_u32 event);
+void woal_ioctl_get_bss_resp(moal_private *priv, mlan_ds_bss *bss);
+void woal_ioctl_get_info_resp(moal_private *priv, mlan_ds_get_info *info);
+mlan_status woal_get_assoc_rsp(moal_private *priv,
+			       mlan_ds_misc_assoc_rsp *assoc_rsp,
+			       t_u8 wait_option);
+/** Get signal information */
+mlan_status woal_get_signal_info(moal_private *priv, t_u8 wait_option,
+				 mlan_ds_get_signal *signal);
+/** Get mode */
+t_u32 woal_get_mode(moal_private *priv, t_u8 wait_option);
+mlan_status woal_get_sta_channel(moal_private *priv, t_u8 wait_option,
+				 chan_band_info * channel);
+#ifdef STA_WEXT
+/** Get data rates */
+mlan_status woal_get_data_rates(moal_private *priv, t_u8 wait_option,
+				pmoal_802_11_rates m_rates);
+void woal_send_iwevcustom_event(moal_private *priv, char *str);
+/** Get channel list */
+mlan_status woal_get_channel_list(moal_private *priv, t_u8 wait_option,
+				  mlan_chan_list *chanlist);
+mlan_status woal_11d_check_ap_channel(moal_private *priv, t_u8 wait_option,
+				      mlan_ssid_bssid *ssid_bssid);
+#endif
+/** Set/Get retry count */
+mlan_status woal_set_get_retry(moal_private *priv, t_u32 action,
+			       t_u8 wait_option, int *value);
+/** Set/Get RTS threshold */
+mlan_status woal_set_get_rts(moal_private *priv, t_u32 action, t_u8 wait_option,
+			     int *value);
+/** Set/Get fragment threshold */
+mlan_status woal_set_get_frag(moal_private *priv, t_u32 action,
+			      t_u8 wait_option, int *value);
+/** Set/Get TX power */
+mlan_status woal_set_get_tx_power(moal_private *priv, t_u32 action,
+				  mlan_power_cfg_t *pwr);
+/** Set/Get power IEEE management */
+mlan_status woal_set_get_power_mgmt(moal_private *priv, t_u32 action,
+				    int *disabled, int type, t_u8 wait_option);
+/** Get data rate */
+mlan_status woal_set_get_data_rate(moal_private *priv, t_u8 action,
+				   mlan_rate_cfg_t *datarate);
+/** Request a network scan */
+mlan_status woal_request_scan(moal_private *priv, t_u8 wait_option,
+			      mlan_802_11_ssid *req_ssid);
+/** Set radio on/off */
+int woal_set_radio(moal_private *priv, t_u8 option);
+/** Set region code */
+mlan_status woal_set_region_code(moal_private *priv, char *region);
+/** Set authentication mode */
+mlan_status woal_set_auth_mode(moal_private *priv, t_u8 wait_option,
+			       t_u32 auth_mode);
+/** Set encryption mode */
+mlan_status woal_set_encrypt_mode(moal_private *priv, t_u8 wait_option,
+				  t_u32 encrypt_mode);
+/** Enable wep key */
+mlan_status woal_enable_wep_key(moal_private *priv, t_u8 wait_option);
+/** Set WPA enable */
+mlan_status woal_set_wpa_enable(moal_private *priv, t_u8 wait_option,
+				t_u32 enable);
+/** cancel scan command */
+mlan_status woal_cancel_scan(moal_private *priv, t_u8 wait_option);
+/** Find best network to connect */
+mlan_status woal_find_best_network(moal_private *priv, t_u8 wait_option,
+				   mlan_ssid_bssid *ssid_bssid);
+/** Set Ad-Hoc channel */
+mlan_status woal_change_adhoc_chan(moal_private *priv, int channel,
+				   t_u8 wait_option);
+
+/** Get scan table */
+mlan_status woal_get_scan_table(moal_private *priv, t_u8 wait_option,
+				mlan_scan_resp *scanresp);
+/** Get authentication mode */
+mlan_status woal_get_auth_mode(moal_private *priv, t_u8 wait_option,
+			       t_u32 *auth_mode);
+/** Get encryption mode */
+mlan_status woal_get_encrypt_mode(moal_private *priv, t_u8 wait_option,
+				  t_u32 *encrypt_mode);
+/** Get WPA state */
+mlan_status woal_get_wpa_enable(moal_private *priv, t_u8 wait_option,
+				t_u32 *enable);
+#endif /**STA_SUPPORT */
+
+mlan_status woal_set_11d(moal_private *priv, t_u8 wait_option, t_u8 enable);
+
+mlan_status woal_process_rf_test_mode(moal_handle *handle, t_u32 mode);
+mlan_status woal_process_rf_test_mode_cmd(moal_handle *handle, t_u32 cmd,
+					  const char *buffer, size_t len,
+					  t_u32 action, t_u32 val);
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+/** Get statistics information */
+mlan_status woal_get_stats_info(moal_private *priv, t_u8 wait_option,
+				pmlan_ds_get_stats stats);
+#endif /**STA_SUPPORT||UAP_SUPPORT*/
+
+mlan_status woal_set_wapi_enable(moal_private *priv, t_u8 wait_option,
+				 t_u32 enable);
+
+/** Initialize priv */
+void woal_init_priv(moal_private *priv, t_u8 wait_option);
+/** Reset interface(s) */
+int woal_reset_intf(moal_private *priv, t_u8 wait_option, int all_intf);
+#define TLV_TYPE_MGMT_IE (0x169)
+#define MGMT_MASK_ASSOC_REQ 0x01
+#define MGMT_MASK_REASSOC_REQ 0x04
+#define MGMT_MASK_ASSOC_RESP 0x02
+#define MGMT_MASK_REASSOC_RESP 0x08
+#define MGMT_MASK_PROBE_REQ 0x10
+#define MGMT_MASK_PROBE_RESP 0x20
+#define MGMT_MASK_BEACON 0x100
+#define MGMT_MASK_ASSOC_RESP_QOS_MAP 0x4000
+#define MGMT_MASK_BEACON_WPS_P2P 0x8000
+#define MLAN_CUSTOM_IE_DELETE_MASK 0x0
+/** common ioctl for uap, station */
+int woal_custom_ie_ioctl(struct net_device *dev, struct ifreq *req);
+#ifdef UAP_SUPPORT
+int woal_priv_get_nonglobal_operclass_by_bw_channel(moal_private *priv,
+						    t_u8 bandwidth,
+						    t_u8 channel,
+						    t_u8 *oper_class);
+#endif
+int woal_send_host_packet(struct net_device *dev, struct ifreq *req);
+/** Private command ID to pass mgmt frame */
+#define WOAL_MGMT_FRAME_TX_IOCTL (SIOCDEVPRIVATE + 12)
+/** common ioctl for TDLS */
+int woal_tdls_config_ioctl(struct net_device *dev, struct ifreq *req);
+
+int woal_get_bss_type(struct net_device *dev, struct ifreq *req);
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+int woal_host_command(moal_private *priv, struct iwreq *wrq);
+#endif
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+mlan_status woal_bss_role_cfg(moal_private *priv, t_u8 action, t_u8 wait_option,
+			      t_u8 *bss_role);
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+void woal_go_timer_func(void *context);
+#endif
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+int woal_set_get_bss_role(moal_private *priv, struct iwreq *wrq);
+#endif
+#endif
+#if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT)
+/** hostcmd ioctl for uap, wifidirect */
+int woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req);
+#endif
+
+mlan_status woal_set_remain_channel_ioctl(moal_private *priv, t_u8 wait_option,
+					  pmlan_ds_remain_chan pchan);
+void woal_remain_timer_func(void *context);
+#ifdef WIFI_DIRECT_SUPPORT
+mlan_status woal_wifi_direct_mode_cfg(moal_private *priv, t_u16 action,
+				      t_u16 *mode);
+mlan_status woal_p2p_config(moal_private *priv, t_u32 action,
+			    mlan_ds_wifi_direct_config *p2p_config);
+#endif /* WIFI_DIRECT_SUPPORT */
+
+int woal_11h_cancel_chan_report_ioctl(moal_private *priv, t_u8 wait_option);
+
+#ifdef CONFIG_PROC_FS
+/** Initialize /proc/mwlan */
+mlan_status woal_root_proc_init(void);
+/** Remove /proc/mwlan */
+void woal_root_proc_remove(void);
+/** Initialize proc fs */
+void woal_proc_init(moal_handle *handle);
+/** Clean up proc fs */
+void woal_proc_exit(moal_handle *handle);
+/** Create proc entry */
+void woal_create_proc_entry(moal_private *priv);
+/** Remove proc entry */
+void woal_proc_remove(moal_private *priv);
+/** string to number */
+int woal_string_to_number(char *s);
+#endif
+
+/** Create debug proc fs */
+void woal_debug_entry(moal_private *priv);
+/** Remove debug proc fs */
+void woal_debug_remove(moal_private *priv);
+
+/** check pm info */
+mlan_status woal_get_pm_info(moal_private *priv, mlan_ds_ps_info *pm_info);
+/** get mlan debug info */
+void woal_mlan_debug_info(moal_private *priv);
+
+#ifdef USB
+#ifdef CONFIG_USB_SUSPEND
+/** Enter USB Suspend */
+int woal_enter_usb_suspend(moal_handle *handle);
+/** Exit from USB Suspend */
+int woal_exit_usb_suspend(moal_handle *handle);
+#endif /* CONFIG_USB_SUSPEND */
+#endif
+
+#ifdef REASSOCIATION
+int woal_reassociation_thread(void *data);
+void woal_reassoc_timer_func(void *context);
+#endif /* REASSOCIATION */
+
+void woal_fw_dump_timer_func(void *context);
+
+t_void woal_main_work_queue(struct work_struct *work);
+t_void woal_rx_work_queue(struct work_struct *work);
+t_void woal_evt_work_queue(struct work_struct *work);
+t_void woal_mclist_work_queue(struct work_struct *work);
+#ifdef STA_CFG80211
+t_void woal_scan_timeout_handler(struct work_struct *work);
+#endif
+
+netdev_tx_t woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+#ifdef STA_SUPPORT
+mlan_status woal_init_sta_dev(struct net_device *dev, moal_private *priv);
+#endif
+#ifdef UAP_SUPPORT
+mlan_status woal_init_uap_dev(struct net_device *dev, moal_private *priv);
+#endif
+mlan_status woal_update_drv_tbl(moal_handle *handle, int drv_mode_local);
+void woal_fill_mlan_buffer(moal_private *priv, mlan_buffer *pmbuf,
+			   struct sk_buff *skb);
+moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_num,
+				 t_u8 bss_type);
+void woal_remove_interface(moal_handle *handle, t_u8 bss_index);
+void woal_set_multicast_list(struct net_device *dev);
+mlan_status woal_request_fw(moal_handle *handle);
+int woal_11h_channel_check_ioctl(moal_private *priv, t_u8 wait_option);
+void woal_cancel_cac_block(moal_private *priv);
+void woal_moal_debug_info(moal_private *priv, moal_handle *handle, u8 flag);
+
+#ifdef STA_SUPPORT
+mlan_status woal_get_powermode(moal_private *priv, int *powermode);
+mlan_status woal_set_scan_type(moal_private *priv, t_u32 scan_type);
+mlan_status woal_get_scan_config(moal_private *priv, mlan_scan_cfg *scan_cfg);
+mlan_status woal_enable_ext_scan(moal_private *priv, t_u8 enable);
+mlan_status woal_set_powermode(moal_private *priv, char *powermode);
+int woal_find_essid(moal_private *priv, mlan_ssid_bssid *ssid_bssid,
+		    t_u8 wait_option);
+mlan_status woal_find_bssid(moal_private *priv, mlan_802_11_mac_addr bssid);
+mlan_status woal_request_userscan(moal_private *priv, t_u8 wait_option,
+				  wlan_user_scan_cfg *scan_cfg);
+mlan_status woal_do_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg);
+int woal_set_combo_scan(moal_private *priv, char *buf, int length);
+mlan_status woal_set_scan_time(moal_private *priv, t_u16 active_scan_time,
+			       t_u16 passive_scan_time,
+			       t_u16 specific_scan_time);
+mlan_status woal_get_band(moal_private *priv, int *band);
+mlan_status woal_set_band(moal_private *priv, char *pband);
+mlan_status woal_add_rxfilter(moal_private *priv, char *rxfilter);
+mlan_status woal_remove_rxfilter(moal_private *priv, char *rxfilter);
+mlan_status woal_priv_qos_cfg(moal_private *priv, t_u32 action, char *qos_cfg);
+mlan_status woal_set_sleeppd(moal_private *priv, char *psleeppd);
+int woal_set_scan_cfg(moal_private *priv, char *buf, int length);
+void woal_update_dscp_mapping(moal_private *priv);
+
+/* EVENT: BCN_RSSI_LOW */
+#define EVENT_BCN_RSSI_LOW 0x0001
+/* EVENT: PRE_BCN_LOST */
+#define EVENT_PRE_BCN_LOST 0x0002
+mlan_status woal_set_rssi_low_threshold(moal_private *priv, char *rssi,
+					t_u8 wait_option);
+mlan_status woal_set_rssi_threshold(moal_private *priv, t_u32 event_id,
+				    t_u8 wait_option);
+/* EVENT: BG_SCAN_REPORT */
+#define EVENT_BG_SCAN_REPORT 0x0004
+mlan_status woal_set_bg_scan(moal_private *priv, char *buf, int length);
+mlan_status woal_stop_bg_scan(moal_private *priv, t_u8 wait_option);
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+mlan_status
+woal_set_wifi_low_latency_mode(moal_private *priv, t_u8 mode);
+#endif  // defined(WIFI_LATENCY_MODE_SUPPORT)
+void woal_reconfig_bgscan(moal_handle *handle);
+#ifdef STA_CFG80211
+void woal_config_bgscan_and_rssi(moal_private *priv, t_u8 set_rssi);
+void woal_start_roaming(moal_private *priv);
+#endif
+mlan_status woal_request_bgscan(moal_private *priv, t_u8 wait_option,
+				wlan_bgscan_cfg *scan_cfg);
+#endif
+#ifdef STA_CFG80211
+void woal_save_conn_params(moal_private *priv,
+			   struct cfg80211_connect_params *sme);
+void woal_clear_conn_params(moal_private *priv);
+#endif
+
+void woal_flush_tcp_sess_queue(moal_private *priv);
+#ifdef STA_CFG80211
+void woal_flush_tdls_list(moal_private *priv);
+#endif
+void wlan_scan_create_brief_table_entry(t_u8 **ppbuffer,
+					BSSDescriptor_t *pbss_desc);
+int wlan_get_scan_table_ret_entry(BSSDescriptor_t *pbss_desc, t_u8 **ppbuffer,
+				  int *pspace_left);
+BOOLEAN woal_ssid_valid(mlan_802_11_ssid *pssid);
+int woal_is_connected(moal_private *priv, mlan_ssid_bssid *ssid_bssid);
+int woal_priv_hostcmd(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen,
+		      t_u8 wait_option);
+void woal_flush_tx_stat_queue(moal_private *priv);
+struct tx_status_info *woal_get_tx_info(moal_private *priv, t_u8 tx_seq_num);
+void woal_remove_tx_info(moal_private *priv, t_u8 tx_seq_num);
+
+mlan_status woal_request_country_power_table(moal_private *priv, char *region);
+#ifdef RX_PACKET_COALESCE
+mlan_status woal_rx_pkt_coalesce_cfg(moal_private *priv, t_u16 *enable,
+				     t_u8 wait_option, t_u8 action);
+#endif
+mlan_status woal_set_low_pwr_mode(moal_handle *handle, t_u8 wait_option);
+int woal_hexval(char chr);
+mlan_status woal_pmic_configure(moal_handle *handle, t_u8 wait_option);
+mlan_status woal_set_user_antcfg(moal_handle *handle, t_u8 wait_option);
+void woal_hist_data_reset(moal_private *priv);
+void woal_hist_do_reset(moal_private *priv, void *data);
+void woal_hist_reset_table(moal_private *priv, t_u8 antenna);
+void woal_hist_data_add(moal_private *priv, t_u16 rx_rate, t_s8 snr, t_s8 nflr,
+			t_u8 antenna);
+mlan_status woal_set_hotspotcfg(moal_private *priv, t_u8 wait_option,
+				t_u32 hotspotcfg);
+
+mlan_status woal_set_get_wowlan_config(moal_private *priv, t_u16 action,
+				       t_u8 wait_option,
+				       mlan_ds_misc_mef_flt_cfg *mefcfg);
+mlan_status woal_set_auto_arp_ext(moal_handle *handle, t_u8 enable);
+mlan_status woal_delba_all(moal_private *priv, t_u8 wait_option);
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+int woal_mkeep_alive_vendor_event(moal_private *priv,
+				  pmlan_ds_misc_keep_alive mkeep_alive);
+#endif
+#endif
+int woal_start_mkeep_alive(moal_private *priv, t_u8 mkeep_alive_id,
+			   t_u8 *ip_pkt, t_u16 ip_pkt_len, t_u8 *src_mac,
+			   t_u8 *dst_mac, t_u32 period_msec,
+			   t_u32 retry_interval, t_u8 retry_cnt);
+int woal_stop_mkeep_alive(moal_private *priv, t_u8 mkeep_alive_id, t_u8 reset,
+			  t_u8 *ip_pkt, t_u8 *pkt_len);
+int woal_priv_save_cloud_keep_alive_params(moal_private *priv,
+					   t_u8 mkeep_alive_id, t_u8 enable,
+					   t_u16 ether_type, t_u8 *ip_pkt,
+					   t_u16 ip_pkt_len, t_u8 *src_mac,
+					   t_u8 *dst_mac, t_u32 period_msec,
+					   t_u32 retry_interval,
+					   t_u8 retry_cnt);
+#ifdef UAP_SUPPORT
+mlan_status woal_set_wacp_mode(moal_private *priv, t_u8 wait_option);
+#endif
+mlan_status woal_init_aggr_ctrl(moal_handle *handle, t_u8 wait_option);
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+void woal_cfg80211_vendor_event_fw_dump(moal_private *priv);
+#endif
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+mlan_status woal_set_rekey_data(moal_private *priv,
+				mlan_ds_misc_gtk_rekey_data * gtk_rekey,
+				t_u8 action, t_u8 wait_option);
+#endif
+#endif
+
+mlan_status woal_vdll_req_fw(moal_handle *handle);
+
+void woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info);
+t_u8 woal_get_second_channel_offset(moal_private *priv, int chan);
+
+#ifdef IMX_SUPPORT
+void woal_regist_oob_wakeup_irq(moal_handle *handle);
+void woal_unregist_oob_wakeup_irq(moal_handle *handle);
+void woal_disable_oob_wakeup_irq(moal_handle *handle);
+void woal_enable_oob_wakeup_irq(moal_handle *handle);
+irqreturn_t woal_oob_wakeup_irq_handler(int irq, void *priv);
+#endif /* IMX_SUPPORT */
+#endif /* _MOAL_MAIN_H */
diff --git a/wlan_sd8987/mlinux/moal_pcie.c b/wlan_sd8987/mlinux/moal_pcie.c
new file mode 100755
index 0000000..dda7701
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_pcie.c
@@ -0,0 +1,2474 @@
+/** @file moal_pcie.c
+ *
+ *  @brief This file contains PCIE IF (interface) module
+ *  related functions.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/01/2012: initial version
+********************************************************/
+
+#include <linux/firmware.h>
+
+#include "moal_pcie.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
+#ifdef IMX_SUPPORT
+#include <linux/busfreq-imx.h>
+#endif
+#endif
+
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/addrconf.h>
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+#define DRV_NAME "NXP mdriver PCIe"
+
+/* PCIE resume handler */
+static int woal_pcie_resume(struct pci_dev *pdev);
+static void woal_pcie_reg_dbg(moal_handle *phandle);
+static void woal_pcie_unregister_dev(moal_handle *handle);
+static void woal_pcie_cleanup(pcie_service_card *card);
+static mlan_status woal_pcie_init(pcie_service_card *card);
+
+/** WLAN IDs */
+static const struct pci_device_id wlan_ids[] = {
+#ifdef PCIE8897
+	{
+	 PCIE_VENDOR_ID_NXP,
+	 PCIE_DEVICE_ID_NXP_88W8897P,
+	 PCI_ANY_ID,
+	 PCI_ANY_ID,
+	 0,
+	 0,
+	 },
+#endif
+#ifdef PCIE8997
+	{
+	 PCIE_VENDOR_ID_NXP,
+	 PCIE_DEVICE_ID_NXP_88W8997P,
+	 PCI_ANY_ID,
+	 PCI_ANY_ID,
+	 0,
+	 0,
+	 },
+	{
+	 PCIE_VENDOR_ID_V2_NXP,
+	 PCIE_DEVICE_ID_NXP_88W8997P,
+	 PCI_ANY_ID,
+	 PCI_ANY_ID,
+	 0,
+	 0,
+	 },
+#endif
+#ifdef PCIE9097
+	{
+	 PCIE_VENDOR_ID_V2_NXP,
+	 PCIE_DEVICE_ID_NXP_88W9097,
+	 PCI_ANY_ID,
+	 PCI_ANY_ID,
+	 0,
+	 0,
+	 },
+#endif
+#ifdef PCIE9098
+	{
+	 PCIE_VENDOR_ID_V2_NXP,
+	 PCIE_DEVICE_ID_NXP_88W9098P_FN0,
+	 PCI_ANY_ID,
+	 PCI_ANY_ID,
+	 0,
+	 0,
+	 },
+	{
+	 PCIE_VENDOR_ID_V2_NXP,
+	 PCIE_DEVICE_ID_NXP_88W9098P_FN1,
+	 PCI_ANY_ID,
+	 PCI_ANY_ID,
+	 0,
+	 0,
+	 },
+#endif
+	{},
+};
+
+/* moal interface ops */
+static moal_if_ops pcie_ops;
+
+MODULE_DEVICE_TABLE(pci, wlan_ids);
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+static mlan_status woal_pcie_preinit(struct pci_dev *pdev);
+
+/**  @brief This function updates the card types
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param card     A Pointer to card
+ *
+ *  @return         N/A
+ */
+static t_u16
+woal_update_card_type(t_void *card)
+{
+	pcie_service_card *cardp_pcie = (pcie_service_card *)card;
+	t_u16 card_type = 0;
+
+	/* Update card type */
+#ifdef PCIE8897
+	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_NXP_88W8897P) {
+		card_type = CARD_TYPE_PCIE8897;
+		moal_memcpy_ext(NULL, driver_version, CARD_PCIE8897,
+				strlen(CARD_PCIE8897), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V15, strlen(V15),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef PCIE8997
+	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_NXP_88W8997P) {
+		card_type = CARD_TYPE_PCIE8997;
+		moal_memcpy_ext(NULL, driver_version, CARD_PCIE8997,
+				strlen(CARD_PCIE8997), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef PCIE9097
+	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_NXP_88W9097) {
+		card_type = CARD_TYPE_PCIE9097;
+		moal_memcpy_ext(NULL, driver_version, CARD_PCIEIW620,
+				strlen(CARD_PCIEIW620), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V17, strlen(V17),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef PCIE9098
+	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_NXP_88W9098P_FN0 ||
+	    cardp_pcie->dev->device == PCIE_DEVICE_ID_NXP_88W9098P_FN1) {
+		card_type = CARD_TYPE_PCIE9098;
+		moal_memcpy_ext(NULL, driver_version, CARD_PCIE9098,
+				strlen(CARD_PCIE9098), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V17, strlen(V17),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+	return card_type;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+/**
+ * @brief Function to process pre/post PCIe function level reset
+ *
+ * @param handle    A pointer to moal_handle structure
+ * @param prepare   True :- its a pre FLR call from the kernel
+ *		    False :- its a post FLR call from the kernel
+ * @param flr       True: call from FLR
+ *
+ * Note: This function is mix of woal_switch_drv_mode() and
+ * remove_card(). Idea is to cleanup the software only without
+ * touching the PCIe specific code. Likewise, during init init
+ * everything, including hw, but do not reinitiate PCIe stack
+ *
+ * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_do_flr(moal_handle *handle, bool prepare, bool flr_flag)
+{
+	unsigned int i;
+	int index = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	pcie_service_card *card = NULL;
+	int fw_serial_bkp = 0;
+
+	ENTER();
+
+	if (!handle) {
+		PRINTM(MINFO, "\n Handle null during prepare=%d\n", prepare);
+		LEAVE();
+		return status;
+	}
+
+	card = (pcie_service_card *)handle->card;
+
+	if (card == NULL) {
+		PRINTM(MERROR, "The parameter 'card' is NULL\n");
+		LEAVE();
+		return (mlan_status)MLAN_STATUS_FAILURE;
+	}
+
+	if (!IS_PCIE8997(handle->card_type) &&
+	    !IS_PCIE9097(handle->card_type) &&
+	    !IS_PCIE9098(handle->card_type)) {
+		LEAVE();
+		return status;
+	}
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
+		goto exit_sem_err;
+
+	if (!prepare)
+		goto perform_init;
+
+	/* Reset all interfaces */
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE);
+
+	/* Shutdown firmware */
+	handle->init_wait_q_woken = MFALSE;
+	status = mlan_shutdown_fw(handle->pmlan_adapter);
+
+	if (status == MLAN_STATUS_PENDING)
+		wait_event_interruptible(handle->init_wait_q,
+					 handle->init_wait_q_woken);
+
+	if (atomic_read(&handle->rx_pending) ||
+	    atomic_read(&handle->tx_pending) ||
+	    atomic_read(&handle->ioctl_pending)) {
+		PRINTM(MERROR,
+		       "ERR: rx_pending=%d,tx_pending=%d,ioctl_pending=%d\n",
+		       atomic_read(&handle->rx_pending),
+		       atomic_read(&handle->tx_pending),
+		       atomic_read(&handle->ioctl_pending));
+	}
+
+	unregister_inetaddr_notifier(&handle->woal_notifier);
+#if IS_ENABLED(CONFIG_IPV6)
+	unregister_inet6addr_notifier(&handle->woal_inet6_notifier);
+#endif
+
+	/* Remove interface */
+	for (i = 0; i < handle->priv_num; i++)
+		woal_remove_interface(handle, i);
+
+	/* Unregister mlan */
+	if (handle->pmlan_adapter) {
+		mlan_unregister(handle->pmlan_adapter);
+		if (atomic_read(&handle->lock_count) ||
+		    atomic_read(&handle->malloc_count) ||
+		    atomic_read(&handle->mbufalloc_count)) {
+			PRINTM(MERROR,
+			       "mlan has memory leak: lock_count=%d,"
+			       " malloc_count=%d, mbufalloc_count=%d\n",
+			       atomic_read(&handle->lock_count),
+			       atomic_read(&handle->malloc_count),
+			       atomic_read(&handle->mbufalloc_count));
+		}
+		if (atomic_read(&handle->malloc_cons_count)) {
+			PRINTM(MERROR,
+			       "mlan has memory leak: malloc_cons_count=%d\n",
+			       atomic_read(&handle->malloc_cons_count));
+		}
+		handle->pmlan_adapter = NULL;
+	}
+
+	goto exit;
+
+perform_init:
+	handle->priv_num = 0;
+
+	/* Init SW */
+	if (woal_init_sw(handle)) {
+		PRINTM(MFATAL, "Software Init Failed\n");
+		goto err_init_fw;
+	}
+#ifdef PCIE9098
+	if (card->dev->device == PCIE_DEVICE_ID_NXP_88W9098P_FN1)
+		mlan_set_int_mode(handle->pmlan_adapter, pcie_int_mode, 1);
+	else
+#endif
+		/* Update pcie_int_mode in mlan adapter */
+		mlan_set_int_mode(handle->pmlan_adapter,
+				  handle->params.pcie_int_mode, 0);
+
+	/* Init FW and HW */
+	/* Load wlan only binary */
+	if (flr_flag) {
+		fw_serial_bkp = moal_extflg_isset(handle, EXT_FW_SERIAL);
+		moal_extflg_clear(handle, EXT_FW_SERIAL);
+		woal_update_firmware_name(handle);
+	}
+	if (woal_init_fw(handle)) {
+		PRINTM(MFATAL, "Firmware Init Failed\n");
+		woal_pcie_reg_dbg(handle);
+		if (fw_serial_bkp)
+			moal_extflg_set(handle, EXT_FW_SERIAL);
+		goto err_init_fw;
+	}
+	if (flr_flag && fw_serial_bkp)
+		moal_extflg_set(handle, EXT_FW_SERIAL);
+	if (IS_PCIE9098(handle->card_type))
+		handle->event_fw_dump = MTRUE;
+exit:
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+
+exit_sem_err:
+	LEAVE();
+	return status;
+
+err_init_fw:
+	if ((handle->hardware_status == HardwareStatusFwReady) ||
+	    (handle->hardware_status == HardwareStatusReady)) {
+		PRINTM(MINFO, "shutdown mlan\n");
+		handle->init_wait_q_woken = MFALSE;
+		status = mlan_shutdown_fw(handle->pmlan_adapter);
+		if (status == MLAN_STATUS_PENDING)
+			wait_event_interruptible(handle->init_wait_q,
+						 handle->init_wait_q_woken);
+	}
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+	wakeup_source_trash(&handle->ws);
+#else
+	wake_lock_destroy(&handle->wake_lock);
+#endif
+#endif
+#ifdef CONFIG_PROC_FS
+	woal_proc_exit(handle);
+#endif
+	/* Unregister device */
+	PRINTM(MINFO, "unregister device\n");
+	woal_pcie_unregister_dev(handle);
+	handle->surprise_removed = MTRUE;
+#ifdef REASSOCIATION
+	if (handle->reassoc_thread.pid)
+		wake_up_interruptible(&handle->reassoc_thread.wait_q);
+	/* waiting for main thread quit */
+	while (handle->reassoc_thread.pid)
+		woal_sched_timeout(2);
+#endif /* REASSOCIATION */
+	woal_terminate_workqueue(handle);
+	woal_free_moal_handle(handle);
+
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == handle)
+			break;
+	}
+	if (index < MAX_MLAN_ADAPTER)
+		m_handle[index] = NULL;
+	card->handle = NULL;
+	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
+	LEAVE();
+	return (mlan_status)MLAN_STATUS_FAILURE;
+}
+#endif
+
+/**
+ *  @brief This function handles PCIE driver probe
+ *
+ *  @param pdev     A pointer to pci_dev structure
+ *  @param id       A pointer to pci_device_id structure
+ *
+ *  @return         error code
+ */
+static int
+woal_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	pcie_service_card *card = NULL;
+	t_u16 card_type = 0;
+	int ret = 0;
+
+	ENTER();
+
+	PRINTM(MINFO, "vendor=0x%4.04X device=0x%4.04X rev=%d\n", pdev->vendor,
+	       pdev->device, pdev->revision);
+
+	/* Preinit PCIE device so allocate PCIE memory can be successful */
+	if (woal_pcie_preinit(pdev)) {
+		PRINTM(MFATAL, "MOAL PCIE preinit failed\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	card = kzalloc(sizeof(pcie_service_card), GFP_KERNEL);
+	if (!card) {
+		PRINTM(MERROR, "%s: failed to alloc memory\n", __func__);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	card->dev = pdev;
+
+	card_type = woal_update_card_type(card);
+	if (!card_type) {
+		PRINTM(MERROR, "pcie probe: woal_update_card_type() failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err;
+	}
+	woal_pcie_init(card);
+
+	if (woal_add_card(card, &card->dev->dev, &pcie_ops, card_type) == NULL) {
+		woal_pcie_cleanup(card);
+		PRINTM(MERROR, "%s: failed\n", __func__);
+		ret = -EFAULT;
+		goto err;
+	}
+#ifdef IMX_SUPPORT
+	woal_regist_oob_wakeup_irq(card->handle);
+#endif /* IMX_SUPPORT */
+
+	LEAVE();
+	return ret;
+err:
+	kfree(card);
+	if (pci_is_enabled(pdev))
+		pci_disable_device(pdev);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles PCIE driver remove
+ *
+ *  @param pdev     A pointer to pci_dev structure
+ *
+ *  @return         error code
+ */
+static void
+woal_pcie_remove(struct pci_dev *dev)
+{
+	pcie_service_card *card;
+	moal_handle *handle;
+
+	ENTER();
+	card = pci_get_drvdata(dev);
+	if (!card) {
+		PRINTM(MINFO, "PCIE card removed from slot\n");
+		LEAVE();
+		return;
+	}
+
+	handle = card->handle;
+	if (!handle || !handle->priv_num) {
+		PRINTM(MINFO, "PCIE card handle removed\n");
+		LEAVE();
+		return;
+	}
+	handle->surprise_removed = MTRUE;
+
+#ifdef IMX_SUPPORT
+	woal_unregist_oob_wakeup_irq(card->handle);
+#endif /* IMX_SUPPORT */
+	woal_remove_card(card);
+	woal_pcie_cleanup(card);
+	kfree(card);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief Handle suspend
+ *
+ *  @param pdev     A pointer to pci_dev structure
+ *  @param state    PM state message
+ *
+ *  @return         error code
+ */
+static int
+woal_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	pcie_service_card *cardp;
+	moal_handle *handle = NULL;
+	moal_handle *ref_handle = NULL;
+	int i;
+	int ret = MLAN_STATUS_SUCCESS;
+	int hs_actived;
+	mlan_ds_ps_info pm_info;
+	int keep_power = 0;
+
+	ENTER();
+	if (pdev) {
+		cardp = (pcie_service_card *)pci_get_drvdata(pdev);
+		if (!cardp || !cardp->handle) {
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	} else {
+		PRINTM(MERROR, "PCIE device is not specified\n");
+		LEAVE();
+		return -ENOSYS;
+	}
+
+	handle = cardp->handle;
+	if (handle->second_mac)
+		PRINTM(MCMND, "<--- Enter woal_pcie_suspend# --->\n");
+	else
+		PRINTM(MCMND, "<--- Enter woal_pcie_suspend --->\n");
+	if (handle->is_suspended == MTRUE) {
+		PRINTM(MWARN, "Device already suspended\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	if (handle->fw_dump) {
+		PRINTM(MMSG, "suspend not allowed while FW dump!");
+		ret = -EBUSY;
+		goto done;
+	}
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA))
+			woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT);
+	}
+	handle->suspend_fail = MFALSE;
+	memset(&pm_info, 0, sizeof(pm_info));
+#define MAX_RETRY_NUM 8
+	for (i = 0; i < MAX_RETRY_NUM; i++) {
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+				     &pm_info)) {
+			if (pm_info.is_suspend_allowed == MTRUE)
+				break;
+			else
+				PRINTM(MMSG,
+				       "Suspend not allowed and retry again\n");
+		}
+		woal_sched_timeout(100);
+	}
+	if (pm_info.is_suspend_allowed == MFALSE) {
+		PRINTM(MMSG, "Suspend not allowed\n");
+		ret = -EBUSY;
+		goto done;
+	}
+
+	for (i = 0; i < handle->priv_num; i++)
+		netif_device_detach(handle->priv[i]->netdev);
+	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER))
+		keep_power = MTRUE;
+	else
+		keep_power = MFALSE;
+
+	if (keep_power) {
+		/* Enable Host Sleep */
+		hs_actived =
+			woal_enable_hs(woal_get_priv
+				       (handle, MLAN_BSS_ROLE_ANY));
+		if (hs_actived == MTRUE) {
+			/* Indicate device suspended */
+			handle->is_suspended = MTRUE;
+		} else {
+			PRINTM(MMSG, "HS not actived, suspend fail!");
+			handle->suspend_fail = MTRUE;
+			for (i = 0; i < handle->priv_num; i++)
+				netif_device_attach(handle->priv[i]->netdev);
+			ret = -EBUSY;
+			goto done;
+		}
+	}
+	woal_flush_workqueue(handle);
+	if (!keep_power) {
+		woal_do_flr(handle, true, false);
+		handle->surprise_removed = MTRUE;
+		handle->is_suspended = MTRUE;
+	}
+#ifdef IMX_SUPPORT
+	woal_enable_oob_wakeup_irq(handle);
+#endif /* IMX_SUPPORT */
+	pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+	pci_save_state(pdev);
+	ref_handle = (moal_handle *)handle->pref_mac;
+	if (ref_handle && ref_handle->is_suspended)
+		pci_set_power_state(pdev, pci_choose_state(pdev, state));
+done:
+	PRINTM(MCMND, "<--- Leave woal_pcie_suspend --->\n");
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle resume
+ *
+ *  @param pdev     A pointer to pci_dev structure
+ *
+ *  @return         error code
+ */
+static int
+woal_pcie_resume(struct pci_dev *pdev)
+{
+	moal_handle *handle;
+	pcie_service_card *cardp;
+	int keep_power = 0;
+	int i;
+
+	ENTER();
+	if (pdev) {
+		cardp = (pcie_service_card *)pci_get_drvdata(pdev);
+		if (!cardp || !cardp->handle) {
+			PRINTM(MERROR, "Card or handle is not valid\n");
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+	} else {
+		PRINTM(MERROR, "PCIE device is not specified\n");
+		LEAVE();
+		return -ENOSYS;
+	}
+	handle = cardp->handle;
+	if (handle->second_mac)
+		PRINTM(MCMND, "<--- Enter woal_pcie_resume# --->\n");
+	else
+		PRINTM(MCMND, "<--- Enter woal_pcie_resume --->\n");
+	if (handle->is_suspended == MFALSE) {
+		PRINTM(MWARN, "Device already resumed\n");
+		goto done;
+	}
+	handle->is_suspended = MFALSE;
+
+	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER))
+		keep_power = MTRUE;
+	else
+		keep_power = MFALSE;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, PCI_D0, 0);
+	if (!keep_power) {
+		handle->surprise_removed = MFALSE;
+		woal_do_flr(handle, false, false);
+	} else {
+		if (woal_check_driver_status(handle)) {
+			PRINTM(MERROR, "Resuem, device is in hang state\n");
+			LEAVE();
+			return MLAN_STATUS_SUCCESS;
+		}
+		for (i = 0; i < handle->priv_num; i++)
+			netif_device_attach(handle->priv[i]->netdev);
+
+		woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+			       MOAL_NO_WAIT);
+#ifdef IMX_SUPPORT
+		woal_disable_oob_wakeup_irq(handle);
+#endif /* IMX_SUPPORT */
+	}
+done:
+	PRINTM(MCMND, "<--- Leave woal_pcie_resume --->\n");
+	LEAVE();
+	return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
+/**
+ *  @brief Pcie reset prepare handler
+ *
+ *  @param pdev     A pointer to pci_dev structure
+ */
+static void
+woal_pcie_reset_prepare(struct pci_dev *pdev)
+{
+	pcie_service_card *card;
+	moal_handle *handle;
+	moal_handle *ref_handle = NULL;
+
+	ENTER();
+
+	card = pci_get_drvdata(pdev);
+	if (!card) {
+		PRINTM(MINFO, "PCIE card removed from slot\n");
+		LEAVE();
+		return;
+	}
+
+	handle = card->handle;
+
+	if (!handle) {
+		PRINTM(MINFO, "Invalid handle\n");
+		LEAVE();
+		return;
+	}
+
+	PRINTM(MMSG, "%s: vendor=0x%4.04X device=0x%4.04X rev=%d Pre-FLR\n",
+	       __func__, pdev->vendor, pdev->device, pdev->revision);
+
+	/* Kernel would be performing FLR after this notification.
+	 * Cleanup up all software withouth cleaning anything related to
+	 * PCIe and HW.
+	 * Note. FW might not be healthy.
+	 */
+	// handle-> mac0 , ref_handle->second mac
+	if (handle->pref_mac) {
+		if (handle->second_mac) {
+			handle = (moal_handle *)handle->pref_mac;
+			ref_handle = (moal_handle *)handle->pref_mac;
+		} else {
+			ref_handle = (moal_handle *)handle->pref_mac;
+		}
+	}
+	handle->surprise_removed = MTRUE;
+	woal_do_flr(handle, true, true);
+	if (ref_handle) {
+		ref_handle->surprise_removed = MTRUE;
+		woal_do_flr(ref_handle, true, true);
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Pcie reset done handler
+ *
+ *  @param pdev     A pointer to pci_dev structure
+ */
+static void
+woal_pcie_reset_done(struct pci_dev *pdev)
+{
+	pcie_service_card *card;
+	moal_handle *handle;
+	moal_handle *ref_handle = NULL;
+	ENTER();
+
+	card = pci_get_drvdata(pdev);
+	if (!card) {
+		PRINTM(MINFO, "PCIE card removed from slot\n");
+		LEAVE();
+		return;
+	}
+
+	handle = card->handle;
+	if (!handle) {
+		PRINTM(MINFO, "Invalid handle\n");
+		LEAVE();
+		return;
+	}
+
+	PRINTM(MMSG, "%s: vendor=0x%4.04X device=0x%4.04X rev=%d Post-FLR\n",
+	       __func__, pdev->vendor, pdev->device, pdev->revision);
+
+	/* Kernel stores and restores PCIe function context before and
+	 * after performing FLR, respectively.
+	 *
+	 * Reconfigure the sw and fw including fw redownload
+	 */
+	// handle-> mac0 , ref_handle->second mac
+	if (handle->pref_mac) {
+		if (handle->second_mac) {
+			handle = (moal_handle *)handle->pref_mac;
+			ref_handle = (moal_handle *)handle->pref_mac;
+		} else {
+			ref_handle = (moal_handle *)handle->pref_mac;
+		}
+	}
+	handle->surprise_removed = MFALSE;
+	woal_do_flr(handle, false, true);
+	if (ref_handle) {
+		ref_handle->surprise_removed = MFALSE;
+		woal_do_flr(ref_handle, false, true);
+	}
+
+	LEAVE();
+}
+#else
+static void
+woal_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
+{
+	pcie_service_card *card;
+	moal_handle *handle;
+	moal_handle *ref_handle = NULL;
+
+	ENTER();
+
+	card = pci_get_drvdata(pdev);
+	if (!card) {
+		PRINTM(MINFO, "PCIE card removed from slot\n");
+		LEAVE();
+		return;
+	}
+
+	handle = card->handle;
+	if (!handle) {
+		PRINTM(MINFO, "Invalid handle\n");
+		LEAVE();
+		return;
+	}
+
+	PRINTM(MMSG, "%s: vendor=0x%4.04X device=0x%4.04X rev=%d %s\n",
+	       __func__, pdev->vendor, pdev->device, pdev->revision,
+	       prepare ? "Pre-FLR" : "Post-FLR");
+
+	// handle-> mac0 , ref_handle->second mac
+	if (handle->pref_mac) {
+		if (handle->second_mac) {
+			handle = (moal_handle *)handle->pref_mac;
+			ref_handle = (moal_handle *)handle->pref_mac;
+		} else {
+			ref_handle = (moal_handle *)handle->pref_mac;
+		}
+	}
+
+	if (prepare) {
+		/* Kernel would be performing FLR after this notification.
+		 * Cleanup up all software withouth cleaning anything related to
+		 * PCIe and HW.
+		 * Note. FW might not be healthy.
+		 */
+		handle->surprise_removed = MTRUE;
+		woal_do_flr(handle, prepare, true);
+		if (ref_handle) {
+			ref_handle->surprise_removed = MTRUE;
+			woal_do_flr(ref_handle, prepare, true);
+		}
+	} else {
+		/* Kernel stores and restores PCIe function context before and
+		 * after performing FLR, respectively.
+		 *
+		 * Reconfigure the sw and fw including fw redownload
+		 */
+		handle->surprise_removed = MFALSE;
+		woal_do_flr(handle, prepare, true);
+		if (ref_handle) {
+			ref_handle->surprise_removed = MFALSE;
+			woal_do_flr(ref_handle, prepare, true);
+		}
+	}
+	LEAVE();
+}
+#endif
+
+static const struct pci_error_handlers woal_pcie_err_handler[] = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
+	{
+	 .reset_prepare = woal_pcie_reset_prepare,
+	 .reset_done = woal_pcie_reset_done,
+	 },
+#else
+	{
+	 .reset_notify = woal_pcie_reset_notify,
+	 },
+#endif
+};
+#endif // KERNEL_VERSION(3.18.0)
+
+/* PCI Device Driver */
+static struct pci_driver REFDATA wlan_pcie = {
+	.name = "wlan_pcie",
+	.id_table = wlan_ids,
+	.probe = woal_pcie_probe,
+	.remove = woal_pcie_remove,
+#ifdef CONFIG_PM
+	/* Power Management Hooks */
+	.suspend = woal_pcie_suspend,
+	.resume = woal_pcie_resume,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+	.err_handler = woal_pcie_err_handler,
+#endif
+};
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief This function writes data into card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_write_reg(moal_handle *handle, t_u32 reg, t_u32 data)
+{
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+
+	iowrite32(data, card->pci_mmap1 + reg);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads data from card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data)
+{
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+	*data = ioread32(card->pci_mmap1 + reg);
+
+	if (*data == MLAN_STATUS_FAILURE)
+		return MLAN_STATUS_FAILURE;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function writes multiple bytes into card memory
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param pmbuf	Pointer to mlan_buffer structure
+ *  @param port		Port
+ *  @param timeout 	Time out value
+ *
+ *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_write_data_sync(moal_handle *handle, mlan_buffer *pmbuf,
+			  t_u32 port, t_u32 timeout)
+{
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function reads multiple bytes from card memory
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param pmbuf	Pointer to mlan_buffer structure
+ *  @param port		Port
+ *  @param timeout 	Time out value
+ *
+ *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_read_data_sync(moal_handle *handle, mlan_buffer *pmbuf,
+			 t_u32 port, t_u32 timeout)
+{
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param irq	    The irq no. of PCIE device
+ *  @param dev_id   A pointer to the pci_dev structure
+ *
+ *  @return         IRQ_HANDLED
+ */
+static irqreturn_t
+woal_pcie_interrupt(int irq, void *dev_id)
+{
+	struct pci_dev *pdev;
+	pcie_service_card *card;
+	moal_handle *handle;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	pdev = (struct pci_dev *)dev_id;
+	if (!pdev) {
+		PRINTM(MFATAL, "%s: pdev is NULL\n", (t_u8 *)pdev);
+		goto exit;
+	}
+
+	card = (pcie_service_card *)pci_get_drvdata(pdev);
+	if (!card || !card->handle) {
+		PRINTM(MFATAL, "%s: card=%p handle=%p\n", __func__, card,
+		       card ? card->handle : NULL);
+		goto exit;
+	}
+	handle = card->handle;
+	if (handle->surprise_removed == MTRUE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(MINFO, "*** IN PCIE IRQ ***\n");
+	handle->main_state = MOAL_RECV_INT;
+	if (handle->second_mac)
+		PRINTM(MINTR, "**\n");
+	else
+		PRINTM(MINTR, "*\n");
+
+	ret = mlan_interrupt(0xffff, handle->pmlan_adapter);
+	if (handle->is_suspended) {
+		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
+		goto exit;
+	}
+	queue_work(handle->workqueue, &handle->main_work);
+
+exit:
+	if (ret == MLAN_STATUS_SUCCESS)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+/**
+ *  @brief This function handles the MSI-X interrupt.
+ *
+ *  @param irq	    The irq no. of PCIE device
+ *  @param dev_id   A pointer to the msix_context structure
+ *
+ *  @return         IRQ_HANDLED
+ */
+static irqreturn_t
+woal_pcie_msix_interrupt(int irq, void *dev_id)
+{
+	struct pci_dev *pdev;
+	pcie_service_card *card;
+	moal_handle *handle;
+	msix_context *ctx = (msix_context *) dev_id;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	if (!ctx) {
+		PRINTM(MFATAL, "%s: ctx=%p is NULL\n", __func__, ctx);
+		goto exit;
+	}
+
+	pdev = ctx->dev;
+
+	if (!pdev) {
+		PRINTM(MFATAL, "%s: pdev is NULL\n", (t_u8 *)pdev);
+		goto exit;
+	}
+
+	card = (pcie_service_card *)pci_get_drvdata(pdev);
+	if (!card || !card->handle) {
+		PRINTM(MFATAL, "%s: card=%p handle=%p\n", __func__, card,
+		       card ? card->handle : NULL);
+		goto exit;
+	}
+	handle = card->handle;
+	if (handle->surprise_removed == MTRUE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto exit;
+	}
+	PRINTM(MINFO, "*** IN PCIE IRQ ***\n");
+	handle->main_state = MOAL_RECV_INT;
+	if (handle->second_mac)
+		PRINTM(MINTR, "**\n");
+	else
+		PRINTM(MINTR, "*\n");
+	ret = mlan_interrupt(ctx->msg_id, handle->pmlan_adapter);
+	queue_work(handle->workqueue, &handle->main_work);
+
+exit:
+	if (ret == MLAN_STATUS_SUCCESS)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+/**
+ *  @brief This function pre-initializes the PCI-E host
+ *  memory space, etc.
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_preinit(struct pci_dev *pdev)
+{
+	int ret;
+
+	if (pdev->multifunction)
+		device_disable_async_suspend(&pdev->dev);
+
+	ret = pci_enable_device(pdev);
+
+	if (ret)
+		goto err_enable_dev;
+
+	pci_set_master(pdev);
+
+	PRINTM(MINFO, "Try set_consistent_dma_mask(32)\n");
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		PRINTM(MERROR, "set_dma_mask(32) failed\n");
+		goto err_set_dma_mask;
+	}
+
+	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		PRINTM(MERROR, "set_consistent_dma_mask(64) failed\n");
+		goto err_set_dma_mask;
+	}
+	return MLAN_STATUS_SUCCESS;
+
+err_set_dma_mask:
+	pci_disable_device(pdev);
+err_enable_dev:
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function initializes the PCI-E host
+ *  memory space, etc.
+ *
+ *  @param card   A pointer to pcie_service_card structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_init(pcie_service_card *card)
+{
+	struct pci_dev *pdev = NULL;
+	int ret;
+
+	pdev = card->dev;
+	pci_set_drvdata(pdev, card);
+#if 0
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto err_enable_dev;
+
+	pci_set_master(pdev);
+
+	PRINTM(MINFO, "Try set_consistent_dma_mask(32)\n");
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		PRINTM(MERROR, "set_dma_mask(32) failed\n");
+		goto err_set_dma_mask;
+	}
+
+	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		PRINTM(MERROR, "set_consistent_dma_mask(64) failed\n");
+		goto err_set_dma_mask;
+	}
+#endif
+
+	ret = pci_request_region(pdev, 0, DRV_NAME);
+	if (ret) {
+		PRINTM(MERROR, "req_reg(0) error\n");
+		goto err_req_region0;
+	}
+	card->pci_mmap = pci_iomap(pdev, 0, 0);
+	if (!card->pci_mmap) {
+		PRINTM(MERROR, "iomap(0) error\n");
+		goto err_iomap0;
+	}
+	ret = pci_request_region(pdev, 2, DRV_NAME);
+	if (ret) {
+		PRINTM(MERROR, "req_reg(2) error\n");
+		goto err_req_region2;
+	}
+	card->pci_mmap1 = pci_iomap(pdev, 2, 0);
+	if (!card->pci_mmap1) {
+		PRINTM(MERROR, "iomap(2) error\n");
+		goto err_iomap2;
+	}
+
+	PRINTM(MINFO,
+	       "PCI memory map Virt0: %p PCI memory map Virt2: "
+	       "%p\n", card->pci_mmap, card->pci_mmap1);
+
+	return MLAN_STATUS_SUCCESS;
+
+err_iomap2:
+	pci_release_region(pdev, 2);
+err_req_region2:
+	pci_iounmap(pdev, card->pci_mmap);
+err_iomap0:
+	pci_release_region(pdev, 0);
+err_req_region0:
+#if 0
+err_set_dma_mask:
+#endif
+
+#if 0
+err_enable_dev:
+#endif
+	pci_set_drvdata(pdev, NULL);
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function registers the PCIE device
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_pcie_register_dev(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	pcie_service_card *card = NULL;
+	struct pci_dev *pdev = NULL;
+	unsigned char nvec;
+	unsigned char i, j;
+	ENTER();
+
+	if (!handle || !handle->card) {
+		PRINTM(MINFO, "%s: handle=%p card=%p\n", __FUNCTION__, handle,
+		       handle ? handle->card : NULL);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	card = (pcie_service_card *)handle->card;
+	pdev = card->dev;
+	/* save adapter pointer in card */
+	card->handle = handle;
+
+	switch (pcie_int_mode) {
+	case PCIE_INT_MODE_MSIX:
+		pcie_int_mode = PCIE_INT_MODE_MSIX;
+		nvec = PCIE_NUM_MSIX_VECTORS;
+
+		for (i = 0; i < nvec; i++) {
+			card->msix_entries[i].entry = i;
+		}
+
+		/* Try to enable msix */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		ret = pci_enable_msix_exact(pdev, card->msix_entries, nvec);
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */
+		ret = pci_enable_msix(pdev, card->msix_entries, nvec);
+#endif
+
+		if (ret == 0) {
+			for (i = 0; i < nvec; i++) {
+				card->msix_contexts[i].dev = pdev;
+				card->msix_contexts[i].msg_id = i;
+				ret = request_irq(card->msix_entries[i].vector,
+						  woal_pcie_msix_interrupt, 0,
+						  "mrvl_pcie_msix",
+						  &(card->msix_contexts[i]));
+
+				if (ret) {
+					PRINTM(MFATAL,
+					       "request_irq failed: ret=%d\n",
+					       ret);
+					for (j = 0; j < i; j++)
+						free_irq(card->msix_entries[j]
+							 .vector,
+							 &(card->msix_contexts
+							   [i]));
+					pci_disable_msix(pdev);
+					break;
+				}
+			}
+			if (i == nvec)
+				break;
+		}
+		// follow through
+
+		/* fall through */
+	case PCIE_INT_MODE_MSI:
+		pcie_int_mode = PCIE_INT_MODE_MSI;
+		ret = pci_enable_msi(pdev);
+		if (ret == 0) {
+			ret = request_irq(pdev->irq, woal_pcie_interrupt, 0,
+					  "mrvl_pcie_msi", pdev);
+			if (ret) {
+				PRINTM(MFATAL, "request_irq failed: ret=%d\n",
+				       ret);
+				pci_disable_msi(pdev);
+			} else {
+				break;
+			}
+		}
+		// follow through
+
+		/* fall through */
+	case PCIE_INT_MODE_LEGACY:
+		pcie_int_mode = PCIE_INT_MODE_LEGACY;
+		ret = request_irq(pdev->irq, woal_pcie_interrupt, IRQF_SHARED,
+				  "mrvl_pcie", pdev);
+		if (ret) {
+			PRINTM(MFATAL, "request_irq failed: ret=%d\n", ret);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		break;
+
+	default:
+		PRINTM(MFATAL, "pcie_int_mode %d failed\n", pcie_int_mode);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+		break;
+	}
+
+#ifdef PCIE9098
+	if (card->dev->device == PCIE_DEVICE_ID_NXP_88W9098P_FN1)
+		mlan_set_int_mode(handle->pmlan_adapter, pcie_int_mode, 1);
+	else
+#endif
+		mlan_set_int_mode(handle->pmlan_adapter, pcie_int_mode, 0);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function cleans up the host memory spaces
+ *
+ *  @param card   A pointer to pcie_service_card structure
+ *
+ *  @return         N/A
+ */
+static void
+woal_pcie_cleanup(pcie_service_card *card)
+{
+	struct pci_dev *pdev = NULL;
+	pdev = card->dev;
+	PRINTM(MINFO, "Clearing driver ready signature\n");
+
+	if (pdev) {
+		pci_iounmap(pdev, card->pci_mmap);
+		pci_iounmap(pdev, card->pci_mmap1);
+
+		if (pci_is_enabled(pdev))
+			pci_disable_device(pdev);
+
+		pci_release_region(pdev, 0);
+		pci_release_region(pdev, 2);
+		pci_set_drvdata(pdev, NULL);
+	}
+}
+
+/**
+ *  @brief This function unregisters the PCIE device
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static void
+woal_pcie_unregister_dev(moal_handle *handle)
+{
+	pcie_service_card *card =
+		handle ? (pcie_service_card *)handle->card : NULL;
+	struct pci_dev *pdev = NULL;
+	unsigned char i;
+	unsigned char nvec;
+	ENTER();
+
+	if (card) {
+		pdev = card->dev;
+		PRINTM(MINFO, "%s(): calling free_irq()\n", __func__);
+
+		switch (pcie_int_mode) {
+		case PCIE_INT_MODE_MSIX:
+			nvec = PCIE_NUM_MSIX_VECTORS;
+
+			for (i = 0; i < nvec; i++)
+				synchronize_irq(card->msix_entries[i].vector);
+
+			for (i = 0; i < nvec; i++)
+				free_irq(card->msix_entries[i].vector,
+					 &(card->msix_contexts[i]));
+
+			pci_disable_msix(pdev);
+
+			break;
+
+		case PCIE_INT_MODE_MSI:
+			free_irq(card->dev->irq, pdev);
+			pci_disable_msi(pdev);
+			break;
+
+		case PCIE_INT_MODE_LEGACY:
+			free_irq(card->dev->irq, pdev);
+			break;
+
+		default:
+			PRINTM(MFATAL, "pcie_int_mode %d failed\n",
+			       pcie_int_mode);
+			break;
+		}
+		card->handle = NULL;
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the IF module in bus driver
+ *
+ *  @return	    MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_pcie_bus_register(void)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* API registers the NXP PCIE driver */
+	if (pci_register_driver(&wlan_pcie)) {
+		PRINTM(MFATAL, "PCIE Driver Registration Failed \n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the IF module in bus driver
+ *
+ *  @return 	   N/A
+ */
+void
+woal_pcie_bus_unregister(void)
+{
+	ENTER();
+
+	/* PCIE Driver Unregistration */
+	pci_unregister_driver(&wlan_pcie);
+
+	LEAVE();
+}
+
+#if defined(PCIE9098) || defined(PCIE9097)
+#define PCIE9098_DUMP_CTRL_REG 0x1C94
+#define PCIE9098_DUMP_START_REG 0x1C98
+#define PCIE9098_DUMP_END_REG 0x1C9F
+#endif
+#if defined(PCIE8897) || defined(PCIE8997)
+#define DEBUG_DUMP_CTRL_REG 0xCF4
+#define DEBUG_DUMP_START_REG 0xCF8
+#define DEBUG_DUMP_END_REG 0xCFF
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+#define PCIE9098_SCRATCH_12_REG 0x1C90
+#define PCIE9098_SCRATCH_14_REG 0x1C98
+#define PCIE9098_SCRATCH_15_REG 0x1C9C
+#define PCIE9098_DUMP_REG_START 0x1C20
+#define PCIE9098_DUMP_REG_END 0x1C9C
+#endif
+
+#if defined(PCIE8997) || defined(PCIE8897)
+#define PCIE_SCRATCH_12_REG 0x0CF0;
+#define PCIE_SCRATCH_14_REG 0x0CF8;
+#define PCIE_SCRATCH_15_REG 0x0CFC;
+#define PCIE_DUMP_START_REG 0xC00
+#define PCIE_DUMP_END_REG 0xCFC
+#endif
+/**
+ *  @brief This function save the log of pcie register value
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buffer    A pointer to buffer saving log
+ *
+ *  @return         The length of this log
+ */
+static int
+woal_pcie_dump_reg_info(moal_handle *phandle, t_u8 *buffer)
+{
+	char *drv_ptr = (char *)buffer;
+	t_u32 reg = 0, value = 0;
+	t_u8 i;
+	char buf[256], *ptr;
+	pcie_service_card *card = (pcie_service_card *)phandle->card;
+	int config_reg_table[] = { 0x00, 0x04, 0x10, 0x18, 0x2c,
+		0x3c, 0x44, 0x80, 0x98, 0x170
+	};
+	t_u32 dump_start_reg = 0;
+	t_u32 dump_end_reg = 0;
+	t_u32 scratch_14_reg = 0;
+	t_u32 scratch_15_reg = 0;
+#if defined(PCIE9098) || defined(PCIE9097)
+	/* Tx/Rx/Event AMDA start address */
+	t_u32 adma_reg_table[] =
+		{ 0x10000, 0x10800, 0x10880, 0x11000, 0x11080 };
+	t_u8 j;
+#endif
+	ENTER();
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
+	drv_ptr += sprintf(drv_ptr,
+			   "------------PCIe Registers dump-------------\n");
+	drv_ptr += sprintf(drv_ptr, "Config Space Registers:\n");
+	for (i = 0; i < ARRAY_SIZE(config_reg_table); i++) {
+		pci_read_config_dword(card->dev, config_reg_table[i], &value);
+		drv_ptr += sprintf(drv_ptr, "reg:0x%02x value=0x%08x\n",
+				   config_reg_table[i], value);
+	}
+	drv_ptr += sprintf(drv_ptr, "FW Scrach Registers:\n");
+
+#if defined(PCIE8897) || defined(PCIE8997)
+	if (IS_PCIE8897(phandle->card_type) || IS_PCIE8997(phandle->card_type)) {
+		reg = PCIE_SCRATCH_12_REG;
+		dump_start_reg = PCIE_DUMP_START_REG;
+		dump_end_reg = PCIE_DUMP_END_REG;
+		scratch_14_reg = PCIE_SCRATCH_14_REG;
+		scratch_15_reg = PCIE_SCRATCH_15_REG;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		reg = PCIE9098_SCRATCH_12_REG;
+		dump_start_reg = PCIE9098_DUMP_REG_START;
+		dump_end_reg = PCIE9098_DUMP_REG_END;
+		scratch_14_reg = PCIE9098_SCRATCH_14_REG;
+		scratch_15_reg = PCIE9098_SCRATCH_15_REG;
+	}
+#endif
+
+	woal_pcie_read_reg(phandle, reg, &value);
+	drv_ptr += sprintf(drv_ptr, "reg:0x%x value=0x%x\n", reg, value);
+	for (i = 0; i < 2; i++) {
+		reg = scratch_14_reg;
+		woal_pcie_read_reg(phandle, reg, &value);
+		drv_ptr +=
+			sprintf(drv_ptr, "reg:0x%x value=0x%x\n", reg, value);
+
+		reg = scratch_15_reg;
+		woal_pcie_read_reg(phandle, reg, &value);
+		drv_ptr +=
+			sprintf(drv_ptr, "reg:0x%x value=0x%x\n", reg, value);
+
+		mdelay(100);
+	}
+	drv_ptr +=
+		sprintf(drv_ptr,
+			"Interface registers dump from offset 0x%x to 0x%x\n",
+			dump_start_reg, dump_end_reg);
+	memset(buf, 0, sizeof(buf));
+	ptr = buf;
+	i = 1;
+	for (reg = dump_start_reg; reg <= dump_end_reg; reg += 4) {
+		woal_pcie_read_reg(phandle, reg, &value);
+		ptr += sprintf(ptr, "%08x ", value);
+		if (!(i % 8)) {
+			drv_ptr += sprintf(drv_ptr, "%s\n", buf);
+			memset(buf, 0, sizeof(buf));
+			ptr = buf;
+		}
+		i++;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		drv_ptr += sprintf(drv_ptr,
+				   "PCIE registers from offset 0x1c20 to 0x1c9c:\n");
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		i = 1;
+		for (reg = 0x1c20; reg <= 0x1c9c; reg += 4) {
+			woal_pcie_read_reg(phandle, reg, &value);
+			ptr += sprintf(ptr, "%08x ", value);
+			if (!(i % 8)) {
+				drv_ptr += sprintf(drv_ptr, "%s\n", buf);
+				memset(buf, 0, sizeof(buf));
+				ptr = buf;
+			}
+			i++;
+		}
+		drv_ptr += sprintf(drv_ptr, "%s\n", buf);
+	}
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		drv_ptr += sprintf(drv_ptr,
+				   "ADMA Tx/Rx/Event/Cmd/CmdResp registers:\n");
+		for (j = 0; j < ARRAY_SIZE(adma_reg_table); j++) {
+			drv_ptr += sprintf(drv_ptr,
+					   "ADMA registers dump from offset 0x%x to 0x%x\n",
+					   adma_reg_table[j],
+					   adma_reg_table[j] + 0x68);
+			memset(buf, 0, sizeof(buf));
+			ptr = buf;
+			i = 1;
+			for (reg = adma_reg_table[j];
+			     reg <= (adma_reg_table[j] + 0x68); reg += 4) {
+				woal_pcie_read_reg(phandle, reg, &value);
+				ptr += sprintf(ptr, "%08x ", value);
+				if (!(i % 8)) {
+					drv_ptr +=
+						sprintf(drv_ptr, "%s\n", buf);
+					memset(buf, 0, sizeof(buf));
+					ptr = buf;
+				}
+				i++;
+			}
+			drv_ptr += sprintf(drv_ptr, "%s\n", buf);
+		}
+	}
+#endif
+	drv_ptr += sprintf(drv_ptr,
+			   "-----------PCIe Registers dump End-----------\n");
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+	LEAVE();
+	return drv_ptr - (char *)buffer;
+}
+
+/**
+ *  @brief This function reads and displays PCIE scratch registers for debugging
+ *
+ *  @param phandle  A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_pcie_reg_dbg(moal_handle *phandle)
+{
+	t_u32 reg = 0, value = 0;
+	t_u8 i;
+	char buf[256], *ptr;
+	pcie_service_card *card = (pcie_service_card *)phandle->card;
+	int config_reg_table[] = { 0x00, 0x04, 0x10, 0x18, 0x2c,
+		0x3c, 0x44, 0x80, 0x98, 0x170
+	};
+	t_u32 dump_start_reg = 0;
+	t_u32 dump_end_reg = 0;
+	t_u32 scratch_14_reg = 0;
+	t_u32 scratch_15_reg = 0;
+#if defined(PCIE9098) || defined(PCIE9097)
+	/* Tx/Rx/Event AMDA start address */
+	t_u32 adma_reg_table[] =
+		{ 0x10000, 0x10800, 0x10880, 0x11000, 0x11080 };
+	t_u8 j;
+#endif
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
+	PRINTM(MMSG, "Config Space Registers:\n");
+	for (i = 0; i < ARRAY_SIZE(config_reg_table); i++) {
+		pci_read_config_dword(card->dev, config_reg_table[i], &value);
+		PRINTM(MERROR, "reg:0x%02x value=0x%08x\n", config_reg_table[i],
+		       value);
+	}
+	PRINTM(MMSG, "FW Scrach Registers:\n");
+#if defined(PCIE8897) || defined(PCIE8997)
+	if (IS_PCIE8897(phandle->card_type) || IS_PCIE8997(phandle->card_type)) {
+		reg = PCIE_SCRATCH_12_REG;
+		dump_start_reg = PCIE_DUMP_START_REG;
+		dump_end_reg = PCIE_DUMP_END_REG;
+		scratch_14_reg = PCIE_SCRATCH_14_REG;
+		scratch_15_reg = PCIE_SCRATCH_15_REG;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		reg = PCIE9098_SCRATCH_12_REG;
+		dump_start_reg = PCIE9098_DUMP_START_REG;
+		dump_end_reg = PCIE9098_DUMP_END_REG;
+		scratch_14_reg = PCIE9098_SCRATCH_14_REG;
+		scratch_15_reg = PCIE9098_SCRATCH_15_REG;
+	}
+#endif
+	woal_pcie_read_reg(phandle, reg, &value);
+	PRINTM(MERROR, "reg:0x%x value=0x%x\n", reg, value);
+	for (i = 0; i < 2; i++) {
+		reg = scratch_14_reg;
+		woal_pcie_read_reg(phandle, reg, &value);
+		PRINTM(MERROR, "reg:0x%x value=0x%x\n", reg, value);
+
+		reg = scratch_15_reg;
+		woal_pcie_read_reg(phandle, reg, &value);
+		PRINTM(MERROR, "reg:0x%x value=0x%x\n", reg, value);
+
+		mdelay(100);
+	}
+	PRINTM(MMSG, "Interface registers dump from offset 0x%x to 0x%x\n",
+	       dump_start_reg, dump_end_reg);
+	memset(buf, 0, sizeof(buf));
+	ptr = buf;
+	i = 1;
+	for (reg = dump_start_reg; reg <= dump_end_reg; reg += 4) {
+		woal_pcie_read_reg(phandle, reg, &value);
+		ptr += sprintf(ptr, "%08x ", value);
+		if (!(i % 8)) {
+			PRINTM(MMSG, "%s\n", buf);
+			memset(buf, 0, sizeof(buf));
+			ptr = buf;
+		}
+		i++;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		PRINTM(MMSG, "PCIE registers from offset 0x1c20 to 0x1c9c:\n");
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		i = 1;
+		for (reg = 0x1c20; reg <= 0x1c9c; reg += 4) {
+			woal_pcie_read_reg(phandle, reg, &value);
+			ptr += sprintf(ptr, "%08x ", value);
+			if (!(i % 8)) {
+				PRINTM(MMSG, "%s\n", buf);
+				memset(buf, 0, sizeof(buf));
+				ptr = buf;
+			}
+			i++;
+		}
+		PRINTM(MMSG, "%s\n", buf);
+	}
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		PRINTM(MMSG, "ADMA Tx/Rx/Event/Cmd/CmdResp registers:\n");
+		for (j = 0; j < ARRAY_SIZE(adma_reg_table); j++) {
+			PRINTM(MMSG,
+			       "ADMA registers dump from offset 0x%x to 0x%x\n",
+			       adma_reg_table[j], adma_reg_table[j] + 0x68);
+			memset(buf, 0, sizeof(buf));
+			ptr = buf;
+			i = 1;
+			for (reg = adma_reg_table[j];
+			     reg <= (adma_reg_table[j] + 0x68); reg += 4) {
+				woal_pcie_read_reg(phandle, reg, &value);
+				ptr += sprintf(ptr, "%08x ", value);
+				if (!(i % 8)) {
+					PRINTM(MMSG, "%s\n", buf);
+					memset(buf, 0, sizeof(buf));
+					ptr = buf;
+				}
+				i++;
+			}
+			PRINTM(MMSG, "%s\n", buf);
+		}
+	}
+#endif
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+}
+
+#define DEBUG_FW_DONE 0xFF
+#define MAX_POLL_TRIES 100
+
+typedef enum {
+	DUMP_TYPE_ITCM = 0,
+	DUMP_TYPE_DTCM = 1,
+	DUMP_TYPE_SQRAM = 2,
+	DUMP_TYPE_IRAM = 3,
+	DUMP_TYPE_APU = 4,
+	DUMP_TYPE_CIU = 5,
+	DUMP_TYPE_ICU = 6,
+	DUMP_TYPE_MAC = 7,
+} dumped_mem_type;
+
+#define MAX_NAME_LEN 8
+
+typedef struct {
+	t_u8 mem_name[MAX_NAME_LEN];
+	t_u8 *mem_Ptr;
+	struct file *pfile_mem;
+	t_u8 done_flag;
+	t_u8 type;
+} memory_type_mapping;
+
+#ifdef PCIE8897
+#define DEBUG_HOST_READY_8897 0xEE
+#define DEBUG_MEMDUMP_FINISH_8897 0xFE
+static memory_type_mapping mem_type_mapping_tbl_8897[] = {
+	{"ITCM", NULL, NULL, 0xF0, FW_DUMP_TYPE_MEM_ITCM},
+	{"DTCM", NULL, NULL, 0xF1, FW_DUMP_TYPE_MEM_DTCM},
+	{"SQRAM", NULL, NULL, 0xF2, FW_DUMP_TYPE_MEM_SQRAM},
+	{"IRAM", NULL, NULL, 0xF3, FW_DUMP_TYPE_MEM_IRAM},
+	{"APU", NULL, NULL, 0xF4, FW_DUMP_TYPE_REG_APU},
+	{"CIU", NULL, NULL, 0xF5, FW_DUMP_TYPE_REG_CIU},
+	{"ICU", NULL, NULL, 0xF6, FW_DUMP_TYPE_REG_ICU},
+	{"MAC", NULL, NULL, 0xF7, FW_DUMP_TYPE_REG_MAC},
+};
+#endif
+
+#if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097)
+#define DEBUG_HOST_READY_8997 0xCC
+#define DEBUG_HOST_EVENT_READY 0xAA
+static memory_type_mapping mem_type_mapping_tbl_8997 =
+	{ "DUMP", NULL, NULL, 0xDD,
+	0x00
+};
+
+#endif
+
+#if defined(PCIE8897) || defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097)
+/**
+ *  @brief This function reads data by 8 bit from card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_read_reg_eight_bit(moal_handle *handle, t_u32 reg, t_u8 *data)
+{
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+	*data = ioread8(card->pci_mmap1 + reg);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function read/write firmware
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param doneflag  done flag
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static rdwr_status
+woal_pcie_rdwr_firmware(moal_handle *phandle, t_u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	t_u8 ctrl_data = 0;
+	t_u32 reg_data = 0;
+	t_u32 debug_host_ready = 0;
+	t_u32 dump_ctrl_reg = 0;
+
+#ifdef PCIE8897
+	if (IS_PCIE8897(phandle->card_type)) {
+		debug_host_ready = DEBUG_HOST_READY_8897;
+		dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
+	}
+#endif
+#if defined(PCIE8997)
+	if (IS_PCIE8997(phandle->card_type)) {
+		debug_host_ready = DEBUG_HOST_READY_8997;
+		dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
+	}
+#endif
+
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		if (phandle->event_fw_dump)
+			debug_host_ready = DEBUG_HOST_EVENT_READY;
+		else
+			debug_host_ready = DEBUG_HOST_READY_8997;
+		dump_ctrl_reg = PCIE9098_DUMP_CTRL_REG;
+	}
+#endif
+
+	ret = woal_pcie_write_reg(phandle, dump_ctrl_reg, debug_host_ready);
+	if (ret) {
+		PRINTM(MERROR, "PCIE Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		if (phandle->event_fw_dump)
+			return RDWR_STATUS_SUCCESS;
+	}
+#endif
+	ret = woal_pcie_read_reg(phandle, dump_ctrl_reg, &reg_data);
+	if (ret) {
+		PRINTM(MERROR, "PCIE Read DEBUG_DUMP_CTRL_REG fail\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		ret = woal_read_reg_eight_bit(phandle, dump_ctrl_reg,
+					      &ctrl_data);
+		if (ret) {
+			PRINTM(MERROR, "PCIE READ ERR\n");
+			return RDWR_STATUS_FAILURE;
+		}
+		if (ctrl_data == DEBUG_FW_DONE)
+			break;
+		if (doneflag && ctrl_data == doneflag)
+			return RDWR_STATUS_DONE;
+		if (ctrl_data != debug_host_ready) {
+			PRINTM(MMSG, "The ctrl reg was changed, try again!\n");
+			ret = woal_pcie_write_reg(phandle, dump_ctrl_reg,
+						  debug_host_ready);
+			if (ret) {
+				PRINTM(MERROR, "PCIE Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+		usleep_range(99, 100);
+#else
+		udelay(100);
+#endif
+	}
+	if (ctrl_data == debug_host_ready) {
+		PRINTM(MERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	return RDWR_STATUS_SUCCESS;
+}
+#endif
+
+#ifdef PCIE8897
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_pcie_dump_fw_info_v1(moal_handle *phandle)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	t_u8 *dbg_ptr = NULL;
+	t_u32 sec, usec;
+	t_u8 dump_num = 0;
+	t_u8 idx = 0;
+	t_u8 doneflag = 0;
+	rdwr_status stat;
+	t_u8 i = 0;
+	t_u8 read_reg = 0;
+	t_u32 memory_size = 0;
+	t_u32 memdump_finsh = 0;
+	t_u8 *end_ptr = NULL;
+	memory_type_mapping *mem_type_mapping_tbl = mem_type_mapping_tbl_8897;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+	if (!phandle->fw_dump_buf) {
+		ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
+				   &(phandle->fw_dump_buf));
+		if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
+			PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n");
+			return;
+		}
+	} else {
+		memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
+	}
+	phandle->fw_dump_len = 0;
+	/* start dump fw memory */
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT START: %u.%06u ====\n", sec,
+	       usec);
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == woal_pcie_rdwr_firmware(phandle, doneflag))
+		goto done;
+	reg = DEBUG_DUMP_START_REG;
+	ret = woal_read_reg_eight_bit(phandle, reg, &dump_num);
+	if (ret) {
+		PRINTM(MMSG, "PCIE READ MEM NUM ERR\n");
+		goto done;
+	}
+
+	/* read the length of every memory which will dump */
+	for (idx = 0;
+	     idx < dump_num && idx < ARRAY_SIZE(mem_type_mapping_tbl_8897);
+	     idx++) {
+		if (RDWR_STATUS_FAILURE ==
+		    woal_pcie_rdwr_firmware(phandle, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = DEBUG_DUMP_START_REG;
+		for (i = 0; i < 4; i++) {
+			ret = woal_read_reg_eight_bit(phandle, reg, &read_reg);
+			if (ret) {
+				PRINTM(MMSG, "PCIE READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MMSG, "Firmware Dump Finished!\n");
+			ret = woal_pcie_write_reg(phandle, DEBUG_DUMP_CTRL_REG,
+						  memdump_finsh);
+			if (ret) {
+				PRINTM(MERROR,
+				       "PCIE Write MEMDUMP_FINISH ERR\n");
+				goto done;
+			}
+			break;
+		} else {
+			PRINTM(MMSG, "%s_SIZE=0x%x\n",
+			       mem_type_mapping_tbl[idx].mem_name, memory_size);
+			ret = moal_vmalloc(phandle, memory_size + 1,
+					   (t_u8 **)&mem_type_mapping_tbl[idx].
+					   mem_Ptr);
+			if ((ret != MLAN_STATUS_SUCCESS) ||
+			    !mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(MERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = mem_type_mapping_tbl[idx].done_flag;
+		moal_get_system_time(phandle, &sec, &usec);
+		PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
+		       mem_type_mapping_tbl[idx].mem_name, sec, usec);
+		do {
+			stat = woal_pcie_rdwr_firmware(phandle, doneflag);
+			if (RDWR_STATUS_FAILURE == stat)
+				goto done;
+
+			reg_start = DEBUG_DUMP_START_REG;
+			reg_end = DEBUG_DUMP_END_REG;
+			for (reg = reg_start; reg <= reg_end; reg++) {
+				ret = woal_read_reg_eight_bit(phandle, reg,
+							      dbg_ptr);
+				if (ret) {
+					PRINTM(MMSG, "PCIE READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MINFO,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+				PRINTM(MMSG, "%s done: size=0x%x\n",
+				       mem_type_mapping_tbl[idx].mem_name,
+				       (unsigned int)(dbg_ptr -
+						      mem_type_mapping_tbl[idx]
+						      .mem_Ptr));
+				woal_save_dump_info_to_buf(phandle,
+							   mem_type_mapping_tbl
+							   [idx].mem_Ptr,
+							   memory_size,
+							   mem_type_mapping_tbl
+							   [idx].type);
+				moal_vfree(phandle,
+					   mem_type_mapping_tbl[idx].mem_Ptr);
+				mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	woal_append_end_block(phandle);
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT END: %u.%06u ====\n", sec,
+	       usec);
+	/* end dump fw memory */
+done:
+	for (idx = 0;
+	     idx < dump_num && idx < ARRAY_SIZE(mem_type_mapping_tbl_8897);
+	     idx++) {
+		if (mem_type_mapping_tbl[idx].mem_Ptr) {
+			moal_vfree(phandle, mem_type_mapping_tbl[idx].mem_Ptr);
+			mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+
+	return;
+}
+#endif
+
+#if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097)
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_pcie_dump_fw_info_v2(moal_handle *phandle)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	t_u8 *dbg_ptr = NULL;
+	t_u8 *tmp_ptr = NULL;
+	t_u32 sec, usec;
+	t_u8 dump_num = 0;
+	t_u8 doneflag = 0;
+	rdwr_status stat;
+	t_u32 memory_size = 0;
+	t_u8 *end_ptr = NULL;
+	memory_type_mapping *mem_type_mapping_tbl = &mem_type_mapping_tbl_8997;
+	t_u32 dump_start_reg = 0;
+	t_u32 dump_end_reg = 0;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		if (phandle->event_fw_dump) {
+			if (RDWR_STATUS_FAILURE !=
+			    woal_pcie_rdwr_firmware(phandle, doneflag)) {
+				PRINTM(MMSG,
+				       "====PCIE FW DUMP EVENT MODE START ====\n");
+				return;
+			}
+		}
+	}
+#endif
+
+	/* start dump fw memory */
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT START: %u.%06u ====\n", sec,
+	       usec);
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == woal_pcie_rdwr_firmware(phandle, doneflag))
+		goto done;
+#if defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE9098(phandle->card_type) || IS_PCIE9097(phandle->card_type)) {
+		dump_start_reg = PCIE9098_DUMP_START_REG;
+		dump_end_reg = PCIE9098_DUMP_END_REG;
+	}
+#endif
+#ifdef PCIE8997
+	if (IS_PCIE8997(phandle->card_type)) {
+		dump_start_reg = DEBUG_DUMP_START_REG;
+		dump_end_reg = DEBUG_DUMP_END_REG;
+	}
+#endif
+	reg = dump_start_reg;
+	ret = woal_read_reg_eight_bit(phandle, reg, &dump_num);
+	if (ret) {
+		PRINTM(MMSG, "PCIE READ MEM NUM ERR\n");
+		goto done;
+	}
+
+	memory_size = 0x80000;
+	ret = moal_vmalloc(phandle, memory_size + 1,
+			   (t_u8 **)&mem_type_mapping_tbl->mem_Ptr);
+	if ((ret != MLAN_STATUS_SUCCESS) || !mem_type_mapping_tbl->mem_Ptr) {
+		PRINTM(MERROR, "Error: vmalloc %s buffer failed!!!\n",
+		       mem_type_mapping_tbl->mem_name);
+		goto done;
+	}
+	dbg_ptr = mem_type_mapping_tbl->mem_Ptr;
+	end_ptr = dbg_ptr + memory_size;
+
+	doneflag = mem_type_mapping_tbl->done_flag;
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
+	       mem_type_mapping_tbl->mem_name, sec, usec);
+	do {
+		stat = woal_pcie_rdwr_firmware(phandle, doneflag);
+		if (RDWR_STATUS_FAILURE == stat)
+			goto done;
+
+		reg_start = dump_start_reg;
+		reg_end = dump_end_reg;
+		for (reg = reg_start; reg <= reg_end; reg++) {
+			ret = woal_read_reg_eight_bit(phandle, reg, dbg_ptr);
+			if (ret) {
+				PRINTM(MMSG, "PCIE READ ERR\n");
+				goto done;
+			}
+			dbg_ptr++;
+			if (dbg_ptr >= end_ptr) {
+				PRINTM(MINFO,
+				       "pre-allocced buf is not enough\n");
+				ret = moal_vmalloc(phandle,
+						   memory_size + 0x4000 + 1,
+						   (t_u8 **)&tmp_ptr);
+				if ((ret != MLAN_STATUS_SUCCESS) || !tmp_ptr) {
+					PRINTM(MERROR,
+					       "Error: vmalloc  buffer failed!!!\n");
+					goto done;
+				}
+				moal_memcpy_ext(phandle, tmp_ptr,
+						mem_type_mapping_tbl->mem_Ptr,
+						memory_size,
+						memory_size + 0x4000);
+				moal_vfree(phandle,
+					   mem_type_mapping_tbl->mem_Ptr);
+				mem_type_mapping_tbl->mem_Ptr = tmp_ptr;
+				tmp_ptr = NULL;
+				dbg_ptr = mem_type_mapping_tbl->mem_Ptr +
+					memory_size;
+				memory_size += 0x4000;
+				end_ptr = mem_type_mapping_tbl->mem_Ptr +
+					memory_size;
+			}
+		}
+		if (RDWR_STATUS_DONE == stat) {
+#ifdef MLAN_64BIT
+			PRINTM(MMSG,
+			       "%s done:"
+			       "size = 0x%lx\n",
+			       mem_type_mapping_tbl->mem_name,
+			       dbg_ptr - mem_type_mapping_tbl->mem_Ptr);
+#else
+			PRINTM(MMSG,
+			       "%s done:"
+			       "size = 0x%x\n",
+			       mem_type_mapping_tbl->mem_name,
+			       dbg_ptr - mem_type_mapping_tbl->mem_Ptr);
+#endif
+			if (phandle->fw_dump_buf) {
+				moal_vfree(phandle, phandle->fw_dump_buf);
+				phandle->fw_dump_buf = NULL;
+				phandle->fw_dump_len = 0;
+			}
+			phandle->fw_dump_buf = mem_type_mapping_tbl->mem_Ptr;
+			phandle->fw_dump_len =
+				dbg_ptr - mem_type_mapping_tbl->mem_Ptr;
+			mem_type_mapping_tbl->mem_Ptr = NULL;
+			break;
+		}
+	} while (1);
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT END: %u.%06u ====\n", sec,
+	       usec);
+	/* end dump fw memory */
+done:
+	if (mem_type_mapping_tbl->mem_Ptr) {
+		moal_vfree(phandle, mem_type_mapping_tbl->mem_Ptr);
+		mem_type_mapping_tbl->mem_Ptr = NULL;
+	}
+
+	return;
+}
+#endif
+
+/**
+ *  @brief This function check if this is second mac
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @return         MTRUE/MFALSE
+ *
+ */
+static t_u8
+woal_pcie_is_second_mac(moal_handle *handle)
+{
+#ifdef PCIE9098
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+	if (card->dev->device == PCIE_DEVICE_ID_NXP_88W9098P_FN1)
+		return MTRUE;
+#endif
+	return MFALSE;
+}
+
+static void
+woal_pcie_dump_fw_info(moal_handle *phandle)
+{
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
+	phandle->fw_dump = MTRUE;
+#ifdef PCIE8897
+	if (IS_PCIE8897(phandle->card_type))
+		woal_pcie_dump_fw_info_v1(phandle);
+#endif
+#if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097)
+	if (IS_PCIE8997(phandle->card_type) ||
+	    IS_PCIE9098(phandle->card_type) ||
+	    IS_PCIE9097(phandle->card_type)) {
+		woal_pcie_dump_fw_info_v2(phandle);
+		if (phandle->event_fw_dump) {
+			phandle->event_fw_dump = MFALSE;
+			queue_work(phandle->workqueue, &phandle->main_work);
+			phandle->is_fw_dump_timer_set = MTRUE;
+			woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
+			return;
+		}
+	}
+#endif
+	woal_send_fw_dump_complete_event(woal_get_priv
+					 (phandle, MLAN_BSS_ROLE_ANY));
+	phandle->fw_dump = MFALSE;
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+	queue_work(phandle->workqueue, &phandle->main_work);
+	woal_process_hang(phandle);
+}
+
+static mlan_status
+woal_pcie_get_fw_name(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef PCIE9098
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+	moal_handle *ref_handle = NULL;
+#endif
+
+#if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097)
+	t_u32 rev_id_reg = handle->card_info->rev_id_reg;
+	t_u32 revision_id = 0;
+#endif
+
+#if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097)
+	t_u32 host_strap_reg = handle->card_info->host_strap_reg;
+	t_u32 magic_reg = handle->card_info->magic_reg;
+	t_u32 strap = 0;
+	t_u32 magic = 0;
+#endif
+
+	ENTER();
+
+	if (handle->params.fw_name) {
+#ifdef PCIE9097
+		if (IS_PCIE9097(handle->card_type)) {
+			woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
+			revision_id &= 0xff;
+			PRINTM(MCMND, "revision_id=0x%x\n", revision_id);
+			switch (revision_id) {
+			case PCIE9097_A0:
+				break;
+			case PCIE9097_B0:
+			case PCIE9097_B1:
+				handle->card_rev = CHIP_9097_REV_B0;
+				break;
+			default:
+				break;
+			}
+		}
+#endif
+		goto done;
+	}
+#ifdef PCIE8997
+	if (IS_PCIE8997(handle->card_type)) {
+		woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
+		woal_pcie_read_reg(handle, host_strap_reg, &strap);
+		woal_pcie_read_reg(handle, magic_reg, &magic);
+		revision_id &= 0xff;
+		strap &= 0x7;
+		magic &= 0xff;
+		PRINTM(MCMND, "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
+		       magic, strap, revision_id);
+		if ((revision_id == PCIE8997_A1) && (magic == CHIP_MAGIC_VALUE)) {
+			if (strap == CARD_TYPE_PCIE_UART)
+				strcpy(handle->card_info->fw_name,
+				       PCIEUART8997_DEFAULT_COMBO_FW_NAME);
+			else
+				strcpy(handle->card_info->fw_name,
+				       PCIEUSB8997_DEFAULT_COMBO_FW_NAME);
+		}
+	}
+#endif
+#ifdef PCIE9098
+	if (IS_PCIE9098(handle->card_type)) {
+		if (card->dev->device == PCIE_DEVICE_ID_NXP_88W9098P_FN0) {
+			woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
+			woal_pcie_read_reg(handle, host_strap_reg, &strap);
+			woal_pcie_read_reg(handle, magic_reg, &magic);
+			revision_id &= 0xff;
+			strap &= 0x7;
+			magic &= 0xff;
+			PRINTM(MCMND,
+			       "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
+			       magic, strap, revision_id);
+			switch (revision_id) {
+			case PCIE9098_Z1Z2:
+				if (magic == CHIP_MAGIC_VALUE) {
+					if (strap == CARD_TYPE_PCIE_UART)
+						strcpy(handle->card_info->
+						       fw_name,
+						       PCIEUART9098_DEFAULT_COMBO_FW_NAME);
+					else if (strap == CARD_TYPE_PCIE_PCIE)
+						strcpy(handle->card_info->
+						       fw_name,
+						       PCIEPCIE9098_DEFAULT_COMBO_FW_NAME);
+					else
+						strcpy(handle->card_info->
+						       fw_name,
+						       PCIEUSB9098_DEFAULT_COMBO_FW_NAME);
+				}
+				strcpy(handle->card_info->fw_name_wlan,
+				       PCIE9098_DEFAULT_WLAN_FW_NAME);
+				break;
+			case PCIE9098_A0:
+			case PCIE9098_A1:
+			case PCIE9098_A2:
+				if (magic == CHIP_MAGIC_VALUE) {
+					if (strap == CARD_TYPE_PCIE_UART)
+						strcpy(handle->card_info->
+						       fw_name,
+						       PCIEUART9098_COMBO_V1_FW_NAME);
+					else if (strap == CARD_TYPE_PCIE_PCIE)
+						strcpy(handle->card_info->
+						       fw_name,
+						       PCIEPCIE9098_COMBO_V1_FW_NAME);
+					else
+						strcpy(handle->card_info->
+						       fw_name,
+						       PCIEUSB9098_COMBO_V1_FW_NAME);
+				}
+				strcpy(handle->card_info->fw_name_wlan,
+				       PCIE9098_WLAN_V1_FW_NAME);
+				break;
+			default:
+				break;
+			}
+		} else {
+			ref_handle = (moal_handle *)handle->pref_mac;
+			if (ref_handle) {
+				strcpy(handle->card_info->fw_name,
+				       ref_handle->card_info->fw_name);
+				strcpy(handle->card_info->fw_name_wlan,
+				       ref_handle->card_info->fw_name_wlan);
+			}
+		}
+	}
+#endif
+#ifdef PCIE9097
+	if (IS_PCIE9097(handle->card_type)) {
+		woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
+		woal_pcie_read_reg(handle, host_strap_reg, &strap);
+		woal_pcie_read_reg(handle, magic_reg, &magic);
+		revision_id &= 0xff;
+		strap &= 0x7;
+		magic &= 0xff;
+		PRINTM(MCMND, "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
+		       magic, strap, revision_id);
+		switch (revision_id) {
+		case PCIE9097_A0:
+			if (magic == CHIP_MAGIC_VALUE) {
+				if (strap == CARD_TYPE_PCIE_UART)
+					strcpy(handle->card_info->fw_name,
+					       PCIEUART9097_DEFAULT_COMBO_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       PCIEUSB9097_DEFAULT_COMBO_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       PCIE9097_DEFAULT_WLAN_FW_NAME);
+			break;
+		case PCIE9097_B0:
+		case PCIE9097_B1:
+			if (magic == CHIP_MAGIC_VALUE) {
+				if (strap == CARD_TYPE_PCIE_UART)
+					strcpy(handle->card_info->fw_name,
+					       PCIEUART9097_COMBO_V1_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       PCIEUSB9097_COMBO_V1_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       PCIE9097_WLAN_V1_FW_NAME);
+			handle->card_rev = CHIP_9097_REV_B0;
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+done:
+	PRINTM(MCMND, "combo fw:%s wlan fw:%s \n", handle->card_info->fw_name,
+	       handle->card_info->fw_name_wlan);
+	LEAVE();
+	return ret;
+}
+
+static moal_if_ops pcie_ops = {
+	.register_dev = woal_pcie_register_dev,
+	.unregister_dev = woal_pcie_unregister_dev,
+	.read_reg = woal_pcie_read_reg,
+	.write_reg = woal_pcie_write_reg,
+	.read_data_sync = woal_pcie_read_data_sync,
+	.write_data_sync = woal_pcie_write_data_sync,
+	.get_fw_name = woal_pcie_get_fw_name,
+	.dump_fw_info = woal_pcie_dump_fw_info,
+	.reg_dbg = woal_pcie_reg_dbg,
+	.dump_reg_info = woal_pcie_dump_reg_info,
+	.is_second_mac = woal_pcie_is_second_mac,
+};
diff --git a/wlan_sd8987/mlinux/moal_pcie.h b/wlan_sd8987/mlinux/moal_pcie.h
new file mode 100755
index 0000000..58f3055
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_pcie.h
@@ -0,0 +1,143 @@
+/** @file moal_pcie.h
+ *
+ *  @brief This file contains definitions for PCIE interface.
+ *  driver.
+ *
+ *
+ * Copyright 2014-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/01/2012: initial version
+********************************************************/
+
+#ifndef _MOAL_PCIE_H_
+#define _MOAL_PCIE_H_
+
+#define PCIE_VENDOR_ID_NXP (0x11ab)
+#define PCIE_VENDOR_ID_V2_NXP (0x1b4b)
+#ifdef PCIE8997
+/** PCIE device ID for 8997 card */
+#define PCIE_DEVICE_ID_NXP_88W8997P (0x2b42)
+#endif
+#ifdef PCIE8897
+/** PCIE device ID for 8897 card */
+#define PCIE_DEVICE_ID_NXP_88W8897P (0x2b38)
+#endif
+
+#ifdef PCIE9097
+/** PCIE device ID for 9097 card */
+#define PCIE_DEVICE_ID_NXP_88W9097 (0x2b56)
+#endif
+
+#ifdef PCIE9098
+/** PCIE device ID for 9098 card FN0 */
+#define PCIE_DEVICE_ID_NXP_88W9098P_FN0 (0x2b43)
+/** PCIE device ID for 9098 card FN1 */
+#define PCIE_DEVICE_ID_NXP_88W9098P_FN1 (0x2b44)
+#endif
+
+#include <linux/version.h>
+#include <linux/pci.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
+#include <linux/pcieport_if.h>
+#endif
+#include <linux/interrupt.h>
+
+#include "moal_main.h"
+
+/** Default firmware name */
+#ifdef PCIE8997
+#define PCIE8997_DEFAULT_COMBO_FW_NAME "nxp/pcieusb8997_combo_v4.bin"
+#define PCIEUART8997_DEFAULT_COMBO_FW_NAME "nxp/pcieuart8997_combo_v4.bin"
+#define PCIEUSB8997_DEFAULT_COMBO_FW_NAME "nxp/pcieusb8997_combo_v4.bin"
+#define PCIE8997_DEFAULT_WLAN_FW_NAME "nxp/pcie8997_wlan_v4.bin"
+/** PCIE8997 chip revision ID */
+#define PCIE8997_A0 0x10
+#define PCIE8997_A1 0x11
+#endif /* PCIE8997 */
+
+#ifdef PCIE8897
+#define PCIE8897_DEFAULT_COMBO_FW_NAME "nxp/pcie8897_uapsta.bin"
+#define PCIE8897_DEFAULT_WLAN_FW_NAME "nxp/pcie8897_wlan.bin"
+#endif /* PCIE8897 */
+
+#ifdef PCIE9098
+#define PCIE9098_Z1Z2 0x00
+#define PCIE9098_A0 0x01
+#define PCIE9098_A1 0x02
+#define PCIE9098_A2 0x03
+#define PCIE9098_DEFAULT_COMBO_FW_NAME "nxp/pcieusb9098_combo.bin"
+#define PCIEUART9098_DEFAULT_COMBO_FW_NAME "nxp/pcieuart9098_combo.bin"
+#define PCIEUSB9098_DEFAULT_COMBO_FW_NAME "nxp/pcieusb9098_combo.bin"
+#define PCIEPCIE9098_DEFAULT_COMBO_FW_NAME "nxp/pciepcie9098_combo.bin"
+#define PCIEUART9098_COMBO_V1_FW_NAME "nxp/pcieuart9098_combo_v1.bin"
+#define PCIEUSB9098_COMBO_V1_FW_NAME "nxp/pcieusb9098_combo_v1.bin"
+#define PCIEPCIE9098_COMBO_V1_FW_NAME "nxp/pciepcie9098_combo_v1.bin"
+#define PCIE9098_DEFAULT_WLAN_FW_NAME "nxp/pcie9098_wlan.bin"
+#define PCIE9098_WLAN_V1_FW_NAME "nxp/pcie9098_wlan_v1.bin"
+#endif /* PCIE9098 */
+
+#ifdef PCIE9097
+#define PCIE9097_A0 0x00
+#define PCIE9097_B0 0x01
+#define PCIE9097_B1 0x02
+#define PCIE9097_DEFAULT_COMBO_FW_NAME "nxp/pcieusbiw620_combo.bin"
+#define PCIEUART9097_DEFAULT_COMBO_FW_NAME "nxp/pcieuartiw620_combo.bin"
+#define PCIEUSB9097_DEFAULT_COMBO_FW_NAME "nxp/pcieusbiw620_combo.bin"
+#define PCIEUART9097_COMBO_V1_FW_NAME "nxp/pcieuartiw620_combo_v1.bin"
+#define PCIEUSB9097_COMBO_V1_FW_NAME "nxp/pcieusbiw620_combo_v1.bin"
+#define PCIE9097_DEFAULT_WLAN_FW_NAME "nxp/pcieiw620_wlan.bin"
+#define PCIE9097_WLAN_V1_FW_NAME "nxp/pcieiw620_wlan_v1.bin"
+#endif /* PCIE9097 */
+
+#if defined(PCIE9098) || defined(PCIE9097)
+#define PCIE_NUM_MSIX_VECTORS 32
+#else
+#define PCIE_NUM_MSIX_VECTORS 4
+#endif
+
+typedef struct _msix_context {
+	/** pci_dev structure pointer */
+	struct pci_dev *dev;
+	/** message id related to msix vector */
+	t_u16 msg_id;
+} msix_context;
+
+/** Structure: PCIE service card */
+typedef struct _pcie_service_card {
+	/** pci_dev structure pointer */
+	struct pci_dev *dev;
+	/** moal_handle structure pointer */
+	moal_handle *handle;
+	/** I/O memory regions pointer to the bus */
+	void __iomem *pci_mmap;
+	/** I/O memory regions pointer to the bus */
+	void __iomem *pci_mmap1;
+#if defined(PCIE)
+	struct msix_entry msix_entries[PCIE_NUM_MSIX_VECTORS];
+	msix_context msix_contexts[PCIE_NUM_MSIX_VECTORS];
+#endif
+} pcie_service_card, *ppcie_service_card;
+
+/** Register to bus driver function */
+mlan_status woal_pcie_bus_register(void);
+/** Unregister from bus driver function */
+void woal_pcie_bus_unregister(void);
+
+#endif /* _MOAL_PCIE_H_ */
diff --git a/wlan_sd8987/mlinux/moal_priv.c b/wlan_sd8987/mlinux/moal_priv.c
new file mode 100755
index 0000000..b1d6f6c
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_priv.c
@@ -0,0 +1,6981 @@
+/** @file  moal_priv.c
+ *
+ * @brief This file contains standard ioctl functions
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/************************************************************************
+Change log:
+    10/30/2008: initial version
+************************************************************************/
+
+#include "moal_main.h"
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif /* SDIO */
+
+#include "moal_eth_ioctl.h"
+#ifdef USB
+#include "moal_usb.h"
+#endif
+
+/********************************************************
+			Local Variables
+********************************************************/
+/** Bands supported in Infra mode */
+static t_u8 SupportedInfraBand[] = {
+	BAND_B,
+	BAND_B | BAND_G,
+	BAND_G,
+	BAND_GN,
+	BAND_B | BAND_G | BAND_GN,
+	BAND_G | BAND_GN,
+	BAND_A,
+	BAND_B | BAND_A,
+	BAND_B | BAND_G | BAND_A,
+	BAND_G | BAND_A,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN,
+	BAND_A | BAND_G | BAND_AN | BAND_GN,
+	BAND_A | BAND_AN,
+	BAND_GN | BAND_GAC,
+	BAND_B | BAND_G | BAND_GN | BAND_GAC,
+	BAND_G | BAND_GN | BAND_GAC,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
+	BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
+	BAND_A | BAND_AN | BAND_AAC,
+};
+
+/** Bands supported in Ad-Hoc mode */
+static t_u8 SupportedAdhocBand[] = {
+	BAND_B,
+	BAND_B | BAND_G,
+	BAND_G,
+	BAND_A,
+};
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ * @brief Associated to a specific indexed entry in the ScanTable
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param req          A pointer to ifreq structure
+ *
+ * @return             0 --success, otherwise fail
+ */
+static int
+woal_associate_ssid_bssid(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ssid_bssid ssid_bssid;
+#ifdef REASSOCIATION
+	mlan_bss_info bss_info;
+#endif
+	char buf[64];
+	t_u8 buflen;
+	t_u8 mac_idx;
+	t_u8 i;
+
+	ENTER();
+
+	memset(&ssid_bssid, 0, sizeof(ssid_bssid));
+	mac_idx = 0;
+	buflen = MIN(wrq->u.data.length, (sizeof(buf) - 1));
+	memset(buf, 0, sizeof(buf));
+
+	if (buflen < (3 * ETH_ALEN) + 2) {
+		PRINTM(MERROR,
+		       "Associate: Insufficient length in IOCTL input\n");
+
+		/* buffer should be at least 3 characters per BSSID octet "00:"
+		 **   plus a space separater and at least 1 char in the SSID
+		 */
+		LEAVE();
+		return -EINVAL;
+	}
+
+	if (copy_from_user(buf, wrq->u.data.pointer, buflen) != 0) {
+		/* copy_from_user failed  */
+		PRINTM(MERROR, "Associate: copy from user failed\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	for (i = 0; (i < buflen) && (buf[i] == ' '); i++) {
+		/* Skip white space */
+	}
+
+	/* Copy/Convert the BSSID */
+	for (; (i < buflen) && (mac_idx < ETH_ALEN) && (buf[i] != ' '); i++) {
+		if (buf[i] == ':') {
+			mac_idx++;
+		} else {
+			if (mac_idx < ETH_ALEN)
+				ssid_bssid.bssid[mac_idx] =
+					(t_u8)woal_atox(buf + i);
+
+			while ((i < buflen) && (isxdigit(buf[i + 1]))) {
+				/* Skip entire hex value */
+				i++;
+			}
+		}
+	}
+
+	/* Skip one space between the BSSID and start of the SSID */
+	i++;
+
+	/* Copy the SSID */
+	ssid_bssid.ssid.ssid_len = buflen - i - 1;
+	moal_memcpy_ext(priv->phandle, ssid_bssid.ssid.ssid, buf + i,
+			sizeof(ssid_bssid.ssid.ssid),
+			sizeof(ssid_bssid.ssid.ssid));
+
+	PRINTM(MCMND, "iwpriv assoc: AP=[" MACSTR "], ssid(%d)=[%s]\n",
+	       MAC2STR(ssid_bssid.bssid), (int)ssid_bssid.ssid.ssid_len,
+	       ssid_bssid.ssid.ssid);
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		LEAVE();
+		return -EFAULT;
+	}
+#ifdef REASSOCIATION
+	memset(&bss_info, 0x00, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
+				&bss_info.ssid, sizeof(mlan_802_11_ssid),
+				sizeof(mlan_802_11_ssid));
+		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
+				&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
+				sizeof(mlan_802_11_mac_addr));
+	}
+#endif /* REASSOCIATION */
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Copy Rates
+ *
+ *  @param dest    A pointer to destination buffer
+ *  @param pos     The position for copy
+ *  @param src     A pointer to source buffer
+ *  @param len     Length of the source buffer
+ *
+ *  @return        Number of rates copied
+ */
+static inline int
+woal_copy_rates(t_u8 *dest, int pos, t_u8 *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len && src[i]; i++, pos++) {
+		if (pos >= MLAN_SUPPORTED_RATES)
+			break;
+		dest[pos] = src[i];
+	}
+	return pos;
+}
+
+/**
+ *  @brief Performs warm reset
+ *
+ *  @param priv         A pointer to moal_private structure
+ *
+ *  @return             0/MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_warm_reset(moal_private *priv)
+{
+	int ret = 0;
+	moal_handle *handle = priv->phandle;
+	moal_handle *ref_handle;
+	moal_private *ref_priv;
+	ENTER();
+	ret = woal_pre_warmreset(priv);
+	if (ret)
+		goto done;
+	ref_handle = (moal_handle *)handle->pref_mac;
+	if (ref_handle) {
+		ref_priv = woal_get_priv(ref_handle, MLAN_BSS_ROLE_ANY);
+		if (ref_priv) {
+			ret = woal_pre_warmreset(ref_priv);
+			if (ret)
+				goto done;
+			ret = woal_warmreset(ref_priv);
+			if (ret)
+				goto done;
+		}
+	}
+	ret = woal_warmreset(priv);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get signal
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_get_signal(moal_private *priv, struct iwreq *wrq)
+{
+/** Input data size */
+#define IN_DATA_SIZE 2
+/** Output data size */
+#define OUT_DATA_SIZE 12
+	int ret = 0;
+	int in_data[IN_DATA_SIZE];
+	int out_data[OUT_DATA_SIZE];
+	mlan_ds_get_signal signal;
+	int data_length = 0;
+	int buflen = 0;
+
+	ENTER();
+
+	memset(in_data, 0, sizeof(in_data));
+	memset(out_data, 0, sizeof(out_data));
+	buflen = MIN(wrq->u.data.length, IN_DATA_SIZE);
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can not get RSSI in disconnected state\n");
+		ret = -ENOTSUPP;
+		goto done;
+	}
+
+	if (wrq->u.data.length) {
+		if (sizeof(int) * wrq->u.data.length > sizeof(in_data)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (copy_from_user(in_data, wrq->u.data.pointer,
+				   sizeof(int) * buflen)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	switch (wrq->u.data.length) {
+	case 0:		/* No checking, get everything */
+		break;
+	case 2:		/* Check subtype range */
+		if (in_data[1] < 1 || in_data[1] > 4) {
+			ret = -EINVAL;
+			goto done;
+		}
+		/* Fall through */
+	case 1:		/* Check type range */
+		if (in_data[0] < 1 || in_data[0] > 3) {
+			ret = -EINVAL;
+			goto done;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		goto done;
+	}
+
+	memset(&signal, 0, sizeof(mlan_ds_get_signal));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_signal_info(priv, MOAL_IOCTL_WAIT, &signal)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MINFO, "RSSI Beacon Last   : %d\n", (int)signal.bcn_rssi_last);
+	PRINTM(MINFO, "RSSI Beacon Average: %d\n", (int)signal.bcn_rssi_avg);
+	PRINTM(MINFO, "RSSI Data Last     : %d\n", (int)signal.data_rssi_last);
+	PRINTM(MINFO, "RSSI Data Average  : %d\n", (int)signal.data_rssi_avg);
+	PRINTM(MINFO, "SNR Beacon Last    : %d\n", (int)signal.bcn_snr_last);
+	PRINTM(MINFO, "SNR Beacon Average : %d\n", (int)signal.bcn_snr_avg);
+	PRINTM(MINFO, "SNR Data Last      : %d\n", (int)signal.data_snr_last);
+	PRINTM(MINFO, "SNR Data Average   : %d\n", (int)signal.data_snr_avg);
+	PRINTM(MINFO, "NF Beacon Last     : %d\n", (int)signal.bcn_nf_last);
+	PRINTM(MINFO, "NF Beacon Average  : %d\n", (int)signal.bcn_nf_avg);
+	PRINTM(MINFO, "NF Data Last       : %d\n", (int)signal.data_nf_last);
+	PRINTM(MINFO, "NF Data Average    : %d\n", (int)signal.data_nf_avg);
+
+	/* Check type */
+	switch (in_data[0]) {
+	case 0:		/* Send everything */
+		out_data[data_length++] = signal.bcn_rssi_last;
+		out_data[data_length++] = signal.bcn_rssi_avg;
+		out_data[data_length++] = signal.data_rssi_last;
+		out_data[data_length++] = signal.data_rssi_avg;
+		out_data[data_length++] = signal.bcn_snr_last;
+		out_data[data_length++] = signal.bcn_snr_avg;
+		out_data[data_length++] = signal.data_snr_last;
+		out_data[data_length++] = signal.data_snr_avg;
+		out_data[data_length++] = signal.bcn_nf_last;
+		out_data[data_length++] = signal.bcn_nf_avg;
+		out_data[data_length++] = signal.data_nf_last;
+		out_data[data_length++] = signal.data_nf_avg;
+		break;
+	case 1:		/* RSSI */
+		/* Check subtype */
+		switch (in_data[1]) {
+		case 0:	/* Everything */
+			out_data[data_length++] = signal.bcn_rssi_last;
+			out_data[data_length++] = signal.bcn_rssi_avg;
+			out_data[data_length++] = signal.data_rssi_last;
+			out_data[data_length++] = signal.data_rssi_avg;
+			break;
+		case 1:	/* bcn last */
+			out_data[data_length++] = signal.bcn_rssi_last;
+			break;
+		case 2:	/* bcn avg */
+			out_data[data_length++] = signal.bcn_rssi_avg;
+			break;
+		case 3:	/* data last */
+			out_data[data_length++] = signal.data_rssi_last;
+			break;
+		case 4:	/* data avg */
+			out_data[data_length++] = signal.data_rssi_avg;
+			break;
+		default:
+			break;
+		}
+		break;
+	case 2:		/* SNR */
+		/* Check subtype */
+		switch (in_data[1]) {
+		case 0:	/* Everything */
+			out_data[data_length++] = signal.bcn_snr_last;
+			out_data[data_length++] = signal.bcn_snr_avg;
+			out_data[data_length++] = signal.data_snr_last;
+			out_data[data_length++] = signal.data_snr_avg;
+			break;
+		case 1:	/* bcn last */
+			out_data[data_length++] = signal.bcn_snr_last;
+			break;
+		case 2:	/* bcn avg */
+			out_data[data_length++] = signal.bcn_snr_avg;
+			break;
+		case 3:	/* data last */
+			out_data[data_length++] = signal.data_snr_last;
+			break;
+		case 4:	/* data avg */
+			out_data[data_length++] = signal.data_snr_avg;
+			break;
+		default:
+			break;
+		}
+		break;
+	case 3:		/* NF */
+		/* Check subtype */
+		switch (in_data[1]) {
+		case 0:	/* Everything */
+			out_data[data_length++] = signal.bcn_nf_last;
+			out_data[data_length++] = signal.bcn_nf_avg;
+			out_data[data_length++] = signal.data_nf_last;
+			out_data[data_length++] = signal.data_nf_avg;
+			break;
+		case 1:	/* bcn last */
+			out_data[data_length++] = signal.bcn_nf_last;
+			break;
+		case 2:	/* bcn avg */
+			out_data[data_length++] = signal.bcn_nf_avg;
+			break;
+		case 3:	/* data last */
+			out_data[data_length++] = signal.data_nf_last;
+			break;
+		case 4:	/* data avg */
+			out_data[data_length++] = signal.data_nf_avg;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	wrq->u.data.length = data_length;
+	if (copy_to_user(wrq->u.data.pointer, out_data,
+			 wrq->u.data.length * sizeof(out_data[0]))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set DeepSleep mode
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wreq	    A pointer to iwreq structure
+ *
+ *  @return          0 --success, otherwise fail
+ */
+static int
+woal_deep_sleep_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	int user_data_len;
+	t_u32 deep_sleep = DEEP_SLEEP_OFF;
+	t_u32 data[2] = { 0 };
+	int copy_len;
+	t_u16 idletime = DEEP_SLEEP_IDLE_TIME;
+
+	ENTER();
+
+	user_data_len = wrq->u.data.length;
+	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
+	if (user_data_len == 1 || user_data_len == 2) {
+		if (copy_from_user(&data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			LEAVE();
+			return -EFAULT;
+		}
+		deep_sleep = data[0];
+		if (deep_sleep == DEEP_SLEEP_OFF) {
+			PRINTM(MINFO, "Exit Deep Sleep Mode\n");
+			ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MFALSE,
+						  0);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				LEAVE();
+				return -EINVAL;
+			}
+		} else if (deep_sleep == DEEP_SLEEP_ON) {
+			PRINTM(MINFO, "Enter Deep Sleep Mode\n");
+			if (user_data_len == 2)
+				idletime = data[1];
+			else
+				idletime = 0;
+			ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MTRUE,
+						  idletime);
+			if (ret != MLAN_STATUS_SUCCESS) {
+				LEAVE();
+				return -EINVAL;
+			}
+		} else {
+			PRINTM(MERROR, "Unknown option = %u\n", deep_sleep);
+			LEAVE();
+			return -EINVAL;
+		}
+	} else if (user_data_len > 2) {
+		PRINTM(MERROR, "Invalid number of arguments %d\n",
+		       user_data_len);
+		LEAVE();
+		return -EINVAL;
+	} else {		/* Display Deep Sleep settings */
+		PRINTM(MINFO, "Get Deep Sleep Mode\n");
+		if (MLAN_STATUS_SUCCESS != woal_get_deep_sleep(priv, data)) {
+			LEAVE();
+			return -EFAULT;
+		}
+		if (data[0] == 0)
+			wrq->u.data.length = 1;
+		else
+			wrq->u.data.length = 2;
+	}
+
+	/* Copy the Deep Sleep setting to user */
+	if (copy_to_user(wrq->u.data.pointer, data,
+			 wrq->u.data.length * sizeof(int))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Set/Get Usr 11n configuration request
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_11n_htcap_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int data[2], copy_len;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (data_length > 2) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	if (data_length == 0) {
+		/* Get 11n tx parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BG;
+	} else {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		cfg_11n->param.htcap_cfg.htcap = data[0];
+		PRINTM(MINFO, "SET: htcapinfo:0x%x\n", data[0]);
+		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BOTH;
+		if (data_length == 2) {
+			if (data[1] != BAND_SELECT_BG &&
+			    data[1] != BAND_SELECT_A &&
+			    data[1] != BAND_SELECT_BOTH) {
+				PRINTM(MERROR, "Invalid band selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			cfg_11n->param.htcap_cfg.misc_cfg = data[1];
+			PRINTM(MINFO, "SET: htcapinfo band:0x%x\n", data[1]);
+		}
+		/* Update 11n tx parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data[0] = cfg_11n->param.htcap_cfg.htcap;
+
+	if (req->action == MLAN_ACT_GET) {
+		data_length = 1;
+		cfg_11n->param.htcap_cfg.htcap = 0;
+		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((int)cfg_11n->param.htcap_cfg.htcap != data[0]) {
+			data_length = 2;
+			data[1] = cfg_11n->param.htcap_cfg.htcap;
+			PRINTM(MINFO, "GET: htcapinfo for 2.4GHz:0x%x\n",
+			       data[0]);
+			PRINTM(MINFO, "GET: htcapinfo for 5GHz:0x%x\n",
+			       data[1]);
+		} else
+			PRINTM(MINFO, "GET: htcapinfo:0x%x\n", data[0]);
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	wrq->u.data.length = data_length;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable/Disable amsdu_aggr_ctrl
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_11n_amsdu_aggr_ctrl(moal_private *priv, struct iwreq *wrq)
+{
+	int data[2], copy_len;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if ((data_length != 0) && (data_length != 1)) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (data_length == 0) {
+		/* Get 11n tx parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+	} else if (data_length == 1) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		cfg_11n->param.amsdu_aggr_ctrl.enable = data[0];
+		/* Update 11n tx parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data[0] = cfg_11n->param.amsdu_aggr_ctrl.enable;
+	data[1] = cfg_11n->param.amsdu_aggr_ctrl.curr_buf_size;
+
+	if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 2;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11n configuration request
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_11n_tx_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int data[2], copy_len;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (data_length > 2) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (data_length == 0) {
+		/* Get 11n tx parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
+	} else {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		cfg_11n->param.tx_cfg.httxcap = data[0];
+		PRINTM(MINFO, "SET: httxcap:0x%x\n", data[0]);
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BOTH;
+		if (data_length == 2) {
+			if (data[1] != BAND_SELECT_BG &&
+			    data[1] != BAND_SELECT_A &&
+			    data[1] != BAND_SELECT_BOTH) {
+				PRINTM(MERROR, "Invalid band selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			cfg_11n->param.tx_cfg.misc_cfg = data[1];
+			PRINTM(MINFO, "SET: httxcap band:0x%x\n", data[1]);
+		}
+		/* Update 11n tx parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	data[0] = cfg_11n->param.tx_cfg.httxcap;
+
+	if (req->action == MLAN_ACT_GET) {
+		data_length = 1;
+		cfg_11n->param.tx_cfg.httxcap = 0;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (cfg_11n->param.tx_cfg.httxcap != data[0]) {
+			data_length = 2;
+			data[1] = cfg_11n->param.tx_cfg.httxcap;
+			PRINTM(MINFO, "GET: httxcap for 2.4GHz:0x%x\n",
+			       data[0]);
+			PRINTM(MINFO, "GET: httxcap for 5GHz:0x%x\n", data[1]);
+		} else
+			PRINTM(MINFO, "GET: httxcap:0x%x\n", data[0]);
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = data_length;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable/Disable TX Aggregation
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_11n_prio_tbl(moal_private *priv, struct iwreq *wrq)
+{
+	int data[MAX_NUM_TID * 2], i, j, copy_len;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wrq->u.data.pointer == NULL) {
+		LEAVE();
+		return -EINVAL;
+	}
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (data_length == 0) {
+		/* Get aggr priority table from MLAN */
+		req->action = MLAN_ACT_GET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+		wrq->u.data.length = MAX_NUM_TID * 2;
+		for (i = 0, j = 0; i < (wrq->u.data.length); i = i + 2, ++j) {
+			data[i] = cfg_11n->param.aggr_prio_tbl.ampdu[j];
+			data[i + 1] = cfg_11n->param.aggr_prio_tbl.amsdu[j];
+		}
+
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+	} else if (data_length == 16) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+		for (i = 0, j = 0; i < (data_length); i = i + 2, ++j) {
+			if ((data[i] > 7 && data[i] != 0xff) ||
+			    (data[i + 1] > 7 && data[i + 1] != 0xff)) {
+				PRINTM(MERROR,
+				       "Invalid priority, valid value 0-7 or 0xff.\n");
+				ret = -EFAULT;
+				goto error;
+			}
+			cfg_11n->param.aggr_prio_tbl.ampdu[j] = data[i];
+			cfg_11n->param.aggr_prio_tbl.amsdu[j] = data[i + 1];
+		}
+
+		/* Update aggr priority table in MLAN */
+		req->action = MLAN_ACT_SET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get add BA Reject parameters
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_addba_reject(moal_private *priv, struct iwreq *wrq)
+{
+	int data[MAX_NUM_TID], ret = 0, i, copy_len;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (data_length == 0) {
+		PRINTM(MERROR, "Addba reject moal\n");
+		/* Get aggr priority table from MLAN */
+		req->action = MLAN_ACT_GET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+
+		wrq->u.data.length = MAX_NUM_TID;
+		for (i = 0; i < (wrq->u.data.length); ++i)
+			data[i] = cfg_11n->param.addba_reject[i];
+
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+	} else if (data_length == 8) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+		for (i = 0; i < (data_length); ++i) {
+			if (data[i] != 0 && data[i] != 1) {
+				PRINTM(MERROR,
+				       "addba reject only takes argument as 0 or 1\n");
+				ret = -EFAULT;
+				goto error;
+			}
+			cfg_11n->param.addba_reject[i] = data[i];
+		}
+
+		/* Update aggr priority table in MLAN */
+		req->action = MLAN_ACT_SET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto error;
+	}
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get add BA parameters
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_addba_para_updt(moal_private *priv, struct iwreq *wrq)
+{
+	int data[5], ret = 0, copy_len;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (data_length == 0) {
+		/* Get Add BA parameters from MLAN */
+		req->action = MLAN_ACT_GET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+		data[0] = cfg_11n->param.addba_param.timeout;
+		data[1] = cfg_11n->param.addba_param.txwinsize;
+		data[2] = cfg_11n->param.addba_param.rxwinsize;
+		data[3] = cfg_11n->param.addba_param.txamsdu;
+		data[4] = cfg_11n->param.addba_param.rxamsdu;
+		PRINTM(MINFO,
+		       "GET: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d, rxamsdu=%d\n",
+		       data[0], data[1], data[2], data[3], data[4]);
+		wrq->u.data.length = 5;
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 wrq->u.data.length * sizeof(int))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+	} else if (data_length == 5) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+		if (data[0] < 0 || data[0] > MLAN_DEFAULT_BLOCK_ACK_TIMEOUT) {
+			PRINTM(MERROR, "Incorrect addba timeout value.\n");
+			ret = -EFAULT;
+			goto error;
+		}
+		if (data[1] <= 0 || data[1] > MLAN_AMPDU_MAX_TXWINSIZE ||
+		    data[2] <= 0 || data[2] > MLAN_AMPDU_MAX_RXWINSIZE) {
+			PRINTM(MERROR, "Incorrect Tx/Rx window size.\n");
+			ret = -EFAULT;
+			goto error;
+		}
+		cfg_11n->param.addba_param.timeout = data[0];
+		cfg_11n->param.addba_param.txwinsize = data[1];
+		cfg_11n->param.addba_param.rxwinsize = data[2];
+		if (data[3] < 0 || data[3] > 1 || data[4] < 0 || data[4] > 1) {
+			PRINTM(MERROR, "Incorrect Tx/Rx amsdu.\n");
+			ret = -EFAULT;
+			goto error;
+		}
+		cfg_11n->param.addba_param.txamsdu = data[3];
+		cfg_11n->param.addba_param.rxamsdu = data[4];
+		PRINTM(MINFO,
+		       "SET: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d rxamsdu=%d\n",
+		       data[0], data[1], data[2], data[3], data[4]);
+		/* Update Add BA parameters in MLAN */
+		req->action = MLAN_ACT_SET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Transmit buffer size
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_txbuf_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int buf_size;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (wrq->u.data.length == 0) {
+		/* Get Tx buffer size from MLAN */
+		req->action = MLAN_ACT_GET;
+	} else {
+		ret = -EINVAL;
+		PRINTM(MERROR,
+		       "Don't support set Tx buffer size after driver loaded!\n");
+		goto done;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	buf_size = cfg_11n->param.tx_buf_size;
+	if (copy_to_user(wrq->u.data.pointer, &buf_size, sizeof(buf_size))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Host Sleep configuration
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wrq              A pointer to iwreq structure
+ *  @param invoke_hostcmd   MTRUE --invoke HostCmd, otherwise MFALSE
+ *
+ *  @return                 0 --success, otherwise fail
+ */
+static int
+woal_hs_cfg(moal_private *priv, struct iwreq *wrq, BOOLEAN invoke_hostcmd)
+{
+	int data[3], copy_len;
+	int ret = 0;
+	mlan_ds_hs_cfg hscfg;
+	t_u16 action;
+	mlan_bss_info bss_info;
+	int data_length = wrq->u.data.length;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	if (data_length == 0) {
+		action = MLAN_ACT_GET;
+	} else {
+		action = MLAN_ACT_SET;
+		if (data_length >= 1 && data_length <= 3) {
+			if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+				PRINTM(MERROR, "Copy from user failed\n");
+				ret = -EFAULT;
+				goto done;
+			}
+		} else {
+			PRINTM(MERROR, "Invalid arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* HS config is blocked if HS is already activated */
+	if (data_length &&
+	    (data[0] != (int)HOST_SLEEP_CFG_CANCEL ||
+	     invoke_hostcmd == MFALSE)) {
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		if (bss_info.is_hs_configured) {
+			PRINTM(MERROR, "HS already configured\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	/* Do a GET first if some arguments are not provided */
+	if (data_length >= 1 && data_length < 3) {
+		woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
+				       &hscfg);
+	}
+
+	if (data_length)
+		hscfg.conditions = data[0];
+	if (data_length >= 2)
+		hscfg.gpio = data[1];
+	if (data_length == 3)
+		hscfg.gap = data[2];
+
+	if ((invoke_hostcmd == MTRUE) && (action == MLAN_ACT_SET)) {
+		/* Need to issue an extra IOCTL first to set up parameters */
+		hscfg.is_invoke_hostcmd = MFALSE;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					   &hscfg)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	hscfg.is_invoke_hostcmd = invoke_hostcmd;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_GET) {
+		data[0] = hscfg.conditions;
+		data[1] = hscfg.gpio;
+		data[2] = hscfg.gap;
+		wrq->u.data.length = 3;
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Host Sleep parameters
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_hs_setpara(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	int data_length = wrq->u.data.length;
+
+	ENTER();
+
+	if (data_length >= 1 && data_length <= 3) {
+		ret = woal_hs_cfg(priv, wrq, MFALSE);
+		goto done;
+	} else {
+		PRINTM(MERROR, "Invalid arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set inactivity timeout extend
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_inactivity_timeout_ext(moal_private *priv, struct iwreq *wrq)
+{
+	int data[4], copy_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pmcfg = NULL;
+	pmlan_ds_inactivity_to inac_to = NULL;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	memset(data, 0, sizeof(data));
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
+	inac_to = &pmcfg->param.inactivity_to;
+	pmcfg->sub_command = MLAN_OID_PM_CFG_INACTIVITY_TO;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	if ((data_length != 0 && data_length != 3 && data_length != 4) ||
+	    sizeof(int) * data_length > sizeof(data)) {
+		PRINTM(MERROR, "Invalid number of parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req->action = MLAN_ACT_GET;
+	if (data_length) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		inac_to->timeout_unit = data[0];
+		inac_to->unicast_timeout = data[1];
+		inac_to->mcast_timeout = data[2];
+		inac_to->ps_entry_timeout = data[3];
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy back current values regardless of GET/SET */
+	data[0] = inac_to->timeout_unit;
+	data[1] = inac_to->unicast_timeout;
+	data[2] = inac_to->mcast_timeout;
+	data[3] = inac_to->ps_entry_timeout;
+
+	if (req->action == MLAN_ACT_GET) {
+		wrq->u.data.length = 4;
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 wrq->u.data.length * sizeof(int))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get system clock
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_ecl_sys_clock(moal_private *priv, struct iwreq *wrq)
+{
+	int data[64], copy_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int data_length = wrq->u.data.length;
+	int i = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_SYS_CLOCK;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (!data_length)
+		req->action = MLAN_ACT_GET;
+	else if (data_length <= MLAN_MAX_CLK_NUM) {
+		req->action = MLAN_ACT_SET;
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		PRINTM(MERROR, "Invalid arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		/* Get configurable clocks */
+		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_CONFIGURABLE;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		/* Current system clock */
+		data[0] = (int)cfg->param.sys_clock.cur_sys_clk;
+		wrq->u.data.length = 1;
+
+		data_length =
+			MIN(cfg->param.sys_clock.sys_clk_num, MLAN_MAX_CLK_NUM);
+
+		/* Configurable clocks */
+		for (i = 0; i < data_length; i++) {
+			data[i + wrq->u.data.length] =
+				(int)cfg->param.sys_clock.sys_clk[i];
+		}
+		wrq->u.data.length += data_length;
+
+		/* Get supported clocks */
+		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_SUPPORTED;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		data_length =
+			MIN(cfg->param.sys_clock.sys_clk_num, MLAN_MAX_CLK_NUM);
+
+		/* Supported clocks */
+		for (i = 0; i < data_length; i++) {
+			data[i + wrq->u.data.length] =
+				(int)cfg->param.sys_clock.sys_clk[i];
+		}
+
+		wrq->u.data.length += data_length;
+
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		/* Set configurable clocks */
+		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_CONFIGURABLE;
+		cfg->param.sys_clock.sys_clk_num =
+			MIN(MLAN_MAX_CLK_NUM, data_length);
+		for (i = 0; i < cfg->param.sys_clock.sys_clk_num; i++)
+			cfg->param.sys_clock.sys_clk[i] = (t_u16)data[i];
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Band and Adhoc-band setting
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_band_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	unsigned int i;
+	int data[3];
+	int user_data_len = wrq->u.data.length, copy_len;
+	t_u32 infra_band = 0;
+	t_u32 adhoc_band = 0;
+	t_u32 adhoc_channel = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (sizeof(int) * user_data_len > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	if (user_data_len > 0) {
+		if (priv->media_connected == MTRUE) {
+			LEAVE();
+			return -EOPNOTSUPP;
+		}
+	}
+
+	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+
+	if (wrq->u.data.length == 0) {
+		/* Get config_bands, adhoc_start_band and adhoc_channel values
+		 * from MLAN */
+		req->action = MLAN_ACT_GET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+		/* Infra Band */
+		data[0] = radio_cfg->param.band_cfg.config_bands;
+		/* Adhoc Band */
+		data[1] = radio_cfg->param.band_cfg.adhoc_start_band;
+		/* Adhoc Channel */
+		data[2] = radio_cfg->param.band_cfg.adhoc_channel;
+		wrq->u.data.length = 3;
+
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 sizeof(int) * wrq->u.data.length)) {
+			ret = -EFAULT;
+			goto error;
+		}
+	} else {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto error;
+		}
+
+		/* To support only <b/bg/bgn/n> */
+		infra_band = data[0];
+		for (i = 0; i < sizeof(SupportedInfraBand); i++)
+			if (infra_band == SupportedInfraBand[i])
+				break;
+		if (i == sizeof(SupportedInfraBand)) {
+			ret = -EINVAL;
+			goto error;
+		}
+
+		/* Set Adhoc band */
+		if (user_data_len >= 2) {
+			adhoc_band = data[1];
+			for (i = 0; i < sizeof(SupportedAdhocBand); i++)
+				if (adhoc_band == SupportedAdhocBand[i])
+					break;
+			if (i == sizeof(SupportedAdhocBand)) {
+				ret = -EINVAL;
+				goto error;
+			}
+		}
+
+		/* Set Adhoc channel */
+		if (user_data_len >= 3) {
+			adhoc_channel = data[2];
+			if (adhoc_channel == 0) {
+				/* Check if specified adhoc channel is non-zero
+				 */
+				ret = -EINVAL;
+				goto error;
+			}
+		}
+		/* Set config_bands and adhoc_start_band values to MLAN */
+		req->action = MLAN_ACT_SET;
+		radio_cfg->param.band_cfg.config_bands = infra_band;
+		radio_cfg->param.band_cfg.adhoc_start_band = adhoc_band;
+		radio_cfg->param.band_cfg.adhoc_channel = adhoc_channel;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto error;
+		}
+	}
+
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read/Write adapter registers value
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_reg_read_write(moal_private *priv, struct iwreq *wrq)
+{
+	int data[3], copy_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg = NULL;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg = (mlan_ds_reg_mem *)req->pbuf;
+	reg->sub_command = MLAN_OID_REG_RW;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+
+	if (data_length == 2) {
+		req->action = MLAN_ACT_GET;
+	} else if (data_length == 3) {
+		req->action = MLAN_ACT_SET;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	reg->param.reg_rw.type = (t_u32)data[0];
+	reg->param.reg_rw.offset = (t_u32)data[1];
+	if (data_length == 3)
+		reg->param.reg_rw.value = (t_u32)data[2];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		if (copy_to_user(wrq->u.data.pointer, &reg->param.reg_rw.value,
+				 sizeof(int))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read the EEPROM contents of the card
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_read_eeprom(moal_private *priv, struct iwreq *wrq)
+{
+	int data[2], copy_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg = NULL;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg = (mlan_ds_reg_mem *)req->pbuf;
+	reg->sub_command = MLAN_OID_EEPROM_RD;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+
+	if (data_length == 2) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	reg->param.rd_eeprom.offset = (t_u16)data[0];
+	reg->param.rd_eeprom.byte_count = (t_u16)data[1];
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		wrq->u.data.length = reg->param.rd_eeprom.byte_count;
+		if (copy_to_user(wrq->u.data.pointer,
+				 reg->param.rd_eeprom.value,
+				 MIN(wrq->u.data.length, MAX_EEPROM_DATA))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read/Write device memory value
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_mem_read_write(moal_private *priv, struct iwreq *wrq)
+{
+	t_u32 data[2];
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_reg_mem *reg_mem = NULL;
+	int data_length = wrq->u.data.length, copy_len;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	reg_mem = (mlan_ds_reg_mem *)req->pbuf;
+	reg_mem->sub_command = MLAN_OID_MEM_RW;
+	req->req_id = MLAN_IOCTL_REG_MEM;
+
+	if (data_length == 1) {
+		PRINTM(MINFO, "MEM_RW: GET\n");
+		req->action = MLAN_ACT_GET;
+	} else if (data_length == 2) {
+		PRINTM(MINFO, "MEM_RW: SET\n");
+		req->action = MLAN_ACT_SET;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	reg_mem->param.mem_rw.addr = (t_u32)data[0];
+	if (data_length == 2)
+		reg_mem->param.mem_rw.value = (t_u32)data[1];
+
+	PRINTM(MINFO, "MEM_RW: Addr=0x%x, Value=0x%x\n",
+	       (int)reg_mem->param.mem_rw.addr,
+	       (int)reg_mem->param.mem_rw.value);
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->action == MLAN_ACT_GET) {
+		if (copy_to_user(wrq->u.data.pointer,
+				 &reg_mem->param.mem_rw.value, sizeof(int))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get LOG
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_get_log(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_get_stats stats;
+	char *buf = NULL;
+	int i = 0;
+
+	ENTER();
+
+	PRINTM(MINFO, " GET STATS\n");
+	buf = kmalloc(GETLOG_BUFSIZE, GFP_KERNEL);
+	if (!buf) {
+		PRINTM(MERROR, "kmalloc failed!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	memset(&stats, 0, sizeof(mlan_ds_get_stats));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, &stats)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (wrq->u.data.pointer) {
+		sprintf(buf,
+			"\n"
+			"mcasttxframe     %u\n"
+			"failed           %u\n"
+			"retry            %u\n"
+			"multiretry       %u\n"
+			"framedup         %u\n"
+			"rtssuccess       %u\n"
+			"rtsfailure       %u\n"
+			"ackfailure       %u\n"
+			"rxfrag           %u\n"
+			"mcastrxframe     %u\n"
+			"fcserror         %u\n"
+			"txframe          %u\n"
+			"wepicverrcnt-1   %u\n"
+			"wepicverrcnt-2   %u\n"
+			"wepicverrcnt-3   %u\n"
+			"wepicverrcnt-4   %u\n"
+			"beacon_rcnt      %u\n"
+			"beacon_mcnt      %u\n",
+			stats.mcast_tx_frame, stats.failed, stats.retry,
+			stats.multi_retry, stats.frame_dup, stats.rts_success,
+			stats.rts_failure, stats.ack_failure, stats.rx_frag,
+			stats.mcast_rx_frame, stats.fcs_error, stats.tx_frame,
+			stats.wep_icv_error[0], stats.wep_icv_error[1],
+			stats.wep_icv_error[2], stats.wep_icv_error[3],
+			stats.bcn_rcv_cnt, stats.bcn_miss_cnt);
+		if (priv->phandle->fw_getlog_enable) {
+			sprintf(buf + strlen(buf), "tx_frag_cnt       %u\n",
+				stats.tx_frag_cnt);
+			sprintf(buf + strlen(buf), "qos_tx_frag_cnt        ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_tx_frag_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_failed_cnt         ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_failed_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_retry_cnt          ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_retry_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_multi_retry_cnt    ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_multi_retry_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_frm_dup_cnt        ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_frm_dup_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_rts_suc_cnt        ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_rts_suc_cnt[i]);
+			}
+			sprintf(buf + strlen(buf),
+				"\nqos_rts_failure_cnt        ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_rts_failure_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_ack_failure_cnt    ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_ack_failure_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_rx_frag_cnt        ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_rx_frag_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_tx_frm_cnt         ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_tx_frm_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_discarded_frm_cnt  ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_discarded_frm_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_mpdus_rx_cnt       ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_mpdus_rx_cnt[i]);
+			}
+			sprintf(buf + strlen(buf), "\nqos_retries_rx_cnt     ");
+			for (i = 0; i < 8; i++) {
+				sprintf(buf + strlen(buf), "%u ",
+					stats.qos_retries_rx_cnt[i]);
+			}
+			sprintf(buf + strlen(buf),
+				"\nmgmt_ccmp_replays      %u\n"
+				"tx_amsdu_cnt           %u\n"
+				"failed_amsdu_cnt       %u\n"
+				"retry_amsdu_cnt        %u\n"
+				"multi_retry_amsdu_cnt  %u\n"
+				"tx_octets_in_amsdu_cnt %llu\n"
+				"amsdu_ack_failure_cnt  %u\n"
+				"rx_amsdu_cnt           %u\n"
+				"rx_octets_in_amsdu_cnt %llu\n"
+				"tx_ampdu_cnt           %u\n"
+				"tx_mpdus_in_ampdu_cnt  %u\n"
+				"tx_octets_in_ampdu_cnt %llu\n"
+				"ampdu_rx_cnt           %u\n"
+				"mpdu_in_rx_ampdu_cnt   %u\n"
+				"rx_octets_in_ampdu_cnt %llu\n"
+				"ampdu_delimiter_crc_error_cnt      %u\n",
+				stats.mgmt_ccmp_replays, stats.tx_amsdu_cnt,
+				stats.failed_amsdu_cnt, stats.retry_amsdu_cnt,
+				stats.multi_retry_amsdu_cnt,
+				stats.tx_octets_in_amsdu_cnt,
+				stats.amsdu_ack_failure_cnt, stats.rx_amsdu_cnt,
+				stats.rx_octets_in_amsdu_cnt,
+				stats.tx_ampdu_cnt, stats.tx_mpdus_in_ampdu_cnt,
+				stats.tx_octets_in_ampdu_cnt,
+				stats.ampdu_rx_cnt, stats.mpdu_in_rx_ampdu_cnt,
+				stats.rx_octets_in_ampdu_cnt,
+				stats.ampdu_delimiter_crc_error_cnt);
+		}
+		wrq->u.data.length = MIN(GETLOG_BUFSIZE - 1, strlen(buf) + 1);
+		if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Deauthenticate
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_deauth(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	struct sockaddr saddr;
+
+	ENTER();
+	if (wrq->u.data.length) {
+		/* Deauth mentioned BSSID */
+		if (copy_from_user(&saddr, wrq->u.data.pointer, sizeof(saddr))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_disconnect(priv, MOAL_IOCTL_WAIT,
+				    (t_u8 *)saddr.sa_data,
+				    DEF_DEAUTH_REASON_CODE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
+				    DEF_DEAUTH_REASON_CODE))
+			ret = -EFAULT;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get TX power configurations
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_tx_power_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int data[5], user_data_len, copy_len;
+	int ret = 0;
+	mlan_bss_info bss_info;
+	mlan_ds_power_cfg *pcfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int power_data[MAX_POWER_TABLE_SIZE];
+	int i, power_ext_len = 0;
+	int *ptr = power_data;
+	mlan_power_group *pwr_grp = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+	memset(data, 0, sizeof(data));
+	user_data_len = wrq->u.data.length;
+	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
+
+	if (user_data_len) {
+		if (sizeof(int) * user_data_len > sizeof(data)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		switch (user_data_len) {
+		case 1:
+			if (data[0] != 0xFF)
+				ret = -EINVAL;
+			break;
+		case 2:
+		case 4:
+			if (data[0] == 0xFF) {
+				ret = -EINVAL;
+				break;
+			}
+			if (data[1] < bss_info.min_power_level) {
+				PRINTM(MERROR,
+				       "The set powercfg rate value %d dBm is out of range (%d dBm-%d dBm)!\n",
+				       data[1], (int)bss_info.min_power_level,
+				       (int)bss_info.max_power_level);
+				ret = -EINVAL;
+				break;
+			}
+			if (user_data_len == 4) {
+				if (data[1] > data[2]) {
+					PRINTM(MERROR,
+					       "Min power should be less than maximum!\n");
+					ret = -EINVAL;
+					break;
+				}
+				if (data[3] < 0) {
+					PRINTM(MERROR,
+					       "Step should not less than 0!\n");
+					ret = -EINVAL;
+					break;
+				}
+				if (data[2] > bss_info.max_power_level) {
+					PRINTM(MERROR,
+					       "The set powercfg rate value %d dBm is out of range (%d dBm-%d dBm)!\n",
+					       data[2],
+					       (int)bss_info.min_power_level,
+					       (int)bss_info.max_power_level);
+					ret = -EINVAL;
+					break;
+				}
+				if (data[3] > data[2] - data[1]) {
+					PRINTM(MERROR,
+					       "Step should not greater than power difference!\n");
+					ret = -EINVAL;
+					break;
+				}
+			}
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		if (ret)
+			goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pcfg = (mlan_ds_power_cfg *)req->pbuf;
+	pcfg->sub_command = MLAN_OID_POWER_CFG_EXT;
+	req->req_id = MLAN_IOCTL_POWER_CFG;
+	if (!user_data_len)
+		req->action = MLAN_ACT_GET;
+	else {
+		req->action = MLAN_ACT_SET;
+		if (data[0] == 0xFF)
+			pcfg->param.power_ext.power_group[0].rate_format =
+				TX_PWR_CFG_AUTO_CTRL_OFF;
+		else {
+			pcfg->param.power_ext.power_group[0].power_step = 0;
+			pcfg->param.power_ext.power_group[0].first_rate_ind =
+				data[0];
+			pcfg->param.power_ext.power_group[0].last_rate_ind =
+				data[0];
+			if (data[0] <= 11) {
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_LG;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW20;
+			} else if (data[0] <= 27) {
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_HT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW20;
+				pcfg->param.power_ext.power_group[0]
+					.first_rate_ind -= 12;
+				pcfg->param.power_ext.power_group[0]
+					.last_rate_ind -= 12;
+			} else if ((140 <= data[0]) && (data[0] <= 155)) {
+				pcfg->param.power_ext.power_group[0]
+					.rate_format = MLAN_RATE_FORMAT_HT;
+				pcfg->param.power_ext.power_group[0].bandwidth =
+					MLAN_HT_BW40;
+				pcfg->param.power_ext.power_group[0]
+					.first_rate_ind -= 140;
+				pcfg->param.power_ext.power_group[0]
+					.last_rate_ind -= 140;
+			}
+			if (user_data_len == 2) {
+				pcfg->param.power_ext.power_group[0].power_min =
+					data[1];
+				pcfg->param.power_ext.power_group[0].power_max =
+					data[1];
+			} else if (user_data_len == 4) {
+				pcfg->param.power_ext.power_group[0].power_min =
+					data[1];
+				pcfg->param.power_ext.power_group[0].power_max =
+					data[2];
+				pcfg->param.power_ext.power_group[0].
+					power_step = data[3];
+			}
+			pcfg->param.power_ext.num_pwr_grp = 1;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!user_data_len) {
+		/* GET operation */
+		i = 0;
+		power_ext_len = 0;
+		ptr = power_data;
+		while ((i < (int)pcfg->param.power_ext.num_pwr_grp) &&
+		       ((power_ext_len + 5) < MAX_POWER_TABLE_SIZE)) {
+			pwr_grp = &pcfg->param.power_ext.power_group[i];
+			if (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT) {
+				if (pwr_grp->bandwidth == MLAN_HT_BW20) {
+					pwr_grp->first_rate_ind += 12;
+					pwr_grp->last_rate_ind += 12;
+				} else if (pwr_grp->bandwidth == MLAN_HT_BW40) {
+					pwr_grp->first_rate_ind += 140;
+					pwr_grp->last_rate_ind += 140;
+				}
+			}
+
+			if ((pwr_grp->rate_format == MLAN_RATE_FORMAT_LG) ||
+			    (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT)) {
+				*ptr = pwr_grp->first_rate_ind;
+				ptr++;
+				*ptr = pwr_grp->last_rate_ind;
+				ptr++;
+				*ptr = pwr_grp->power_min;
+				ptr++;
+				*ptr = pwr_grp->power_max;
+				ptr++;
+				*ptr = pwr_grp->power_step;
+				ptr++;
+				power_ext_len += 5;
+			}
+			i++;
+		}
+		if (copy_to_user(wrq->u.data.pointer, (t_u8 *)power_data,
+				 sizeof(int) * power_ext_len)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = power_ext_len;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Tx/Rx data rates
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_get_txrx_rate(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_rate *rate = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->sub_command = MLAN_OID_GET_DATA_RATE;
+	req->req_id = MLAN_IOCTL_RATE;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)&rate->param.data_rate,
+			 sizeof(int) * 2)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 2;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO
+/**
+ *  @brief Turn on/off the sdio clock
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0/MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_sdio_clock_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	int data = 2;
+	/* Initialize the clock state as on */
+	static int clock_state = 1;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		wrq->u.data.length = sizeof(clock_state) / sizeof(int);
+		if (copy_to_user(wrq->u.data.pointer, &clock_state,
+				 sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		goto done;
+	}
+	switch (data) {
+	case CMD_DISABLED:
+		PRINTM(MINFO, "SDIO clock is turned off\n");
+		ret = woal_sdio_set_bus_clock(priv->phandle, MFALSE);
+		clock_state = data;
+		break;
+	case CMD_ENABLED:
+		PRINTM(MINFO, "SDIO clock is turned on\n");
+		ret = woal_sdio_set_bus_clock(priv->phandle, MTRUE);
+		clock_state = data;
+		break;
+	default:
+		ret = -EINVAL;
+		PRINTM(MINFO, "sdioclock: wrong parameter\n");
+		break;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO */
+
+/**
+ *  @brief Set/Get beacon interval
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_beacon_interval(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	int bcn = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&bcn, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((bcn < MLAN_MIN_BEACON_INTERVAL) ||
+		    (bcn > MLAN_MAX_BEACON_INTERVAL)) {
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_IBSS_BCN_INTERVAL;
+	req->req_id = MLAN_IOCTL_BSS;
+	if (!wrq->u.data.length)
+		req->action = MLAN_ACT_GET;
+	else {
+		req->action = MLAN_ACT_SET;
+		bss->param.bcn_interval = bcn;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)&bss->param.bcn_interval,
+			 sizeof(int))) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get TX data rate
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param wrq       A pointer to iwreq structure
+ *
+ * @return          0 --success, otherwise fail
+ */
+static int
+woal_set_get_txrate(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_rate *rate = NULL;
+	mlan_ioctl_req *req = NULL;
+	int rateindex = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (wrq->u.data.length) {
+		if (copy_from_user(&rateindex, wrq->u.data.pointer,
+				   sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
+	rate->sub_command = MLAN_OID_RATE_CFG;
+	req->req_id = MLAN_IOCTL_RATE;
+	if (!wrq->u.data.length)
+		req->action = MLAN_ACT_GET;
+	else {
+		req->action = MLAN_ACT_SET;
+		if (rateindex == AUTO_RATE)
+			rate->param.rate_cfg.is_rate_auto = 1;
+		else {
+			if ((rateindex != MLAN_RATE_INDEX_MCS32) &&
+			    ((rateindex < 0) ||
+			     (rateindex > MLAN_RATE_INDEX_MCS15))) {
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		rate->param.rate_cfg.rate = rateindex;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	} else {
+		if (wrq->u.data.length)
+			priv->rate_index = rateindex;
+	}
+	if (!wrq->u.data.length) {
+		if (rate->param.rate_cfg.is_rate_auto)
+			rateindex = AUTO_RATE;
+		else
+			rateindex = rate->param.rate_cfg.rate;
+		wrq->u.data.length = 1;
+		if (copy_to_user(wrq->u.data.pointer, &rateindex, sizeof(int)))
+			ret = -EFAULT;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get region code
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param wrq       A pointer to iwreq structure
+ *
+ * @return          0 --success, otherwise fail
+ */
+static int
+woal_set_get_regioncode(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int region = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&region, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_MISC_REGION;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if (!wrq->u.data.length)
+		req->action = MLAN_ACT_GET;
+	else {
+		req->action = MLAN_ACT_SET;
+		cfg->param.region_code = region;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!wrq->u.data.length) {
+		wrq->u.data.length = 1;
+		if (copy_to_user(wrq->u.data.pointer, &cfg->param.region_code,
+				 sizeof(int)))
+			ret = -EFAULT;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get radio
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param wrq       A pointer to iwreq structure
+ *
+ * @return          0 --success, otherwise fail
+ */
+static int
+woal_set_get_radio(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_bss_info bss_info;
+	int option = 0;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	if (wrq->u.data.length) {
+		/* Set radio */
+		if (copy_from_user(&option, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS != woal_set_radio(priv, (t_u8)option))
+			ret = -EFAULT;
+	} else {
+		/* Get radio status */
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		wrq->u.data.length = 1;
+		if (copy_to_user(wrq->u.data.pointer, &bss_info.radio_on,
+				 sizeof(bss_info.radio_on))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+#ifdef DEBUG_LEVEL1
+/**
+ *  @brief Get/Set the bit mask of driver debug message control
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to wrq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_drv_dbg(moal_private *priv, struct iwreq *wrq)
+{
+	int data[4], copy_len;
+	int ret = 0;
+	int data_length = wrq->u.data.length;
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	if (!data_length) {
+		data[0] = drvdbg;
+		/* Return the current driver debug bit masks */
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto drvdbgexit;
+		}
+		wrq->u.data.length = 1;
+	} else if (data_length < 3) {
+		/* Get the driver debug bit masks from user */
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto drvdbgexit;
+		}
+		drvdbg = data[0];
+		/* Set the driver debug bit masks into mlan */
+		woal_set_drvdbg(priv, drvdbg);
+	} else {
+		PRINTM(MERROR, "Invalid parameter number\n");
+		goto drvdbgexit;
+	}
+
+	printk(KERN_ALERT "drvdbg = 0x%08x\n", drvdbg);
+#ifdef DEBUG_LEVEL2
+	printk(KERN_ALERT "MINFO  (%08x) %s\n", MINFO,
+	       (drvdbg & MINFO) ? "X" : "");
+	printk(KERN_ALERT "MWARN  (%08x) %s\n", MWARN,
+	       (drvdbg & MWARN) ? "X" : "");
+	printk(KERN_ALERT "MENTRY (%08x) %s\n", MENTRY,
+	       (drvdbg & MENTRY) ? "X" : "");
+#endif
+	printk(KERN_ALERT "MMPA_D (%08x) %s\n", MMPA_D,
+	       (drvdbg & MMPA_D) ? "X" : "");
+	printk(KERN_ALERT "MIF_D  (%08x) %s\n", MIF_D,
+	       (drvdbg & MIF_D) ? "X" : "");
+	printk(KERN_ALERT "MFW_D  (%08x) %s\n", MFW_D,
+	       (drvdbg & MFW_D) ? "X" : "");
+	printk(KERN_ALERT "MEVT_D (%08x) %s\n", MEVT_D,
+	       (drvdbg & MEVT_D) ? "X" : "");
+	printk(KERN_ALERT "MCMD_D (%08x) %s\n", MCMD_D,
+	       (drvdbg & MCMD_D) ? "X" : "");
+	printk(KERN_ALERT "MDAT_D (%08x) %s\n", MDAT_D,
+	       (drvdbg & MDAT_D) ? "X" : "");
+	printk(KERN_ALERT "MREG_D (%08x) %s\n", MREG_D,
+	       (drvdbg & MREG_D) ? "X" : "");
+	printk(KERN_ALERT "MIOCTL (%08x) %s\n", MIOCTL,
+	       (drvdbg & MIOCTL) ? "X" : "");
+	printk(KERN_ALERT "MINTR  (%08x) %s\n", MINTR,
+	       (drvdbg & MINTR) ? "X" : "");
+	printk(KERN_ALERT "MEVENT (%08x) %s\n", MEVENT,
+	       (drvdbg & MEVENT) ? "X" : "");
+	printk(KERN_ALERT "MCMND  (%08x) %s\n", MCMND,
+	       (drvdbg & MCMND) ? "X" : "");
+	printk(KERN_ALERT "MDATA  (%08x) %s\n", MDATA,
+	       (drvdbg & MDATA) ? "X" : "");
+	printk(KERN_ALERT "MERROR (%08x) %s\n", MERROR,
+	       (drvdbg & MERROR) ? "X" : "");
+	printk(KERN_ALERT "MFATAL (%08x) %s\n", MFATAL,
+	       (drvdbg & MFATAL) ? "X" : "");
+	printk(KERN_ALERT "MMSG   (%08x) %s\n", MMSG,
+	       (drvdbg & MMSG) ? "X" : "");
+
+drvdbgexit:
+	LEAVE();
+	return ret;
+}
+#endif /* DEBUG_LEVEL1 */
+
+/**
+ * @brief Set/Get QoS configuration
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_set_get_qos_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_wmm_cfg *cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		cfg->param.qos_cfg = (t_u8)data;
+	} else
+		req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!wrq->u.data.length) {
+		data = (int)cfg->param.qos_cfg;
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#ifndef OPCHAN
+/**
+ * @brief Set/Get WWS mode
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param wrq       A pointer to iwreq structure
+ *
+ * @return          0 --success, otherwise fail
+ */
+static int
+woal_wws_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *wws = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	wws = (mlan_ds_misc_cfg *)req->pbuf;
+	wws->sub_command = MLAN_OID_MISC_WWS;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data != CMD_DISABLED && data != CMD_ENABLED) {
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		wws->param.wws_cfg = data;
+	} else
+		req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!wrq->u.data.length) {
+		data = wws->param.wws_cfg;
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Set/Get sleep period
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_sleep_pd(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((data <= MAX_SLEEP_PERIOD && data >= MIN_SLEEP_PERIOD) ||
+		    (data == 0)
+		    || (data == SLEEP_PERIOD_RESERVED_FF)
+			) {
+			req->action = MLAN_ACT_SET;
+			pm_cfg->param.sleep_period = data;
+		} else {
+			ret = -EINVAL;
+			goto done;
+		}
+	} else
+		req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!wrq->u.data.length) {
+		data = pm_cfg->param.sleep_period;
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Configure sleep parameters
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param req          A pointer to ifreq structure
+ *
+ * @return             0 --success, otherwise fail
+ */
+static int
+woal_sleep_params_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_pm_cfg *pm = NULL;
+	mlan_ds_sleep_params *psleep_params = NULL;
+	int data[6] = { 0 }, i, copy_len;
+	int data_length = wrq->u.data.length;
+#ifdef DEBUG_LEVEL1
+	char err_str[][36] = { {"sleep clock error in ppm"},
+	{"wakeup offset in usec"},
+	{"clock stabilization time in usec"},
+	{"control periodic calibration(0-2)"},
+	{"control of external sleepClock(0-2)"},
+	{"value of reserved for debug"}
+	};
+#endif
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	pm = (mlan_ds_pm_cfg *)req->pbuf;
+	pm->sub_command = MLAN_OID_PM_CFG_SLEEP_PARAMS;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	psleep_params = (pmlan_ds_sleep_params)&pm->param.sleep_params;
+
+	if (data_length == 0) {
+		req->action = MLAN_ACT_GET;
+	} else if (data_length == 6) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			/* copy_from_user failed  */
+			PRINTM(MERROR, "S_PARAMS: copy from user failed\n");
+			ret = -EINVAL;
+			goto done;
+		}
+#define MIN_VAL 0x0000
+#define MAX_VAL 0xFFFF
+		for (i = 0; i < 6; i++) {
+			if ((i == 3) || (i == 4)) {
+				/* These two cases are handled below the loop */
+				continue;
+			}
+			if (data[i] < MIN_VAL || data[i] > MAX_VAL) {
+				PRINTM(MERROR, "Invalid %s (0-65535)!\n",
+				       err_str[i]);
+				ret = -EINVAL;
+				goto done;
+			}
+		}
+		if (data[3] < 0 || data[3] > 2) {
+			PRINTM(MERROR,
+			       "Invalid control periodic calibration (0-2)!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[4] < 0 || data[4] > 2) {
+			PRINTM(MERROR,
+			       "Invalid control of external sleep clock (0-2)!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		psleep_params->error = data[0];
+		psleep_params->offset = data[1];
+		psleep_params->stable_time = data[2];
+		psleep_params->cal_control = data[3];
+		psleep_params->ext_sleep_clk = data[4];
+		psleep_params->reserved = data[5];
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = psleep_params->error;
+	data[1] = psleep_params->offset;
+	data[2] = psleep_params->stable_time;
+	data[3] = psleep_params->cal_control;
+	data[4] = psleep_params->ext_sleep_clk;
+	data[5] = psleep_params->reserved;
+	wrq->u.data.length = 6;
+
+	if (copy_to_user(wrq->u.data.pointer, data,
+			 sizeof(int) * wrq->u.data.length)) {
+		PRINTM(MERROR, "QCONFIG: copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get user provisioned local power constraint
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_set_get_11h_local_pwr_constraint(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		ds_11hcfg->param.usr_local_power_constraint = (t_s8)data;
+		req->action = MLAN_ACT_SET;
+	} else
+		req->action = MLAN_ACT_GET;
+
+	ds_11hcfg->sub_command = MLAN_OID_11H_LOCAL_POWER_CONSTRAINT;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy response to user */
+	if (req->action == MLAN_ACT_GET) {
+		data = (int)ds_11hcfg->param.usr_local_power_constraint;
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			PRINTM(MINFO, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get HT stream configurations
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_ht_stream_cfg_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg = (mlan_ds_11n_cfg *)req->pbuf;
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data != HT_STREAM_MODE_1X1 && data != HT_STREAM_MODE_2X2) {
+			PRINTM(MINFO, "Invalid argument\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		cfg->param.stream_cfg = data;
+		req->action = MLAN_ACT_SET;
+	} else
+		req->action = MLAN_ACT_GET;
+
+	cfg->sub_command = MLAN_OID_11N_CFG_STREAM_CFG;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy response to user */
+	data = (int)cfg->param.stream_cfg;
+	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+		PRINTM(MINFO, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get MAC control configuration
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_mac_control_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Validation will be done later */
+		cfg->param.mac_ctrl = data;
+		req->action = MLAN_ACT_SET;
+	} else
+		req->action = MLAN_ACT_GET;
+
+	cfg->sub_command = MLAN_OID_MISC_MAC_CONTROL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy response to user */
+	data = (int)cfg->param.mac_ctrl;
+	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+		PRINTM(MINFO, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get thermal reading
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_thermal_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	if (wrq->u.data.length) {
+		PRINTM(MERROR, "Set is not supported for this command\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	req->action = MLAN_ACT_GET;
+
+	cfg->sub_command = MLAN_OID_MISC_THERMAL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy response to user */
+	data = (int)cfg->param.thermal;
+	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+		PRINTM(MINFO, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get hotspot enable state
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      Pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_cfg_hotspot(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *cfg = NULL;
+	int config;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wrq->u.data.length > 1) {
+		PRINTM(MERROR, "Invalid no of arguments!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	if (wrq->u.data.length == 0)
+		req->action = MLAN_ACT_GET;
+	else {
+		if (copy_from_user(&config, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		cfg->param.hotspot_cfg = config;
+		req->action = MLAN_ACT_SET;
+	}
+
+	cfg->sub_command = MLAN_OID_MISC_HOTSPOT_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	config = cfg->param.hotspot_cfg;
+	if (copy_to_user(wrq->u.data.pointer, &config, sizeof(int))) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+#if defined(REASSOCIATION)
+/**
+ * @brief Set/Get reassociation settings
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_set_get_reassoc(moal_private *priv, struct iwreq *wrq)
+{
+	moal_handle *handle = priv->phandle;
+	int ret = 0;
+	int data = 0;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data == 0) {
+			handle->reassoc_on &= ~MBIT(priv->bss_index);
+			priv->reassoc_on = MFALSE;
+			priv->reassoc_required = MFALSE;
+			if (!handle->reassoc_on &&
+			    handle->is_reassoc_timer_set == MTRUE) {
+				woal_cancel_timer(&handle->reassoc_timer);
+				handle->is_reassoc_timer_set = MFALSE;
+			}
+		} else {
+			handle->reassoc_on |= MBIT(priv->bss_index);
+			priv->reassoc_on = MTRUE;
+		}
+	} else {
+		data = (int)(priv->reassoc_on);
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* REASSOCIATION */
+
+/**
+ *  @brief implement WMM enable command
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      Pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_wmm_enable_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_wmm_cfg *wmm = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	wmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	wmm->sub_command = MLAN_OID_WMM_CFG_ENABLE;
+
+	if (wrq->u.data.length) {
+		/* Set WMM configuration */
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		if (data == CMD_DISABLED)
+			wmm->param.wmm_enable = MFALSE;
+		else
+			wmm->param.wmm_enable = MTRUE;
+	} else {
+		/* Get WMM status */
+		req->action = MLAN_ACT_GET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, &wmm->param.wmm_enable,
+				 sizeof(wmm->param.wmm_enable))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Implement 802.11D enable command
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      Pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_11d_enable_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_11d_cfg *pcfg_11d = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pcfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11D_CFG;
+	pcfg_11d->sub_command = MLAN_OID_11D_CFG_ENABLE;
+	if (wrq->u.data.length) {
+		/* Set 11D configuration */
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data == CMD_DISABLED)
+			pcfg_11d->param.enable_11d = MFALSE;
+		else
+			pcfg_11d->param.enable_11d = MTRUE;
+		req->action = MLAN_ACT_SET;
+	} else {
+		req->action = MLAN_ACT_GET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer,
+				 &pcfg_11d->param.enable_11d,
+				 sizeof(pcfg_11d->param.enable_11d))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Implement 802.11D clear chan table command
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      Pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_11d_clr_chan_table(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_11d_cfg *pcfg_11d = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pcfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11D_CFG;
+	pcfg_11d->sub_command = MLAN_OID_11D_CLR_CHAN_TABLE;
+	req->action = MLAN_ACT_SET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Control WPS Session Enable/Disable
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      Pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_wps_cfg_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_wps_cfg *pwps = NULL;
+	mlan_ioctl_req *req = NULL;
+	char buf[8];
+	struct iwreq *wreq = (struct iwreq *)wrq;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	PRINTM(MINFO, "WOAL_WPS_SESSION\n");
+
+	memset(buf, 0, sizeof(buf));
+	if (copy_from_user(buf, wreq->u.data.pointer,
+			   MIN(sizeof(buf) - 1, wreq->u.data.length))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pwps = (mlan_ds_wps_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_WPS_CFG;
+	req->action = MLAN_ACT_SET;
+	pwps->sub_command = MLAN_OID_WPS_CFG_SESSION;
+	if (buf[0] == 1)
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START;
+	else
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_END;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set WPA passphrase and SSID
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_passphrase(moal_private *priv, struct iwreq *wrq)
+{
+	t_u16 len = 0;
+	char buf[256];
+	char *begin = NULL, *end = NULL, *opt = NULL;
+	int ret = 0, action = -1, i;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
+	t_u8 *mac = NULL;
+	int data_length = wrq->u.data.length, copy_len;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->phandle->card_info->embedded_supp) {
+		PRINTM(MERROR, "Not supported cmd on this card\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+	if (!data_length || data_length >= (int)sizeof(buf) - 1) {
+		PRINTM(MERROR,
+		       "Argument missing or too long for setpassphrase\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	memset(buf, 0, sizeof(buf));
+	copy_len = data_length;
+
+	if (copy_from_user(buf, wrq->u.data.pointer, copy_len)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	buf[copy_len] = '\0';
+
+	/* Parse the buf to get the cmd_action */
+	begin = buf;
+	end = woal_strsep(&begin, ';', '/');
+	if (!end) {
+		PRINTM(MERROR, "Invalid option\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	action = woal_atox(end);
+	if (action < 0 || action > 2 || end[1] != '\0') {
+		PRINTM(MERROR, "Invalid action argument %s\n", end);
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	if (action == 0)
+		req->action = MLAN_ACT_GET;
+	else
+		req->action = MLAN_ACT_SET;
+	while (begin) {
+		end = woal_strsep(&begin, ';', '/');
+		opt = woal_strsep(&end, '=', '/');
+		if (!opt || !end || !end[0]) {
+			PRINTM(MERROR, "Invalid option\n");
+			ret = -EINVAL;
+			break;
+		} else if (!strnicmp(opt, "ssid", strlen(opt))) {
+			if (strlen(end) > MLAN_MAX_SSID_LENGTH) {
+				PRINTM(MERROR,
+				       "SSID length exceeds max length\n");
+				ret = -EFAULT;
+				break;
+			}
+			sec->param.passphrase.ssid.ssid_len = strlen(end);
+			moal_memcpy_ext(priv->phandle,
+					sec->param.passphrase.ssid.ssid, end,
+					strlen(end), MLAN_MAX_SSID_LENGTH);
+			PRINTM(MINFO, "ssid=%s, len=%d\n",
+			       sec->param.passphrase.ssid.ssid,
+			       (int)sec->param.passphrase.ssid.ssid_len);
+		} else if (!strnicmp(opt, "bssid", strlen(opt))) {
+			woal_mac2u8(sec->param.passphrase.bssid, end);
+		} else if (!strnicmp(opt, "psk", strlen(opt)) &&
+			   req->action == MLAN_ACT_SET) {
+			if (strlen(end) != MLAN_PMK_HEXSTR_LENGTH) {
+				PRINTM(MERROR, "Invalid PMK length\n");
+				ret = -EINVAL;
+				break;
+			}
+			woal_ascii2hex((t_u8 *)(sec->param.passphrase.psk.pmk.
+						pmk), end,
+				       MLAN_PMK_HEXSTR_LENGTH / 2);
+			sec->param.passphrase.psk_type = MLAN_PSK_PMK;
+		} else if (!strnicmp(opt, "passphrase", strlen(opt)) &&
+			   req->action == MLAN_ACT_SET) {
+			if (strlen(end) < MLAN_MIN_PASSPHRASE_LENGTH ||
+			    strlen(end) > MLAN_MAX_PASSPHRASE_LENGTH) {
+				PRINTM(MERROR,
+				       "Invalid length for passphrase\n");
+				ret = -EINVAL;
+				break;
+			}
+			sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE;
+			moal_memcpy_ext(priv->phandle,
+					sec->param.passphrase.psk.passphrase.
+					passphrase, end,
+					sizeof(sec->param.passphrase.psk.
+					       passphrase.passphrase),
+					sizeof(sec->param.passphrase.psk.
+					       passphrase.passphrase));
+			sec->param.passphrase.psk.passphrase.passphrase_len =
+				strlen(end);
+			PRINTM(MINFO, "passphrase=%s, len=%d\n",
+			       sec->param.passphrase.psk.passphrase.passphrase,
+			       (int)sec->param.passphrase.psk.passphrase.
+			       passphrase_len);
+		} else {
+			PRINTM(MERROR, "Invalid option %s\n", opt);
+			ret = -EINVAL;
+			break;
+		}
+	}
+	if (ret)
+		goto done;
+
+	if (action == 2)
+		sec->param.passphrase.psk_type = MLAN_PSK_CLEAR;
+	else if (action == 0)
+		sec->param.passphrase.psk_type = MLAN_PSK_QUERY;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (action == 0) {
+		memset(buf, 0, sizeof(buf));
+		if (sec->param.passphrase.ssid.ssid_len) {
+			len += sprintf(buf + len, "ssid:");
+			moal_memcpy_ext(priv->phandle, buf + len,
+					sec->param.passphrase.ssid.ssid,
+					sec->param.passphrase.ssid.ssid_len,
+					sizeof(buf) - len);
+			len += sec->param.passphrase.ssid.ssid_len;
+			len += sprintf(buf + len, " ");
+		}
+		if (memcmp(&sec->param.passphrase.bssid, zero_mac,
+			   sizeof(zero_mac))) {
+			mac = (t_u8 *)&sec->param.passphrase.bssid;
+			len += sprintf(buf + len, "bssid:");
+			for (i = 0; i < ETH_ALEN - 1; ++i)
+				len += sprintf(buf + len, "%02x:", mac[i]);
+			len += sprintf(buf + len, "%02x ", mac[i]);
+		}
+		if (sec->param.passphrase.psk_type == MLAN_PSK_PMK) {
+			len += sprintf(buf + len, "psk:");
+			for (i = 0; i < MLAN_MAX_KEY_LENGTH; ++i)
+				len += sprintf(buf + len, "%02x",
+					       sec->param.passphrase.psk.pmk.
+					       pmk[i]);
+			len += sprintf(buf + len, "\n");
+		}
+		if (sec->param.passphrase.psk_type == MLAN_PSK_PASSPHRASE) {
+			len += sprintf(buf + len, "passphrase:%s\n",
+				       sec->param.passphrase.psk.passphrase.
+				       passphrase);
+		}
+		if (wrq->u.data.pointer) {
+			if (copy_to_user(wrq->u.data.pointer, buf,
+					 MIN(len, sizeof(buf)))) {
+				PRINTM(MERROR, "Copy to user failed, len %d\n",
+				       len);
+				ret = -EFAULT;
+				goto done;
+			}
+			wrq->u.data.length = len;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get esupp mode
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_get_esupp_mode(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->phandle->card_info->embedded_supp) {
+		PRINTM(MERROR, "Not supported cmd on this card\n");
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ESUPP_MODE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)&sec->param.esupp_mode,
+			 sizeof(int) * 3)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 3;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get GTK/PTK
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_get_key_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	unsigned int i;
+	t_u8 key_ascii[256];
+	t_u8 *tmp;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(key_ascii, 0x00, sizeof(key_ascii));
+	tmp = key_ascii;
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MERROR, "Can't get key in un-associated state\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Get Unicast Key */
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
+	sec->param.encrypt_key.key_index = 0;
+	sec->param.encrypt_key.key_flags = 0;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (sec->param.encrypt_key.key_len) {
+		sprintf((char *)tmp, "\n%s", "PTK: ");
+		tmp += 5;
+		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
+			tmp += sprintf((char *)tmp, "%02x",
+				       sec->param.encrypt_key.key_material[i]);
+	}
+
+	/* Get Multicase Key */
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
+	sec->param.encrypt_key.key_index = 0;
+	sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
+	memset(sec->param.encrypt_key.mac_addr, 0x0, MLAN_MAC_ADDR_LENGTH);
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (sec->param.encrypt_key.key_len) {
+		sprintf((char *)tmp, "\n%s", "GTK: ");
+		tmp += 5;
+		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
+			tmp += sprintf((char *)tmp, "%02x",
+				       sec->param.encrypt_key.key_material[i]);
+	}
+
+	/* Get IGTK Key */
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
+	sec->param.encrypt_key.key_index = 0;
+	sec->param.encrypt_key.key_flags = KEY_FLAG_AES_MCAST_IGTK;
+	memset(sec->param.encrypt_key.mac_addr, 0x0, MLAN_MAC_ADDR_LENGTH);
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (sec->param.encrypt_key.key_len) {
+		sprintf((char *)tmp, "\n%s", "IGTK: ");
+		tmp += 6;
+		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
+			tmp += sprintf((char *)tmp, "%02x",
+				       sec->param.encrypt_key.key_material[i]);
+	}
+
+	wrq->u.data.length = sizeof(key_ascii) + 1;
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, &key_ascii,
+				 tmp - key_ascii)) {
+			PRINTM(MERROR, "copy_to_user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief arpfilter ioctl function
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_arp_filter(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data_length = wrq->u.data.length, copy_len;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	copy_len = MIN(sizeof(misc->param.gen_ie.ie_data),
+		       sizeof(int) * data_length);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GEN_IE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+	misc->param.gen_ie.type = MLAN_IE_TYPE_ARP_FILTER;
+	misc->param.gen_ie.len = data_length;
+
+	/* get the whole command from user */
+	if (copy_from_user(misc->param.gen_ie.ie_data, wrq->u.data.pointer,
+			   copy_len)) {
+		PRINTM(MERROR, "copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/get IP address
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_set_get_ip_addr(moal_private *priv, struct iwreq *wrq)
+{
+	char buf[IPADDR_MAX_BUF];
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0, op_code = 0, data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(buf, 0, IPADDR_MAX_BUF);
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+
+	if (data_length <= 1) {	/* GET */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		if (copy_from_user(buf, wrq->u.data.pointer,
+				   MIN(IPADDR_MAX_BUF - 1, data_length))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Make sure we have the operation argument */
+		if (data_length > 2 && buf[1] != ';') {
+			PRINTM(MERROR,
+			       "No operation argument. Separate with ';'\n");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			buf[1] = '\0';
+		}
+		ioctl_req->action = MLAN_ACT_SET;
+		/* only one IP is supported in current firmware */
+		memset(misc->param.ipaddr_cfg.ip_addr[0], 0, IPADDR_LEN);
+		in4_pton(&buf[2], MIN((IPADDR_MAX_BUF - 3), (data_length - 2)),
+			 misc->param.ipaddr_cfg.ip_addr[0], ' ', NULL);
+		/* only one IP is supported in current firmware */
+		misc->param.ipaddr_cfg.ip_addr_num = 1;
+		misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
+	}
+	if (woal_atoi(&op_code, buf) != MLAN_STATUS_SUCCESS) {
+		ret = -EINVAL;
+		goto done;
+	}
+	misc->param.ipaddr_cfg.op_code = (t_u32)op_code;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->sub_command = MLAN_OID_MISC_IP_ADDR;
+
+	/* Send ioctl to mlan */
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		snprintf(buf, IPADDR_MAX_BUF, "%d;%d.%d.%d.%d",
+			 misc->param.ipaddr_cfg.op_code,
+			 misc->param.ipaddr_cfg.ip_addr[0][0],
+			 misc->param.ipaddr_cfg.ip_addr[0][1],
+			 misc->param.ipaddr_cfg.ip_addr[0][2],
+			 misc->param.ipaddr_cfg.ip_addr[0][3]);
+		wrq->u.data.length = IPADDR_MAX_BUF;
+		if (copy_to_user(wrq->u.data.pointer, buf, IPADDR_MAX_BUF)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Transmit beamforming capabilities
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 -- success, otherwise fail
+ */
+static int
+woal_tx_bf_cap_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data_length = wrq->u.data.length;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11n_cfg *bf_cfg = NULL;
+	int bf_cap = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (data_length > 1) {
+		PRINTM(MERROR, "Invalid no of arguments!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
+	req->action = MLAN_ACT_GET;
+	if (data_length) {	/* SET */
+		if (copy_from_user(&bf_cap, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		bf_cfg->param.tx_bf_cap = bf_cap;
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	bf_cap = bf_cfg->param.tx_bf_cap;
+	if (copy_to_user(wrq->u.data.pointer, &bf_cap, sizeof(int))) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/* Maximum input output characters in group WOAL_SET_GET_256_CHAR */
+#define MAX_IN_OUT_CHAR 256
+/** Tx BF Global conf argument index */
+#define BF_ENABLE_PARAM 1
+#define SOUND_ENABLE_PARAM 2
+#define FB_TYPE_PARAM 3
+#define SNR_THRESHOLD_PARAM 4
+#define SOUND_INTVL_PARAM 5
+#define BF_MODE_PARAM 6
+#define BF_CFG_ACT_GET 0
+#define BF_CFG_ACT_SET 1
+
+/**
+ *  @brief Set/Get Transmit beamforming configuration
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 -- success, otherwise fail
+ */
+static int
+woal_tx_bf_cfg_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data_length = wrq->u.data.length;
+	int bf_action = 0, interval = 0;
+	int snr = 0, i, tmp_val = 0;
+	t_u8 buf[MAX_IN_OUT_CHAR], char_count = 0;
+	t_u8 *str, *token, *pos;
+	t_u16 action = 0;
+
+	mlan_ds_11n_tx_bf_cfg bf_cfg;
+	mlan_trigger_sound_args *bf_sound = NULL;
+	mlan_tx_bf_peer_args *tx_bf_peer = NULL;
+	mlan_snr_thr_args *bf_snr = NULL;
+	mlan_bf_periodicity_args *bf_periodicity = NULL;
+	mlan_bf_global_cfg_args *bf_global = NULL;
+
+	ENTER();
+
+	memset(&bf_cfg, 0, sizeof(bf_cfg));
+	/* Pointer to corresponding buffer */
+	bf_sound = bf_cfg.body.bf_sound;
+	tx_bf_peer = bf_cfg.body.tx_bf_peer;
+	bf_snr = bf_cfg.body.bf_snr;
+	bf_periodicity = bf_cfg.body.bf_periodicity;
+	bf_global = &bf_cfg.body.bf_global_cfg;
+
+	/* Total characters in buffer */
+	char_count = data_length - 1;
+	memset(buf, 0, sizeof(buf));
+	if (char_count) {
+		if (data_length > (int)sizeof(buf)) {
+			PRINTM(MERROR, "Too many arguments\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (copy_from_user(buf, wrq->u.data.pointer, data_length)) {
+			PRINTM(MERROR, "copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		if (char_count > 1 && buf[1] != ';') {
+			PRINTM(MERROR,
+			       "No action argument. Separate with ';'\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		/* Replace ';' with NULL in the string to separate args */
+		for (i = 0; i < char_count; i++) {
+			if (buf[i] == ';')
+				buf[i] = '\0';
+		}
+		/* The first byte represents the beamforming action */
+		if (woal_atoi(&bf_action, &buf[0]) != MLAN_STATUS_SUCCESS) {
+			ret = -EINVAL;
+			goto done;
+		}
+		switch (bf_action) {
+		case BF_GLOBAL_CONFIGURATION:
+			if (char_count == 1) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+				/* Eliminate action field */
+				token = &buf[2];
+				for (i = 1, str = &buf[2]; token != NULL; i++) {
+					token = strstr(str, " ");
+					pos = str;
+					if (token != NULL) {
+						*token = '\0';
+						str = token + 1;
+					}
+					woal_atoi(&tmp_val, pos);
+					switch (i) {
+					case BF_ENABLE_PARAM:
+						bf_global->bf_enbl =
+							(t_u8)tmp_val;
+						break;
+					case SOUND_ENABLE_PARAM:
+						bf_global->sounding_enbl =
+							(t_u8)tmp_val;
+						break;
+					case FB_TYPE_PARAM:
+						bf_global->fb_type =
+							(t_u8)tmp_val;
+						break;
+					case SNR_THRESHOLD_PARAM:
+						bf_global->snr_threshold =
+							(t_u8)tmp_val;
+						break;
+					case SOUND_INTVL_PARAM:
+						bf_global->sounding_interval =
+							(t_u16)tmp_val;
+						break;
+					case BF_MODE_PARAM:
+						bf_global->bf_mode =
+							(t_u8)tmp_val;
+						break;
+					default:
+						PRINTM(MERROR,
+						       "Invalid Argument\n");
+						ret = -EINVAL;
+						goto done;
+					}
+				}
+			}
+			break;
+		case TRIGGER_SOUNDING_FOR_PEER:
+			/*
+			 * First arg  = 2   BfAction
+			 * Second arg = 17  MAC "00:50:43:20:BF:64"
+			 */
+			if (char_count != 19) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			woal_mac2u8(bf_sound->peer_mac, &buf[2]);
+			action = MLAN_ACT_SET;
+			bf_cfg.action = BF_CFG_ACT_SET;
+			break;
+		case SET_GET_BF_PERIODICITY:
+			/*
+			 * First arg  = 2   BfAction
+			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
+			 * Third arg =  1  (min char)  TX BF interval
+			 *              10 (max char)  u32 maximum value
+			 * 4294967295
+			 */
+			if (char_count < 19 || char_count > 30) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+
+			woal_mac2u8(bf_periodicity->peer_mac, &buf[2]);
+			if (char_count == 19) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+				if (woal_atoi(&interval, &buf[20]) !=
+				    MLAN_STATUS_SUCCESS) {
+					ret = -EINVAL;
+					goto done;
+				}
+				bf_periodicity->interval = interval;
+			}
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			/*
+			 * Handle only SET operation here
+			 * First arg  = 2   BfAction
+			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
+			 * Third arg  = 2   enable/disable bf
+			 * Fourth arg = 2   enable/disable sounding
+			 * Fifth arg  = 1   FB Type
+			 */
+			if (char_count != 25 && char_count != 1) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (char_count == 1) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				woal_mac2u8(tx_bf_peer->peer_mac, &buf[2]);
+				woal_atoi(&tmp_val, &buf[20]);
+				tx_bf_peer->bf_enbl = (t_u8)tmp_val;
+				woal_atoi(&tmp_val, &buf[22]);
+				tx_bf_peer->sounding_enbl = (t_u8)tmp_val;
+				woal_atoi(&tmp_val, &buf[24]);
+				tx_bf_peer->fb_type = (t_u8)tmp_val;
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			/*
+			 * First arg  = 2   BfAction
+			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
+			 * Third arg  = 1/2 SNR u8 - can be 1/2 charerters
+			 */
+			if (char_count != 1 &&
+			    !(char_count == 21 || char_count == 22)) {
+				PRINTM(MERROR, "Invalid argument\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			if (char_count == 1) {
+				action = MLAN_ACT_GET;
+				bf_cfg.action = BF_CFG_ACT_GET;
+			} else {
+				woal_mac2u8(bf_snr->peer_mac, &buf[2]);
+				if (woal_atoi(&snr, &buf[20]) !=
+				    MLAN_STATUS_SUCCESS) {
+					ret = -EINVAL;
+					goto done;
+				}
+				bf_snr->snr = snr;
+				action = MLAN_ACT_SET;
+				bf_cfg.action = BF_CFG_ACT_SET;
+			}
+			break;
+		default:
+			ret = -EINVAL;
+			goto done;
+		}
+
+		/* Save the value */
+		bf_cfg.bf_action = bf_action;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_GET) {
+		data_length = 0;
+		memset(buf, 0, sizeof(buf));
+		switch (bf_action) {
+		case BF_GLOBAL_CONFIGURATION:
+			data_length += sprintf(buf + data_length, "%d ",
+					       (int)bf_global->bf_enbl);
+			data_length += sprintf(buf + data_length, "%d ",
+					       (int)bf_global->sounding_enbl);
+			data_length += sprintf(buf + data_length, "%d ",
+					       (int)bf_global->fb_type);
+			data_length += sprintf(buf + data_length, "%d ",
+					       (int)bf_global->snr_threshold);
+			data_length +=
+				sprintf(buf + data_length, "%d ",
+					(int)bf_global->sounding_interval);
+			data_length += sprintf(buf + data_length, "%d ",
+					       (int)bf_global->bf_mode);
+			break;
+		case SET_GET_BF_PERIODICITY:
+			data_length += sprintf(buf + data_length,
+					       "%02x:%02x:%02x:%02x:%02x:%02x",
+					       bf_periodicity->peer_mac[0],
+					       bf_periodicity->peer_mac[1],
+					       bf_periodicity->peer_mac[2],
+					       bf_periodicity->peer_mac[3],
+					       bf_periodicity->peer_mac[4],
+					       bf_periodicity->peer_mac[5]);
+			data_length += sprintf(buf + data_length, "%c", ' ');
+			data_length += sprintf(buf + data_length, "%d",
+					       bf_periodicity->interval);
+			break;
+		case TX_BF_FOR_PEER_ENBL:
+			for (i = 0; i < (int)bf_cfg.no_of_peers; i++) {
+				data_length +=
+					sprintf(buf + data_length,
+						"%02x:%02x:%02x:%02x:%02x:%02x",
+						tx_bf_peer->peer_mac[0],
+						tx_bf_peer->peer_mac[1],
+						tx_bf_peer->peer_mac[2],
+						tx_bf_peer->peer_mac[3],
+						tx_bf_peer->peer_mac[4],
+						tx_bf_peer->peer_mac[5]);
+				data_length +=
+					sprintf(buf + data_length, "%c", ' ');
+				data_length += sprintf(buf + data_length, "%d;",
+						       tx_bf_peer->bf_enbl);
+				data_length +=
+					sprintf(buf + data_length, "%d;",
+						tx_bf_peer->sounding_enbl);
+				data_length += sprintf(buf + data_length, "%d ",
+						       tx_bf_peer->fb_type);
+				tx_bf_peer++;
+			}
+			break;
+		case SET_SNR_THR_PEER:
+			for (i = 0; i < (int)bf_cfg.no_of_peers; i++) {
+				data_length +=
+					sprintf(buf + data_length,
+						"%02x:%02x:%02x:%02x:%02x:%02x",
+						bf_snr->peer_mac[0],
+						bf_snr->peer_mac[1],
+						bf_snr->peer_mac[2],
+						bf_snr->peer_mac[3],
+						bf_snr->peer_mac[4],
+						bf_snr->peer_mac[5]);
+				data_length +=
+					sprintf(buf + data_length, "%c", ';');
+				data_length += sprintf(buf + data_length, "%d",
+						       bf_snr->snr);
+				data_length +=
+					sprintf(buf + data_length, "%c", ' ');
+				bf_snr++;
+			}
+			break;
+		}
+		buf[data_length] = '\0';
+	}
+
+	wrq->u.data.length = data_length;
+	if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Retrieve the scan response/beacon table
+ *
+ *  @param wrq          A pointer to iwreq structure
+ *  @param scan_resp    A pointer to mlan_scan_resp structure
+ *  @param scan_start   argument
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+moal_ret_get_scan_table_ioctl(struct iwreq *wrq,
+			      mlan_scan_resp *scan_resp, t_u32 scan_start)
+{
+	pBSSDescriptor_t pbss_desc, scan_table;
+	wlan_ioctl_get_scan_table_info *prsp_info;
+	int ret_code;
+	int ret_len;
+	int space_left;
+	t_u8 *pcurrent;
+	t_u8 *pbuffer_end;
+	t_u32 num_scans_done;
+
+	ENTER();
+
+	num_scans_done = 0;
+	ret_code = MLAN_STATUS_SUCCESS;
+
+	prsp_info =
+		(wlan_ioctl_get_scan_table_info __force *)wrq->u.data.pointer;
+	pcurrent = (t_u8 *)prsp_info->scan_table_entry_buf;
+
+	pbuffer_end =
+		(t_u8 __force *)wrq->u.data.pointer + wrq->u.data.length - 1;
+	space_left = pbuffer_end - pcurrent;
+	scan_table = (BSSDescriptor_t *)(scan_resp->pscan_table);
+
+	PRINTM(MINFO, "GetScanTable: scan_start req = %d\n", scan_start);
+	PRINTM(MINFO, "GetScanTable: length avail = %d\n", wrq->u.data.length);
+
+	if (!scan_start) {
+		PRINTM(MINFO, "GetScanTable: get current BSS Descriptor\n");
+
+		/* Use to get current association saved descriptor */
+		pbss_desc = scan_table;
+
+		ret_code = wlan_get_scan_table_ret_entry(pbss_desc, &pcurrent,
+							 &space_left);
+
+		if (ret_code == MLAN_STATUS_SUCCESS)
+			num_scans_done = 1;
+	} else {
+		scan_start--;
+
+		while (space_left &&
+		       (scan_start + num_scans_done <
+			scan_resp->num_in_scan_table) &&
+		       (ret_code == MLAN_STATUS_SUCCESS)) {
+			pbss_desc =
+				(scan_table + (scan_start + num_scans_done));
+
+			PRINTM(MINFO,
+			       "GetScanTable: get current BSS Descriptor [%d]\n",
+			       scan_start + num_scans_done);
+
+			ret_code =
+				wlan_get_scan_table_ret_entry(pbss_desc,
+							      &pcurrent,
+							      &space_left);
+
+			if (ret_code == MLAN_STATUS_SUCCESS)
+				num_scans_done++;
+		}
+	}
+
+	prsp_info->scan_number = num_scans_done;
+	ret_len = pcurrent - (t_u8 __force *)wrq->u.data.pointer;
+
+	wrq->u.data.length = ret_len;
+
+	/* Return ret_code (EFAULT or E2BIG) in the case where no scan results
+	 * were successfully encoded.
+	 */
+	LEAVE();
+	return num_scans_done ? MLAN_STATUS_SUCCESS : ret_code;
+}
+
+/**
+ *  @brief Get scan table ioctl
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_get_scan_table_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_scan *scan = NULL;
+	int scan_start = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	scan = (mlan_ds_scan *)req->pbuf;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_GET;
+
+	/* get the whole command from user */
+	if (copy_from_user(&scan_start, wrq->u.data.pointer,
+			   sizeof(scan_start))) {
+		PRINTM(MERROR, "copy from user failed\n");
+		goto done;
+	}
+	if (scan_start > 0)
+		scan->sub_command = MLAN_OID_SCAN_NORMAL;
+	else
+		scan->sub_command = MLAN_OID_SCAN_GET_CURRENT_BSS;
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		status = moal_ret_get_scan_table_ioctl(wrq,
+						       &scan->param.scan_resp,
+						       scan_start);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set user scan ext -- Async mode, without wait
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 -- success, otherwise fail
+ */
+static int
+woal_set_user_scan_ext_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	wlan_user_scan_cfg scan_req;
+	ENTER();
+	memset(&scan_req, 0x00, sizeof(scan_req));
+	if (copy_from_user(&scan_req, wrq->u.data.pointer,
+			   MIN(wrq->u.data.length, sizeof(scan_req)))) {
+		PRINTM(MINFO, "Copy from user failed\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_req))
+		ret = -EFAULT;
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set user scan
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_set_user_scan_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_scan *scan = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	union iwreq_data wrqu;
+	moal_handle *handle = priv->phandle;
+
+	ENTER();
+
+	if (handle->scan_pending_on_block == MTRUE) {
+		PRINTM(MINFO, "scan already in processing...\n");
+		LEAVE();
+		return ret;
+	}
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	handle->scan_pending_on_block = MTRUE;
+	handle->scan_priv = priv;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
+					wrq->u.data.length);
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+	req->action = MLAN_ACT_SET;
+
+	if (copy_from_user(scan->param.user_scan.scan_cfg_buf,
+			   wrq->u.data.pointer, wrq->u.data.length)) {
+		PRINTM(MINFO, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		memset(&wrqu, 0, sizeof(union iwreq_data));
+		wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
+	}
+
+done:
+	handle->scan_pending_on_block = MFALSE;
+	handle->scan_priv = NULL;
+	MOAL_REL_SEMAPHORE(&handle->async_sem);
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+#ifdef SDIO
+/**
+ *  @brief Cmd52 read/write register
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_cmd52rdwr_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	t_u8 rw = 0, func, data = 0;
+	int buf[3], reg, ret = MLAN_STATUS_SUCCESS;
+	int data_length = wrq->u.data.length;
+
+	ENTER();
+
+	if (data_length < 2 || data_length > 3) {
+		PRINTM(MERROR, "Invalid number of arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (copy_from_user(buf, wrq->u.data.pointer, sizeof(int) * data_length)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	func = (t_u8)buf[0];
+	if (func > 7) {
+		PRINTM(MERROR, "Invalid function number!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	reg = (t_u32)buf[1];
+	if (data_length == 2) {
+		rw = 0;		/* CMD52 read */
+		PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
+	}
+	if (data_length == 3) {
+		rw = 1;		/* CMD52 write */
+		data = (t_u8)buf[2];
+		PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
+		       func, reg, data);
+	}
+
+	if (!rw) {
+#ifdef SDIO_MMC
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (func)
+			data = sdio_readb(((struct sdio_mmc_card *)priv->
+					   phandle->card)
+					  ->func, reg, &ret);
+		else
+			data = sdio_f0_readb(((struct sdio_mmc_card *)priv->
+					      phandle->card)
+					     ->func, reg, &ret);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		if (ret) {
+			PRINTM(MERROR,
+			       "sdio_readb: reading register 0x%X failed\n",
+			       reg);
+			goto done;
+		}
+#else
+		if (sdio_read_ioreg(priv->phandle->card, func, reg, &data) < 0) {
+			PRINTM(MERROR,
+			       "sdio_read_ioreg: reading register 0x%X failed\n",
+			       reg);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#endif
+	} else {
+#ifdef SDIO_MMC
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (func)
+			sdio_writeb(((struct sdio_mmc_card *)priv->phandle->
+				     card)
+				    ->func, data, reg, &ret);
+		else
+			sdio_f0_writeb(((struct sdio_mmc_card *)priv->phandle->
+					card)
+				       ->func, data, reg, &ret);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		if (ret) {
+			PRINTM(MERROR,
+			       "sdio_writeb: writing register 0x%X failed\n",
+			       reg);
+			goto done;
+		}
+#else
+		if (sdio_write_ioreg(priv->phandle->card, func, reg, data) < 0) {
+			PRINTM(MERROR,
+			       "sdio_write_ioreg: writing register 0x%X failed\n",
+			       reg);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#endif
+	}
+
+	buf[0] = data;
+	wrq->u.data.length = 1;
+	if (copy_to_user(wrq->u.data.pointer, buf, sizeof(int))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Cmd53 read/write register
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_cmd53rdwr_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	t_u8 *buf = NULL;
+	t_u8 rw, mode;
+	t_u16 blklen = 0, blknum = 0;
+	int reg = 0, pattern_len = 0, pos = 0, ret = MLAN_STATUS_SUCCESS;
+	t_u32 total_len = 0;
+	t_u8 *data = NULL;
+
+	ENTER();
+
+	buf = kmalloc(WOAL_2K_BYTES, GFP_KERNEL);
+	if (!buf) {
+		PRINTM(MERROR, "Cannot allocate buffer for command!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	data = kmalloc(WOAL_2K_BYTES, GFP_KERNEL);
+	if (!data) {
+		PRINTM(MERROR, "Cannot allocate buffer for command!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (wrq->u.data.length > WOAL_2K_BYTES) {
+		PRINTM(MERROR, "Data lengh is too large!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length)) {
+		PRINTM(MINFO, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	rw = buf[0];		/* read/write (0/1) */
+	reg = buf[5];		/* address */
+	reg = (reg << 8) + buf[4];
+	reg = (reg << 8) + buf[3];
+	reg = (reg << 8) + buf[2];
+	mode = buf[6];		/* byte mode/block mode (0/1) */
+	blklen = buf[8];	/* block size */
+	blklen = (blklen << 8) + buf[7];
+	blknum = buf[10];	/* block number or byte number */
+	blknum = (blknum << 8) + buf[9];
+
+	if (mode != BYTE_MODE)
+		mode = BLOCK_MODE;
+	total_len = (mode == BLOCK_MODE) ? blknum * blklen : blknum;
+	if (total_len > WOAL_2K_BYTES) {
+		PRINTM(MERROR, "Total data length is too large!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	PRINTM(MINFO,
+	       "CMD53 read/write, addr = %#x, mode = %d, block size = %d, block(byte) number = %d\n",
+	       reg, mode, blklen, blknum);
+
+	if (!rw) {
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (sdio_readsb
+		    (((struct sdio_mmc_card *)priv->phandle->card)->func, data,
+		     reg, total_len))
+			PRINTM(MERROR,
+			       "sdio_readsb: reading memory 0x%x failed\n",
+			       reg);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+
+		if (copy_to_user(wrq->u.data.pointer, data, total_len)) {
+			PRINTM(MINFO, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = total_len;
+	} else {
+		pattern_len = wrq->u.data.length - 11;
+		if (pattern_len > (int)total_len)
+			pattern_len = total_len;
+		memset(data, 0, WOAL_2K_BYTES);
+
+		/* Copy/duplicate the pattern to data buffer */
+		for (pos = 0; pos < (int)total_len; pos++)
+			data[pos] = buf[11 + (pos % pattern_len)];
+
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (sdio_writesb
+		    (((struct sdio_mmc_card *)priv->phandle->card)->func, reg,
+		     data, total_len))
+			PRINTM(MERROR,
+			       "sdio_writesb: writing memory 0x%x failed\n",
+			       reg);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+	}
+
+done:
+	kfree(buf);
+	kfree(data);
+	LEAVE();
+	return ret;
+}
+#endif /* SDIO */
+
+#ifdef SDIO
+/**
+ * @brief Set SDIO Multi-point aggregation control parameters
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0/MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static int
+woal_do_sdio_mpa_ctrl(moal_private *priv, struct iwreq *wrq)
+{
+	int data[6], data_length = wrq->u.data.length, copy_len;
+	int ret = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (sizeof(int) * wrq->u.data.length > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	memset(misc, 0, sizeof(mlan_ds_misc_cfg));
+
+	misc->sub_command = MLAN_OID_MISC_SDIO_MPA_CTRL;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	/* Get the values first, then modify these values if
+	 * user had modified them */
+
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "woal_request_ioctl returned %d\n", ret);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (data_length == 0) {
+		data[0] = misc->param.mpa_ctrl.tx_enable;
+		data[1] = misc->param.mpa_ctrl.rx_enable;
+		data[2] = misc->param.mpa_ctrl.tx_buf_size;
+		data[3] = misc->param.mpa_ctrl.rx_buf_size;
+		data[4] = misc->param.mpa_ctrl.tx_max_ports;
+		data[5] = misc->param.mpa_ctrl.rx_max_ports;
+
+		PRINTM(MINFO, "Get Param: %d %d %d %d %d %d\n", data[0],
+		       data[1], data[2], data[3], data[4], data[5]);
+
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = ARRAY_SIZE(data);
+		goto done;
+	}
+
+	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+		PRINTM(MINFO, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	switch (data_length) {
+	case 6:
+		misc->param.mpa_ctrl.rx_max_ports = data[5];
+		/* fall through */
+	case 5:
+		misc->param.mpa_ctrl.tx_max_ports = data[4];
+		/* fall through */
+	case 4:
+		misc->param.mpa_ctrl.rx_buf_size = data[3];
+		/* fall through */
+	case 3:
+		misc->param.mpa_ctrl.tx_buf_size = data[2];
+		/* fall through */
+	case 2:
+		misc->param.mpa_ctrl.rx_enable = data[1];
+		/* fall through */
+	case 1:
+		/* Set cmd */
+		req->action = MLAN_ACT_SET;
+
+		PRINTM(MINFO, "Set Param: %d %d %d %d %d %d\n", data[0],
+		       data[1], data[2], data[3], data[4], data[5]);
+
+		misc->param.mpa_ctrl.tx_enable = data[0];
+		break;
+	default:
+		PRINTM(MERROR, "Default case error\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "woal_request_ioctl returned %d\n", ret);
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Set/Get scan configuration parameters
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_set_get_scan_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	int data[7], copy_len;
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int arg_len = 0;
+
+	ENTER();
+	arg_len = 7;
+	if (data_length > arg_len) {
+		PRINTM(MERROR, "Too much arguments\n");
+		LEAVE();
+		return -EINVAL;
+	}
+	copy_len = sizeof(int) * data_length;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+	memset(data, 0, sizeof(data));
+
+	if (data_length) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((data[0] < 0) || (data[0] > MLAN_SCAN_TYPE_PASSIVE)) {
+			PRINTM(MERROR, "Invalid argument for scan type\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[1] < 0) || (data[1] > MLAN_SCAN_MODE_ANY)) {
+			PRINTM(MERROR, "Invalid argument for scan mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[2] < 0) || (data[2] > MAX_PROBES)) {
+			PRINTM(MERROR, "Invalid argument for scan probes\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (((data[3] < 0) ||
+		     (data[3] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME)) ||
+		    ((data[4] < 0) ||
+		     (data[4] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME)) ||
+		    ((data[5] < 0) ||
+		     (data[5] > MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME))) {
+			PRINTM(MERROR, "Invalid argument for scan time\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[6] < 0) || (data[6] > 1)) {
+			PRINTM(MERROR, "Invalid argument for extended scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, data,
+				sizeof(data), sizeof(scan->param.scan_cfg));
+	} else
+		req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!data_length) {
+		moal_memcpy_ext(priv->phandle, data, &scan->param.scan_cfg,
+				sizeof(scan->param.scan_cfg), sizeof(data));
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = arg_len;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get PS configuration parameters
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_set_get_ps_cfg(moal_private *priv, struct iwreq *wrq)
+{
+	int data[7], copy_len, ret = 0;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	int allowed = 3;
+	int i = 3;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	allowed++;		/* For beacon missing timeout parameter */
+	allowed += 2;		/* For delay to PS and PS mode parameters */
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (data_length > allowed) {
+		ret = -EINVAL;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_CFG;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+	memset(data, 0, sizeof(data));
+
+	if (data_length) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((data[0] < PS_NULL_DISABLE)) {
+			PRINTM(MERROR,
+			       "Invalid argument for PS null interval\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((data[1] != MRVDRV_IGNORE_MULTIPLE_DTIM) &&
+		    (data[1] != MRVDRV_MATCH_CLOSEST_DTIM) &&
+		    ((data[1] < MRVDRV_MIN_MULTIPLE_DTIM) ||
+		     (data[1] > MRVDRV_MAX_MULTIPLE_DTIM))) {
+			PRINTM(MERROR, "Invalid argument for multiple DTIM\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		if ((data[2] < MRVDRV_MIN_LISTEN_INTERVAL) &&
+		    (data[2] != MRVDRV_LISTEN_INTERVAL_DISABLE)) {
+			PRINTM(MERROR,
+			       "Invalid argument for listen interval\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		if ((data[i] != DISABLE_BCN_MISS_TO) &&
+		    ((data[i] < MIN_BCN_MISS_TO) ||
+		     (data[i] > MAX_BCN_MISS_TO))) {
+			PRINTM(MERROR,
+			       "Invalid argument for beacon miss timeout\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		if (data_length < allowed - 1)
+			data[i] = DELAY_TO_PS_UNCHANGED;
+		else if ((data[i] < MIN_DELAY_TO_PS) ||
+			 (data[i] > MAX_DELAY_TO_PS)) {
+			PRINTM(MERROR, "Invalid argument for delay to PS\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		if ((data[i] != PS_MODE_UNCHANGED) &&
+		    (data[i] != PS_MODE_AUTO) && (data[i] != PS_MODE_POLL) &&
+		    (data[i] != PS_MODE_NULL)) {
+			PRINTM(MERROR, "Invalid argument for PS mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		i++;
+		req->action = MLAN_ACT_SET;
+		moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_cfg, data,
+				sizeof(data), sizeof(pm_cfg->param.ps_cfg));
+	} else
+		req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, data, &pm_cfg->param.ps_cfg,
+			MIN((sizeof(int) * allowed),
+			    sizeof(pm_cfg->param.ps_cfg)), sizeof(data));
+	if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * allowed)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = allowed;
+
+	if (req->action == MLAN_ACT_SET) {
+		pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+		pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
+		pm_cfg->param.ps_mode = 1;
+		req->req_id = MLAN_IOCTL_PM_CFG;
+		req->action = MLAN_ACT_SET;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to send an ADDTS TSPEC
+ *
+ *  Receive a ADDTS command from the application.  The command structure
+ *    contains a TSPEC and timeout in milliseconds.  The timeout is performed
+ *    in the firmware after the ADDTS command frame is sent.
+ *
+ *  The TSPEC is received in the API as an opaque block. The firmware will
+ *    send the entire data block, including the bytes after the TSPEC.  This
+ *    is done to allow extra IEs to be packaged with the TSPEC in the ADDTS
+ *    action frame.
+ *
+ *  The IOCTL structure contains two return fields:
+ *    - The firmware command result, which indicates failure and timeouts
+ *    - The IEEE Status code which contains the corresponding value from
+ *      any ADDTS response frame received.
+ *
+ *  In addition, the opaque TSPEC data block passed in is replaced with the
+ *    TSPEC received in the ADDTS response frame.  In case of failure, the
+ *    AP may modify the TSPEC on return and in the case of success, the
+ *    medium time is returned as calculated by the AP.  Along with the TSPEC,
+ *    any IEs that are sent in the ADDTS response are also returned and can be
+ *    parsed using the IOCTL length as an indicator of extra elements.
+ *
+ *  The return value to the application layer indicates a driver execution
+ *    success or failure.  A successful return could still indicate a firmware
+ *    failure or AP negotiation failure via the commandResult field copied
+ *    back to the application.
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the
+ *                 wlan_ioctl_wmm_addts_req_t struct for this ADDTS request
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_wmm_addts_req_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *cfg = NULL;
+	wlan_ioctl_wmm_addts_req_t addts_ioctl;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_WMM_CFG_ADDTS;
+
+	memset(&addts_ioctl, 0x00, sizeof(addts_ioctl));
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&addts_ioctl, wrq->u.data.pointer,
+				   MIN(wrq->u.data.length,
+				       sizeof(addts_ioctl)))) {
+			PRINTM(MERROR, "TSPEC: ADDTS copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		cfg->param.addts.timeout = addts_ioctl.timeout_ms;
+		cfg->param.addts.ie_data_len = addts_ioctl.ie_data_len;
+
+		if (cfg->param.addts.ie_data_len >
+		    sizeof(cfg->param.addts.ie_data)) {
+			PRINTM(MERROR, "IE data length too large\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		moal_memcpy_ext(priv->phandle, cfg->param.addts.ie_data,
+				addts_ioctl.ie_data,
+				cfg->param.addts.ie_data_len,
+				sizeof(cfg->param.addts.ie_data));
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		addts_ioctl.cmd_result = cfg->param.addts.result;
+		addts_ioctl.ieee_status_code =
+			(t_u8)cfg->param.addts.status_code;
+		addts_ioctl.ie_data_len = cfg->param.addts.ie_data_len;
+
+		moal_memcpy_ext(priv->phandle, addts_ioctl.ie_data,
+				cfg->param.addts.ie_data,
+				cfg->param.addts.ie_data_len,
+				sizeof(addts_ioctl.ie_data));
+
+		wrq->u.data.length =
+			(sizeof(addts_ioctl) - sizeof(addts_ioctl.ie_data) +
+			 cfg->param.addts.ie_data_len);
+
+		if (copy_to_user(wrq->u.data.pointer, &addts_ioctl,
+				 wrq->u.data.length)) {
+			PRINTM(MERROR, "TSPEC: ADDTS copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to send a DELTS TSPEC
+ *
+ *  Receive a DELTS command from the application.  The command structure
+ *    contains a TSPEC and reason code along with space for a command result
+ *    to be returned.  The information is packaged is sent to the wlan_cmd.c
+ *    firmware command prep and send routines for execution in the firmware.
+ *
+ *  The reason code is not used for WMM implementations but is indicated in
+ *    the 802.11e specification.
+ *
+ *  The return value to the application layer indicates a driver execution
+ *    success or failure.  A successful return could still indicate a firmware
+ *    failure via the cmd_result field copied back to the application.
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the
+ *                 wlan_ioctl_wmm_delts_req_t struct for this DELTS request
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_wmm_delts_req_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *cfg = NULL;
+	wlan_ioctl_wmm_delts_req_t delts_ioctl;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
+	cfg->sub_command = MLAN_OID_WMM_CFG_DELTS;
+
+	memset(&delts_ioctl, 0x00, sizeof(delts_ioctl));
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&delts_ioctl, wrq->u.data.pointer,
+				   MIN(wrq->u.data.length,
+				       sizeof(delts_ioctl)))) {
+			PRINTM(MERROR, "TSPEC: DELTS copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		cfg->param.delts.status_code =
+			(t_u32)delts_ioctl.ieee_reason_code;
+		cfg->param.delts.ie_data_len = (t_u8)delts_ioctl.ie_data_len;
+
+		if ((cfg->param.delts.ie_data_len) >
+		    sizeof(cfg->param.delts.ie_data)) {
+			PRINTM(MERROR, "IE data length too large\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		moal_memcpy_ext(priv->phandle, cfg->param.delts.ie_data,
+				delts_ioctl.ie_data,
+				cfg->param.delts.ie_data_len,
+				sizeof(cfg->param.delts.ie_data));
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		/* Return the firmware command result back to the application
+		 * layer */
+		delts_ioctl.cmd_result = cfg->param.delts.result;
+		wrq->u.data.length = sizeof(delts_ioctl);
+
+		if (copy_to_user(wrq->u.data.pointer, &delts_ioctl,
+				 wrq->u.data.length)) {
+			PRINTM(MERROR, "TSPEC: DELTS copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get/set a specified AC Queue's parameters
+ *
+ *  Receive a AC Queue configuration command which is used to get, set, or
+ *    default the parameters associated with a specific WMM AC Queue.
+ *
+ *  @param priv    Pointer to the mlan_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the
+ *                 wlan_ioctl_wmm_queue_config_t struct
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_wmm_queue_config_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	mlan_ds_wmm_queue_config *pqcfg = NULL;
+	wlan_ioctl_wmm_queue_config_t qcfg_ioctl;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_CONFIG;
+
+	memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl));
+	pqcfg = (mlan_ds_wmm_queue_config *)&pwmm->param.q_cfg;
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&qcfg_ioctl, wrq->u.data.pointer,
+				   MIN(wrq->u.data.length,
+				       sizeof(qcfg_ioctl)))) {
+			PRINTM(MERROR, "QCONFIG: copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		pqcfg->action = qcfg_ioctl.action;
+		pqcfg->access_category = qcfg_ioctl.access_category;
+		pqcfg->msdu_lifetime_expiry = qcfg_ioctl.msdu_lifetime_expiry;
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl));
+		qcfg_ioctl.action = pqcfg->action;
+		qcfg_ioctl.access_category = pqcfg->access_category;
+		qcfg_ioctl.msdu_lifetime_expiry = pqcfg->msdu_lifetime_expiry;
+		wrq->u.data.length = sizeof(qcfg_ioctl);
+
+		if (copy_to_user(wrq->u.data.pointer, &qcfg_ioctl,
+				 wrq->u.data.length)) {
+			PRINTM(MERROR, "QCONFIG: copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get and start/stop queue stats on a WMM AC
+ *
+ *  Receive a AC Queue statistics command from the application for a specific
+ *    WMM AC.  The command can:
+ *         - Turn stats on
+ *         - Turn stats off
+ *         - Collect and clear the stats
+ *
+ *  @param priv    Pointer to the moal_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the
+ *                 wlan_ioctl_wmm_queue_stats_t struct
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_wmm_queue_stats_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	mlan_ds_wmm_queue_stats *pqstats = NULL;
+	wlan_ioctl_wmm_queue_stats_t qstats_ioctl;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_STATS;
+
+	memset(&qstats_ioctl, 0x00, sizeof(qstats_ioctl));
+	pqstats = (mlan_ds_wmm_queue_stats *)&pwmm->param.q_stats;
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&qstats_ioctl, wrq->u.data.pointer,
+				   MIN(wrq->u.data.length,
+				       sizeof(qstats_ioctl)))) {
+			PRINTM(MERROR, "QSTATS: copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		moal_memcpy_ext(priv->phandle, (void *)pqstats,
+				(void *)&qstats_ioctl, sizeof(qstats_ioctl),
+				sizeof(qstats_ioctl));
+		PRINTM(MINFO, "QSTATS: IOCTL [%d,%d]\n", qstats_ioctl.action,
+		       qstats_ioctl.user_priority);
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memset(&qstats_ioctl, 0x00, sizeof(qstats_ioctl));
+		moal_memcpy_ext(priv->phandle, (void *)&qstats_ioctl,
+				(void *)pqstats, sizeof(qstats_ioctl),
+				sizeof(qstats_ioctl));
+		wrq->u.data.length = sizeof(qstats_ioctl);
+
+		if (copy_to_user(wrq->u.data.pointer, &qstats_ioctl,
+				 wrq->u.data.length)) {
+			PRINTM(MERROR, "QSTATS: copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get the status of the WMM queues
+ *
+ *  Return the following information for each WMM AC:
+ *        - WMM IE Acm Required
+ *        - Firmware Flow Required
+ *        - Firmware Flow Established
+ *        - Firmware Queue Enabled
+ *        - Firmware Delivery Enabled
+ *        - Firmware Trigger Enabled
+ *
+ *  @param priv    Pointer to the moal_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the
+ *                 wlan_ioctl_wmm_queue_status_t struct for request
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_wmm_queue_status_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	wlan_ioctl_wmm_queue_status_t qstatus_ioctl;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_STATUS;
+
+	if (wrq->u.data.length == sizeof(qstatus_ioctl)) {
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memset(&qstatus_ioctl, 0x00, sizeof(qstatus_ioctl));
+		moal_memcpy_ext(priv->phandle, (void *)&qstatus_ioctl,
+				(void *)&pwmm->param.q_status,
+				sizeof(qstatus_ioctl), sizeof(qstatus_ioctl));
+		wrq->u.data.length = sizeof(qstatus_ioctl);
+	} else {
+		wrq->u.data.length = 0;
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, &qstatus_ioctl,
+			 wrq->u.data.length)) {
+		PRINTM(MERROR, "QSTATUS: copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get the status of the WMM Traffic Streams
+ *
+ *  @param priv    Pointer to the moal_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the
+ *                 wlan_ioctl_wmm_ts_status_t struct for request
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_wmm_ts_status_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_wmm_cfg *pwmm = NULL;
+	wlan_ioctl_wmm_ts_status_t ts_status_ioctl;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_WMM_CFG;
+	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
+	pwmm->sub_command = MLAN_OID_WMM_CFG_TS_STATUS;
+
+	memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl));
+
+	if (wrq->u.data.length == sizeof(ts_status_ioctl)) {
+		if (copy_from_user(&ts_status_ioctl, wrq->u.data.pointer,
+				   MIN(wrq->u.data.length,
+				       sizeof(ts_status_ioctl)))) {
+			PRINTM(MERROR, "TS_STATUS: copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memset(&pwmm->param.ts_status, 0x00, sizeof(ts_status_ioctl));
+		pwmm->param.ts_status.tid = ts_status_ioctl.tid;
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl));
+		moal_memcpy_ext(priv->phandle, (void *)&ts_status_ioctl,
+				(void *)&pwmm->param.ts_status,
+				sizeof(ts_status_ioctl),
+				sizeof(ts_status_ioctl));
+		wrq->u.data.length = sizeof(ts_status_ioctl);
+	} else {
+		wrq->u.data.length = 0;
+	}
+
+	if (copy_to_user(wrq->u.data.pointer, &ts_status_ioctl,
+			 wrq->u.data.length)) {
+		PRINTM(MERROR, "TS_STATUS: copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Private IOCTL entry to get the By-passed TX packet from upper layer
+ *
+ *  @param priv    Pointer to the moal_private driver data struct
+ *  @param wrq     A pointer to iwreq structure containing the packet
+ *
+ *  @return        0 if successful; IOCTL error code otherwise
+ */
+static int
+woal_bypassed_packet_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	struct sk_buff *skb = NULL;
+	struct ethhdr *eth;
+	t_u16 moreLen = 0, copyLen = 0;
+	ENTER();
+
+#define MLAN_BYPASS_PKT_EXTRA_OFFSET (4)
+
+	copyLen = wrq->u.data.length;
+	moreLen = MLAN_MIN_DATA_HEADER_LEN + MLAN_BYPASS_PKT_EXTRA_OFFSET +
+		sizeof(mlan_buffer);
+
+	skb = alloc_skb(copyLen + moreLen, GFP_KERNEL);
+	if (skb == NULL) {
+		PRINTM(MERROR, "kmalloc no memory !!\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, moreLen);
+
+	if (copy_from_user(skb_put(skb, copyLen), wrq->u.data.pointer, copyLen)) {
+		PRINTM(MERROR, "PortBlock: copy from user failed\n");
+		dev_kfree_skb_any(skb);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	eth = (struct ethhdr *)skb->data;
+	eth->h_proto = __constant_htons(eth->h_proto);
+	skb->dev = priv->netdev;
+
+	HEXDUMP("Bypass TX Data", skb->data, MIN(skb->len, 100));
+
+	woal_hard_start_xmit(skb, priv->netdev);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get auth type
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_auth_type(moal_private *priv, struct iwreq *wrq)
+{
+	int auth_type;
+	t_u32 auth_mode;
+	int ret = 0;
+
+	ENTER();
+	if (wrq->u.data.length == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		auth_type = auth_mode;
+		if (copy_to_user(wrq->u.data.pointer, &auth_type,
+				 sizeof(auth_type))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	} else {
+		if (copy_from_user(&auth_type, wrq->u.data.pointer,
+				   sizeof(auth_type))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		PRINTM(MINFO, "SET: auth_type %d\n", auth_type);
+		if (((auth_type < MLAN_AUTH_MODE_OPEN) ||
+		     (auth_type > MLAN_AUTH_MODE_SHARED)) &&
+		    (auth_type != MLAN_AUTH_MODE_AUTO)) {
+			ret = -EINVAL;
+			goto done;
+		}
+		auth_mode = auth_type;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Port Control mode
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_port_ctrl(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+
+	if (wrq->u.data.length) {
+		if (copy_from_user(&sec->param.port_ctrl_enabled,
+				   wrq->u.data.pointer, sizeof(int)) != 0) {
+			PRINTM(MERROR, "port_ctrl:Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+	} else {
+		req->action = MLAN_ACT_GET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!wrq->u.data.length) {
+		if (copy_to_user(wrq->u.data.pointer,
+				 &sec->param.port_ctrl_enabled, sizeof(int))) {
+			PRINTM(MERROR, "port_ctrl:Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 1;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get DFS Testing settings
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_dfs_testing(moal_private *priv, struct iwreq *wrq)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+	int ret = 0;
+	int data[4], copy_len;
+	int data_length = wrq->u.data.length;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+	ds_11hcfg->sub_command = MLAN_OID_11H_DFS_TESTING;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+
+	if (!data_length) {
+		req->action = MLAN_ACT_GET;
+	} else if (data_length == 4) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((unsigned)data[0] > 1800) {
+			PRINTM(MERROR, "The maximum user CAC is 1800 sec.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[1] > 0xFFFF) {
+			PRINTM(MERROR, "The maximum user NOP is 65535 sec.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((unsigned)data[3] > 0xFF) {
+			PRINTM(MERROR,
+			       "The maximum user fixed channel is 255.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		ds_11hcfg->param.dfs_testing.usr_cac_period_msec =
+			(t_u16)data[0];
+		ds_11hcfg->param.dfs_testing.usr_nop_period_sec =
+			(t_u16)data[1];
+		ds_11hcfg->param.dfs_testing.usr_no_chan_change =
+			data[2] ? 1 : 0;
+		ds_11hcfg->param.dfs_testing.usr_fixed_new_chan = (t_u8)data[3];
+		priv->phandle->cac_period_jiffies = (t_u16)data[0] * HZ;
+		req->action = MLAN_ACT_SET;
+	} else {
+		PRINTM(MERROR, "Invalid number of args!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!data_length) {
+		data[0] = ds_11hcfg->param.dfs_testing.usr_cac_period_msec;
+		data[1] = ds_11hcfg->param.dfs_testing.usr_nop_period_sec;
+		data[2] = ds_11hcfg->param.dfs_testing.usr_no_chan_change;
+		data[3] = ds_11hcfg->param.dfs_testing.usr_fixed_new_chan;
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int) * 4)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = 4;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Mgmt Frame passthru mask
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 -- success, otherwise fail
+ */
+static int
+woal_mgmt_frame_passthru_ctrl(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data_length = wrq->u.data.length;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *mgmt_cfg = NULL;
+	int mask = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (data_length > 1) {
+		PRINTM(MERROR, "Invalid no of arguments!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	mgmt_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	mgmt_cfg->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
+
+	if (data_length) {	/* SET */
+		if (copy_from_user(&mask, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(MERROR, "copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		mgmt_cfg->param.mgmt_subtype_mask = mask;
+		req->action = MLAN_ACT_SET;
+	} else {
+		req->action = MLAN_ACT_GET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	mask = mgmt_cfg->param.mgmt_subtype_mask;
+	if (copy_to_user(wrq->u.data.pointer, &mask, sizeof(int))) {
+		ret = -EFAULT;
+		goto done;
+	}
+	wrq->u.data.length = 1;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get CFP table codes
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param wrq      A pointer to iwreq structure
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_cfp_code(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	int data[2], copy_len;
+	int data_length = wrq->u.data.length;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_ds_misc_cfp_code *cfp_code = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (data_length > 2) {
+		PRINTM(MERROR, "Invalid number of argument!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	cfp_code = &misc_cfg->param.cfp_code;
+	misc_cfg->sub_command = MLAN_OID_MISC_CFP_CODE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (!data_length) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		cfp_code->cfp_code_bg = data[0];
+		if (data_length == 2)
+			cfp_code->cfp_code_a = data[1];
+		req->action = MLAN_ACT_SET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!data_length) {
+		data[0] = cfp_code->cfp_code_bg;
+		data[1] = cfp_code->cfp_code_a;
+		data_length = 2;
+		if (copy_to_user(wrq->u.data.pointer, &data,
+				 sizeof(int) * data_length)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		wrq->u.data.length = data_length;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get Tx/Rx antenna
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int
+woal_set_get_tx_rx_ant(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *req = NULL;
+	int data[3] = { 0 };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int copy_len;
+
+	ENTER();
+
+	if (wrq->u.data.length > 2) {
+		PRINTM(MERROR, "Invalid number of argument!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (wrq->u.data.length * sizeof(int) > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	copy_len = MIN(sizeof(data), wrq->u.data.length * sizeof(int));
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	if (wrq->u.data.length) {
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+
+		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+			radio->param.ant_cfg.tx_antenna = data[0];
+			radio->param.ant_cfg.rx_antenna = data[0];
+			if (wrq->u.data.length == 2)
+				radio->param.ant_cfg.rx_antenna = data[1];
+		} else {
+			radio->param.ant_cfg_1x1.antenna = data[0];
+			if (wrq->u.data.length == 2)
+				radio->param.ant_cfg_1x1.evaluate_time =
+					data[1];
+		}
+		req->action = MLAN_ACT_SET;
+	} else
+		req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!wrq->u.data.length) {
+		wrq->u.data.length = 1;
+		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
+			data[0] = radio->param.ant_cfg.tx_antenna;
+			data[1] = radio->param.ant_cfg.rx_antenna;
+			if (data[0] && data[1] && (data[0] != data[1]))
+				wrq->u.data.length = 2;
+		} else {
+			data[0] = (int)radio->param.ant_cfg_1x1.antenna;
+			data[1] = (int)radio->param.ant_cfg_1x1.evaluate_time;
+			data[2] = (int)radio->param.ant_cfg_1x1.current_antenna;
+			if (data[0] == 0xffff && data[2] > 0)
+				wrq->u.data.length = 3;
+			else if (data[0] == 0xffff)
+				wrq->u.data.length = 2;
+		}
+		if (copy_to_user(wrq->u.data.pointer, data,
+				 wrq->u.data.length * sizeof(int))) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Configure gpio independent reset
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param req          A pointer to ifreq structure
+ *
+ * @return             0 --success, otherwise fail
+ */
+static int
+woal_ind_rst_ioctl(moal_private *priv, struct iwreq *wrq)
+{
+	int data[2], data_length = wrq->u.data.length, copy_len;
+	int ret = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (sizeof(int) * wrq->u.data.length > sizeof(data)) {
+		PRINTM(MERROR, "Too many arguments\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	memset(misc, 0, sizeof(mlan_ds_misc_cfg));
+
+	misc->sub_command = MLAN_OID_MISC_IND_RST_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (data_length == 0) {
+		req->action = MLAN_ACT_GET;
+	} else if ((data_length == 1) || (data_length == 2)) {
+		req->action = MLAN_ACT_SET;
+
+		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
+			/* copy_from_user failed  */
+			PRINTM(MERROR, "S_PARAMS: copy from user failed\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		/* ir_mode */
+		if (data[0] < 0 || data[0] > 2) {
+			PRINTM(MERROR, "Invalid ir mode parameter (0/1/2)!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.ind_rst_cfg.ir_mode = data[0];
+
+		/* gpio_pin */
+		if (data_length == 2) {
+			if ((data[1] != 0xFF) && (data[1] < 0)) {
+				PRINTM(MERROR, "Invalid gpio pin no !\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			misc->param.ind_rst_cfg.gpio_pin = data[1];
+		}
+
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = misc->param.ind_rst_cfg.ir_mode;
+	data[1] = misc->param.ind_rst_cfg.gpio_pin;
+	wrq->u.data.length = 2;
+
+	if (copy_to_user(wrq->u.data.pointer, data,
+			 sizeof(int) * wrq->u.data.length)) {
+		PRINTM(MERROR, "QCONFIG: copy to user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+			Global Functions
+********************************************************/
+/**
+ *  @brief ioctl function - entry point
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @param cmd      Command
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iwreq *wrq = (struct iwreq *)req;
+	int ret = 0;
+
+	if (!IS_STA_WEXT(priv->phandle->params.cfg80211_wext))
+		return -EOPNOTSUPP;
+
+	ENTER();
+
+	PRINTM(MINFO, "woal_wext_do_ioctl: ioctl cmd = 0x%x\n", cmd);
+	switch (cmd) {
+	case WOAL_SETONEINT_GETWORDCHAR:
+		switch (wrq->u.data.flags) {
+		case WOAL_VERSION:	/* Get driver version */
+			ret = woal_get_driver_version(priv, req);
+			break;
+		case WOAL_VEREXT:	/* Get extended driver version */
+			ret = woal_get_driver_verext(priv, req);
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		break;
+	case WOAL_SETNONE_GETNONE:
+		switch (wrq->u.data.flags) {
+		case WOAL_WARMRESET:
+			ret = woal_warm_reset(priv);
+			break;
+#ifdef USB
+#ifdef CONFIG_USB_SUSPEND
+		case WOAL_USB_SUSPEND:
+			ret = woal_enter_usb_suspend(priv->phandle);
+			break;
+		case WOAL_USB_RESUME:
+			ret = woal_exit_usb_suspend(priv->phandle);
+			break;
+#endif /* CONFIG_USB_SUSPEND */
+#endif
+		case WOAL_11D_CLR_CHAN_TABLE:
+			ret = woal_11d_clr_chan_table(priv, wrq);
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		break;
+	case WOAL_SETONEINT_GETONEINT:
+		switch (wrq->u.data.flags) {
+		case WOAL_SET_GET_TXRATE:
+			ret = woal_set_get_txrate(priv, wrq);
+			break;
+		case WOAL_SET_GET_REGIONCODE:
+			ret = woal_set_get_regioncode(priv, wrq);
+			break;
+		case WOAL_SET_RADIO:
+			ret = woal_set_get_radio(priv, wrq);
+			break;
+		case WOAL_WMM_ENABLE:
+			ret = woal_wmm_enable_ioctl(priv, wrq);
+			break;
+		case WOAL_11D_ENABLE:
+			ret = woal_11d_enable_ioctl(priv, wrq);
+			break;
+		case WOAL_SET_GET_QOS_CFG:
+			ret = woal_set_get_qos_cfg(priv, wrq);
+			break;
+#if defined(REASSOCIATION)
+		case WOAL_SET_GET_REASSOC:
+			ret = woal_set_get_reassoc(priv, wrq);
+			break;
+#endif /* REASSOCIATION */
+		case WOAL_TXBUF_CFG:
+			ret = woal_txbuf_cfg(priv, wrq);
+			break;
+#ifndef OPCHAN
+		case WOAL_SET_GET_WWS_CFG:
+			ret = woal_wws_cfg(priv, wrq);
+			break;
+#endif
+		case WOAL_SLEEP_PD:
+			ret = woal_sleep_pd(priv, wrq);
+			break;
+		case WOAL_AUTH_TYPE:
+			ret = woal_auth_type(priv, wrq);
+			break;
+		case WOAL_PORT_CTRL:
+			ret = woal_port_ctrl(priv, wrq);
+			break;
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		case WOAL_SET_GET_BSS_ROLE:
+			ret = woal_set_get_bss_role(priv, wrq);
+			break;
+#endif
+#endif
+		case WOAL_SET_GET_11H_LOCAL_PWR_CONSTRAINT:
+			ret = woal_set_get_11h_local_pwr_constraint(priv, wrq);
+			break;
+		case WOAL_HT_STREAM_CFG:
+			ret = woal_ht_stream_cfg_ioctl(priv, wrq);
+			break;
+		case WOAL_MAC_CONTROL:
+			ret = woal_mac_control_ioctl(priv, wrq);
+			break;
+		case WOAL_THERMAL:
+			ret = woal_thermal_ioctl(priv, wrq);
+			break;
+		case WOAL_CFG_HOTSPOT:
+			ret = woal_cfg_hotspot(priv, wrq);
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		break;
+
+	case WOAL_SET_GET_SIXTEEN_INT:
+		switch ((int)wrq->u.data.flags) {
+		case WOAL_TX_POWERCFG:
+			ret = woal_tx_power_cfg(priv, wrq);
+			break;
+#ifdef DEBUG_LEVEL1
+		case WOAL_DRV_DBG:
+			ret = woal_drv_dbg(priv, wrq);
+			break;
+#endif
+		case WOAL_BEACON_INTERVAL:
+			ret = woal_beacon_interval(priv, wrq);
+			break;
+		case WOAL_SIGNAL:
+			ret = woal_get_signal(priv, wrq);
+			break;
+		case WOAL_DEEP_SLEEP:
+			ret = woal_deep_sleep_ioctl(priv, wrq);
+			break;
+		case WOAL_11N_TX_CFG:
+			ret = woal_11n_tx_cfg(priv, wrq);
+			break;
+		case WOAL_11N_AMSDU_AGGR_CTRL:
+			ret = woal_11n_amsdu_aggr_ctrl(priv, wrq);
+			break;
+		case WOAL_11N_HTCAP_CFG:
+			ret = woal_11n_htcap_cfg(priv, wrq);
+			break;
+		case WOAL_PRIO_TBL:
+			ret = woal_11n_prio_tbl(priv, wrq);
+			break;
+		case WOAL_ADDBA_UPDT:
+			ret = woal_addba_para_updt(priv, wrq);
+			break;
+		case WOAL_ADDBA_REJECT:
+			ret = woal_addba_reject(priv, wrq);
+			break;
+		case WOAL_TX_BF_CAP:
+			ret = woal_tx_bf_cap_ioctl(priv, wrq);
+			break;
+		case WOAL_HS_CFG:
+			ret = woal_hs_cfg(priv, wrq, MTRUE);
+			break;
+		case WOAL_HS_SETPARA:
+			ret = woal_hs_setpara(priv, wrq);
+			break;
+		case WOAL_REG_READ_WRITE:
+			ret = woal_reg_read_write(priv, wrq);
+			break;
+		case WOAL_INACTIVITY_TIMEOUT_EXT:
+			ret = woal_inactivity_timeout_ext(priv, wrq);
+			break;
+#ifdef SDIO
+		case WOAL_SDIO_CLOCK:
+			ret = woal_sdio_clock_ioctl(priv, wrq);
+			break;
+		case WOAL_CMD_52RDWR:
+			ret = woal_cmd52rdwr_ioctl(priv, wrq);
+			break;
+		case WOAL_SDIO_MPA_CTRL:
+			ret = woal_do_sdio_mpa_ctrl(priv, wrq);
+			break;
+#endif
+		case WOAL_BAND_CFG:
+			ret = woal_band_cfg(priv, wrq);
+			break;
+		case WOAL_SCAN_CFG:
+			ret = woal_set_get_scan_cfg(priv, wrq);
+			break;
+		case WOAL_PS_CFG:
+			ret = woal_set_get_ps_cfg(priv, wrq);
+			break;
+		case WOAL_MEM_READ_WRITE:
+			ret = woal_mem_read_write(priv, wrq);
+			break;
+		case WOAL_SLEEP_PARAMS:
+			ret = woal_sleep_params_ioctl(priv, wrq);
+			break;
+		case WOAL_DFS_TESTING:
+			ret = woal_dfs_testing(priv, wrq);
+			break;
+		case WOAL_MGMT_FRAME_CTRL:
+			ret = woal_mgmt_frame_passthru_ctrl(priv, wrq);
+			break;
+		case WOAL_CFP_CODE:
+			ret = woal_cfp_code(priv, wrq);
+			break;
+		case WOAL_SET_GET_TX_RX_ANT:
+			ret = woal_set_get_tx_rx_ant(priv, wrq);
+			break;
+		case WOAL_IND_RST_CFG:
+			ret = woal_ind_rst_ioctl(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+
+	case WOALGETLOG:
+		ret = woal_get_log(priv, wrq);
+		break;
+
+	case WOAL_SET_GET_256_CHAR:
+		switch (wrq->u.data.flags) {
+		case WOAL_PASSPHRASE:
+			ret = woal_passphrase(priv, wrq);
+			break;
+		case WOAL_GET_KEY:
+			ret = woal_get_key_ioctl(priv, wrq);
+			break;
+		case WOAL_ASSOCIATE:
+			ret = woal_associate_ssid_bssid(priv, wrq);
+			break;
+		case WOAL_WMM_QUEUE_STATUS:
+			ret = woal_wmm_queue_status_ioctl(priv, wrq);
+			break;
+
+		case WOAL_WMM_TS_STATUS:
+			ret = woal_wmm_ts_status_ioctl(priv, wrq);
+			break;
+		case WOAL_IP_ADDRESS:
+			ret = woal_set_get_ip_addr(priv, wrq);
+			break;
+		case WOAL_TX_BF_CFG:
+			ret = woal_tx_bf_cfg_ioctl(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+
+	case WOAL_SETADDR_GETNONE:
+		switch ((int)wrq->u.data.flags) {
+		case WOAL_DEAUTH:
+			ret = woal_deauth(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+
+	case WOAL_SETNONE_GETTWELVE_CHAR:
+		/*
+		 * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
+		 * in flags of iwreq structure, otherwise it will be in
+		 * mode member of iwreq structure.
+		 */
+		switch ((int)wrq->u.data.flags) {
+		case WOAL_WPS_SESSION:
+			ret = woal_wps_cfg_ioctl(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	case WOAL_SETNONE_GET_FOUR_INT:
+		switch ((int)wrq->u.data.flags) {
+		case WOAL_DATA_RATE:
+			ret = woal_get_txrx_rate(priv, wrq);
+			break;
+		case WOAL_ESUPP_MODE:
+			ret = woal_get_esupp_mode(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+
+	case WOAL_SET_GET_64_INT:
+		switch ((int)wrq->u.data.flags) {
+		case WOAL_ECL_SYS_CLOCK:
+			ret = woal_ecl_sys_clock(priv, wrq);
+			break;
+		}
+
+		break;
+
+	case WOAL_HOST_CMD:
+		ret = woal_host_command(priv, wrq);
+		break;
+	case WOAL_ARP_FILTER:
+		ret = woal_arp_filter(priv, wrq);
+		break;
+	case WOAL_SET_INTS_GET_CHARS:
+		switch ((int)wrq->u.data.flags) {
+		case WOAL_READ_EEPROM:
+			ret = woal_read_eeprom(priv, wrq);
+			break;
+		}
+		break;
+	case WOAL_SET_GET_2K_BYTES:
+		switch ((int)wrq->u.data.flags) {
+#ifdef SDIO
+		case WOAL_CMD_53RDWR:
+			ret = woal_cmd53rdwr_ioctl(priv, wrq);
+			break;
+#endif
+		case WOAL_SET_USER_SCAN:
+			ret = woal_set_user_scan_ioctl(priv, wrq);
+			break;
+		case WOAL_GET_SCAN_TABLE:
+			ret = woal_get_scan_table_ioctl(priv, wrq);
+			break;
+		case WOAL_SET_USER_SCAN_EXT:
+			ret = woal_set_user_scan_ext_ioctl(priv, wrq);
+			break;
+		case WOAL_WMM_ADDTS:
+			ret = woal_wmm_addts_req_ioctl(priv, wrq);
+			break;
+		case WOAL_WMM_DELTS:
+			ret = woal_wmm_delts_req_ioctl(priv, wrq);
+			break;
+		case WOAL_WMM_QUEUE_CONFIG:
+			ret = woal_wmm_queue_config_ioctl(priv, wrq);
+			break;
+		case WOAL_WMM_QUEUE_STATS:
+			ret = woal_wmm_queue_stats_ioctl(priv, wrq);
+			break;
+		case WOAL_BYPASSED_PACKET:
+			ret = woal_bypassed_packet_ioctl(priv, wrq);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+
+#ifdef UAP_WEXT
+	case WOAL_FROYO_START:
+		break;
+	case WOAL_FROYO_WL_FW_RELOAD:
+		break;
+	case WOAL_FROYO_STOP:
+		if (IS_UAP_WEXT(priv->phandle->params.cfg80211_wext) &&
+		    MLAN_STATUS_SUCCESS !=
+		    woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
+				    DEF_DEAUTH_REASON_CODE)) {
+			ret = -EFAULT;
+		}
+		break;
+#endif
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get data rates
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param wait_option   Wait option
+ *  @param m_rates       A pointer to moal_802_11_rates structure
+ *
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_get_data_rates(moal_private *priv, t_u8 wait_option,
+		    moal_802_11_rates *m_rates)
+{
+	mlan_ds_rate *rate = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->sub_command = MLAN_OID_SUPPORTED_RATES;
+	req->req_id = MLAN_IOCTL_RATE;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (m_rates)
+			m_rates->num_of_rates =
+				woal_copy_rates(m_rates->rates,
+						m_rates->num_of_rates,
+						rate->param.rates,
+						MLAN_SUPPORTED_RATES);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Get channel list
+ *
+ *  @param priv            A pointer to moal_private structure
+ *  @param wait_option     Wait option
+ *  @param chan_list       A pointer to mlan_chan_list structure
+ *
+ *  @return                MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+mlan_status
+woal_get_channel_list(moal_private *priv, t_u8 wait_option,
+		      mlan_chan_list *chan_list)
+{
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_CHANNEL_LIST;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (chan_list) {
+			moal_memcpy_ext(priv->phandle, chan_list,
+					&bss->param.chanlist,
+					sizeof(mlan_chan_list),
+					sizeof(mlan_chan_list));
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Handle get info resp
+ *
+ *  @param priv     Pointer to moal_private structure
+ *  @param info     Pointer to mlan_ds_get_info structure
+ *
+ *  @return         N/A
+ */
+void
+woal_ioctl_get_info_resp(moal_private *priv, mlan_ds_get_info *info)
+{
+	ENTER();
+	switch (info->sub_command) {
+	case MLAN_OID_GET_STATS:
+		priv->w_stats.discard.fragment = info->param.stats.fcs_error;
+		priv->w_stats.discard.retries = info->param.stats.retry;
+		priv->w_stats.discard.misc = info->param.stats.ack_failure;
+		break;
+	case MLAN_OID_GET_SIGNAL:
+		if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
+			priv->w_stats.qual.level =
+				info->param.signal.bcn_rssi_avg;
+		if (info->param.signal.selector & BCN_NF_AVG_MASK)
+			priv->w_stats.qual.noise =
+				info->param.signal.bcn_nf_avg;
+		break;
+	default:
+		break;
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Handle get BSS resp
+ *
+ *  @param priv     Pointer to moal_private structure
+ *  @param bss      Pointer to mlan_ds_bss structure
+ *
+ *  @return         N/A
+ */
+void
+woal_ioctl_get_bss_resp(moal_private *priv, mlan_ds_bss *bss)
+{
+	t_u32 mode = 0;
+
+	ENTER();
+
+	switch (bss->sub_command) {
+	case MLAN_OID_BSS_MODE:
+		if (bss->param.bss_mode == MLAN_BSS_MODE_INFRA)
+			mode = IW_MODE_INFRA;
+		else if (bss->param.bss_mode == MLAN_BSS_MODE_IBSS)
+			mode = IW_MODE_ADHOC;
+		else
+			mode = IW_MODE_AUTO;
+		priv->w_stats.status = mode;
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return;
+}
diff --git a/wlan_sd8987/mlinux/moal_priv.h b/wlan_sd8987/mlinux/moal_priv.h
new file mode 100755
index 0000000..7f6d2f6
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_priv.h
@@ -0,0 +1,294 @@
+
+/** @file moal_priv.h
+ *
+ * @brief This file contains definition for extended private IOCTL call.
+ *
+ *
+ * Copyright 2008-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/31/2008: initial version
+********************************************************/
+
+#ifndef _WOAL_PRIV_H_
+#define _WOAL_PRIV_H_
+
+/** 2K bytes */
+#define WOAL_2K_BYTES 2000
+
+/** PRIVATE CMD ID */
+#define WOAL_IOCTL (SIOCIWFIRSTPRIV)	/* 0x8BE0 defined in wireless.h */
+
+/** Private command ID to set one int/get word char */
+#define WOAL_SETONEINT_GETWORDCHAR (WOAL_IOCTL + 1)
+/** Private command ID to get version */
+#define WOAL_VERSION 1
+/** Private command ID to get extended version */
+#define WOAL_VEREXT 2
+
+/** Private command ID to set/get none */
+#define WOAL_SETNONE_GETNONE (WOAL_IOCTL + 2)
+/** Private command ID for warm reset */
+#define WOAL_WARMRESET 1
+
+/**
+ * Linux Kernels later 3.9 use CONFIG_PM_RUNTIME instead of
+ * CONFIG_USB_SUSPEND
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+#ifdef CONFIG_PM
+#ifndef CONFIG_USB_SUSPEND
+#define CONFIG_USB_SUSPEND
+#endif
+#endif
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
+#ifdef CONFIG_PM_RUNTIME
+#ifndef CONFIG_USB_SUSPEND
+#define CONFIG_USB_SUSPEND
+#endif
+#endif
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
+#endif
+
+#ifdef CONFIG_USB_SUSPEND
+/** Private command ID for usb suspend */
+#define WOAL_USB_SUSPEND 2
+/** Private command ID for usb resume */
+#define WOAL_USB_RESUME 3
+#endif /* CONFIG_USB_SUSPEND */
+/** Private command ID to clear 11d chan table */
+#define WOAL_11D_CLR_CHAN_TABLE 4
+
+/** Private command ID to set/get sixteen int */
+#define WOAL_SET_GET_SIXTEEN_INT (WOAL_IOCTL + 3)
+/** Private command ID to set/get TX power configurations */
+#define WOAL_TX_POWERCFG 1
+#ifdef DEBUG_LEVEL1
+/** Private command ID to set/get driver debug */
+#define WOAL_DRV_DBG 2
+#endif
+/** Private command ID to set/get beacon interval */
+#define WOAL_BEACON_INTERVAL 3
+/** Private command ID to get RSSI */
+#define WOAL_SIGNAL 5
+/** Private command ID to set/get Deep Sleep mode */
+#define WOAL_DEEP_SLEEP 7
+/** Private command ID for 11n ht configration */
+#define WOAL_11N_TX_CFG 8
+/** Private command ID for 11n usr ht configration */
+#define WOAL_11N_HTCAP_CFG 9
+/** Private command ID for TX Aggregation */
+#define WOAL_PRIO_TBL 10
+/** Private command ID for Updating ADDBA variables */
+#define WOAL_ADDBA_UPDT 11
+/** Private command ID to set/get Host Sleep configuration */
+#define WOAL_HS_CFG 12
+/** Private command ID to set Host Sleep parameters */
+#define WOAL_HS_SETPARA 13
+/** Private command ID to read/write registers */
+#define WOAL_REG_READ_WRITE 14
+/** Private command ID to set/get band/adhocband */
+#define WOAL_BAND_CFG 15
+/** Private command ID for TX Aggregation */
+#define WOAL_11N_AMSDU_AGGR_CTRL 17
+/** Private command ID to set/get Inactivity timeout */
+#define WOAL_INACTIVITY_TIMEOUT_EXT 18
+#ifdef SDIO
+/** Private command ID to turn on/off sdio clock */
+#define WOAL_SDIO_CLOCK 19
+/** Private command ID to read/write Command 52 */
+#define WOAL_CMD_52RDWR 20
+#endif
+/** Private command ID to set/get scan configuration parameter */
+#define WOAL_SCAN_CFG 21
+/** Private command ID to set/get PS configuration parameter */
+#define WOAL_PS_CFG 22
+/** Private command ID to read/write memory */
+#define WOAL_MEM_READ_WRITE 23
+#ifdef SDIO
+/** Private command ID to control SDIO MP-A */
+#define WOAL_SDIO_MPA_CTRL 25
+#endif
+/** Private command ID for Updating ADDBA variables */
+#define WOAL_ADDBA_REJECT 27
+/** Private command ID to set/get sleep parameters */
+#define WOAL_SLEEP_PARAMS 28
+/** Private command ID to set/get TX BF capabilities */
+#define WOAL_TX_BF_CAP 31
+/** Private command ID to set/get dfs testing settings */
+#define WOAL_DFS_TESTING 33
+/** Private command ID to set/get CFP table codes */
+#define WOAL_CFP_CODE 34
+/** Private command ID to set/get tx/rx antenna */
+#define WOAL_SET_GET_TX_RX_ANT 35
+/** Private command ID to set/get management frame passthru mask */
+#define WOAL_MGMT_FRAME_CTRL 36
+
+/** Private command ID to configure gpio independent reset */
+#define WOAL_IND_RST_CFG 37
+
+/** Private command ID to set one int/get one int */
+#define WOAL_SETONEINT_GETONEINT (WOAL_IOCTL + 5)
+/** Private command ID to set/get Tx rate */
+#define WOAL_SET_GET_TXRATE 1
+/** Private command ID to set/get region code */
+#define WOAL_SET_GET_REGIONCODE 2
+/** Private command ID to turn on/off radio */
+#define WOAL_SET_RADIO 3
+/** Private command ID to enable WMM */
+#define WOAL_WMM_ENABLE 4
+/** Private command ID to enable 802.11D */
+#define WOAL_11D_ENABLE 5
+/** Private command ID to set/get QoS configuration */
+#define WOAL_SET_GET_QOS_CFG 7
+#if defined(REASSOCIATION)
+/** Private command ID to set/get reassociation setting */
+#define WOAL_SET_GET_REASSOC 9
+#endif /* REASSOCIATION */
+/** Private command ID for Updating Transmit buffer configration */
+#define WOAL_TXBUF_CFG 10
+/** Private command ID to set/get WWS mode */
+#define WOAL_SET_GET_WWS_CFG 12
+/** Private command ID to set/get sleep period */
+#define WOAL_SLEEP_PD 13
+/** Private command ID to set/get auth type */
+#define WOAL_AUTH_TYPE 18
+/** Private command ID to set/get port control */
+#define WOAL_PORT_CTRL 19
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Private command ID for set/get BSS role */
+#define WOAL_SET_GET_BSS_ROLE 21
+#endif
+#endif
+/** Private command ID for set/get 11h local power constraint */
+#define WOAL_SET_GET_11H_LOCAL_PWR_CONSTRAINT 22
+/** Private command ID to set/get 11N HT stream configuration */
+#define WOAL_HT_STREAM_CFG 23
+/** Private command ID to set/get MAC control */
+#define WOAL_MAC_CONTROL 24
+/** Private command ID to get thermal value */
+#define WOAL_THERMAL 25
+/** Private command ID to set/get hs cfg param */
+#define WOAL_CFG_HOTSPOT 26
+
+/** Private command ID to get log */
+#define WOALGETLOG (WOAL_IOCTL + 7)
+
+/** Private command ID to set a wext address variable */
+#define WOAL_SETADDR_GETNONE (WOAL_IOCTL + 8)
+/** Private command ID to send deauthentication */
+#define WOAL_DEAUTH 1
+
+/** Private command to get/set 256 chars */
+#define WOAL_SET_GET_256_CHAR (WOAL_IOCTL + 9)
+/** Private command to read/write passphrase */
+#define WOAL_PASSPHRASE 1
+#define WOAL_ASSOCIATE 3
+/** Private command ID to get WMM queue status */
+#define WOAL_WMM_QUEUE_STATUS 4
+/** Private command ID to get Traffic stream status */
+#define WOAL_WMM_TS_STATUS 5
+#define WOAL_IP_ADDRESS 7
+/** Private command ID to set/get TX bemaforming */
+#define WOAL_TX_BF_CFG 8
+/** Private command ID to get PTK/GTK */
+#define WOAL_GET_KEY 9
+
+/** Get log buffer size */
+#define GETLOG_BUFSIZE 1500
+
+/** Private command ID to set none/get twelve chars*/
+#define WOAL_SETNONE_GETTWELVE_CHAR (WOAL_IOCTL + 11)
+/** Private command ID for WPS session */
+#define WOAL_WPS_SESSION 1
+
+/** Private command ID to set none/get four int */
+#define WOAL_SETNONE_GET_FOUR_INT (WOAL_IOCTL + 13)
+/** Private command ID to get data rates */
+#define WOAL_DATA_RATE 1
+/** Private command ID to get E-Supplicant mode */
+#define WOAL_ESUPP_MODE 2
+
+/** Private command to get/set 64 ints */
+#define WOAL_SET_GET_64_INT (WOAL_IOCTL + 15)
+/** Private command ID to set/get ECL system clock */
+#define WOAL_ECL_SYS_CLOCK 1
+
+/** Private command ID for hostcmd */
+#define WOAL_HOST_CMD (WOAL_IOCTL + 17)
+
+/** Private command ID for arpfilter */
+#define WOAL_ARP_FILTER (WOAL_IOCTL + 19)
+
+/** Private command ID to set ints and get chars */
+#define WOAL_SET_INTS_GET_CHARS (WOAL_IOCTL + 21)
+/** Private command ID to read EEPROM data */
+#define WOAL_READ_EEPROM 1
+
+/** Private command ID to set/get 2K bytes */
+#define WOAL_SET_GET_2K_BYTES (WOAL_IOCTL + 23)
+
+#ifdef SDIO
+/** Private command ID to read/write Command 53 */
+#define WOAL_CMD_53RDWR 2
+#endif
+
+/** Private command ID for setuserscan */
+#define WOAL_SET_USER_SCAN 3
+/** Private command ID for getscantable */
+#define WOAL_GET_SCAN_TABLE 4
+/** Private command ID for setuserscanext: async without wait */
+#define WOAL_SET_USER_SCAN_EXT 5
+
+/** Private command ID to request ADDTS */
+#define WOAL_WMM_ADDTS 7
+/** Private command ID to request DELTS */
+#define WOAL_WMM_DELTS 8
+/** Private command ID to queue configuration */
+#define WOAL_WMM_QUEUE_CONFIG 9
+/** Private command ID to queue stats */
+#define WOAL_WMM_QUEUE_STATS 10
+/** Private command ID to Bypass auth packet */
+#define WOAL_BYPASSED_PACKET 11
+
+#ifdef UAP_WEXT
+/** The following command IDs are for Froyo app */
+/** Private command ID to start driver */
+#define WOAL_FROYO_START (WOAL_IOCTL + 28)
+/** Private command ID to reload FW */
+#define WOAL_FROYO_WL_FW_RELOAD (WOAL_IOCTL + 29)
+/** Private command ID to stop driver */
+#define WOAL_FROYO_STOP (WOAL_IOCTL + 30)
+#endif
+
+/** moal_802_11_rates  */
+typedef struct _moal_802_11_rates {
+	/** Num of rates */
+	t_u8 num_of_rates;
+	/** Rates */
+	t_u8 rates[MLAN_SUPPORTED_RATES];
+} moal_802_11_rates, *pmoal_802_11_rates;
+
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+int woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+#endif
+
+#endif /* _WOAL_PRIV_H_ */
diff --git a/wlan_sd8987/mlinux/moal_proc.c b/wlan_sd8987/mlinux/moal_proc.c
new file mode 100755
index 0000000..72efd84
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_proc.c
@@ -0,0 +1,1377 @@
+/**  @file moal_proc.c
+ *
+ * @brief This file contains functions for proc file.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif
+
+/********************************************************
+		Local Variables
+********************************************************/
+#ifdef CONFIG_PROC_FS
+#define STATUS_PROC "wifi_status"
+#define MWLAN_PROC "mwlan"
+#define WLAN_PROC "adapter%d"
+/** Proc mwlan directory entry */
+static struct proc_dir_entry *proc_mwlan;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+#define PROC_DIR NULL
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+#define PROC_DIR (&proc_root)
+#else
+#define PROC_DIR proc_net
+#endif
+
+#ifdef STA_SUPPORT
+static char *szModes[] = {
+	"Unknown",
+	"Managed",
+	"Ad-hoc",
+	"Auto",
+};
+#endif
+
+/********************************************************
+		Global Variables
+********************************************************/
+int wifi_status;
+
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief Proc read function for info
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data
+ *
+ *  @return         Number of output data
+ */
+static int
+woal_info_proc_read(struct seq_file *sfp, void *data)
+{
+	struct net_device *netdev = (struct net_device *)sfp->private;
+	char fmt[MLAN_MAX_VER_STR_LEN];
+	moal_private *priv = (moal_private *)netdev_priv(netdev);
+#ifdef STA_SUPPORT
+	int i = 0;
+	moal_handle *handle = NULL;
+	mlan_bss_info info;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+	struct dev_mc_list *mcptr = netdev->mc_list;
+	int mc_count = netdev->mc_count;
+#else
+	struct netdev_hw_addr *mcptr = NULL;
+	int mc_count = netdev_mc_count(netdev);
+#endif /* < 2.6.35 */
+#else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	int i = 0;
+#endif /* >= 2.6.29 */
+#endif
+#ifdef UAP_SUPPORT
+	mlan_ds_uap_stats ustats;
+#endif
+	union {
+		t_u32 l;
+		t_u8 c[4];
+	} ver;
+
+	ENTER();
+
+	if (priv == NULL)
+		goto exit;
+#ifdef STA_SUPPORT
+	handle = priv->phandle;
+	if (handle == NULL)
+		goto exit;
+#endif
+
+	if (!MODULE_GET) {
+		LEAVE();
+		return 0;
+	}
+
+	memset(fmt, 0, sizeof(fmt));
+#ifdef UAP_SUPPORT
+	memset(&ustats, 0, sizeof(ustats));
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		seq_printf(sfp, "driver_name = " "\"uap\"\n");
+		woal_uap_get_version(priv, fmt, sizeof(fmt) - 1);
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_get_stats(priv, MOAL_IOCTL_WAIT, &ustats)) {
+			MODULE_PUT;
+			LEAVE();
+			return -EFAULT;
+		}
+	}
+#endif /* UAP_SUPPORT */
+#ifdef STA_SUPPORT
+	memset(&info, 0, sizeof(info));
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		woal_get_version(handle, fmt, sizeof(fmt) - 1);
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &info)) {
+			MODULE_PUT;
+			LEAVE();
+			return -EFAULT;
+		}
+		seq_printf(sfp, "driver_name = " "\"wlan\"\n");
+	}
+#endif
+	seq_printf(sfp, "driver_version = %s", fmt);
+	seq_printf(sfp, "\ninterface_name=\"%s\"\n", netdev->name);
+	ver.l = handle->fw_release_number;
+	seq_printf(sfp, "firmware_major_version=%u.%u.%u\n", ver.c[2], ver.c[1],
+		   ver.c[0]);
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
+			seq_printf(sfp, "bss_mode = \"WIFIDIRECT-Client\"\n");
+		else
+			seq_printf(sfp, "bss_mode = \"WIFIDIRECT-GO\"\n");
+	}
+#endif
+#ifdef STA_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		seq_printf(sfp, "bss_mode =\"%s\"\n", szModes[info.bss_mode]);
+#endif
+	seq_printf(sfp, "media_state=\"%s\"\n",
+		   ((priv->media_connected == MFALSE) ? "Disconnected" :
+		    "Connected"));
+	seq_printf(sfp, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
+		   netdev->dev_addr[0], netdev->dev_addr[1],
+		   netdev->dev_addr[2], netdev->dev_addr[3],
+		   netdev->dev_addr[4], netdev->dev_addr[5]);
+#ifdef STA_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		seq_printf(sfp, "multicast_count=\"%d\"\n", mc_count);
+		seq_printf(sfp, "essid=\"%s\"\n", info.ssid.ssid);
+		seq_printf(sfp, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
+			   info.bssid[0], info.bssid[1], info.bssid[2],
+			   info.bssid[3], info.bssid[4], info.bssid[5]);
+		seq_printf(sfp, "channel=\"%d\"\n", (int)info.bss_chan);
+		seq_printf(sfp, "region_code = \"%02x\"\n",
+			   (t_u8)info.region_code);
+
+		/*
+		 * Put out the multicast list
+		 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+		for (i = 0; i < netdev->mc_count; i++) {
+			seq_printf(sfp,
+				   "multicast_address[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
+				   i, mcptr->dmi_addr[0], mcptr->dmi_addr[1],
+				   mcptr->dmi_addr[2], mcptr->dmi_addr[3],
+				   mcptr->dmi_addr[4], mcptr->dmi_addr[5]);
+
+			mcptr = mcptr->next;
+		}
+#else
+		netdev_for_each_mc_addr(mcptr, netdev)
+			seq_printf(sfp,
+				   "multicast_address[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
+				   i++, mcptr->addr[0], mcptr->addr[1],
+				   mcptr->addr[2], mcptr->addr[3],
+				   mcptr->addr[4], mcptr->addr[5]);
+#endif /* < 2.6.35 */
+	}
+#endif
+	seq_printf(sfp, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
+	seq_printf(sfp, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
+	seq_printf(sfp, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
+	seq_printf(sfp, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
+	seq_printf(sfp, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
+	seq_printf(sfp, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
+	seq_printf(sfp, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
+	seq_printf(sfp, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
+	seq_printf(sfp, "carrier %s\n",
+		   ((netif_carrier_ok(priv->netdev)) ? "on" : "off"));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	for (i = 0; i < (int)netdev->num_tx_queues; i++) {
+		seq_printf(sfp, "tx queue %d:  %s\n", i,
+			   ((netif_tx_queue_stopped
+			     (netdev_get_tx_queue(netdev, 0))) ? "stopped" :
+			    "started"));
+	}
+#else
+	seq_printf(sfp, "tx queue %s\n",
+		   ((netif_queue_stopped(priv->netdev)) ? "stopped" :
+		    "started"));
+#endif
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		seq_printf(sfp, "tkip_mic_failures = %u\n",
+			   ustats.tkip_mic_failures);
+		seq_printf(sfp, "ccmp_decrypt_errors = %u\n",
+			   ustats.ccmp_decrypt_errors);
+		seq_printf(sfp, "wep_undecryptable_count = %u\n",
+			   ustats.wep_undecryptable_count);
+		seq_printf(sfp, "wep_icv_error_count = %u\n",
+			   ustats.wep_icv_error_count);
+		seq_printf(sfp, "decrypt_failure_count = %u\n",
+			   ustats.decrypt_failure_count);
+		seq_printf(sfp, "mcast_tx_count = %u\n", ustats.mcast_tx_count);
+		seq_printf(sfp, "failed_count = %u\n", ustats.failed_count);
+		seq_printf(sfp, "retry_count = %u\n", ustats.retry_count);
+		seq_printf(sfp, "multiple_retry_count = %u\n",
+			   ustats.multi_retry_count);
+		seq_printf(sfp, "frame_duplicate_count = %u\n",
+			   ustats.frame_dup_count);
+		seq_printf(sfp, "rts_success_count = %u\n",
+			   ustats.rts_success_count);
+		seq_printf(sfp, "rts_failure_count = %u\n",
+			   ustats.rts_failure_count);
+		seq_printf(sfp, "ack_failure_count = %u\n",
+			   ustats.ack_failure_count);
+		seq_printf(sfp, "rx_fragment_count = %u\n",
+			   ustats.rx_fragment_count);
+		seq_printf(sfp, "mcast_rx_frame_count = %u\n",
+			   ustats.mcast_rx_frame_count);
+		seq_printf(sfp, "fcs_error_count = %u\n",
+			   ustats.fcs_error_count);
+		seq_printf(sfp, "tx_frame_count = %u\n", ustats.tx_frame_count);
+		seq_printf(sfp, "rsna_tkip_cm_invoked = %u\n",
+			   ustats.rsna_tkip_cm_invoked);
+		seq_printf(sfp, "rsna_4way_hshk_failures = %u\n",
+			   ustats.rsna_4way_hshk_failures);
+	}
+#endif /* UAP_SUPPORT */
+	seq_printf(sfp, "=== tp_acnt.on:%d drop_point:%d ===\n",
+		   handle->tp_acnt.on, handle->tp_acnt.drop_point);
+	seq_printf(sfp, "====Tx accounting====\n");
+	for (i = 0; i < MAX_TP_ACCOUNT_DROP_POINT_NUM; i++) {
+		seq_printf(sfp, "[%d] Tx packets     : %lu\n", i,
+			   handle->tp_acnt.tx_packets[i]);
+		seq_printf(sfp, "[%d] Tx packets last: %lu\n", i,
+			   handle->tp_acnt.tx_packets_last[i]);
+		seq_printf(sfp, "[%d] Tx packets rate: %lu\n", i,
+			   handle->tp_acnt.tx_packets_rate[i]);
+		seq_printf(sfp, "[%d] Tx bytes       : %lu\n", i,
+			   handle->tp_acnt.tx_bytes[i]);
+		seq_printf(sfp, "[%d] Tx bytes last  : %lu\n", i,
+			   handle->tp_acnt.tx_bytes_last[i]);
+		seq_printf(sfp, "[%d] Tx bytes rate  : %luMbps\n", i,
+			   handle->tp_acnt.tx_bytes_rate[i] * 8 / 1024 / 1024);
+	}
+	seq_printf(sfp, "Tx amsdu cnt		: %lu\n",
+		   handle->tp_acnt.tx_amsdu_cnt);
+	seq_printf(sfp, "Tx amsdu cnt last	: %lu\n",
+		   handle->tp_acnt.tx_amsdu_cnt_last);
+	seq_printf(sfp, "Tx amsdu cnt rate	: %lu\n",
+		   handle->tp_acnt.tx_amsdu_cnt_rate);
+	seq_printf(sfp, "Tx amsdu pkt cnt	: %lu\n",
+		   handle->tp_acnt.tx_amsdu_pkt_cnt);
+	seq_printf(sfp, "Tx amsdu pkt cnt last : %lu\n",
+		   handle->tp_acnt.tx_amsdu_pkt_cnt_last);
+	seq_printf(sfp, "Tx amsdu pkt cnt rate : %lu\n",
+		   handle->tp_acnt.tx_amsdu_pkt_cnt_rate);
+	seq_printf(sfp, "Tx intr cnt    		: %lu\n",
+		   handle->tp_acnt.tx_intr_cnt);
+	seq_printf(sfp, "Tx intr last        : %lu\n",
+		   handle->tp_acnt.tx_intr_last);
+	seq_printf(sfp, "Tx intr rate        : %lu\n",
+		   handle->tp_acnt.tx_intr_rate);
+	seq_printf(sfp, "Tx pending          : %lu\n",
+		   handle->tp_acnt.tx_pending);
+	seq_printf(sfp, "Tx xmit skb realloc : %lu\n",
+		   handle->tp_acnt.tx_xmit_skb_realloc_cnt);
+	seq_printf(sfp, "Tx stop queue cnt : %lu\n",
+		   handle->tp_acnt.tx_stop_queue_cnt);
+	seq_printf(sfp, "====Rx accounting====\n");
+	for (i = 0; i < MAX_TP_ACCOUNT_DROP_POINT_NUM; i++) {
+		seq_printf(sfp, "[%d] Rx packets     : %lu\n", i,
+			   handle->tp_acnt.rx_packets[i]);
+		seq_printf(sfp, "[%d] Rx packets last: %lu\n", i,
+			   handle->tp_acnt.rx_packets_last[i]);
+		seq_printf(sfp, "[%d] Rx packets rate: %lu\n", i,
+			   handle->tp_acnt.rx_packets_rate[i]);
+		seq_printf(sfp, "[%d] Rx bytes       : %lu\n", i,
+			   handle->tp_acnt.rx_bytes[i]);
+		seq_printf(sfp, "[%d] Rx bytes last  : %lu\n", i,
+			   handle->tp_acnt.rx_bytes_last[i]);
+		seq_printf(sfp, "[%d] Rx bytes rate  : %luMbps\n", i,
+			   handle->tp_acnt.rx_bytes_rate[i] * 8 / 1024 / 1024);
+	}
+	seq_printf(sfp, "Rx amsdu cnt		 : %lu\n",
+		   handle->tp_acnt.rx_amsdu_cnt);
+	seq_printf(sfp, "Rx amsdu cnt last	 : %lu\n",
+		   handle->tp_acnt.rx_amsdu_cnt_last);
+	seq_printf(sfp, "Rx amsdu cnt rate	 : %lu\n",
+		   handle->tp_acnt.rx_amsdu_cnt_rate);
+	seq_printf(sfp, "Rx amsdu pkt cnt	 : %lu\n",
+		   handle->tp_acnt.rx_amsdu_pkt_cnt);
+	seq_printf(sfp, "Rx amsdu pkt cnt last : %lu\n",
+		   handle->tp_acnt.rx_amsdu_pkt_cnt_last);
+	seq_printf(sfp, "Rx amsdu pkt cnt rate : %lu\n",
+		   handle->tp_acnt.rx_amsdu_pkt_cnt_rate);
+	seq_printf(sfp, "Rx intr cnt    	 : %lu\n",
+		   handle->tp_acnt.rx_intr_cnt);
+	seq_printf(sfp, "Rx intr last        : %lu\n",
+		   handle->tp_acnt.rx_intr_last);
+	seq_printf(sfp, "Rx intr rate        : %lu\n",
+		   handle->tp_acnt.rx_intr_rate);
+	seq_printf(sfp, "Rx pending          : %lu\n",
+		   handle->tp_acnt.rx_pending);
+	seq_printf(sfp, "Rx pause            : %lu\n",
+		   handle->tp_acnt.rx_paused_cnt);
+	seq_printf(sfp, "Rx rdptr full cnt   : %lu\n",
+		   handle->tp_acnt.rx_rdptr_full_cnt);
+exit:
+	LEAVE();
+	MODULE_PUT;
+	return 0;
+}
+
+static int
+woal_info_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_info_proc_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_info_proc_read, PDE(inode)->data);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops info_proc_fops = {
+	.proc_open = woal_info_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+#else
+static const struct file_operations info_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_info_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+
+#ifdef SDIO
+#define CMD52_STR_LEN 50
+/*
+ *  @brief Parse cmd52 string
+ *
+ *  @param buffer   A pointer user buffer
+ *  @param len      Length user buffer
+ *  @param func     Parsed func number
+ *  @param reg      Parsed reg value
+ *  @param val      Parsed value to set
+ *  @return         BT_STATUS_SUCCESS
+ */
+static int
+parse_cmd52_string(const char *buffer, size_t len, int *func,
+		   int *reg, int *val)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+	gfp_t flag;
+
+	ENTER();
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	string = kzalloc(CMD52_STR_LEN, flag);
+	if (string == NULL)
+		return -ENOMEM;
+
+	moal_memcpy_ext(NULL, string, buffer + strlen("sdcmd52rw="),
+			len - strlen("sdcmd52rw="), CMD52_STR_LEN - 1);
+	string = strstrip(string);
+
+	*func = -1;
+	*reg = -1;
+	*val = -1;
+
+	/* Get func */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*func = woal_string_to_number(pos);
+
+	/* Get reg */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*reg = woal_string_to_number(pos);
+
+	/* Get val (optional) */
+	pos = strsep(&string, " \t");
+	if (pos)
+		*val = woal_string_to_number(pos);
+	kfree(string);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief config proc write function
+ *
+ *  @param f        file pointer
+ *  @param buf      pointer to data buffer
+ *  @param count    data number to write
+ *  @param off      Offset
+ *
+ *  @return         number of data
+ */
+static ssize_t
+woal_config_write(struct file *f, const char __user * buf,
+		  size_t count, loff_t * off)
+{
+	char databuf[101];
+	char *line = NULL;
+	t_u32 config_data = 0;
+	struct seq_file *sfp = f->private_data;
+	moal_handle *handle = (moal_handle *)sfp->private;
+
+#ifdef SDIO
+	int func = 0, reg = 0, val = 0;
+#endif
+	moal_handle *ref_handle = NULL;
+	t_u32 cmd = 0;
+	int copy_len;
+	moal_private *priv = NULL;
+
+	ENTER();
+	if (!MODULE_GET) {
+		LEAVE();
+		return 0;
+	}
+
+	if (count >= sizeof(databuf)) {
+		MODULE_PUT;
+		LEAVE();
+		return (int)count;
+	}
+	memset(databuf, 0, sizeof(databuf));
+	copy_len = MIN((sizeof(databuf) - 1), count);
+	if (copy_from_user(databuf, buf, copy_len)) {
+		MODULE_PUT;
+		LEAVE();
+		return 0;
+	}
+	line = databuf;
+	if (!strncmp(databuf, "soft_reset", strlen("soft_reset"))) {
+		line += strlen("soft_reset") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		PRINTM(MINFO, "soft_reset: %d\n", (int)config_data);
+		if (woal_request_soft_reset(handle) == MLAN_STATUS_SUCCESS)
+			handle->hardware_status = HardwareStatusReset;
+		else
+			PRINTM(MERROR, "Could not perform soft reset\n");
+	}
+	if (!strncmp(databuf, "drv_mode", strlen("drv_mode"))) {
+		line += strlen("drv_mode") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		PRINTM(MINFO, "drv_mode: %d\n", (int)config_data);
+		if (config_data != (t_u32)handle->params.drv_mode)
+			if (woal_switch_drv_mode(handle, config_data) !=
+			    MLAN_STATUS_SUCCESS) {
+				PRINTM(MERROR, "Could not switch drv mode\n");
+			}
+	}
+#ifdef SDIO
+	if (IS_SD(handle->card_type)) {
+		if (!strncmp(databuf, "sdcmd52rw=", strlen("sdcmd52rw=")) &&
+		    count > strlen("sdcmd52rw=")) {
+			parse_cmd52_string((const char *)databuf,
+					   (size_t) count, &func, &reg, &val);
+			woal_sdio_read_write_cmd52(handle, func, reg, val);
+		}
+	}
+#endif /* SD */
+	if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) {
+		PRINTM(MERROR, "Recevie debug_dump command\n");
+#ifdef USB
+		if (!IS_USB(handle->card_type))
+#endif
+			handle->driver_status = MTRUE;
+		ref_handle = (moal_handle *)handle->pref_mac;
+		if (ref_handle) {
+			priv = woal_get_priv(ref_handle, MLAN_BSS_ROLE_ANY);
+			if (priv) {
+#ifdef DEBUG_LEVEL1
+				drvdbg &= ~MFW_D;
+#endif
+				woal_mlan_debug_info(priv);
+				woal_moal_debug_info(priv, NULL, MFALSE);
+			}
+		}
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+		if (priv) {
+#ifdef DEBUG_LEVEL1
+			drvdbg &= ~MFW_D;
+#endif
+			woal_mlan_debug_info(priv);
+			woal_moal_debug_info(priv, NULL, MFALSE);
+			handle->ops.dump_fw_info(handle);
+		}
+	}
+
+	if (!strncmp(databuf, "fwdump_file=", strlen("fwdump_file="))) {
+		int len = copy_len - strlen("fwdump_file=");
+		gfp_t flag;
+		if (len) {
+			kfree(handle->fwdump_fname);
+			flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC :
+				GFP_KERNEL;
+			handle->fwdump_fname = kzalloc(len, flag);
+			if (handle->fwdump_fname)
+				moal_memcpy_ext(handle, handle->fwdump_fname,
+						databuf +
+						strlen("fwdump_file="),
+						len - 1, len - 1);
+		}
+	}
+	if (!strncmp(databuf, "fw_reload", strlen("fw_reload"))) {
+		if (!strncmp(databuf, "fw_reload=", strlen("fw_reload="))) {
+			line += strlen("fw_reload") + 1;
+			config_data = (t_u32)woal_string_to_number(line);
+		}
+#ifdef SDIO_MMC
+		else if (IS_SD(handle->card_type))
+			config_data = FW_RELOAD_SDIO_INBAND_RESET;
+#endif
+		PRINTM(MMSG, "Request fw_reload=%d\n", config_data);
+		woal_request_fw_reload(handle, config_data);
+	}
+	if (!strncmp(databuf, "drop_point=", strlen("drop_point="))) {
+		line += strlen("drop_point") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		if (config_data) {
+			handle->tp_acnt.on = 1;
+			handle->tp_acnt.drop_point = config_data;
+			if (handle->is_tp_acnt_timer_set == MFALSE) {
+				woal_initialize_timer(&handle->tp_acnt.timer,
+						      woal_tp_acnt_timer_func,
+						      handle);
+				handle->is_tp_acnt_timer_set = MTRUE;
+				woal_mod_timer(&handle->tp_acnt.timer, 1000);
+			}
+		} else {
+			if (handle->is_tp_acnt_timer_set) {
+				woal_cancel_timer(&handle->tp_acnt.timer);
+				handle->is_tp_acnt_timer_set = MFALSE;
+			}
+			memset((void *)&handle->tp_acnt, 0,
+			       sizeof(moal_tp_acnt_t));
+		}
+		priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+		if (priv)
+			woal_set_tp_state(priv);
+		PRINTM(MMSG, "on=%d drop_point=%d\n", handle->tp_acnt.on,
+		       handle->tp_acnt.drop_point);
+	}
+	if (!strncmp(databuf, "rf_test_mode", strlen("rf_test_mode"))) {
+		line += strlen("rf_test_mode") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		PRINTM(MINFO, "RF test mode: %d\n", (int)config_data);
+		if (config_data != (t_u32)handle->rf_test_mode)
+			if (woal_process_rf_test_mode(handle, config_data) !=
+			    MLAN_STATUS_SUCCESS)
+				PRINTM(MERROR, "Could not set RF test mode\n");
+	}
+	if (!strncmp(databuf, "tx_antenna", strlen("tx_antenna"))) {
+		line += strlen("tx_antenna") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		cmd = MFG_CMD_TX_ANT;
+	}
+	if (!strncmp(databuf, "rx_antenna", strlen("rx_antenna"))) {
+		line += strlen("rx_antenna") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		cmd = MFG_CMD_RX_ANT;
+	}
+	if (!strncmp(databuf, "radio_mode", strlen("radio_mode"))) {
+		line += strlen("radio_mode") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		cmd = MFG_CMD_RADIO_MODE_CFG;
+	}
+	if (!strncmp(databuf, "channel", strlen("channel"))) {
+		line += strlen("channel") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		cmd = MFG_CMD_RF_CHAN;
+	}
+	if (!strncmp(databuf, "band", strlen("band"))) {
+		line += strlen("band") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		cmd = MFG_CMD_RF_BAND_AG;
+	}
+	if (!strncmp(databuf, "bw", strlen("bw"))) {
+		line += strlen("bw") + 1;
+		config_data = (t_u32)woal_string_to_number(line);
+		cmd = MFG_CMD_RF_CHANNELBW;
+	}
+	if (!strncmp(databuf, "get_and_reset_per", strlen("get_and_reset_per")))
+		cmd = MFG_CMD_CLR_RX_ERR;
+	if (!strncmp(databuf, "tx_power=", strlen("tx_power="))
+	    && count > strlen("tx_power="))
+		cmd = MFG_CMD_RFPWR;
+	if (!strncmp(databuf, "tx_frame=", strlen("tx_frame="))
+	    && count > strlen("tx_frame="))
+		cmd = MFG_CMD_TX_FRAME;
+	if (!strncmp(databuf, "tx_continuous=", strlen("tx_continuous="))
+	    && count > strlen("tx_continuous="))
+		cmd = MFG_CMD_TX_CONT;
+	if (!strncmp(databuf, "he_tb_tx=", strlen("he_tb_tx="))
+	    && count > strlen("he_tb_tx="))
+		cmd = MFG_CMD_CONFIG_MAC_HE_TB_TX;
+
+	if (cmd && handle->rf_test_mode
+	    && (woal_process_rf_test_mode_cmd(handle, cmd,
+					      (const char *)databuf,
+					      (size_t) count,
+					      MLAN_ACT_SET,
+					      config_data) !=
+		MLAN_STATUS_SUCCESS)) {
+		PRINTM(MERROR, "RF test mode cmd error\n");
+	}
+	if (cmd && !handle->rf_test_mode)
+		PRINTM(MERROR, "RF test mode is disabled\n");
+	MODULE_PUT;
+	LEAVE();
+	return (int)count;
+}
+
+/**
+ *  @brief config proc read function
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data
+ *
+ *  @return         number of output data
+ */
+static int
+woal_config_read(struct seq_file *sfp, void *data)
+{
+	moal_handle *handle = (moal_handle *)sfp->private;
+	int i;
+
+	ENTER();
+
+	if (!MODULE_GET) {
+		LEAVE();
+		return 0;
+	}
+
+	seq_printf(sfp, "hardware_status=%d\n", (int)handle->hardware_status);
+	seq_printf(sfp, "netlink_num=%d\n", (int)handle->netlink_num);
+	seq_printf(sfp, "drv_mode=%d\n", (int)handle->params.drv_mode);
+#ifdef SDIO
+	if (IS_SD(handle->card_type)) {
+		seq_printf(sfp, "sdcmd52rw=%d 0x%0x 0x%02X\n",
+			   handle->cmd52_func, handle->cmd52_reg,
+			   handle->cmd52_val);
+	}
+#endif /* SD */
+	seq_printf(sfp, "rf_test_mode=%u\n", handle->rf_test_mode);
+	if (handle->rf_test_mode && handle->rf_data) {
+		seq_printf(sfp, "tx_antenna=%u\n", handle->rf_data->tx_antenna);
+		seq_printf(sfp, "rx_antenna=%u\n", handle->rf_data->rx_antenna);
+		seq_printf(sfp, "band=%u\n", handle->rf_data->band);
+		seq_printf(sfp, "bw=%u\n", handle->rf_data->bandwidth);
+		if (handle->rf_data->channel)
+			seq_printf(sfp, "channel=%u\n",
+				   handle->rf_data->channel);
+		else
+			seq_printf(sfp, "channel=\n");
+		if (handle->rf_data->radio_mode[0])
+			seq_printf(sfp, "radio_mode[0]=%u\n",
+				   handle->rf_data->radio_mode[0]);
+		else
+			seq_printf(sfp, "radio_mode[0]=\n");
+		if (handle->rf_data->radio_mode[1])
+			seq_printf(sfp, "radio_mode[1]=%u\n",
+				   handle->rf_data->radio_mode[1]);
+		else
+			seq_printf(sfp, "radio_mode[1]=\n");
+		seq_printf(sfp, "total rx pkt count=%u\n",
+			   handle->rf_data->rx_tot_pkt_count);
+		seq_printf(sfp, "rx multicast/broadcast pkt count=%u\n",
+			   handle->rf_data->rx_mcast_bcast_pkt_count);
+		seq_printf(sfp, "rx fcs error pkt count=%u\n",
+			   handle->rf_data->rx_pkt_fcs_err_count);
+		if (handle->rf_data->tx_power_data[0]) {
+			seq_printf(sfp, "tx_power=%u",
+				   handle->rf_data->tx_power_data[0]);
+			seq_printf(sfp, " %u",
+				   handle->rf_data->tx_power_data[1]);
+			seq_printf(sfp, " %u\n",
+				   handle->rf_data->tx_power_data[2]);
+		} else
+			seq_printf(sfp, "tx_power=\n");
+		seq_printf(sfp, "tx_continuous=%u",
+			   handle->rf_data->tx_cont_data[0]);
+		if (handle->rf_data->tx_cont_data[0] == MTRUE) {
+			seq_printf(sfp, " %u",
+				   handle->rf_data->tx_cont_data[1]);
+			seq_printf(sfp, " 0x%x",
+				   handle->rf_data->tx_cont_data[2]);
+			for (i = 3; i < 6; i++)
+				seq_printf(sfp, " %u",
+					   handle->rf_data->tx_cont_data[i]);
+		}
+		seq_printf(sfp, "\n");
+		seq_printf(sfp, "tx_frame=%u",
+			   handle->rf_data->tx_frame_data[0]);
+		if (handle->rf_data->tx_frame_data[0] == MTRUE) {
+			seq_printf(sfp, " %u",
+				   handle->rf_data->tx_frame_data[1]);
+			seq_printf(sfp, " 0x%x",
+				   handle->rf_data->tx_frame_data[2]);
+			for (i = 3; i < 13; i++)
+				seq_printf(sfp, " %u",
+					   handle->rf_data->tx_frame_data[i]);
+			for (i = 13; i < 20; i++)
+				seq_printf(sfp, " %u",
+					   handle->rf_data->tx_frame_data[i]);
+			seq_printf(sfp, " %02x:%02x:%02x:%02x:%02x:%02x",
+				   handle->rf_data->bssid[0],
+				   handle->rf_data->bssid[1],
+				   handle->rf_data->bssid[2],
+				   handle->rf_data->bssid[3],
+				   handle->rf_data->bssid[4],
+				   handle->rf_data->bssid[5]);
+
+		}
+		seq_printf(sfp, "\n");
+		seq_printf(sfp, "he_tb_tx=%u", handle->rf_data->he_tb_tx[0]);
+		if (handle->rf_data->he_tb_tx[0] == MTRUE) {
+			seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[1]);
+			seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[2]);
+			seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[3]);
+			seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[4]);
+		}
+		seq_printf(sfp, "\n");
+
+	}
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+static int
+woal_config_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_config_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_config_read, PDE(inode)->data);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops config_proc_fops = {
+	.proc_open = woal_config_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+	.proc_write = woal_config_write,
+};
+#else
+static const struct file_operations config_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_config_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = woal_config_write,
+};
+#endif
+
+static int
+woal_drv_dump_read(struct seq_file *sfp, void *data)
+{
+	moal_handle *handle = (moal_handle *)sfp->private;
+	int ret = 0;
+
+	ENTER();
+
+	if (MODULE_GET == 0) {
+		LEAVE();
+		return 0;
+	}
+
+	if (!handle) {
+		PRINTM(MERROR, "handle is NULL!\n");
+		LEAVE();
+		return 0;
+	}
+	if (!handle->drv_dump_buf || !handle->drv_dump_len)
+		handle->drv_dump_buf =
+			woal_dump_drv_info(handle, &handle->drv_dump_len);
+	if (!handle->drv_dump_buf || !handle->drv_dump_len) {
+		PRINTM(MERROR,
+		       "driver dump buffer is NULL or total length is zero\n");
+		goto done;
+	}
+	if (sfp->size < handle->drv_dump_len) {
+		PRINTM(MERROR,
+		       "drv dump size too big, size=%d, drv_dump_len=%d\n",
+		       (int)sfp->size, handle->drv_dump_len);
+		sfp->count = sfp->size;
+		ret = 0;
+		MODULE_PUT;
+		return ret;
+	}
+	memset(sfp->buf, 0x00, sfp->size);
+	sfp->count = handle->drv_dump_len;
+	moal_memcpy_ext(handle, sfp->buf, handle->drv_dump_buf,
+			handle->drv_dump_len, sfp->size);
+done:
+	moal_vfree(handle, handle->drv_dump_buf);
+	handle->drv_dump_len = 0;
+	handle->drv_dump_buf = NULL;
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+static int
+woal_drv_dump_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_drv_dump_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_drv_dump_read, PDE(inode)->data);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops drv_dump_fops = {
+	.proc_open = woal_drv_dump_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+#else
+static const struct file_operations drv_dump_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_drv_dump_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+
+static int
+woal_fw_dump_read(struct seq_file *sfp, void *data)
+{
+	moal_handle *handle = (moal_handle *)sfp->private;
+	int ret = 0;
+
+	ENTER();
+
+	if (MODULE_GET == 0) {
+		LEAVE();
+		return 0;
+	}
+
+	if (!handle) {
+		PRINTM(MERROR, "handle is null!\n");
+		goto done;
+	}
+
+	if (handle->fw_dump == MTRUE) {
+		PRINTM(MERROR, "fw dump is in progress\n");
+		goto done;
+	}
+
+	if (!handle->fw_dump_buf || !handle->fw_dump_len) {
+		PRINTM(MERROR,
+		       "fw dump buffer is NULL or total length is zero\n");
+		goto done;
+	}
+
+	if (sfp->size < handle->fw_dump_len) {
+		PRINTM(MERROR,
+		       "fw dump size too big, size=%d, fw_dump_len=%ld\n",
+		       (int)sfp->size, (long int)handle->fw_dump_len);
+		sfp->count = sfp->size;
+		ret = 0;
+		MODULE_PUT;
+		return ret;
+	}
+
+	sfp->count = handle->fw_dump_len;
+	moal_memcpy_ext(handle, sfp->buf, handle->fw_dump_buf,
+			handle->fw_dump_len, sfp->size);
+	moal_vfree(handle, handle->fw_dump_buf);
+	handle->fw_dump_buf = NULL;
+	handle->fw_dump_len = 0;
+
+done:
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+static int
+woal_fw_dump_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_fw_dump_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_fw_dump_read, PDE(inode)->data);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops fw_dump_fops = {
+	.proc_open = woal_fw_dump_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+#else
+static const struct file_operations fw_dump_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_fw_dump_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+
+/**
+ *  @brief wifi status proc read function
+ *
+ *  @param sfp      pointer to seq_file structure
+ *  @param data
+ *
+ *  @return         number of output data
+ */
+static int
+woal_wifi_status_read(struct seq_file *sfp, void *data)
+{
+	ENTER();
+
+	if (!MODULE_GET) {
+		LEAVE();
+		return 0;
+	}
+
+	seq_printf(sfp, "%d\n", wifi_status);
+
+	MODULE_PUT;
+	LEAVE();
+	return 0;
+}
+
+static int
+woal_wifi_status_proc_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	return single_open(file, woal_wifi_status_read, PDE_DATA(inode));
+#else
+	return single_open(file, woal_wifi_status_read, PDE(inode)->data);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+static const struct proc_ops wifi_status_proc_fops = {
+	.proc_open = woal_wifi_status_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+#else
+static const struct file_operations wifi_status_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = woal_wifi_status_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Convert string to number
+ *
+ *  @param s        Pointer to numbered string
+ *
+ *  @return         Converted number from string s
+ */
+int
+woal_string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+	int pn = 1;
+
+	if (!strncmp(s, "-", 1)) {
+		pn = -1;
+		s++;
+	}
+	if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2)) {
+		base = 16;
+		s += 2;
+	} else
+		base = 10;
+
+	for (; *s; s++) {
+		if ((*s >= '0') && (*s <= '9'))
+			r = (r * base) + (*s - '0');
+		else if ((*s >= 'A') && (*s <= 'F'))
+			r = (r * base) + (*s - 'A' + 10);
+		else if ((*s >= 'a') && (*s <= 'f'))
+			r = (r * base) + (*s - 'a' + 10);
+		else
+			break;
+	}
+
+	return r * pn;
+}
+
+/**
+ *  @brief This function creates proc mwlan directory
+ *  directory structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_root_proc_init(void)
+{
+	ENTER();
+
+	PRINTM(MINFO, "Create /proc/mwlan directory\n");
+
+	proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
+	if (!proc_mwlan) {
+		PRINTM(MERROR,
+		       "woal_root_proc_init: Cannot create /proc/mwlan\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* create /proc/mwlan/wifi_status */
+	proc_create_data(STATUS_PROC, 0666, proc_mwlan, &wifi_status_proc_fops,
+			 NULL);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function removes proc mwlan directory
+ *  directory structure
+ *
+ *  @return         N/A
+ */
+void
+woal_root_proc_remove(void)
+{
+	ENTER();
+
+	remove_proc_entry(STATUS_PROC, proc_mwlan);
+
+	remove_proc_entry(MWLAN_PROC, PROC_DIR);
+	proc_mwlan = NULL;
+
+	LEAVE();
+}
+
+/**
+ *  @brief Create the top level proc directory
+ *
+ *  @param handle   Pointer to woal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_proc_init(moal_handle *handle)
+{
+	struct proc_dir_entry *r;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+	struct proc_dir_entry *pde = proc_mwlan;
+#endif
+	char config_proc_dir[20];
+	char drv_dump_dir[20];
+	char fw_dump_dir[20];
+
+	ENTER();
+
+	if (handle->proc_wlan) {
+		PRINTM(MMSG, "woal_proc_init: proc_wlan is already exist %s\n",
+		       handle->proc_wlan_name);
+		goto done;
+	}
+
+	snprintf(handle->proc_wlan_name, sizeof(handle->proc_wlan_name),
+		 WLAN_PROC, handle->handle_idx);
+	PRINTM(MINFO, "Create Proc Interface %s\n", handle->proc_wlan_name);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+	/* Check if directory already exists */
+	for (pde = pde->subdir; pde; pde = pde->next) {
+		if (pde->namelen && !strcmp(handle->proc_wlan_name, pde->name)) {
+			/* Directory exists */
+			PRINTM(MWARN, "proc interface already exists!\n");
+			handle->proc_wlan = pde;
+			break;
+		}
+	}
+	if (pde == NULL) {
+		handle->proc_wlan =
+			proc_mkdir(handle->proc_wlan_name, proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+		if (handle->proc_wlan)
+			atomic_set(&handle->proc_wlan->count, 1);
+#endif
+	}
+#else
+	handle->proc_wlan = proc_mkdir(handle->proc_wlan_name, proc_mwlan);
+#endif
+	if (!handle->proc_wlan) {
+		PRINTM(MERROR, "Cannot create proc interface %s!\n",
+		       handle->proc_wlan_name);
+		goto done;
+	}
+
+	strcpy(config_proc_dir, "config");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	r = proc_create_data(config_proc_dir, 0666, handle->proc_wlan,
+			     &config_proc_fops, handle);
+#else
+	r = create_proc_entry(config_proc_dir, 0644, handle->proc_wlan);
+	if (r) {
+		r->data = handle;
+		r->proc_fops = &config_proc_fops;
+	}
+#endif
+	if (!r)
+		PRINTM(MERROR, "Fail to create proc config\n");
+
+	strcpy(drv_dump_dir, "drv_dump");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	r = proc_create_data(drv_dump_dir, 0644, handle->proc_wlan,
+			     &drv_dump_fops, handle);
+#else
+	r = create_proc_entry(drv_dump_dir, 0644, handle->proc_wlan);
+	if (r) {
+		r->data = handle;
+		r->proc_fops = &drv_dump_fops;
+	}
+#endif
+	if (!r)
+		PRINTM(MERROR, "Failed to create proc drv dump\n");
+
+	strcpy(fw_dump_dir, "fw_dump");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	r = proc_create_data(fw_dump_dir, 0644, handle->proc_wlan,
+			     &fw_dump_fops, handle);
+#else
+	r = create_proc_entry(fw_dump_dir, 0644, handle->proc_wlan);
+	if (r) {
+		r->data = handle;
+		r->proc_fops = &fw_dump_fops;
+	}
+#endif
+	if (!r)
+		PRINTM(MERROR, "Failed to create proc fw dump\n");
+
+done:
+	LEAVE();
+}
+
+/**
+ *  @brief Remove the top level proc directory
+ *
+ *  @param handle   pointer moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_proc_exit(moal_handle *handle)
+{
+	char config_proc_dir[20];
+	char drv_dump_dir[20];
+	char fw_dump_dir[20];
+
+	ENTER();
+
+	PRINTM(MINFO, "Remove Proc Interface %s\n", handle->proc_wlan_name);
+	if (handle->proc_wlan) {
+		strcpy(config_proc_dir, "config");
+		remove_proc_entry(config_proc_dir, handle->proc_wlan);
+		strcpy(drv_dump_dir, "drv_dump");
+		remove_proc_entry(drv_dump_dir, handle->proc_wlan);
+		strcpy(fw_dump_dir, "fw_dump");
+		remove_proc_entry(fw_dump_dir, handle->proc_wlan);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		/* Remove only if we are the only instance using this */
+		if (atomic_read(&(handle->proc_wlan->count)) > 1) {
+			PRINTM(MWARN, "More than one interface using proc!\n");
+		} else {
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+			atomic_dec(&(handle->proc_wlan->count));
+#endif
+			remove_proc_entry(handle->proc_wlan_name, proc_mwlan);
+
+			handle->proc_wlan = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		}
+#endif
+	}
+	if (handle->fw_dump_buf) {
+		moal_vfree(handle, handle->fw_dump_buf);
+		handle->fw_dump_buf = NULL;
+		handle->fw_dump_len = 0;
+	}
+	if (handle->drv_dump_buf) {
+		moal_vfree(handle, handle->drv_dump_buf);
+		handle->drv_dump_len = 0;
+		handle->drv_dump_buf = NULL;
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief Create proc file for interface
+ *
+ *  @param priv     pointer moal_private
+ *
+ *  @return         N/A
+ */
+void
+woal_create_proc_entry(moal_private *priv)
+{
+	struct proc_dir_entry *r;
+	struct net_device *dev = priv->netdev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	char proc_dir_name[22];
+#endif
+
+	ENTER();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+	if (!priv->proc_entry) {
+		memset(proc_dir_name, 0, sizeof(proc_dir_name));
+		memcpy(proc_dir_name, priv->phandle->proc_wlan_name,
+		       sizeof(proc_dir_name) - 2);
+		proc_dir_name[strlen(proc_dir_name)] = '/';
+
+		if (strlen(dev->name) >
+		    ((sizeof(proc_dir_name) - 1) - (strlen(proc_dir_name)))) {
+			PRINTM(MERROR,
+			       "Failed to create proc entry, device name is too long\n");
+			LEAVE();
+			return;
+		}
+		strcat(proc_dir_name, dev->name);
+		/* Try to create adapterX/dev_name directory first under
+		 * /proc/mwlan/ */
+		priv->proc_entry = proc_mkdir(proc_dir_name, proc_mwlan);
+		if (priv->proc_entry) {
+			/* Success. Continue normally */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+			if (!priv->phandle->proc_wlan) {
+				priv->phandle->proc_wlan =
+					priv->proc_entry->parent;
+			}
+			atomic_inc(&(priv->phandle->proc_wlan->count));
+#endif
+		} else {
+			/* Failure. adapterX/ may not exist. Try to create that
+			 * first */
+			priv->phandle->proc_wlan =
+				proc_mkdir(priv->phandle->proc_wlan_name,
+					   proc_mwlan);
+			if (!priv->phandle->proc_wlan) {
+				/* Failure. Something broken */
+				LEAVE();
+				return;
+			} else {
+				/* Success. Now retry creating mlanX */
+				priv->proc_entry =
+					proc_mkdir(proc_dir_name, proc_mwlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+				atomic_inc(&(priv->phandle->proc_wlan->count));
+#endif
+			}
+		}
+#else
+	if (priv->phandle->proc_wlan && !priv->proc_entry) {
+		priv->proc_entry =
+			proc_mkdir(dev->name, priv->phandle->proc_wlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_inc(&(priv->phandle->proc_wlan->count));
+#endif /* < 3.10.0 */
+#endif /* < 2.6.26 */
+		strcpy(priv->proc_entry_name, dev->name);
+		if (priv->proc_entry) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+			r = proc_create_data("info", 0, priv->proc_entry,
+					     &info_proc_fops, dev);
+#else
+			r = create_proc_entry("info", 0, priv->proc_entry);
+			if (r) {
+				r->data = dev;
+				r->proc_fops = &info_proc_fops;
+			}
+#endif
+			if (!r)
+				PRINTM(MMSG, "Fail to create proc info\n");
+		}
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief Remove proc file
+ *
+ *  @param priv     Pointer moal_private
+ *
+ *  @return         N/A
+ */
+void
+woal_proc_remove(moal_private *priv)
+{
+	ENTER();
+	if (priv->phandle->proc_wlan && priv->proc_entry) {
+		remove_proc_entry("info", priv->proc_entry);
+		remove_proc_entry(priv->proc_entry_name,
+				  priv->phandle->proc_wlan);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+		atomic_dec(&(priv->phandle->proc_wlan->count));
+#endif
+		priv->proc_entry = NULL;
+	}
+	LEAVE();
+}
+#endif
diff --git a/wlan_sd8987/mlinux/moal_sdio.h b/wlan_sd8987/mlinux/moal_sdio.h
new file mode 100755
index 0000000..a5d25ba
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sdio.h
@@ -0,0 +1,188 @@
+/** @file moal_sdio.h
+ *
+ * @brief This file contains definitions for SDIO interface.
+ * driver.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/****************************************************
+Change log:
+****************************************************/
+
+#ifndef _MOAL_SDIO_H
+#define _MOAL_SDIO_H
+
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "moal_main.h"
+
+#ifndef BLOCK_MODE
+/** Block mode */
+#define BLOCK_MODE 1
+#endif
+
+#ifndef BYTE_MODE
+/** Byte Mode */
+#define BYTE_MODE 0
+#endif
+
+#ifndef FIXED_ADDRESS
+/** Fixed address mode */
+#define FIXED_ADDRESS 0
+#endif
+
+#if defined(SD8977)
+#define SD8977_V0 0x0
+#define SD8977_V1 0x8
+#define SD8977_V2 0x9
+#define SD8977_V0_FW_NAME "nxp/sdsd8977_combo.bin"
+#define SD8977_V1_FW_NAME "nxp/sdsd8977_combo_v1.bin"
+#define SD8977_V2_FW_NAME "nxp/sdsd8977_combo_v2.bin"
+#define SD8977_WLAN_V2_FW_NAME "nxp/sd8977_wlan_v2.bin"
+#define SD8977_WLAN_V1_FW_NAME "nxp/sd8977_wlan_v1.bin"
+#define SD8977_WLAN_V0_FW_NAME "nxp/sd8977_wlan.bin"
+#endif /* SD8977_MULTI_FW */
+
+#if defined(SD8887)
+/** SD8887 chip revision ID */
+#define SD8887_A0 0x0
+#define SD8887_A2 0x2
+
+#define SD8887_A0_FW_NAME "nxp/sd8887_uapsta.bin"
+#define SD8887_A2_FW_NAME "nxp/sd8887_uapsta_a2.bin"
+#define SD8887_WLAN_A2_FW_NAME "nxp/sd8887_wlan_a2.bin"
+#define SD8887_WLAN_A0_FW_NAME "nxp/sd8887_wlan.bin"
+#endif /* SD8887_MULTI_FW */
+
+#ifdef SD8801
+#define SD8801_DEFAULT_WLAN_FW_NAME	"nxp/sd8801_uapsta.bin"
+#endif /* SD8801 */
+
+/** Default firmware name */
+#ifdef SD8887
+#define SD8887_DEFAULT_COMBO_FW_NAME "nxp/sd8887_uapsta_a2.bin"
+#define SD8887_DEFAULT_WLAN_FW_NAME "nxp/sd8887_wlan_a2.bin"
+#endif /* SD8887 */
+
+#ifdef SD8977
+#define SD8977_DEFAULT_COMBO_FW_NAME "nxp/sdsd8977_combo_v2.bin"
+#define SD8977_DEFAULT_WLAN_FW_NAME "nxp/sd8977_wlan_v2.bin"
+#endif /* SD8977 */
+
+#ifdef SD8997
+#define SD8997_DEFAULT_COMBO_FW_NAME "nxp/sdsd8997_combo_v4.bin"
+#define SDUART8997_DEFAULT_COMBO_FW_NAME "nxp/sduart8997_combo_v4.bin"
+#define SDSD8997_DEFAULT_COMBO_FW_NAME "nxp/sdsd8997_combo_v4.bin"
+#define SD8997_DEFAULT_WLAN_FW_NAME "nxp/sd8997_wlan_v4.bin"
+#endif /* SD8997 */
+
+#ifdef SD8987
+#define SD8987_DEFAULT_COMBO_FW_NAME "nxp/sdsd8987_combo.bin"
+#define SDUART8987_DEFAULT_COMBO_FW_NAME "nxp/sduart8987_combo.bin"
+#define SDSD8987_DEFAULT_COMBO_FW_NAME "nxp/sdsd8987_combo.bin"
+#define SD8987_DEFAULT_WLAN_FW_NAME "nxp/sd8987_wlan.bin"
+#endif /* SD8987 */
+
+#ifdef SD8897
+#define SD8897_DEFAULT_COMBO_FW_NAME "nxp/sdsd8897_uapsta.bin"
+#define SD8897_DEFAULT_WLAN_FW_NAME "nxp/sd8897_wlan.bin"
+#endif /* SD8897 */
+
+#ifdef SD8978
+#define SD8978_DEFAULT_COMBO_FW_NAME "nxp/sdsdiw416_combo.bin"
+#define SDUART8978_DEFAULT_COMBO_FW_NAME "nxp/sduartiw416_combo.bin"
+#define SDSD8978_DEFAULT_COMBO_FW_NAME "nxp/sdsdiw416_combo.bin"
+#define SD8978_DEFAULT_WLAN_FW_NAME "nxp/sdiw416_wlan.bin"
+#endif /* SD8978 */
+
+#ifdef SD9098
+#define SD9098_Z1Z2 0x00
+#define SD9098_A0 0x01
+#define SD9098_A1 0x02
+#define SD9098_A2 0x03
+#define SD9098_DEFAULT_COMBO_FW_NAME "nxp/sdsd9098_combo.bin"
+#define SDUART9098_DEFAULT_COMBO_FW_NAME "nxp/sduart9098_combo.bin"
+#define SDSD9098_DEFAULT_COMBO_FW_NAME "nxp/sdsd9098_combo.bin"
+#define SD9098_DEFAULT_WLAN_FW_NAME "nxp/sd9098_wlan.bin"
+#define SDUART9098_COMBO_V1_FW_NAME "nxp/sduart9098_combo_v1.bin"
+#define SDSD9098_COMBO_V1_FW_NAME "nxp/sdsd9098_combo_v1.bin"
+#define SD9098_WLAN_V1_FW_NAME "nxp/sd9098_wlan_v1.bin"
+#endif /* SD9098 */
+
+#ifdef SD9097
+#define SD9097_B0 0x01
+#define SD9097_B1 0x02
+#define SD9097_DEFAULT_COMBO_FW_NAME "nxp/sdsdiw620_combo_v1.bin"
+
+#define SD9097_DEFAULT_WLAN_FW_NAME "nxp/sdiw620_wlan_v1.bin"
+#define SDUART9097_COMBO_V1_FW_NAME "nxp/sduartiw620_combo_v1.bin"
+#define SDSD9097_COMBO_V1_FW_NAME "nxp/sdsdiw620_combo_v1.bin"
+#define SD9097_WLAN_V1_FW_NAME "nxp/sdiw620_wlan_v1.bin"
+#endif /* SD9097 */
+
+#ifdef SD9177
+#define SD9177_A0 0x01
+#define SD9177_DEFAULT_COMBO_FW_NAME "nxp/sdsd_nw61x.bin"
+#define SDUART9177_DEFAULT_COMBO_FW_NAME "nxp/sduart_nw61x.bin"
+#define SDSD9177_DEFAULT_COMBO_FW_NAME "sdsd_nw61x.bin"
+#define SD9177_DEFAULT_WLAN_FW_NAME "nxp/sd_w61x.bin"
+/** Device ID for SD9177 */
+#define SD_DEVICE_ID_9177 (0x0205)
+#endif /* SD9177 */
+/********************************************************
+		Global Functions
+********************************************************/
+
+/** Register to bus driver function */
+mlan_status woal_sdiommc_bus_register(void);
+/** Unregister from bus driver function */
+void woal_sdiommc_bus_unregister(void);
+
+int woal_sdio_set_bus_clock(moal_handle *handle, t_u8 option);
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_FUNC_SUSPENDED
+/** Notify SDIO bus driver that WLAN is suspended */
+void woal_wlan_is_suspended(moal_handle *handle);
+#endif
+/** SDIO Suspend */
+int woal_sdio_suspend(struct device *dev);
+/** SDIO Resume */
+int woal_sdio_resume(struct device *dev);
+#endif /* SDIO_SUSPEND_RESUME */
+
+#ifdef SDIO_MMC
+/** Structure: SDIO MMC card */
+struct sdio_mmc_card {
+	/** sdio_func structure pointer */
+	struct sdio_func *func;
+	/** moal_handle structure pointer */
+	moal_handle *handle;
+	/** saved host clock value */
+	unsigned int host_clock;
+};
+void woal_sdio_reset_hw(moal_handle *handle);
+#endif /* SDIO_MMC */
+
+/** cmd52 read write */
+int woal_sdio_read_write_cmd52(moal_handle *handle, int func, int reg, int val);
+#endif /* _MOAL_SDIO_H */
diff --git a/wlan_sd8987/mlinux/moal_sdio_mmc.c b/wlan_sd8987/mlinux/moal_sdio_mmc.c
new file mode 100755
index 0000000..02019a6
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sdio_mmc.c
@@ -0,0 +1,2475 @@
+/** @file moal_sdio_mmc.c
+ *
+ *  @brief This file contains SDIO MMC IF (interface) module
+ *  related functions.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/****************************************************
+Change log:
+	02/25/09: Initial creation -
+		  This file supports SDIO MMC only
+****************************************************/
+
+#include <linux/firmware.h>
+
+#include "moal_sdio.h"
+
+/** define nxp vendor id */
+#ifdef SD9177
+#define NXP_VENDOR_ID 0x0471
+#endif
+#define MRVL_VENDOR_ID 0x02df
+
+/********************************************************
+		Local Variables
+********************************************************/
+/* moal interface ops */
+static moal_if_ops sdiommc_ops;
+/********************************************************
+		Global Variables
+********************************************************/
+
+#ifdef SD8887
+/** Device ID for SD8887 */
+#define SD_DEVICE_ID_8887 (0x9135)
+#endif
+#ifdef SD8801
+/** Device ID for SD8801 FN1 */
+#define SD_DEVICE_ID_8801 (0x9139)
+#endif
+#ifdef SD8897
+/** Device ID for SD8897 */
+#define SD_DEVICE_ID_8897 (0x912d)
+#endif
+#ifdef SD8977
+/** Device ID for SD8977 */
+#define SD_DEVICE_ID_8977 (0x9145)
+#endif
+#ifdef SD8978
+/** Device ID for SD8978 */
+#define SD_DEVICE_ID_8978 (0x9159)
+#endif
+#ifdef SD8997
+/** Device ID for SD8997 */
+#define SD_DEVICE_ID_8997 (0x9141)
+#endif
+#ifdef SD8987
+/** Device ID for SD8987 */
+#define SD_DEVICE_ID_8987 (0x9149)
+#endif
+#ifdef SD9098
+/** Device ID for SD9098 */
+#define SD_DEVICE_ID_9098_FN1 (0x914D)
+/** Device ID for SD9098 */
+#define SD_DEVICE_ID_9098_FN2 (0x914E)
+#endif
+#ifdef SD9097
+/** Device ID for SD9097 */
+#define SD_DEVICE_ID_9097 (0x9155)
+#endif
+
+/** WLAN IDs */
+static const struct sdio_device_id wlan_ids[] = {
+#ifdef SD8887
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8887)},
+#endif
+#ifdef SD8801
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8801)},
+#endif
+#ifdef SD8897
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8897)},
+#endif
+#ifdef SD8977
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8977)},
+#endif
+#ifdef SD8978
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8978)},
+#endif
+#ifdef SD8997
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8997)},
+#endif
+#ifdef SD8987
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8987)},
+#endif
+#ifdef SD9098
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_9098_FN1)},
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_9098_FN2)},
+#endif
+#ifdef SD9097
+	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_9097)},
+#endif
+#ifdef SD9177
+	{SDIO_DEVICE(NXP_VENDOR_ID, SD_DEVICE_ID_9177)},
+#endif
+	{},
+};
+
+MODULE_DEVICE_TABLE(sdio, wlan_ids);
+
+int woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id);
+void woal_sdio_remove(struct sdio_func *func);
+#ifdef SDIO
+static void woal_sdiommc_reg_dbg(pmoal_handle handle);
+#endif
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+int woal_sdio_suspend(struct device *dev);
+int woal_sdio_resume(struct device *dev);
+
+static struct dev_pm_ops wlan_sdio_pm_ops = {
+	.suspend = woal_sdio_suspend,
+	.resume = woal_sdio_resume,
+};
+
+void woal_sdio_shutdown(struct device *dev);
+#endif
+#endif
+
+// clang-format off
+static struct sdio_driver REFDATA wlan_sdio = {
+	.name = "wlan_sdio",
+	.id_table = wlan_ids,
+	.probe = woal_sdio_probe,
+	.remove = woal_sdio_remove,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	.drv = {
+		.owner = THIS_MODULE,
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+		.pm = &wlan_sdio_pm_ops,
+		.shutdown = woal_sdio_shutdown,
+#endif
+#endif
+
+		}
+#else
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+	.drv = {
+		.pm = &wlan_sdio_pm_ops,
+		.shutdown = woal_sdio_shutdown,
+		}
+#endif
+#endif
+#endif
+};
+
+// clang-format on
+
+/********************************************************
+		Local Functions
+********************************************************/
+static void woal_sdiommc_dump_fw_info(moal_handle *phandle);
+#if 0
+/**  @brief This function dump the sdio register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @return         N/A
+ */
+static void
+woal_dump_sdio_reg(moal_handle *handle)
+{
+	int ret = 0;
+	t_u8 data, i;
+	int fun0_reg[] = { 0x05, 0x04 };
+	t_u8 array_size = 0;
+#ifdef SD8897
+	int fun1_reg_8897[] = { 0x03, 0x04, 0x05, 0x06, 0x07, 0xC0, 0xC1 };
+#endif
+	int fun1_reg_other[] = { 0x03, 0x04, 0x05, 0x60, 0x61 };
+	int *fun1_reg = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(fun0_reg); i++) {
+		data = sdio_f0_readb(((struct sdio_mmc_card *)handle->card)->
+				     func, fun0_reg[i], &ret);
+		PRINTM(MMSG, "fun0: reg 0x%02x=0x%02x ret=%d\n", fun0_reg[i],
+		       data, ret);
+	}
+
+#ifdef SD8897
+	if (IS_SD8897(handle->card_type)) {
+		fun1_reg = fun1_reg_8897;
+		array_size = sizeof(fun1_reg_8897) / sizeof(int);
+	} else {
+#endif
+		fun1_reg = fun1_reg_other;
+		array_size = sizeof(fun1_reg_other) / sizeof(int);
+#ifdef SD8897
+	}
+#endif
+	for (i = 0; i < array_size; i++) {
+		data = sdio_readb(((struct sdio_mmc_card *)handle->card)->func,
+				  fun1_reg[i], &ret);
+		PRINTM(MMSG, "fun1: reg 0x%02x=0x%02x ret=%d\n", fun1_reg[i],
+		       data, ret);
+	}
+	return;
+}
+#endif
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief This function handles the interrupt.
+ *
+ *  @param func     A pointer to the sdio_func structure
+ *  @return         N/A
+ */
+static void
+woal_sdio_interrupt(struct sdio_func *func)
+{
+	moal_handle *handle;
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->handle) {
+		PRINTM(MINFO,
+		       "sdio_mmc_interrupt(func = %p) card or handle is NULL, card=%p\n",
+		       func, card);
+		LEAVE();
+		return;
+	}
+	handle = card->handle;
+	if (handle->surprise_removed == MTRUE) {
+		LEAVE();
+		return;
+	}
+	handle->main_state = MOAL_RECV_INT;
+	PRINTM(MINFO, "*** IN SDIO IRQ ***\n");
+	PRINTM(MINTR, "*\n");
+
+	/* call mlan_interrupt to read int status */
+	mlan_interrupt(0, handle->pmlan_adapter);
+#ifdef SDIO_SUSPEND_RESUME
+	if (handle->is_suspended) {
+		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
+		LEAVE();
+		return;
+	}
+#endif
+	handle->main_state = MOAL_START_MAIN_PROCESS;
+	/* Call MLAN main process */
+	mlan_main_process(handle->pmlan_adapter);
+	handle->main_state = MOAL_END_MAIN_PROCESS;
+	LEAVE();
+}
+
+/**  @brief This function updates the card types
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param card     A Pointer to card
+ *
+ *  @return         N/A
+ */
+static t_u16
+woal_update_card_type(t_void *card)
+{
+	struct sdio_mmc_card *cardp_sd = (struct sdio_mmc_card *)card;
+	t_u16 card_type = 0;
+
+	/* Update card type */
+#ifdef SD8887
+	if (cardp_sd->func->device == SD_DEVICE_ID_8887) {
+		card_type = CARD_TYPE_SD8887;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD8887,
+				strlen(CARD_SD8887), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V15, strlen(V15),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD8801
+	if (cardp_sd->func->device == SD_DEVICE_ID_8801) {
+		card_type = CARD_TYPE_SD8801;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD8801,
+				strlen(CARD_SD8801), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V14, strlen(V14),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+
+#ifdef SD8897
+	if (cardp_sd->func->device == SD_DEVICE_ID_8897) {
+		card_type = CARD_TYPE_SD8897;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD8897,
+				strlen(CARD_SD8897), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V15, strlen(V15),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD8977
+	if (cardp_sd->func->device == SD_DEVICE_ID_8977) {
+		card_type = CARD_TYPE_SD8977;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD8977,
+				strlen(CARD_SD8977), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD8978
+	if (cardp_sd->func->device == SD_DEVICE_ID_8978) {
+		card_type = CARD_TYPE_SD8978;
+		moal_memcpy_ext(NULL, driver_version, "SDIW416",
+				strlen("SDIW416"), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD8997
+	if (cardp_sd->func->device == SD_DEVICE_ID_8997) {
+		card_type = CARD_TYPE_SD8997;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD8997,
+				strlen(CARD_SD8997), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD8987
+	if (cardp_sd->func->device == SD_DEVICE_ID_8987) {
+		card_type = CARD_TYPE_SD8987;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD8987,
+				strlen(CARD_SD8987), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD9097
+	if (cardp_sd->func->device == SD_DEVICE_ID_9097) {
+		card_type = CARD_TYPE_SD9097;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD9097,
+				strlen(CARD_SD9097), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V17, strlen(V17),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD9098
+	if (cardp_sd->func->device == SD_DEVICE_ID_9098_FN1 ||
+	    cardp_sd->func->device == SD_DEVICE_ID_9098_FN2) {
+		card_type = CARD_TYPE_SD9098;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD9098,
+				strlen(CARD_SD9098), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V17, strlen(V17),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+#ifdef SD9177
+	if (cardp_sd->func->device == SD_DEVICE_ID_9177) {
+		card_type = CARD_TYPE_SD9177;
+		moal_memcpy_ext(NULL, driver_version, CARD_SD9177,
+				strlen(CARD_SD9177), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V18, strlen(V18),
+				strlen(driver_version) -
+				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
+	}
+#endif
+	return card_type;
+}
+
+/**  @brief This function handles client driver probe.
+ *
+ *  @param func     A pointer to sdio_func structure.
+ *  @param id       A pointer to sdio_device_id structure.
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE/error code
+ */
+int
+woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = NULL;
+	t_u16 card_type = 0;
+
+	ENTER();
+
+	PRINTM(MMSG, "vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
+	       func->vendor, func->device, func->class, func->num);
+
+	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	if (!card) {
+		PRINTM(MFATAL,
+		       "Failed to allocate memory in probe function!\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	card->func = func;
+
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	/* The byte mode patch is available in kernel MMC driver
+	 * which fixes one issue in MP-A transfer.
+	 * bit1: use func->cur_blksize for byte mode
+	 */
+	func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+	/* wait for chip fully wake up */
+	if (!func->enable_timeout)
+		func->enable_timeout = 200;
+#endif
+	sdio_claim_host(func);
+	ret = sdio_enable_func(func);
+	if (ret) {
+		sdio_release_host(func);
+		PRINTM(MFATAL, "sdio_enable_func() failed: ret=%d\n", ret);
+		ret = -EIO;
+		goto err;
+	}
+	sdio_release_host(func);
+
+	card_type = woal_update_card_type(card);
+	if (!card_type) {
+		PRINTM(MERROR, "sdmmc probe: woal_update_card_type() failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err;
+	}
+
+	if (NULL ==
+	    woal_add_card(card, &card->func->dev, &sdiommc_ops, card_type)) {
+		PRINTM(MERROR, "woal_add_card failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err;
+	}
+#ifdef IMX_SUPPORT
+	woal_regist_oob_wakeup_irq(card->handle);
+#endif /* IMX_SUPPORT */
+
+	LEAVE();
+	return ret;
+err:
+	kfree(card);
+	sdio_claim_host(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	LEAVE();
+	return ret;
+}
+
+/**  @brief This function handles client driver remove.
+ *
+ *  @param func     A pointer to sdio_func structure.
+ *  @return         N/A
+ */
+void
+woal_sdio_remove(struct sdio_func *func)
+{
+	struct sdio_mmc_card *card;
+
+	ENTER();
+
+	if (func) {
+		PRINTM(MINFO, "SDIO func=%d\n", func->num);
+		card = sdio_get_drvdata(func);
+		if (card) {
+#ifdef IMX_SUPPORT
+			woal_unregist_oob_wakeup_irq(card->handle);
+#endif /* IMX_SUPPORT */
+			woal_remove_card(card);
+			kfree(card);
+		}
+	}
+
+	LEAVE();
+}
+
+#ifdef SDIO_SUSPEND_RESUME
+#ifdef MMC_PM_KEEP_POWER
+#ifdef MMC_PM_FUNC_SUSPENDED
+/**  @brief This function tells lower driver that WLAN is suspended
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @return         N/A
+ */
+void
+woal_wlan_is_suspended(moal_handle *handle)
+{
+	ENTER();
+	if (handle->suspend_notify_req == MTRUE) {
+		handle->is_suspended = MTRUE;
+		sdio_func_suspended(((struct sdio_mmc_card *)handle->card)->
+				    func);
+	}
+	LEAVE();
+}
+#endif
+
+/**  @brief This function handles client driver shutdown
+ *
+ *  @param dev      A pointer to device structure
+ *  @return         N/A
+ */
+void
+woal_sdio_shutdown(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	moal_handle *handle = NULL;
+	struct sdio_mmc_card *cardp;
+	mlan_ds_ps_info pm_info;
+	int i, retry_num = 8;
+
+	ENTER();
+	PRINTM(MCMND, "<--- Enter woal_sdio_shutdown --->\n");
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->handle) {
+		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
+		LEAVE();
+		return;
+	}
+	handle = cardp->handle;
+	for (i = 0; i < handle->priv_num; i++)
+		netif_device_detach(handle->priv[i]->netdev);
+
+	if (moal_extflg_isset(handle, EXT_SHUTDOWN_HS)) {
+		handle->shutdown_hs_in_process = MTRUE;
+		memset(&pm_info, 0, sizeof(pm_info));
+		for (i = 0; i < retry_num; i++) {
+			if (MLAN_STATUS_SUCCESS ==
+			    woal_get_pm_info(woal_get_priv(handle,
+							   MLAN_BSS_ROLE_ANY),
+					     &pm_info)) {
+				if (pm_info.is_suspend_allowed == MTRUE)
+					break;
+				else
+					PRINTM(MMSG,
+					       "Shutdown not allowed and retry again\n");
+			}
+			woal_sched_timeout(100);
+		}
+		if (pm_info.is_suspend_allowed == MFALSE) {
+			PRINTM(MMSG, "Shutdown not allowed\n");
+			goto done;
+		}
+		woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
+
+		wait_event_interruptible_timeout(handle->hs_activate_wait_q,
+						 handle->
+						 hs_activate_wait_q_woken,
+						 HS_ACTIVE_TIMEOUT);
+		if (handle->hs_activated == MTRUE)
+			PRINTM(MMSG, "HS actived in shutdown\n");
+		else
+			PRINTM(MMSG, "Fail to enable HS in shutdown\n");
+	} else {
+		for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+			if (handle->priv[i]) {
+				if (handle->priv[i]->media_connected == MTRUE
+#ifdef UAP_SUPPORT
+				    || (GET_BSS_ROLE(handle->priv[i]) ==
+					MLAN_BSS_ROLE_UAP)
+#endif
+					) {
+					PRINTM(MIOCTL,
+					       "disconnect on suspend\n");
+					woal_disconnect(handle->priv[i],
+							MOAL_NO_WAIT, NULL,
+							DEF_DEAUTH_REASON_CODE);
+				}
+			}
+		}
+	}
+
+done:
+	PRINTM(MCMND, "<--- Leave woal_sdio_shutdown --->\n");
+	LEAVE();
+	return;
+}
+
+/**  @brief This function handles client driver suspend
+ *
+ *  @param dev      A pointer to device structure
+ *  @return         MLAN_STATUS_SUCCESS or error code
+ */
+int
+woal_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	moal_handle *handle = NULL;
+	struct sdio_mmc_card *cardp;
+	int i, retry_num = 8;
+	int ret = MLAN_STATUS_SUCCESS;
+	int hs_actived = 0;
+	mlan_ds_ps_info pm_info;
+
+	ENTER();
+	PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n");
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->handle) {
+		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	handle = cardp->handle;
+
+	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER) &&
+	    !(pm_flags & MMC_PM_KEEP_POWER)) {
+		PRINTM(MERROR,
+		       "%s: cannot remain alive while host is suspended\n",
+		       sdio_func_id(func));
+		LEAVE();
+		return -ENOSYS;
+	}
+	if (handle->is_suspended == MTRUE) {
+		PRINTM(MWARN, "Device already suspended\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	if (handle->fw_dump) {
+		PRINTM(MMSG, "suspend not allowed while FW dump!");
+		ret = -EBUSY;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA))
+			woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT);
+	}
+#endif
+	handle->suspend_fail = MFALSE;
+	memset(&pm_info, 0, sizeof(pm_info));
+	for (i = 0; i < retry_num; i++) {
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+				     &pm_info)) {
+			if (pm_info.is_suspend_allowed == MTRUE)
+				break;
+			else
+				PRINTM(MMSG,
+				       "Suspend not allowed and retry again\n");
+		}
+		woal_sched_timeout(100);
+	}
+	if (pm_info.is_suspend_allowed == MFALSE) {
+		PRINTM(MMSG, "Suspend not allowed\n");
+		ret = -EBUSY;
+		goto done;
+	}
+
+	for (i = 0; i < handle->priv_num; i++)
+		netif_device_detach(handle->priv[i]->netdev);
+
+	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER)) {
+		/* Enable the Host Sleep */
+#ifdef MMC_PM_FUNC_SUSPENDED
+		handle->suspend_notify_req = MTRUE;
+#endif
+		hs_actived =
+			woal_enable_hs(woal_get_priv
+				       (handle, MLAN_BSS_ROLE_ANY));
+#ifdef MMC_PM_FUNC_SUSPENDED
+		handle->suspend_notify_req = MFALSE;
+#endif
+		if (hs_actived) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 4)
+			if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
+				ret = sdio_set_host_pm_flags(func,
+							     MMC_PM_WAKE_SDIO_IRQ);
+				PRINTM(MCMND,
+				       "suspend with MMC_PM_WAKE_SDIO_IRQ ret=%d\n",
+				       ret);
+			}
+#endif
+#ifdef MMC_PM_SKIP_RESUME_PROBE
+			PRINTM(MCMND,
+			       "suspend with MMC_PM_KEEP_POWER and MMC_PM_SKIP_RESUME_PROBE\n");
+			ret = sdio_set_host_pm_flags(func,
+						     MMC_PM_KEEP_POWER |
+						     MMC_PM_SKIP_RESUME_PROBE);
+#else
+			PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
+			ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+#endif
+		} else {
+			PRINTM(MMSG, "HS not actived, suspend fail!");
+			handle->suspend_fail = MTRUE;
+			for (i = 0; i < handle->priv_num; i++)
+				netif_device_attach(handle->priv[i]->netdev);
+			ret = -EBUSY;
+			goto done;
+		}
+	}
+
+	/* Indicate device suspended */
+	handle->is_suspended = MTRUE;
+#ifdef IMX_SUPPORT
+	woal_enable_oob_wakeup_irq(handle);
+#endif /* IMX_SUPPORT */
+done:
+	PRINTM(MCMND, "<--- Leave woal_sdio_suspend --->\n");
+	LEAVE();
+	return ret;
+}
+
+/**  @brief This function handles client driver resume
+ *
+ *  @param dev      A pointer to device structure
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+int
+woal_sdio_resume(struct device *dev)
+{
+	struct sdio_func *func = dev_to_sdio_func(dev);
+	mmc_pm_flag_t pm_flags = 0;
+	moal_handle *handle = NULL;
+	struct sdio_mmc_card *cardp;
+	int i;
+
+	ENTER();
+	PRINTM(MCMND, "<--- Enter woal_sdio_resume --->\n");
+	pm_flags = sdio_get_host_pm_caps(func);
+	PRINTM(MCMND, "%s: resume: PM flags = 0x%x\n", sdio_func_id(func),
+	       pm_flags);
+	cardp = sdio_get_drvdata(func);
+	if (!cardp || !cardp->handle) {
+		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	handle = cardp->handle;
+
+	if (handle->is_suspended == MFALSE) {
+		PRINTM(MWARN, "Device already resumed\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	handle->is_suspended = MFALSE;
+	if (woal_check_driver_status(handle)) {
+		PRINTM(MERROR, "Resuem, device is in hang state\n");
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+	for (i = 0; i < handle->priv_num; i++)
+		netif_device_attach(handle->priv[i]->netdev);
+
+	/* Disable Host Sleep */
+	woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MOAL_NO_WAIT);
+#ifdef IMX_SUPPORT
+	woal_disable_oob_wakeup_irq(handle);
+#endif /* IMX_SUPPORT */
+	PRINTM(MCMND, "<--- Leave woal_sdio_resume --->\n");
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+#endif /* SDIO_SUSPEND_RESUME */
+
+/**
+ *  @brief This function writes data into card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdiommc_write_reg(moal_handle *handle, t_u32 reg, t_u32 data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,
+		    reg, (int *)&ret);
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdiommc_read_reg(moal_handle *handle, t_u32 reg, t_u32 *data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 val;
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
+			 (int *)&ret);
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	*data = val;
+
+	return ret;
+}
+
+/**
+ *  @brief This function writes data into card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdio_writeb(moal_handle *handle, t_u32 reg, t_u8 data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,
+		    reg, (int *)&ret);
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from card register
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdio_readb(moal_handle *handle, t_u32 reg, t_u8 *data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 val;
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
+			 (int *)&ret);
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	*data = val;
+
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from card register FN0
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param reg      Register offset
+ *  @param data     Value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdio_f0_readb(moal_handle *handle, t_u32 reg, t_u8 *data)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 val;
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	val = sdio_f0_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
+			    (int *)&ret);
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	*data = val;
+
+	return ret;
+}
+
+/**
+ *  @brief This function use SG mode to read/write data into card memory
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param pmbuf_list   Pointer to a linked list of mlan_buffer structure
+ *  @param port     Port
+ *  @param write    write flag
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdio_rw_mb(moal_handle *handle, pmlan_buffer pmbuf_list,
+		t_u32 port, t_u8 write)
+{
+	struct scatterlist sg_list[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
+	int num_sg = pmbuf_list->use_count;
+	int i = 0;
+	mlan_buffer *pmbuf = NULL;
+	struct mmc_request mmc_req;
+	struct mmc_command mmc_cmd;
+	struct mmc_data mmc_dat;
+	struct sdio_func *func = ((struct sdio_mmc_card *)handle->card)->func;
+	t_u32 ioport = (port & MLAN_SDIO_IO_PORT_MASK);
+	t_u32 blkcnt = pmbuf_list->data_len / MLAN_SDIO_BLOCK_SIZE;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	int status;
+#endif
+
+	if (num_sg > SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX) {
+		PRINTM(MERROR, "ERROR: num_sg=%d", num_sg);
+		return MLAN_STATUS_FAILURE;
+	}
+	sg_init_table(sg_list, num_sg);
+	pmbuf = pmbuf_list->pnext;
+	for (i = 0; i < num_sg; i++) {
+		if (pmbuf == pmbuf_list)
+			break;
+		sg_set_buf(&sg_list[i], pmbuf->pbuf + pmbuf->data_offset,
+			   pmbuf->data_len);
+		pmbuf = pmbuf->pnext;
+	}
+	memset(&mmc_req, 0, sizeof(struct mmc_request));
+	memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+	memset(&mmc_dat, 0, sizeof(struct mmc_data));
+
+	mmc_dat.sg = sg_list;
+	mmc_dat.sg_len = num_sg;
+	mmc_dat.blksz = MLAN_SDIO_BLOCK_SIZE;
+	mmc_dat.blocks = blkcnt;
+	mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+
+	mmc_cmd.opcode = SD_IO_RW_EXTENDED;
+	mmc_cmd.arg = write ? 1 << 31 : 0;
+	mmc_cmd.arg |= (func->num & 0x7) << 28;
+	mmc_cmd.arg |= 1 << 27;	/* block basic */
+	mmc_cmd.arg |= 0;	/* fix address */
+	mmc_cmd.arg |= (ioport & 0x1FFFF) << 9;
+	mmc_cmd.arg |= blkcnt & 0x1FF;
+	mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+
+	mmc_req.cmd = &mmc_cmd;
+	mmc_req.data = &mmc_dat;
+
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	mmc_set_data_timeout(&mmc_dat,
+			     ((struct sdio_mmc_card *)handle->card)->func->
+			     card);
+	mmc_wait_for_req(((struct sdio_mmc_card *)handle->card)->func->card->
+			 host, &mmc_req);
+
+	if (mmc_cmd.error || mmc_dat.error) {
+		PRINTM(MERROR, "CMD53 %s cmd_error = %d data_error=%d\n",
+		       write ? "write" : "read", mmc_cmd.error, mmc_dat.error);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+		/* issue abort cmd52 command through F0 */
+		sdio_f0_writeb(((struct sdio_mmc_card *)handle->card)->func,
+			       0x01, SDIO_CCCR_ABORT, &status);
+#endif
+		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+		return MLAN_STATUS_FAILURE;
+	}
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function writes multiple bytes into card memory
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param pmbuf    Pointer to mlan_buffer structure
+ *  @param port     Port
+ *  @param timeout  Time out value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdiommc_write_data_sync(moal_handle *handle,
+			     mlan_buffer *pmbuf, t_u32 port, t_u32 timeout)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *buffer = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	t_u8 blkmode =
+		(port & MLAN_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
+	t_u32 blksz = (blkmode == BLOCK_MODE) ? MLAN_SDIO_BLOCK_SIZE : 1;
+	t_u32 blkcnt = (blkmode == BLOCK_MODE) ?
+		(pmbuf->data_len / MLAN_SDIO_BLOCK_SIZE) : pmbuf->data_len;
+	t_u32 ioport = (port & MLAN_SDIO_IO_PORT_MASK);
+	int status = 0;
+	if (pmbuf->use_count > 1)
+		return woal_sdio_rw_mb(handle, pmbuf, port, MTRUE);
+#ifdef SDIO_MMC_DEBUG
+	handle->cmd53w = 1;
+#endif
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	status = sdio_writesb(((struct sdio_mmc_card *)handle->card)->func,
+			      ioport, buffer, blkcnt * blksz);
+	if (!status)
+		ret = MLAN_STATUS_SUCCESS;
+	else {
+		PRINTM(MERROR, "cmd53 write error=%d\n", status);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+		/* issue abort cmd52 command through F0 */
+		sdio_f0_writeb(((struct sdio_mmc_card *)handle->card)->func,
+			       0x01, SDIO_CCCR_ABORT, &status);
+#endif
+	}
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#ifdef SDIO_MMC_DEBUG
+	handle->cmd53w = 2;
+#endif
+	return ret;
+}
+
+/**
+ *  @brief This function reads multiple bytes from card memory
+ *
+ *  @param handle   A Pointer to the moal_handle structure
+ *  @param pmbuf    Pointer to mlan_buffer structure
+ *  @param port     Port
+ *  @param timeout  Time out value
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdiommc_read_data_sync(moal_handle *handle,
+			    mlan_buffer *pmbuf, t_u32 port, t_u32 timeout)
+{
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *buffer = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	t_u8 blkmode =
+		(port & MLAN_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
+	t_u32 blksz = (blkmode == BLOCK_MODE) ? MLAN_SDIO_BLOCK_SIZE : 1;
+	t_u32 blkcnt = (blkmode == BLOCK_MODE) ?
+		(pmbuf->data_len / MLAN_SDIO_BLOCK_SIZE) : pmbuf->data_len;
+	t_u32 ioport = (port & MLAN_SDIO_IO_PORT_MASK);
+	int status = 0;
+	if (pmbuf->use_count > 1)
+		return woal_sdio_rw_mb(handle, pmbuf, port, MFALSE);
+#ifdef SDIO_MMC_DEBUG
+	handle->cmd53r = 1;
+#endif
+	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
+	status = sdio_readsb(((struct sdio_mmc_card *)handle->card)->func,
+			     buffer, ioport, blkcnt * blksz);
+	if (!status) {
+		ret = MLAN_STATUS_SUCCESS;
+	} else {
+		PRINTM(MERROR, "cmd53 read error=%d\n", status);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+		/* issue abort cmd52 command through F0 */
+		sdio_f0_writeb(((struct sdio_mmc_card *)handle->card)->func,
+			       0x01, SDIO_CCCR_ABORT, &status);
+#endif
+	}
+	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
+#ifdef SDIO_MMC_DEBUG
+	handle->cmd53r = 2;
+#endif
+	return ret;
+}
+
+/**
+ *  @brief This function registers the IF module in bus driver
+ *
+ *  @return    MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_sdiommc_bus_register(void)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* SDIO Driver Registration */
+	if (sdio_register_driver(&wlan_sdio)) {
+		PRINTM(MFATAL, "SDIO Driver Registration Failed \n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function de-registers the IF module in bus driver
+ *
+ *  @return         N/A
+ */
+void
+woal_sdiommc_bus_unregister(void)
+{
+	ENTER();
+
+	/* SDIO Driver Unregistration */
+	sdio_unregister_driver(&wlan_sdio);
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function de-registers the device
+ *
+ *  @param handle A pointer to moal_handle structure
+ *  @return         N/A
+ */
+static void
+woal_sdiommc_unregister_dev(moal_handle *handle)
+{
+	ENTER();
+	if (handle->card) {
+		struct sdio_mmc_card *card = handle->card;
+		struct sdio_func *func = card->func;
+
+		/* Release the SDIO IRQ */
+		sdio_claim_host(card->func);
+		sdio_release_irq(card->func);
+		sdio_disable_func(card->func);
+		if (handle->driver_status)
+			mmc_hw_reset(func->card->host);
+		sdio_release_host(card->func);
+
+		sdio_set_drvdata(card->func, NULL);
+
+		PRINTM(MWARN, "Making the sdio dev card as NULL\n");
+		card->handle = NULL;
+	}
+
+	LEAVE();
+}
+
+/**
+ *  @brief This function registers the device
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_sdiommc_register_dev(moal_handle *handle)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = handle->card;
+	struct sdio_func *func;
+
+	ENTER();
+
+	/* save adapter pointer in card */
+	card->handle = handle;
+	func = card->func;
+	sdio_claim_host(func);
+	/* Request the SDIO IRQ */
+	ret = sdio_claim_irq(func, woal_sdio_interrupt);
+	if (ret) {
+		PRINTM(MFATAL, "sdio_claim_irq failed: ret=%d\n", ret);
+		goto release_host;
+	}
+
+	/* Set block size */
+	ret = sdio_set_block_size(card->func, MLAN_SDIO_BLOCK_SIZE);
+	if (ret) {
+		PRINTM(MERROR,
+		       "sdio_set_block_seize(): cannot set SDIO block size\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto release_irq;
+	}
+
+	sdio_release_host(func);
+	sdio_set_drvdata(func, card);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+
+release_irq:
+	sdio_release_irq(func);
+release_host:
+	sdio_release_host(func);
+	handle->card = NULL;
+
+	LEAVE();
+	return MLAN_STATUS_FAILURE;
+}
+
+/**
+ *  @brief This function set bus clock on/off
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param option   TRUE--on , FALSE--off
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+int
+woal_sdio_set_bus_clock(moal_handle *handle, t_u8 option)
+{
+	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)handle->card;
+	struct mmc_host *host = cardp->func->card->host;
+
+	ENTER();
+	if (option == MTRUE) {
+		/* restore value if non-zero */
+		if (cardp->host_clock)
+			host->ios.clock = cardp->host_clock;
+	} else {
+		/* backup value if non-zero, then clear */
+		if (host->ios.clock)
+			cardp->host_clock = host->ios.clock;
+		host->ios.clock = 0;
+	}
+
+	host->ops->set_ios(host, &host->ios);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function updates card reg based on the Cmd52 value in dev
+ * structure
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param func     A pointer to store func variable
+ *  @param reg      A pointer to store reg variable
+ *  @param val      A pointer to store val variable
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+int
+woal_sdio_read_write_cmd52(moal_handle *handle, int func, int reg, int val)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)handle->card;
+
+	ENTER();
+	/* Save current func and reg for read */
+	handle->cmd52_func = func;
+	handle->cmd52_reg = reg;
+	sdio_claim_host(card->func);
+	if (val >= 0) {
+		/* Perform actual write only if val is provided */
+		if (func)
+			sdio_writeb(card->func, val, reg, &ret);
+		else
+			sdio_f0_writeb(card->func, val, reg, &ret);
+		if (ret) {
+			PRINTM(MERROR,
+			       "Cannot write value (0x%x) to func %d reg 0x%x\n",
+			       val, func, reg);
+		} else {
+			PRINTM(MMSG, "write value (0x%x) to func %d reg 0x%x\n",
+			       (u8)val, func, reg);
+			handle->cmd52_val = val;
+		}
+	} else {
+		if (func)
+			val = sdio_readb(card->func, reg, &ret);
+		else
+			val = sdio_f0_readb(card->func, reg, &ret);
+		if (ret) {
+			PRINTM(MERROR,
+			       "Cannot read value from func %d reg 0x%x\n",
+			       func, reg);
+		} else {
+			PRINTM(MMSG,
+			       "read value (0x%x) from func %d reg 0x%x\n",
+			       (u8)val, func, reg);
+			handle->cmd52_val = val;
+		}
+	}
+	sdio_release_host(card->func);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function check if this is second mac
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @return         MTRUE/MFALSE
+ *
+ */
+static t_u8
+woal_sdiommc_is_second_mac(moal_handle *handle)
+{
+#ifdef SD9098
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)handle->card;
+	if (card->func->device == SD_DEVICE_ID_9098_FN2)
+		return MTRUE;
+#endif
+	return MFALSE;
+}
+
+static mlan_status
+woal_sdiommc_get_fw_name(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#ifdef SD9098
+	struct sdio_mmc_card *card = (struct sdio_mmc_card *)handle->card;
+#endif
+	t_u32 revision_id = 0;
+	t_u32 rev_id_reg = handle->card_info->rev_id_reg;
+
+#if defined(SD8987) || defined(SD8997) || defined(SD9098) || defined(SD9097) || defined(SD8978) || defined(SD9177)
+	t_u32 magic_reg = handle->card_info->magic_reg;
+	t_u32 magic = 0;
+	t_u32 host_strap_reg = handle->card_info->host_strap_reg;
+	t_u32 strap = 0;
+#endif
+
+	ENTER();
+
+	if (handle->params.fw_name)
+		goto done;
+#ifdef SD8801
+	if (IS_SD8801(handle->card_type))
+		goto done;
+#endif
+	/** Revision ID register */
+	woal_sdiommc_read_reg(handle, rev_id_reg, &revision_id);
+	PRINTM(MCMND, "revision_id=0x%x\n", revision_id);
+
+#if defined(SD8987) || defined(SD8997) || defined(SD9098) || defined(SD9097) || defined(SD8978) || defined(SD9177)
+	/** Revision ID register */
+	woal_sdiommc_read_reg(handle, magic_reg, &magic);
+	/** Revision ID register */
+	woal_sdiommc_read_reg(handle, host_strap_reg, &strap);
+	strap &= 0x1;
+	magic &= 0xFF;
+	/* 1 = SDSD, 0 --SD UART */
+	PRINTM(MCMND, "magic=0x%x strap=0x%x\n", magic, strap);
+#endif
+#if defined(SD8977)
+	if (IS_SD8977(handle->card_type)) {
+		switch (revision_id) {
+		case SD8977_V0:
+			strcpy(handle->card_info->fw_name, SD8977_V0_FW_NAME);
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD8977_WLAN_V0_FW_NAME);
+			break;
+		case SD8977_V1:
+			strcpy(handle->card_info->fw_name, SD8977_V1_FW_NAME);
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD8977_WLAN_V1_FW_NAME);
+			break;
+		case SD8977_V2:
+			strcpy(handle->card_info->fw_name, SD8977_V2_FW_NAME);
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD8977_WLAN_V2_FW_NAME);
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+#if defined(SD8887)
+	if (IS_SD8887(handle->card_type)) {
+		/* Check revision ID */
+		switch (revision_id) {
+		case SD8887_A0:
+			strcpy(handle->card_info->fw_name, SD8887_A0_FW_NAME);
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD8887_WLAN_A0_FW_NAME);
+			break;
+		case SD8887_A2:
+			strcpy(handle->card_info->fw_name, SD8887_A2_FW_NAME);
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD8887_WLAN_A2_FW_NAME);
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+
+#ifdef SD8997
+	if (IS_SD8997(handle->card_type)) {
+		if (magic == CHIP_MAGIC_VALUE) {
+			if (strap == CARD_TYPE_SD_UART)
+				strcpy(handle->card_info->fw_name,
+				       SDUART8997_DEFAULT_COMBO_FW_NAME);
+			else
+				strcpy(handle->card_info->fw_name,
+				       SDSD8997_DEFAULT_COMBO_FW_NAME);
+		}
+	}
+#endif
+
+#ifdef SD8987
+	if (IS_SD8987(handle->card_type)) {
+		if (magic == CHIP_MAGIC_VALUE) {
+			if (strap == CARD_TYPE_SD_UART)
+				strcpy(handle->card_info->fw_name,
+				       SDUART8987_DEFAULT_COMBO_FW_NAME);
+			else
+				strcpy(handle->card_info->fw_name,
+				       SDSD8987_DEFAULT_COMBO_FW_NAME);
+		}
+	}
+#endif
+
+#ifdef SD8978
+	if (IS_SD8978(handle->card_type)) {
+		if (magic == CHIP_MAGIC_VALUE) {
+			if (strap == CARD_TYPE_SD_UART)
+				strcpy(handle->card_info->fw_name,
+				       SDUART8978_DEFAULT_COMBO_FW_NAME);
+			else
+				strcpy(handle->card_info->fw_name,
+				       SDSD8978_DEFAULT_COMBO_FW_NAME);
+		}
+	}
+#endif
+
+#ifdef SD9098
+	if (IS_SD9098(handle->card_type) &&
+	    (card->func->device == SD_DEVICE_ID_9098_FN1)) {
+		switch (revision_id) {
+		case SD9098_Z1Z2:
+			if (magic == CHIP_MAGIC_VALUE) {
+				if (strap == CARD_TYPE_SD_UART)
+					strcpy(handle->card_info->fw_name,
+					       SDUART9098_DEFAULT_COMBO_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       SDSD9098_DEFAULT_COMBO_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD9098_DEFAULT_WLAN_FW_NAME);
+			break;
+		case SD9098_A0:
+		case SD9098_A1:
+		case SD9098_A2:
+			if (magic == CHIP_MAGIC_VALUE) {
+				if (strap == CARD_TYPE_SD_UART)
+					strcpy(handle->card_info->fw_name,
+					       SDUART9098_COMBO_V1_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       SDSD9098_COMBO_V1_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD9098_WLAN_V1_FW_NAME);
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+#ifdef SD9097
+	if (IS_SD9097(handle->card_type)) {
+		switch (revision_id) {
+		case SD9097_B0:
+		case SD9097_B1:
+			if (magic == CHIP_MAGIC_VALUE) {
+				if (strap == CARD_TYPE_SD_UART)
+					strcpy(handle->card_info->fw_name,
+					       SDUART9097_COMBO_V1_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       SDSD9097_COMBO_V1_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD9097_WLAN_V1_FW_NAME);
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+#ifdef SD9177
+	if (IS_SD9177(handle->card_type)) {
+		switch (revision_id) {
+		case SD9177_A0:
+			if (magic == CHIP_MAGIC_VALUE) {
+				if (strap == CARD_TYPE_SD_UART)
+					strcpy(handle->card_info->fw_name,
+					       SDUART9177_DEFAULT_COMBO_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       SDSD9177_DEFAULT_COMBO_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       SD9177_DEFAULT_WLAN_FW_NAME);
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+done:
+	PRINTM(MCMND, "combo fw:%s wlan fw:%s \n", handle->card_info->fw_name,
+	       handle->card_info->fw_name_wlan);
+	LEAVE();
+	return ret;
+}
+
+#define DEBUG_FW_DONE 0xFF
+#define DEBUG_MEMDUMP_FINISH 0xFE
+#define MAX_POLL_TRIES 100
+
+typedef enum {
+	DUMP_TYPE_ITCM = 0,
+	DUMP_TYPE_DTCM = 1,
+	DUMP_TYPE_SQRAM = 2,
+	DUMP_TYPE_APU_REGS = 3,
+	DUMP_TYPE_CIU_REGS = 4,
+	DUMP_TYPE_ICU_REGS = 5,
+	DUMP_TYPE_MAC_REGS = 6,
+	DUMP_TYPE_EXTEND_7 = 7,
+	DUMP_TYPE_EXTEND_8 = 8,
+	DUMP_TYPE_EXTEND_9 = 9,
+	DUMP_TYPE_EXTEND_10 = 10,
+	DUMP_TYPE_EXTEND_11 = 11,
+	DUMP_TYPE_EXTEND_12 = 12,
+	DUMP_TYPE_EXTEND_13 = 13,
+	DUMP_TYPE_EXTEND_LAST = 14
+} dumped_mem_type;
+
+#define MAX_NAME_LEN 8
+
+typedef struct {
+	t_u8 mem_name[MAX_NAME_LEN];
+	t_u8 *mem_Ptr;
+	struct file *pfile_mem;
+	t_u8 done_flag;
+	t_u8 type;
+} memory_type_mapping;
+
+static memory_type_mapping mem_type_mapping_tbl[] = {
+	{"ITCM", NULL, NULL, 0xF0, FW_DUMP_TYPE_MEM_ITCM},
+	{"DTCM", NULL, NULL, 0xF1, FW_DUMP_TYPE_MEM_DTCM},
+	{"SQRAM", NULL, NULL, 0xF2, FW_DUMP_TYPE_MEM_SQRAM},
+	{"APU", NULL, NULL, 0xF3, FW_DUMP_TYPE_REG_APU},
+	{"CIU", NULL, NULL, 0xF4, FW_DUMP_TYPE_REG_CIU},
+	{"ICU", NULL, NULL, 0xF5, FW_DUMP_TYPE_REG_ICU},
+	{"MAC", NULL, NULL, 0xF6, FW_DUMP_TYPE_REG_MAC},
+	{"EXT7", NULL, NULL, 0xF7, 0},
+	{"EXT8", NULL, NULL, 0xF8, 0},
+	{"EXT9", NULL, NULL, 0xF9, 0},
+	{"EXT10", NULL, NULL, 0xFA, 0},
+	{"EXT11", NULL, NULL, 0xFB, 0},
+	{"EXT12", NULL, NULL, 0xFC, 0},
+	{"EXT13", NULL, NULL, 0xFD, 0},
+	{"EXTLAST", NULL, NULL, 0xFE, 0},
+};
+
+static memory_type_mapping mem_type_mapping_tbl_8977_8997 = { "DUMP", NULL,
+	NULL, 0xDD, 0
+};
+
+/**
+ *  @brief This function read/write firmware via cmd52
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param doneflag  A flag
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+static rdwr_status
+woal_cmd52_rdwr_firmware(moal_handle *phandle, t_u8 doneflag)
+{
+	int ret = 0;
+	int tries = 0;
+	t_u8 ctrl_data = 0;
+	t_u8 dbg_dump_ctrl_reg = phandle->card_info->dump_fw_ctrl_reg;
+	t_u8 debug_host_ready = phandle->card_info->dump_fw_host_ready;
+
+#ifdef SD9177
+	if (IS_SD9177(phandle->card_type)) {
+		if (phandle->event_fw_dump)
+			debug_host_ready = 0xAA;
+	}
+#endif
+	ret = woal_sdio_writeb(phandle, dbg_dump_ctrl_reg, debug_host_ready);
+	if (ret) {
+		PRINTM(MERROR, "SDIO Write ERR\n");
+		return RDWR_STATUS_FAILURE;
+	}
+#ifdef SD9177
+	if (IS_SD9177(phandle->card_type)) {
+		if (phandle->event_fw_dump)
+			return RDWR_STATUS_SUCCESS;
+	}
+#endif
+	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+		ret = woal_sdio_readb(phandle, dbg_dump_ctrl_reg, &ctrl_data);
+		if (ret) {
+			PRINTM(MERROR, "SDIO READ ERR\n");
+			return RDWR_STATUS_FAILURE;
+		}
+		if (ctrl_data == DEBUG_FW_DONE)
+			break;
+		if (doneflag && ctrl_data == doneflag)
+			return RDWR_STATUS_DONE;
+		if (ctrl_data != debug_host_ready) {
+			PRINTM(MMSG,
+			       "The ctrl reg was changed, re-try again!\n");
+			ret = woal_sdio_writeb(phandle, dbg_dump_ctrl_reg,
+					       debug_host_ready);
+			if (ret) {
+				PRINTM(MERROR, "SDIO Write ERR\n");
+				return RDWR_STATUS_FAILURE;
+			}
+		}
+		udelay(100);
+	}
+	if (ctrl_data == debug_host_ready || tries == MAX_POLL_TRIES) {
+		PRINTM(MERROR, "Fail to pull ctrl_data\n");
+		return RDWR_STATUS_FAILURE;
+	}
+	return RDWR_STATUS_SUCCESS;
+}
+
+#ifdef SD8801
+#define DEBUG_HOST_READY		0xEE
+#define DEBUG_FW_DONE			0xFF
+#define DEBUG_MEMDUMP_FINISH            0xFE
+#define MAX_POLL_TRIES			100
+#define DEBUG_ITCM_DONE			0xaa
+#define DEBUG_DTCM_DONE			0xbb
+#define DEBUG_SQRAM_DONE		0xcc
+
+#define DEBUG_DUMP_CTRL_REG               0x63
+#define DEBUG_DUMP_FIRST_REG              0x62
+#define DEBUG_DUMP_START_REG              0x64
+#define DEBUG_DUMP_END_REG                0x6a
+#define ITCM_SIZE                         0x60000
+#define SQRAM_SIZE                        0x33500
+#define DTCM_SIZE                         0x14000
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_dump_firmware_info(moal_handle *phandle)
+{
+
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	t_u8 *ITCM_Ptr = NULL;
+	t_u8 *DTCM_Ptr = NULL;
+	t_u8 *SQRAM_Ptr = NULL;
+	t_u8 *dbg_ptr = NULL;
+	t_u32 sec, usec;
+	t_u8 ctrl_data = 0;
+	t_u32 dtcm_size = DTCM_SIZE;
+	t_u32 sqram_size = SQRAM_SIZE;
+	t_u8 *end_ptr = NULL;
+	int tries;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+	if (!phandle->fw_dump_buf) {
+		ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
+				   &(phandle->fw_dump_buf));
+		if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
+			PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n");
+			return;
+		}
+	} else {
+		memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
+	}
+	phandle->fw_dump_len = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	/* start dump fw memory     */
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec);
+	ret = moal_vmalloc(phandle, ITCM_SIZE + 1, (t_u8 **)&ITCM_Ptr);
+	if ((ret != MLAN_STATUS_SUCCESS) || !ITCM_Ptr) {
+		PRINTM(MERROR, "Error: vmalloc ITCM buffer failed!!!\n");
+		goto done;
+	}
+
+	PRINTM(MMSG, "DTCM_SIZE=0x%x\n", dtcm_size);
+	ret = moal_vmalloc(phandle, dtcm_size + 1, (t_u8 **)&DTCM_Ptr);
+	if ((ret != MLAN_STATUS_SUCCESS) || !DTCM_Ptr) {
+		PRINTM(MERROR, "Error: vmalloc DTCM buffer failed!!!\n");
+		goto done;
+	}
+	ret = moal_vmalloc(phandle, sqram_size + 1, (t_u8 **)&SQRAM_Ptr);
+	if ((ret != MLAN_STATUS_SUCCESS) || !SQRAM_Ptr) {
+		PRINTM(MERROR, "Error: vmalloc SQRAM buffer failed!!!\n");
+		goto done;
+	}
+	dbg_ptr = ITCM_Ptr;
+	end_ptr = ITCM_Ptr + ITCM_SIZE;
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "Start ITCM output %u.%06u, please wait...\n", sec, usec);
+	reg_start = DEBUG_DUMP_START_REG;
+	reg_end = DEBUG_DUMP_END_REG;
+	do {
+		ret = woal_sdio_writeb(phandle, DEBUG_DUMP_CTRL_REG,
+				       DEBUG_HOST_READY);
+		if (ret) {
+			PRINTM(MERROR, "SDIO Write ERR\n");
+			goto done;
+		}
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			ret = woal_sdio_readb(phandle, DEBUG_DUMP_CTRL_REG,
+					      &ctrl_data);
+			if (ret) {
+				PRINTM(MERROR, "SDIO READ ERR\n");
+				goto done;
+			}
+			if ((ctrl_data == DEBUG_FW_DONE) ||
+			    (ctrl_data == DEBUG_ITCM_DONE)
+			    || (ctrl_data == DEBUG_DTCM_DONE) ||
+			    (ctrl_data == DEBUG_SQRAM_DONE))
+				break;
+			if (ctrl_data != DEBUG_HOST_READY) {
+				ret = woal_sdio_writeb(phandle,
+						       DEBUG_DUMP_CTRL_REG,
+						       DEBUG_HOST_READY);
+				if (ret) {
+					PRINTM(MERROR, "SDIO Write ERR\n");
+					goto done;
+				}
+			}
+			udelay(100);
+		}
+		if (ctrl_data == DEBUG_HOST_READY) {
+			PRINTM(MERROR, "Fail to pull ctrl_data\n");
+			goto done;
+		}
+		reg = DEBUG_DUMP_FIRST_REG;
+		ret = woal_sdio_readb(phandle, reg, dbg_ptr);
+		if (ret) {
+			PRINTM(MMSG, "SDIO READ ERR\n");
+			goto done;
+		}
+		if (dbg_ptr < end_ptr)
+			dbg_ptr++;
+		else {
+			PRINTM(MERROR, "pre-allocced buf is not enough\n");
+			goto done;
+		}
+		for (reg = reg_start; reg <= reg_end; reg++) {
+			ret = woal_sdio_readb(phandle, reg, dbg_ptr);
+			if (ret) {
+				PRINTM(MMSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			if (dbg_ptr < end_ptr)
+				dbg_ptr++;
+			else
+				PRINTM(MMSG,
+				       "pre-allocced buf is not enough\n");
+		}
+		switch (ctrl_data) {
+		case DEBUG_ITCM_DONE:
+#ifdef MLAN_64BIT
+			PRINTM(MMSG, "ITCM done: size=0x%lx\n",
+			       dbg_ptr - ITCM_Ptr);
+#else
+			PRINTM(MMSG, "ITCM done: size=0x%x\n",
+			       dbg_ptr - ITCM_Ptr);
+#endif
+			woal_save_dump_info_to_buf(phandle, ITCM_Ptr, ITCM_SIZE,
+						   FW_DUMP_TYPE_MEM_ITCM);
+			dbg_ptr = DTCM_Ptr;
+			end_ptr = DTCM_Ptr + dtcm_size;
+			moal_get_system_time(phandle, &sec, &usec);
+			PRINTM(MMSG,
+			       "Start DTCM output %u.%06u, please wait...\n",
+			       sec, usec);
+			break;
+		case DEBUG_DTCM_DONE:
+#ifdef MLAN_64BIT
+			PRINTM(MMSG, "DTCM done: size=0x%lx\n",
+			       dbg_ptr - DTCM_Ptr);
+#else
+			PRINTM(MMSG, "DTCM done: size=0x%x\n",
+			       dbg_ptr - DTCM_Ptr);
+#endif
+			woal_save_dump_info_to_buf(phandle, ITCM_Ptr, dtcm_size,
+						   FW_DUMP_TYPE_MEM_DTCM);
+			dbg_ptr = SQRAM_Ptr;
+			end_ptr = SQRAM_Ptr + sqram_size;
+			moal_get_system_time(phandle, &sec, &usec);
+			PRINTM(MMSG,
+			       "Start SQRAM output %u.%06u, please wait...\n",
+			       sec, usec);
+			break;
+		case DEBUG_SQRAM_DONE:
+#ifdef MLAN_64BIT
+			PRINTM(MMSG, "SQRAM done: size=0x%lx\n",
+			       dbg_ptr - SQRAM_Ptr);
+#else
+			PRINTM(MMSG, "SQRAM done: size=0x%x\n",
+			       dbg_ptr - SQRAM_Ptr);
+#endif
+			woal_save_dump_info_to_buf(phandle, SQRAM_Ptr,
+						   sqram_size,
+						   FW_DUMP_TYPE_MEM_SQRAM);
+			PRINTM(MMSG, "End output!\n");
+			break;
+		default:
+			break;
+		}
+	} while (ctrl_data != DEBUG_SQRAM_DONE);
+
+	woal_append_end_block(phandle);
+	PRINTM(MMSG,
+	       "The output ITCM/DTCM/SQRAM have been saved to files successfully!\n");
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec);
+	/* end dump fw memory */
+done:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
+#endif
+	if (ITCM_Ptr)
+		moal_vfree(phandle, ITCM_Ptr);
+	if (DTCM_Ptr)
+		moal_vfree(phandle, DTCM_Ptr);
+	if (SQRAM_Ptr)
+		moal_vfree(phandle, SQRAM_Ptr);
+	PRINTM(MMSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+#endif
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_dump_firmware_info_v2(moal_handle *phandle)
+{
+	int ret = 0;
+	unsigned int reg, reg_start, reg_end;
+	t_u8 *dbg_ptr = NULL;
+	t_u32 sec, usec;
+	t_u8 dump_num = 0;
+	t_u8 idx = 0;
+	t_u8 doneflag = 0;
+	rdwr_status stat;
+	t_u8 i = 0;
+	t_u8 read_reg = 0;
+	t_u32 memory_size = 0;
+	t_u8 *end_ptr = NULL;
+	t_u8 dbg_dump_start_reg = 0;
+	t_u8 dbg_dump_end_reg = 0;
+	t_u8 dbg_dump_ctrl_reg = 0;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+
+	dbg_dump_start_reg = phandle->card_info->dump_fw_start_reg;
+	dbg_dump_end_reg = phandle->card_info->dump_fw_end_reg;
+	dbg_dump_ctrl_reg = phandle->card_info->dump_fw_ctrl_reg;
+
+	if (!phandle->fw_dump_buf) {
+		ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
+				   &(phandle->fw_dump_buf));
+		if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
+			PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n");
+			return;
+		}
+	} else {
+		memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
+	}
+	phandle->fw_dump_len = 0;
+
+	/* start dump fw memory */
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec);
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == woal_cmd52_rdwr_firmware(phandle, doneflag))
+		goto done;
+	reg = dbg_dump_start_reg;
+	ret = woal_sdio_readb(phandle, reg, &dump_num);
+	if (ret) {
+		PRINTM(MMSG, "SDIO READ MEM NUM ERR\n");
+		goto done;
+	}
+
+	/* read the length of every memory which will dump */
+	for (idx = 0; idx < dump_num; idx++) {
+		if (RDWR_STATUS_FAILURE ==
+		    woal_cmd52_rdwr_firmware(phandle, doneflag))
+			goto done;
+		memory_size = 0;
+		reg = dbg_dump_start_reg;
+		for (i = 0; i < 4; i++) {
+			ret = woal_sdio_readb(phandle, reg, &read_reg);
+			if (ret) {
+				PRINTM(MMSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			memory_size |= (read_reg << i * 8);
+			reg++;
+		}
+		if (memory_size == 0) {
+			PRINTM(MMSG, "Firmware Dump Finished!\n");
+			ret = woal_sdiommc_write_reg(phandle, dbg_dump_ctrl_reg,
+						     DEBUG_MEMDUMP_FINISH);
+			if (ret) {
+				PRINTM(MERROR,
+				       "SDIO Write MEMDUMP_FINISH ERR\n");
+				goto done;
+			}
+			break;
+		} else {
+			PRINTM(MMSG, "%s_SIZE=0x%x\n",
+			       mem_type_mapping_tbl[idx].mem_name, memory_size);
+			ret = moal_vmalloc(phandle, memory_size + 1,
+					   (t_u8 **)&mem_type_mapping_tbl[idx].
+					   mem_Ptr);
+			if ((ret != MLAN_STATUS_SUCCESS) ||
+			    !mem_type_mapping_tbl[idx].mem_Ptr) {
+				PRINTM(MERROR,
+				       "Error: vmalloc %s buffer failed!!!\n",
+				       mem_type_mapping_tbl[idx].mem_name);
+				goto done;
+			}
+			dbg_ptr = mem_type_mapping_tbl[idx].mem_Ptr;
+			end_ptr = dbg_ptr + memory_size;
+		}
+		doneflag = mem_type_mapping_tbl[idx].done_flag;
+		moal_get_system_time(phandle, &sec, &usec);
+		PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
+		       mem_type_mapping_tbl[idx].mem_name, sec, usec);
+		do {
+			stat = woal_cmd52_rdwr_firmware(phandle, doneflag);
+			if (RDWR_STATUS_FAILURE == stat)
+				goto done;
+			reg_start = dbg_dump_start_reg;
+			reg_end = dbg_dump_end_reg;
+			for (reg = reg_start; reg <= reg_end; reg++) {
+				ret = woal_sdio_readb(phandle, reg, dbg_ptr);
+				if (ret) {
+					PRINTM(MMSG, "SDIO READ ERR\n");
+					goto done;
+				}
+				if (dbg_ptr < end_ptr)
+					dbg_ptr++;
+				else
+					PRINTM(MMSG,
+					       "pre-allocced buf is not enough\n");
+			}
+			if (RDWR_STATUS_DONE == stat) {
+#ifdef MLAN_64BIT
+				PRINTM(MMSG,
+				       "%s done:"
+				       "size = 0x%lx\n",
+				       mem_type_mapping_tbl[idx].mem_name,
+				       dbg_ptr - mem_type_mapping_tbl[idx]
+				       .mem_Ptr);
+#else
+				PRINTM(MMSG,
+				       "%s done:"
+				       "size = 0x%x\n",
+				       mem_type_mapping_tbl[idx].mem_name,
+				       dbg_ptr - mem_type_mapping_tbl[idx]
+				       .mem_Ptr);
+#endif
+				woal_save_dump_info_to_buf(phandle,
+							   mem_type_mapping_tbl
+							   [idx].mem_Ptr,
+							   memory_size,
+							   mem_type_mapping_tbl
+							   [idx].type);
+				moal_vfree(phandle,
+					   mem_type_mapping_tbl[idx].mem_Ptr);
+				mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+				break;
+			}
+		} while (1);
+	}
+	woal_append_end_block(phandle);
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec);
+	/* end dump fw memory */
+done:
+	for (idx = 0; idx < dump_num; idx++) {
+		if (mem_type_mapping_tbl[idx].mem_Ptr) {
+			moal_vfree(phandle, mem_type_mapping_tbl[idx].mem_Ptr);
+			mem_type_mapping_tbl[idx].mem_Ptr = NULL;
+		}
+	}
+	PRINTM(MMSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+void
+woal_dump_firmware_info_v3(moal_handle *phandle)
+{
+	int ret = 0;
+	int tries = 0;
+	unsigned int reg, reg_start, reg_end;
+	t_u8 *dbg_ptr = NULL;
+	t_u8 *temp_Ptr = NULL;
+	t_u32 sec, usec;
+	t_u8 start_flag = 0;
+	t_u8 doneflag = 0;
+	rdwr_status stat;
+	t_u32 memory_size = 0;
+	t_u8 *end_ptr = NULL;
+	t_u8 dbg_dump_start_reg = 0;
+	t_u8 dbg_dump_end_reg = 0;
+	memory_type_mapping *pmem_type_mapping_tbl =
+		&mem_type_mapping_tbl_8977_8997;
+
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+#ifdef SD9177
+	if (IS_SD9177(phandle->card_type)) {
+		if (phandle->event_fw_dump) {
+			if (RDWR_STATUS_FAILURE !=
+			    woal_cmd52_rdwr_firmware(phandle, doneflag)) {
+				PRINTM(MMSG,
+				       "====SDIO FW DUMP EVENT MODE START ====\n");
+				return;
+			}
+		}
+	}
+#endif
+
+	dbg_dump_start_reg = phandle->card_info->dump_fw_start_reg;
+	dbg_dump_end_reg = phandle->card_info->dump_fw_end_reg;
+
+	/* start dump fw memory */
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec);
+	/* read the number of the memories which will dump */
+	if (RDWR_STATUS_FAILURE == woal_cmd52_rdwr_firmware(phandle, doneflag))
+		goto done;
+
+	/** check the reg which indicate dump starting */
+	for (reg = dbg_dump_start_reg; reg <= dbg_dump_end_reg; reg++) {
+		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+			ret = woal_sdio_readb(phandle, reg, &start_flag);
+			if (ret) {
+				PRINTM(MMSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			/** 0 means dump starting*/
+			if (start_flag == 0)
+				break;
+			udelay(100);
+		}
+		if (tries == MAX_POLL_TRIES) {
+			PRINTM(MMSG, "FW not ready to dump\n");
+			goto done;
+		}
+	}
+	memory_size = 0xF0000;
+	PRINTM(MMSG, "%s_SIZE=0x%x\n", pmem_type_mapping_tbl->mem_name,
+	       memory_size);
+	ret = moal_vmalloc(phandle, memory_size + 1,
+			   (t_u8 **)&pmem_type_mapping_tbl->mem_Ptr);
+	if ((ret != MLAN_STATUS_SUCCESS) || !pmem_type_mapping_tbl->mem_Ptr) {
+		PRINTM(MERROR, "Error: vmalloc %s buffer failed!!!\n",
+		       pmem_type_mapping_tbl->mem_name);
+		goto done;
+	}
+	dbg_ptr = pmem_type_mapping_tbl->mem_Ptr;
+	end_ptr = dbg_ptr + memory_size;
+	doneflag = pmem_type_mapping_tbl->done_flag;
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
+	       pmem_type_mapping_tbl->mem_name, sec, usec);
+	do {
+		stat = woal_cmd52_rdwr_firmware(phandle, doneflag);
+		if (RDWR_STATUS_FAILURE == stat)
+			goto done;
+		reg_start = dbg_dump_start_reg;
+		reg_end = dbg_dump_end_reg;
+		for (reg = reg_start; reg <= reg_end; reg++) {
+			ret = woal_sdio_readb(phandle, reg, dbg_ptr);
+			if (ret) {
+				PRINTM(MMSG, "SDIO READ ERR\n");
+				goto done;
+			}
+			dbg_ptr++;
+			if (dbg_ptr >= end_ptr) {
+				PRINTM(MMSG,
+				       "pre-allocced buf is not enough\n");
+				ret = moal_vmalloc(phandle,
+						   memory_size + 0x4000 + 1,
+						   (t_u8 **)&temp_Ptr);
+				if ((ret != MLAN_STATUS_SUCCESS) || !temp_Ptr) {
+					PRINTM(MERROR,
+					       "Error: vmalloc  buffer failed!!!\n");
+					goto done;
+				}
+				moal_memcpy_ext(phandle, temp_Ptr,
+						pmem_type_mapping_tbl->mem_Ptr,
+						memory_size,
+						memory_size + 0x4000);
+				moal_vfree(phandle,
+					   pmem_type_mapping_tbl->mem_Ptr);
+				pmem_type_mapping_tbl->mem_Ptr = temp_Ptr;
+				temp_Ptr = NULL;
+				dbg_ptr = pmem_type_mapping_tbl->mem_Ptr +
+					memory_size;
+				memory_size += 0x4000;
+				end_ptr = pmem_type_mapping_tbl->mem_Ptr +
+					memory_size;
+			}
+		}
+		if (RDWR_STATUS_DONE == stat) {
+#ifdef MLAN_64BIT
+			PRINTM(MMSG,
+			       "%s done:"
+			       "size = 0x%lx\n",
+			       pmem_type_mapping_tbl->mem_name,
+			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
+#else
+			PRINTM(MMSG,
+			       "%s done:"
+			       "size = 0x%x\n",
+			       pmem_type_mapping_tbl->mem_name,
+			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
+
+#endif
+			if (phandle->fw_dump_buf) {
+				moal_vfree(phandle, phandle->fw_dump_buf);
+				phandle->fw_dump_buf = NULL;
+				phandle->fw_dump_len = 0;
+			}
+			phandle->fw_dump_buf = pmem_type_mapping_tbl->mem_Ptr;
+			phandle->fw_dump_len =
+				dbg_ptr - pmem_type_mapping_tbl->mem_Ptr;
+			pmem_type_mapping_tbl->mem_Ptr = NULL;
+			break;
+		}
+	} while (1);
+	moal_get_system_time(phandle, &sec, &usec);
+	PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec);
+	/* end dump fw memory */
+done:
+	if (pmem_type_mapping_tbl->mem_Ptr) {
+		moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr);
+		pmem_type_mapping_tbl->mem_Ptr = NULL;
+	}
+	PRINTM(MMSG, "==== DEBUG MODE END ====\n");
+	return;
+}
+
+/**
+ *  @brief This function reads and displays SDIO registers for debugging
+ *
+ *  @param phandle  A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_sdiommc_reg_dbg(moal_handle *phandle)
+{
+	int ret = 0;
+	t_u8 loop, index = 0, func, data;
+	unsigned int reg, reg_start, reg_end;
+	unsigned int scratch_reg = phandle->card_info->scratch_reg;
+	t_u8 *reg_table = phandle->card_info->dump_reg.reg_table;
+	t_u8 reg_table_size = phandle->card_info->dump_reg.reg_table_size;
+	char buf[256], *ptr;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
+	for (loop = 0; loop < 5; loop++) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		if (loop == 0) {
+			/* Read the registers of SDIO function0 */
+			func = loop;
+			reg_start = 0;
+			reg_end = 9;
+		} else if (loop == 1) {
+			/* Read the registers of SDIO function1 */
+			func = loop;
+			reg_start = phandle->card_info->func1_reg_start;
+			reg_end = phandle->card_info->func1_reg_end;
+		} else if (loop == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 1;
+			reg_start = reg_table[index++];
+			reg_end = reg_table[reg_table_size - 1];
+		} else {
+			/* Read the scratch registers of SDIO function1 */
+			if (loop == 4)
+				mdelay(100);
+			func = 1;
+			reg_start = scratch_reg;
+			reg_end = scratch_reg + 10;
+		}
+		if (loop != 2)
+			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
+				       reg_start, reg_end);
+		else
+			ptr += sprintf(ptr, "SDIO Func%d: ", func);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				ret = woal_sdio_f0_readb(phandle, reg, &data);
+			else
+				ret = woal_sdio_readb(phandle, reg, &data);
+			if (loop == 2)
+				ptr += sprintf(ptr, "(%#x) ", reg);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			if (loop == 2 && reg < reg_end)
+				reg = reg_table[index++];
+			else
+				reg++;
+		}
+		PRINTM(MMSG, "%s\n", buf);
+	}
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_sdiommc_dump_fw_info(moal_handle *phandle)
+{
+	if (!phandle) {
+		PRINTM(MERROR, "Could not dump firmwware info\n");
+		return;
+	}
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
+	phandle->fw_dump = MTRUE;
+	if (phandle->card_info->dump_fw_info == DUMP_FW_SDIO_V2) {
+		woal_dump_firmware_info_v2(phandle);
+	} else if (phandle->card_info->dump_fw_info == DUMP_FW_SDIO_V3) {
+		woal_dump_firmware_info_v3(phandle);
+		if (phandle->event_fw_dump) {
+			phandle->event_fw_dump = MFALSE;
+			queue_work(phandle->workqueue, &phandle->main_work);
+			phandle->is_fw_dump_timer_set = MTRUE;
+			woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
+			return;
+		}
+	}
+#ifdef SD8801
+	else {
+		woal_dump_firmware_info(phandle);
+	}
+#endif
+	woal_send_fw_dump_complete_event(woal_get_priv
+					 (phandle, MLAN_BSS_ROLE_ANY));
+	phandle->fw_dump = MFALSE;
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+	queue_work(phandle->workqueue, &phandle->main_work);
+	woal_process_hang(phandle);
+	return;
+}
+
+/**
+ *  @brief This function save sdio reg info
+ *
+ *  @param phandle   A pointer to moal_handle
+ *  @param buf       A pointer buffer saving log
+ *
+ *  @return          The length of this log
+ */
+static int
+woal_sdiommc_dump_reg_info(moal_handle *phandle, t_u8 *drv_buf)
+{
+	char *drv_ptr = (char *)drv_buf;
+	int ret = 0;
+	t_u8 loop, index = 0, func, data;
+	unsigned int reg, reg_start, reg_end;
+	unsigned int scratch_reg = 0;
+	t_u8 *reg_table = NULL;
+	t_u8 reg_table_size = 0;
+	char buf[256], *ptr;
+
+	ENTER();
+
+	if (!phandle || !drv_buf) {
+		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
+		LEAVE();
+		return 0;
+	}
+
+	scratch_reg = phandle->card_info->scratch_reg;
+	reg_table = phandle->card_info->dump_reg.reg_table;
+	reg_table_size = phandle->card_info->dump_reg.reg_table_size;
+
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
+
+	drv_ptr += sprintf(drv_ptr, "--------sdio_reg_debug_info---------\n");
+	for (loop = 0; loop < 5; loop++) {
+		memset(buf, 0, sizeof(buf));
+		ptr = buf;
+		if (loop == 0) {
+			/* Read the registers of SDIO function0 */
+			func = loop;
+			reg_start = 0;
+			reg_end = 9;
+
+		} else if (loop == 1) {
+			/* Read the registers of SDIO function1 */
+			func = loop;
+			reg_start = phandle->card_info->func1_reg_start;
+			reg_end = phandle->card_info->func1_reg_end;
+		} else if (loop == 2) {
+			/* Read specific registers of SDIO function1 */
+			index = 0;
+			func = 1;
+			reg_start = reg_table[index++];
+			reg_end = reg_table[reg_table_size - 1];
+		} else {
+			/* Read the scratch registers of SDIO function1 */
+			if (loop == 4)
+				mdelay(100);
+			func = 1;
+			reg_start = scratch_reg;
+			reg_end = scratch_reg + 10;
+		}
+		if (loop != 2)
+			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
+				       reg_start, reg_end);
+		else
+			ptr += sprintf(ptr, "SDIO Func%d: ", func);
+		for (reg = reg_start; reg <= reg_end;) {
+			if (func == 0)
+				ret = woal_sdio_f0_readb(phandle, reg, &data);
+			else
+				ret = woal_sdio_readb(phandle, reg, &data);
+
+			if (loop == 2)
+				ptr += sprintf(ptr, "(%#x) ", reg);
+			if (!ret)
+				ptr += sprintf(ptr, "%02x ", data);
+			else {
+				ptr += sprintf(ptr, "ERR");
+				break;
+			}
+			if (loop == 2 && reg < reg_end)
+				reg = reg_table[index++];
+			else
+				reg++;
+		}
+		drv_ptr += sprintf(drv_ptr, "%s\n", buf);
+	}
+
+	drv_ptr +=
+		sprintf(drv_ptr, "--------sdio_reg_debug_info End---------\n");
+	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
+
+	LEAVE();
+	return drv_ptr - (char *)drv_buf;
+}
+
+/**
+ *  @brief This function reset sdio through sdio bus driver
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return          N/A
+ */
+void
+woal_sdio_reset_hw(moal_handle *handle)
+{
+	struct sdio_mmc_card *card = handle->card;
+	struct sdio_func *func = card->func;
+	ENTER();
+	sdio_claim_host(func);
+	sdio_release_irq(card->func);
+	sdio_disable_func(card->func);
+	mmc_hw_reset(func->card->host);
+#ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
+	/* The byte mode patch is available in kernel MMC driver
+	 * which fixes one issue in MP-A transfer.
+	 * bit1: use func->cur_blksize for byte mode
+	 */
+	func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+	/* wait for chip fully wake up */
+	if (!func->enable_timeout)
+		func->enable_timeout = 200;
+#endif
+	sdio_enable_func(func);
+	sdio_claim_irq(func, woal_sdio_interrupt);
+	sdio_set_block_size(card->func, MLAN_SDIO_BLOCK_SIZE);
+	sdio_release_host(func);
+	LEAVE();
+	return;
+}
+
+static moal_if_ops sdiommc_ops = {
+	.register_dev = woal_sdiommc_register_dev,
+	.unregister_dev = woal_sdiommc_unregister_dev,
+	.read_reg = woal_sdiommc_read_reg,
+	.write_reg = woal_sdiommc_write_reg,
+	.read_data_sync = woal_sdiommc_read_data_sync,
+	.write_data_sync = woal_sdiommc_write_data_sync,
+	.get_fw_name = woal_sdiommc_get_fw_name,
+	.dump_fw_info = woal_sdiommc_dump_fw_info,
+	.dump_reg_info = woal_sdiommc_dump_reg_info,
+	.reg_dbg = woal_sdiommc_reg_dbg,
+	.is_second_mac = woal_sdiommc_is_second_mac,
+};
diff --git a/wlan_sd8987/mlinux/moal_shim.c b/wlan_sd8987/mlinux/moal_shim.c
new file mode 100755
index 0000000..1d90b3d
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_shim.c
@@ -0,0 +1,3867 @@
+/** @file moal_shim.c
+ *
+ * @brief This file contains the callback functions registered to MLAN
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#ifdef USB
+#include "moal_usb.h"
+#endif
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif
+#ifdef PCIE
+#include "moal_pcie.h"
+#endif
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#include "moal_cfg80211_util.h"
+#endif
+#include <asm/div64.h>
+
+#if defined(PCIE) || defined(SDIO)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
+#ifdef IMX_SUPPORT
+#include <linux/busfreq-imx.h>
+#endif
+#endif
+
+#include <linux/etherdevice.h>
+
+#endif /*defined(PCIE) || defined(SDIO) */
+
+/********************************************************
+		Local Variables
+********************************************************/
+/** moal_lock */
+typedef struct _moal_lock {
+	/** Lock */
+	spinlock_t lock;
+	/** Flags */
+	unsigned long flags;
+} moal_lock;
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+extern int wifi_status;
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Alloc a buffer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param size     The size of the buffer to be allocated
+ *  @param flag     The type of the buffer to be allocated
+ *  @param ppbuf    Pointer to a buffer location to store buffer pointer
+ * allocated
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_malloc(t_void *pmoal, t_u32 size, t_u32 flag, t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	gfp_t mem_flag =
+		(in_interrupt() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+
+#ifdef USB
+	if (!IS_USB(handle->card_type))
+#endif
+	{
+		if (flag & MLAN_MEM_DMA)
+			mem_flag |= GFP_DMA;
+	}
+	*ppbuf = kzalloc(size, mem_flag);
+	if (*ppbuf == NULL) {
+		PRINTM(MERROR, "%s: allocate memory (%d bytes) failed!\n",
+		       __func__, (int)size);
+		return MLAN_STATUS_FAILURE;
+	}
+	atomic_inc(&handle->malloc_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Free a buffer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pbuf     Pointer to the buffer to be freed
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_mfree(t_void *pmoal, t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+
+	if (!pbuf)
+		return MLAN_STATUS_FAILURE;
+	kfree(pbuf);
+	atomic_dec(&handle->malloc_count);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Alloc a vitual-address-continuous buffer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param size     The size of the buffer to be allocated
+ *  @param ppbuf    Pointer to a buffer location to store buffer pointer
+ * allocated
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_vmalloc(t_void *pmoal, t_u32 size, t_u8 **ppbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+
+	*ppbuf = vmalloc(size);
+	if (*ppbuf == NULL) {
+		PRINTM(MERROR, "%s: vmalloc (%d bytes) failed!", __func__,
+		       (int)size);
+		return MLAN_STATUS_FAILURE;
+	}
+	atomic_inc(&handle->vmalloc_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Free a buffer allocated by vmalloc
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pbuf     Pointer to the buffer to be freed
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_vfree(t_void *pmoal, t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+
+	if (!pbuf)
+		return MLAN_STATUS_FAILURE;
+	vfree(pbuf);
+	atomic_dec(&handle->vmalloc_count);
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef PCIE
+/**
+ *  @brief Alloc a consistent block of memory
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param size         The size of the buffer to be allocated
+ *  @param ppbuf        Pointer to a buffer location to store memory allocated
+ *  @param pbuf_pa      Pointer to a buffer location to store physical address
+ * of above memory
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_malloc_consistent(t_void *pmoal, t_u32 size, t_u8 **ppbuf, t_pu64 pbuf_pa)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+	dma_addr_t dma;
+	*pbuf_pa = 0;
+
+	if (!card)
+		return MLAN_STATUS_FAILURE;
+
+	*ppbuf = (t_u8 *)pci_alloc_consistent(card->dev, size,
+					      (dma_addr_t *) & dma);
+	if (*ppbuf == NULL) {
+		PRINTM(MERROR,
+		       "%s: allocate consistent memory (%d bytes) failed!\n",
+		       __func__, (int)size);
+		return MLAN_STATUS_FAILURE;
+	}
+	*pbuf_pa = (t_u64)dma;
+	atomic_inc(&handle->malloc_cons_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Free a consistent block of memory
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param size         Size of them memory to be freed
+ *  @param pbuf         Pointer to the memory to be freed
+ *  @param buf_pa       Physical address of the memory to be freed
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_mfree_consistent(t_void *pmoal, t_u32 size, t_u8 *pbuf, t_u64 buf_pa)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	pcie_service_card *card = handle->card;
+
+	if (!pbuf || !card)
+		return MLAN_STATUS_FAILURE;
+
+	pci_free_consistent(card->dev, size, pbuf, buf_pa);
+	atomic_dec(&handle->malloc_cons_count);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Map a block of memory to device
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pbuf         Pointer to the buffer to be mapped
+ *  @param pbuf_pa      Pointer to store the physical address of buffer
+ *  @param size         Size of the buffer to be mapped
+ *  @param flag         Flags for mapping IO
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_map_memory(t_void *pmoal, t_u8 *pbuf,
+		t_u64 *pbuf_pa, t_u32 size, t_u32 flag)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+
+	dma_addr_t dma;
+
+	if (!card)
+		return MLAN_STATUS_FAILURE;
+
+	/* Init memory to device */
+	dma = pci_map_single(card->dev, pbuf, size, flag);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+	if (pci_dma_mapping_error(card->dev, dma)) {
+#else
+	if (pci_dma_mapping_error(dma)) {
+#endif
+		PRINTM(MERROR, "Tx ring: failed to pci_map_single\n");
+		return MLAN_STATUS_FAILURE;
+	}
+
+	*pbuf_pa = dma;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Unmap a block of memory from device
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pbuf         Pointer to the buffer to unmap
+ *  @param buf_pa       Physical address of buffer to unmap
+ *  @param size         Size of the buffer to unmap
+ *  @param flag         Flags for mapping IO
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_unmap_memory(t_void *pmoal, t_u8 *pbuf,
+		  t_u64 buf_pa, t_u32 size, t_u32 flag)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	pcie_service_card *card = (pcie_service_card *)handle->card;
+
+	if (!card)
+		return MLAN_STATUS_FAILURE;
+
+	pci_unmap_single(card->dev, buf_pa, size, flag);
+
+	return MLAN_STATUS_SUCCESS;
+}
+#endif /* PCIE */
+
+/**
+ *  @brief Fill memory with constant byte
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmem     Pointer to the memory area
+ *  @param byte     A constant byte
+ *  @param num      Number of bytes to fill
+ *
+ *  @return         Pointer to the memory area
+ */
+t_void *
+moal_memset(t_void *pmoal, t_void *pmem, t_u8 byte, t_u32 num)
+{
+	t_void *p = pmem;
+
+	if (pmem && num)
+		p = memset(pmem, byte, num);
+
+	return p;
+}
+
+/**
+ *  @brief Copy memory from one area to another
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pdest    Pointer to the dest memory
+ *  @param psrc     Pointer to the src memory
+ *  @param num      Number of bytes to move
+ *
+ *  @return         Pointer to the dest memory
+ */
+t_void *
+moal_memcpy(t_void *pmoal, t_void *pdest, const t_void *psrc, t_u32 num)
+{
+	t_void *p = pdest;
+
+	if (pdest && psrc && num)
+		p = memcpy(pdest, psrc, num);
+
+	return p;
+}
+
+/**
+ *  @brief Copy memory from one area to another
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pdest    Pointer to the dest memory
+ *  @param psrc     Pointer to the src memory
+ *  @param num      Number of bytes to move
+ *  @param dest_size size of dest memory.
+ *
+ *  @return         Pointer to the dest memory
+ */
+t_void *
+moal_memcpy_ext(t_void *pmoal, t_void *pdest,
+		const t_void *psrc, t_u32 num, t_u32 dest_size)
+{
+	t_void *p = pdest;
+	if (pdest && psrc && num && dest_size)
+		p = memcpy(pdest, psrc, MIN(num, dest_size));
+
+	return p;
+}
+
+/**
+ *  @brief Move memory from one area to another
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pdest    Pointer to the dest memory
+ *  @param psrc     Pointer to the src memory
+ *  @param num      Number of bytes to move
+ *
+ *  @return         Pointer to the dest memory
+ */
+t_void *
+moal_memmove(t_void *pmoal, t_void *pdest, const t_void *psrc, t_u32 num)
+{
+	t_void *p = pdest;
+
+	if (pdest && psrc && num)
+		p = memmove(pdest, psrc, num);
+
+	return p;
+}
+
+/**
+ *  @brief Compare two memory areas
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmem1    Pointer to the first memory
+ *  @param pmem2    Pointer to the second memory
+ *  @param num      Number of bytes to compare
+ *
+ *  @return         Compare result returns by memcmp
+ */
+t_s32
+moal_memcmp(t_void *pmoal, const t_void *pmem1, const t_void *pmem2, t_u32 num)
+{
+	t_s32 result;
+
+	result = memcmp(pmem1, pmem2, num);
+
+	return result;
+}
+
+/**
+ *  @brief Delay function
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param delay  delay in micro-second
+ *
+ *  @return       N/A
+ */
+t_void
+moal_udelay(t_void *pmoal, t_u32 delay)
+{
+	if (delay >= 1000)
+		msleep(delay / 1000);
+	if (delay % 1000)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+		usleep_range(delay % 1000 - 1, delay % 1000);
+#else
+		udelay(delay % 1000);
+#endif
+}
+
+/**
+ *  @brief  usleep_range function
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param min_delay  minimal delay in micro-second
+ *  @param max_delay  delay in micro-second
+ *
+ *  @return       N/A
+ */
+t_void
+moal_usleep_range(t_void *pmoal, t_u32 min_delay, t_u32 max_delay)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+	usleep_range(min_delay, max_delay);
+#endif
+}
+
+/**
+ *  @brief Retrieves the current system time
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param psec     Pointer to buf for the seconds of system time
+ *  @param pusec    Pointer to buf the micro seconds of system time
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_get_system_time(t_void *pmoal, t_u32 *psec, t_u32 *pusec)
+{
+	wifi_timeval t;
+
+	woal_get_monotonic_time(&t);
+	*psec = t.time_sec;
+	*pusec = t.time_usec;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Retrieves the current boot time
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pnsec     Pointer to buf for the Nanoseconds of boot time
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_get_boot_ktime(t_void *pmoal, t_u64 *pnsec)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+	ktime_t time;
+
+	time = ktime_get_with_offset(TK_OFFS_BOOT);
+	*pnsec = *(t_u64 *)&(time);
+#endif
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Initializes the timer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pptimer      Pointer to the timer
+ *  @param callback     Pointer to callback function
+ *  @param pcontext     Pointer to context
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_init_timer(t_void *pmoal, t_void **pptimer,
+		IN t_void (*callback) (t_void *pcontext), t_void *pcontext)
+{
+	moal_drv_timer *timer = NULL;
+	gfp_t mem_flag =
+		(in_interrupt() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+
+	timer = kmalloc(sizeof(moal_drv_timer), mem_flag);
+	if (timer == NULL)
+		return MLAN_STATUS_FAILURE;
+	woal_initialize_timer(timer, callback, pcontext);
+	*pptimer = (t_void *)timer;
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Free the timer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_timer(t_void *pmoal, t_void *ptimer)
+{
+	moal_drv_timer *timer = (moal_drv_timer *)ptimer;
+
+	if (timer) {
+		if ((timer->timer_is_canceled == MFALSE) && timer->time_period) {
+			PRINTM(MWARN,
+			       "mlan try to free timer without stop timer!\n");
+			woal_cancel_timer(timer);
+		}
+		kfree(timer);
+	}
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Start the timer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param ptimer       Pointer to the timer
+ *  @param periodic     Periodic timer
+ *  @param msec         Timer value in milliseconds
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_start_timer(t_void *pmoal, t_void *ptimer, t_u8 periodic, t_u32 msec)
+{
+	if (!ptimer)
+		return MLAN_STATUS_FAILURE;
+
+	((moal_drv_timer *)ptimer)->timer_is_periodic = periodic;
+	woal_mod_timer((moal_drv_timer *)ptimer, msec);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Stop the timer
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param ptimer   Pointer to the timer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_stop_timer(t_void *pmoal, t_void *ptimer)
+{
+	if (!ptimer)
+		return MLAN_STATUS_FAILURE;
+	woal_cancel_timer((moal_drv_timer *)ptimer);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Initializes the lock
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pplock   Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_init_lock(t_void *pmoal, t_void **pplock)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_lock *mlock = NULL;
+
+	mlock = kmalloc(sizeof(moal_lock), GFP_ATOMIC);
+	if (!mlock)
+		return MLAN_STATUS_FAILURE;
+	spin_lock_init(&mlock->lock);
+	*pplock = (t_void *)mlock;
+
+	atomic_inc(&handle->lock_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Free the lock
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param plock    Lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_free_lock(t_void *pmoal, t_void *plock)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_lock *mlock = plock;
+
+	kfree(mlock);
+	if (mlock)
+		atomic_dec(&handle->lock_count);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Request a spin lock
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_lock(t_void *pmoal, t_void *plock)
+__acquires(&plock->lock)
+{
+	moal_lock *mlock = plock;
+	unsigned long flags = 0;
+	spin_lock_irqsave(&mlock->lock, flags);
+	mlock->flags = flags;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Request a spin_unlock
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param plock    Pointer to the lock
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_spin_unlock(t_void *pmoal, t_void *plock)
+__releases(&plock->lock)
+{
+	moal_lock *mlock = (moal_lock *)plock;
+	spin_unlock_irqrestore(&mlock->lock, mlock->flags);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  This function collects AMSDU TP statistics.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param amsdu_process_delay          amsdu process time
+ *  @param amsdu_copy_delay             amsdu copy time
+ *
+ *  @return         N/A
+ */
+void
+moal_amsdu_tp_accounting(t_void *pmoal, t_s32 amsdu_process_delay,
+			 t_s32 amsdu_copy_delay)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	handle->tp_acnt.rx_amsdu_delay[handle->tp_acnt.rx_amsdu_index] =
+		amsdu_process_delay;
+	handle->tp_acnt.rx_amsdu_copy_delay[handle->tp_acnt.rx_amsdu_index] =
+		amsdu_copy_delay;
+	handle->tp_acnt.rx_amsdu_index++;
+	if (handle->tp_acnt.rx_amsdu_index >= TXRX_MAX_SAMPLE)
+		handle->tp_acnt.rx_amsdu_index = 0;
+}
+
+/**
+ *  @brief  This function collects TP statistics.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param buf          pointer to the buffer of a packet
+ *  @param drop_point   Drop pointer user set
+ *
+ *  @return         N/A
+ */
+void
+moal_tp_accounting(t_void *pmoal, void *buf, t_u32 drop_point)
+{
+	struct sk_buff *skb = NULL;
+	moal_handle *handle = (moal_handle *)pmoal;
+	pmlan_buffer pmbuf = (pmlan_buffer)buf;
+	t_s32 delay;
+	wifi_timeval t;
+
+	if (drop_point < MAX_TP_ACCOUNT_DROP_POINT_NUM) {
+		if (drop_point == 4) {
+			handle->tp_acnt.tx_bytes[drop_point] += pmbuf->data_len;
+		} else {
+			skb = (struct sk_buff *)buf;
+			handle->tp_acnt.tx_bytes[drop_point] += skb->len;
+		}
+		handle->tp_acnt.tx_packets[drop_point]++;
+	} else if (drop_point <= RX_DROP_P5) {
+		t_u16 rx_len = 0;
+		if (drop_point == RX_DROP_P1 || drop_point == RX_DROP_P2)
+			rx_len = pmbuf->data_len - *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset) + 2);	//remove rx_pkt_offset
+		else if (drop_point == RX_DROP_P3)	//aggr pkt
+			rx_len = pmbuf->data_len;
+		else if (drop_point == RX_DROP_P4) {	//before to kernel
+			skb = (struct sk_buff *)buf;
+			rx_len = skb->len;
+		}
+		handle->tp_acnt.rx_bytes[drop_point -
+					 MAX_TP_ACCOUNT_DROP_POINT_NUM] +=
+			rx_len;
+		handle->tp_acnt.rx_packets[drop_point -
+					   MAX_TP_ACCOUNT_DROP_POINT_NUM]++;
+	} else if (drop_point == RX_TIME_PKT) {
+		woal_get_monotonic_time(&t);
+		/* deque - pcie receive */
+		delay = (t_s32)(pmbuf->extra_ts_sec -
+				pmbuf->in_ts_sec) * 1000000;
+		delay += (t_s32)(pmbuf->extra_ts_usec - pmbuf->in_ts_usec);
+		handle->tp_acnt.rx_delay1_driver[handle->tp_acnt.rx_index] =
+			delay;
+		/* before netif_rx - deque */
+		delay = (t_s32)(pmbuf->out_ts_sec -
+				pmbuf->extra_ts_sec) * 1000000;
+		delay += (t_s32)(pmbuf->out_ts_usec - pmbuf->extra_ts_usec);
+		handle->tp_acnt.rx_delay2_driver[handle->tp_acnt.rx_index] =
+			delay;
+		/* netif_rx to netif_rx return */
+		delay = (t_s32)(t.time_sec - pmbuf->out_ts_sec) * 1000000;
+		delay += (t_s32)(t.time_usec - pmbuf->out_ts_usec);
+		handle->tp_acnt.rx_delay_kernel[handle->tp_acnt.rx_index] =
+			delay;
+		handle->tp_acnt.rx_index++;
+		if (handle->tp_acnt.rx_index >= TXRX_MAX_SAMPLE)
+			handle->tp_acnt.rx_index = 0;
+	} else if (drop_point == TX_TIME_PKT) {
+		delay = (t_s32)(pmbuf->out_ts_sec - pmbuf->in_ts_sec) * 1000000;
+		delay += (t_s32)(pmbuf->out_ts_usec - pmbuf->in_ts_usec);
+		handle->tp_acnt.tx_delay_driver[handle->tp_acnt.tx_index] =
+			delay;
+		handle->tp_acnt.tx_index++;
+		if (handle->tp_acnt.tx_index >= TXRX_MAX_SAMPLE)
+			handle->tp_acnt.tx_index = 0;
+	}
+}
+
+void
+moal_tp_accounting_rx_param(t_void *pmoal, unsigned int type,
+			    unsigned int rsvd1)
+{
+	moal_handle *phandle = (moal_handle *)pmoal;
+	switch (type) {
+	case 0:		//Rx interrupt
+		phandle->tp_acnt.rx_intr_cnt++;
+		break;
+	case 1:		//rx_pkts_queued
+		phandle->tp_acnt.rx_pending = rsvd1;
+		break;
+	case 2:		//paused
+		phandle->tp_acnt.rx_paused_cnt++;
+		break;
+	case 3:		//tx interrupt count
+		phandle->tp_acnt.tx_intr_cnt++;
+		break;
+	case 4:		//rx amsdu count
+		phandle->tp_acnt.rx_amsdu_cnt++;
+		phandle->tp_acnt.rx_amsdu_pkt_cnt += rsvd1;
+		break;
+	case 5:		//tx amsdu count
+		phandle->tp_acnt.tx_amsdu_cnt++;
+		phandle->tp_acnt.tx_amsdu_pkt_cnt += rsvd1;
+		break;
+	case 6:		//rxbd rdptr full count
+		phandle->tp_acnt.rx_rdptr_full_cnt++;
+		break;
+	case 7:		//tx hard xmit skb realloc count
+		phandle->tp_acnt.tx_xmit_skb_realloc_cnt++;
+		break;
+	case 8:		//tx stop queue count
+		phandle->tp_acnt.tx_stop_queue_cnt++;
+		break;
+
+	default:
+		break;
+	}
+}
+
+/**
+ *  @brief This function reads one block of firmware data from MOAL
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param offset       Offset from where the data will be copied
+ *  @param len          Length to be copied
+ *  @param pbuf         Buffer where the data will be copied
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_get_fw_data(t_void *pmoal, t_u32 offset, t_u32 len, t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+
+	if (!pbuf || !len || !handle->firmware)
+		return MLAN_STATUS_FAILURE;
+
+	if (offset + len > handle->firmware->size)
+		return MLAN_STATUS_FAILURE;
+
+	moal_memcpy_ext(handle, pbuf, handle->firmware->data + offset, len,
+			len);
+
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function get vdll data from moal
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param len          Length to be copied
+ *  @param pbuf         Buffer where the data will be copied
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_get_vdll_data(t_void *pmoal, t_u32 len, t_u8 *pbuf)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	mlan_status status = MLAN_STATUS_FAILURE;
+	t_u32 offset = 0;
+	t_u8 req_fw = MFALSE;
+
+	if (!handle->firmware) {
+		req_fw = MTRUE;
+		woal_vdll_req_fw(handle);
+	}
+
+	if (handle->firmware) {
+		if (len < handle->firmware->size) {
+			offset = handle->firmware->size - len;
+			moal_memcpy_ext(handle, pbuf,
+					handle->firmware->data + offset, len,
+					len);
+			status = MLAN_STATUS_SUCCESS;
+		} else {
+			PRINTM(MERROR, "Invalid VDLL length = %d, fw_len=%d\n",
+			       len, (int)handle->firmware->size);
+		}
+		if (req_fw) {
+			release_firmware(handle->firmware);
+			handle->firmware = NULL;
+		}
+	}
+	return status;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization
+ * firmware.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param status   The status code for mlan_init_fw request
+ *  @param phw      pointer to mlan_hw_info
+ *  @param ptbl     pointer to mplan_bss_tbl
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_get_hw_spec_complete(t_void *pmoal,
+			  mlan_status status,
+			  mlan_hw_info * phw, pmlan_bss_tbl ptbl)
+{
+#if defined(PCIE9098)
+	moal_handle *handle = (moal_handle *)pmoal;
+#endif
+
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MCMND, "Get Hw Spec done, fw_cap=0x%x\n", phw->fw_cap);
+#ifdef PCIE9098
+	/** Special/Temporary handling to manage the driver version string
+         * to identify Seahawk/AW690 (skyhawk based) based on fw_cap_ext
+         * value set by Fw */
+		if (phw->fw_cap_ext & MBIT(31) &&
+		    IS_PCIE9098(handle->card_type)) {
+			moal_memcpy_ext(handle, driver_version, CARD_PCIEAW690,
+					strlen(CARD_PCIEAW690),
+					strlen(driver_version));
+			moal_memcpy_ext(handle,
+					driver_version + strlen(INTF_CARDTYPE) +
+					strlen(KERN_VERSION), V17, strlen(V17),
+					strlen(driver_version) -
+					strlen(INTF_CARDTYPE) -
+					strlen(KERN_VERSION));
+			moal_memcpy_ext(handle, handle->driver_version,
+					driver_version, strlen(driver_version),
+					MLAN_MAX_VER_STR_LEN - 1);
+		}
+#endif
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN completes the initialization
+ * firmware.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param status   The status code for mlan_init_fw request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_init_fw_complete(t_void *pmoal, mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	ENTER();
+	if (status == MLAN_STATUS_SUCCESS)
+		handle->hardware_status = HardwareStatusReady;
+	handle->init_wait_q_woken = MTRUE;
+	wake_up(&handle->init_wait_q);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN shutdown firmware is completed.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param status   The status code for mlan_shutdown request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_shutdown_fw_complete(t_void *pmoal, mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	ENTER();
+	handle->hardware_status = HardwareStatusNotReady;
+	handle->init_wait_q_woken = MTRUE;
+	wake_up_interruptible(&handle->init_wait_q);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when an MLAN IOCTL is completed.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pioctl_req	pointer to structure mlan_ioctl_req
+ *  @param status   The status code for mlan_ioctl request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_ioctl_complete(t_void *pmoal,
+		    pmlan_ioctl_req pioctl_req, mlan_status status)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_private *priv = NULL;
+	wait_queue *wait;
+	unsigned long flags = 0;
+	ENTER();
+
+	if (!atomic_read(&handle->ioctl_pending))
+		PRINTM(MERROR, "ERR: Unexpected IOCTL completed: %p\n",
+		       pioctl_req);
+	else
+		atomic_dec(&handle->ioctl_pending);
+	priv = woal_bss_index_to_priv(handle, pioctl_req->bss_index);
+	if (!priv) {
+		PRINTM(MERROR,
+		       "IOCTL %p complete with NULL priv, bss_index=%d\n",
+		       pioctl_req, pioctl_req->bss_index);
+		LEAVE();
+		return MLAN_STATUS_SUCCESS;
+	}
+
+	if (status != MLAN_STATUS_SUCCESS && status != MLAN_STATUS_COMPLETE)
+		PRINTM(MERROR,
+		       "IOCTL failed: %p id=0x%x, sub_id=0x%x action=%d, status_code=0x%x\n",
+		       pioctl_req, pioctl_req->req_id,
+		       (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
+		       pioctl_req->status_code);
+	else
+		PRINTM(MIOCTL,
+		       "IOCTL completed: %p id=0x%x sub_id=0x%x, action=%d,  status=%d, status_code=0x%x\n",
+		       pioctl_req, pioctl_req->req_id,
+		       (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
+		       status, pioctl_req->status_code);
+
+	spin_lock_irqsave(&handle->driver_lock, flags);
+	wait = (wait_queue *)pioctl_req->reserved_1;
+	if (wait) {
+		wait->condition = MTRUE;
+		wait->status = status;
+		if (wait->wait_timeout) {
+			wake_up(&wait->wait);
+		} else {
+			if ((status != MLAN_STATUS_SUCCESS) &&
+			    (pioctl_req->status_code ==
+			     MLAN_ERROR_CMD_TIMEOUT)) {
+				PRINTM(MERROR, "IOCTL: command timeout\n");
+			} else {
+				wake_up_interruptible(&wait->wait);
+			}
+		}
+		spin_unlock_irqrestore(&handle->driver_lock, flags);
+	} else {
+		spin_unlock_irqrestore(&handle->driver_lock, flags);
+		if ((status == MLAN_STATUS_SUCCESS) &&
+		    (pioctl_req->action == MLAN_ACT_GET))
+			woal_process_ioctl_resp(priv, pioctl_req);
+		kfree(pioctl_req);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function allocates mlan_buffer.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param size     allocation size requested
+ *  @param pmbuf    pointer to pointer to the allocated buffer
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_alloc_mlan_buffer(t_void *pmoal, t_u32 size, pmlan_buffer *pmbuf)
+{
+	*pmbuf = woal_alloc_mlan_buffer((moal_handle *)pmoal, size);
+	if (NULL == *pmbuf)
+		return MLAN_STATUS_FAILURE;
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function frees mlan_buffer.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    pointer to buffer to be freed
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_free_mlan_buffer(t_void *pmoal, pmlan_buffer pmbuf)
+{
+	if (!pmbuf)
+		return MLAN_STATUS_FAILURE;
+	woal_free_mlan_buffer((moal_handle *)pmoal, pmbuf);
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function is called when MLAN complete send data packet.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *  @param status   The status code for mlan_send_packet request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_send_packet_complete(t_void *pmoal, pmlan_buffer pmbuf, mlan_status status)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)pmoal;
+	struct sk_buff *skb = NULL;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	t_u32 index = 0;
+#endif
+
+	ENTER();
+	if (pmbuf && pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
+		woal_free_mlan_buffer(handle, pmbuf);
+		atomic_dec(&handle->tx_pending);
+		goto done;
+	}
+	if (pmbuf) {
+		priv = woal_bss_index_to_priv(pmoal, pmbuf->bss_index);
+		skb = (struct sk_buff *)pmbuf->pdesc;
+		if (priv) {
+			woal_set_trans_start(priv->netdev);
+			if (skb) {
+				if (status == MLAN_STATUS_SUCCESS) {
+					priv->stats.tx_packets++;
+					priv->stats.tx_bytes += skb->len;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+					woal_packet_fate_monitor(priv,
+								 PACKET_TYPE_TX,
+								 TX_PKT_FATE_SENT,
+								 FRAME_TYPE_ETHERNET_II,
+								 0, 0,
+								 skb->data,
+								 skb->data_len);
+#endif
+				} else {
+					priv->stats.tx_errors++;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+					woal_packet_fate_monitor(priv,
+								 PACKET_TYPE_TX,
+								 TX_PKT_FATE_DRV_DROP_OTHER,
+								 FRAME_TYPE_ETHERNET_II,
+								 0, 0,
+								 skb->data,
+								 skb->data_len);
+#endif
+				}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+				index = skb_get_queue_mapping(skb);
+				atomic_dec(&handle->tx_pending);
+				if (atomic_dec_return
+				    (&priv->wmm_tx_pending[index]) ==
+				    LOW_TX_PENDING) {
+					struct netdev_queue *txq =
+						netdev_get_tx_queue(priv->
+								    netdev,
+								    index);
+					if (netif_tx_queue_stopped(txq)) {
+						netif_tx_wake_queue(txq);
+						PRINTM(MINFO,
+						       "Wakeup Kernel Queue:%d\n",
+						       index);
+					}
+				}
+#else /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
+				if (atomic_dec_return(&handle->tx_pending) <
+				    LOW_TX_PENDING) {
+					int i;
+					for (i = 0; i < handle->priv_num; i++) {
+#ifdef STA_SUPPORT
+						if ((GET_BSS_ROLE
+						     (handle->priv[i]) ==
+						     MLAN_BSS_ROLE_STA) &&
+						    (handle->priv[i]
+						     ->media_connected ||
+						     priv->
+						     is_adhoc_link_sensed)) {
+							woal_wake_queue(handle->
+									priv[i]
+									->
+									netdev);
+						}
+#endif
+#ifdef UAP_SUPPORT
+						if ((GET_BSS_ROLE
+						     (handle->priv[i]) ==
+						     MLAN_BSS_ROLE_UAP) &&
+						    (handle->priv[i]
+						     ->media_connected)) {
+							woal_wake_queue(handle->
+									priv[i]
+									->
+									netdev);
+						}
+#endif
+					}
+				}
+#endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
+			}
+		}
+		if (skb)
+			dev_kfree_skb_any(skb);
+	}
+
+done:
+	if ((atomic_read(&handle->tx_pending) == 0) &&
+	    !is_zero_timeval(handle->tx_time_start)) {
+		woal_get_monotonic_time(&handle->tx_time_end);
+		handle->tx_time +=
+			(t_u64)(timeval_to_usec(handle->tx_time_end) -
+				timeval_to_usec(handle->tx_time_start));
+		PRINTM(MINFO,
+		       "%s : start_timeval=%d:%d end_timeval=%d:%d inter=%llu tx_time=%llu\n",
+		       __func__, handle->tx_time_start.time_sec,
+		       handle->tx_time_start.time_usec,
+		       handle->tx_time_end.time_sec,
+		       handle->tx_time_end.time_usec,
+		       (t_u64)(timeval_to_usec(handle->tx_time_end) -
+			       timeval_to_usec(handle->tx_time_start)),
+		       handle->tx_time);
+		handle->tx_time_start.time_sec = 0;
+		handle->tx_time_start.time_usec = 0;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+#ifdef USB
+/**
+ *  @brief This function is called when MLAN complete receiving
+ *         data/event/command
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *  @param port     Port number for receive
+ *  @param status   The status code for mlan_receive request
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_recv_complete(t_void *pmoal, pmlan_buffer pmbuf,
+		   t_u32 port, mlan_status status)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)pmoal;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	ENTER();
+
+	if ((pmbuf && (pmbuf->flags & MLAN_BUF_FLAG_RX_DEAGGR)) || !pmbuf)
+		atomic_dec(&handle->rx_pending);
+
+	if (pmbuf) {
+		priv = woal_bss_index_to_priv(handle, pmbuf->bss_index);
+		if (priv && (pmbuf->buf_type == MLAN_BUF_TYPE_DATA) &&
+		    (status == MLAN_STATUS_FAILURE)) {
+			priv->stats.rx_dropped++;
+		}
+		/* Reuse the buffer in case of command/event */
+		if (port == cardp->rx_cmd_ep)
+			woal_submit_rx_urb(handle, port);
+		else {
+			woal_free_mlan_buffer(handle, pmbuf);
+			if ((atomic_read(&handle->rx_pending) <
+			     USB_LOW_RX_PENDING) &&
+			    atomic_read(&cardp->rx_data_urb_pending) <
+			    MVUSB_RX_DATA_URB)
+				woal_usb_submit_rx_data_urbs(handle);
+		}
+	} else if (port == cardp->rx_data_ep) {
+		if ((atomic_read(&handle->rx_pending) < USB_LOW_RX_PENDING) &&
+		    atomic_read(&cardp->rx_data_urb_pending) <
+		    MVUSB_RX_DATA_URB)
+			woal_usb_submit_rx_data_urbs(handle);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function write a command/data packet to card.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *  @param port     Port number for sent
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or
+ * MLAN_STATUS_PENDING or MLAN_STATUS_RESOURCE
+ */
+mlan_status
+moal_write_data_async(t_void *pmoal, pmlan_buffer pmbuf, t_u32 port)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	if (handle->is_suspended == MTRUE) {
+		PRINTM(MERROR,
+		       "write_data_async is not allowed while suspended\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	ret = woal_write_data_async((moal_handle *)pmoal, pmbuf, (t_u8)port);
+	LEAVE();
+	return ret;
+}
+#endif /* USB */
+
+/**
+ *  @brief This function write a command/data packet to card.
+ *         This function blocks the call until it finishes
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *  @param port     Port number for sent
+ *  @param timeout  Timeout value in milliseconds (if 0 the wait is forever)
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_write_data_sync(t_void *pmoal, pmlan_buffer pmbuf,
+		     t_u32 port, t_u32 timeout)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	return handle->ops.write_data_sync(handle, pmbuf, port, timeout);
+}
+
+/**
+ *  @brief This function read data packet/event/command from card.
+ *         This function blocks the call until it finish
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *  @param port     Port number for read
+ *  @param timeout  Timeout value in milliseconds (if 0 the wait is forever)
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_read_data_sync(t_void *pmoal,
+		    pmlan_buffer pmbuf, t_u32 port, t_u32 timeout)
+{
+	moal_handle *handle = (moal_handle *)pmoal;
+	return handle->ops.read_data_sync(handle, pmbuf, port, timeout);
+}
+
+#if defined(SDIO) || defined(PCIE)
+/**
+ *  @brief This function writes data into card register.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param reg          register offset
+ *  @param data         value
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_write_reg(t_void *pmoal, t_u32 reg, t_u32 data)
+{
+	int ret = MLAN_STATUS_FAILURE;
+	moal_handle *handle = (moal_handle *)pmoal;
+	if (handle->ops.write_reg)
+		ret = handle->ops.write_reg(handle, reg, data);
+	return ret;
+}
+
+/**
+ *  @brief This function reads data from card register.
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param reg          register offset
+ *  @param data         value
+ *
+ *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_read_reg(t_void *pmoal, t_u32 reg, t_u32 *data)
+{
+	int ret = MLAN_STATUS_FAILURE;
+	moal_handle *handle = (moal_handle *)pmoal;
+	if (handle->ops.read_reg)
+		ret = handle->ops.read_reg(handle, reg, data);
+	return ret;
+}
+
+#endif /* SDIO || PCIE */
+
+/**
+ *  @brief This function uploads amsdu packet to the network stack
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *
+ *  @return         MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_recv_amsdu_packet(t_void *pmoal, pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_FAILURE;
+	struct sk_buff *skb = NULL;
+	struct sk_buff *frame = NULL;
+	int remaining;
+	const struct ethhdr *eth;
+	u8 dst[ETH_ALEN], src[ETH_ALEN];
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_private *priv = NULL;
+	struct net_device *netdev = NULL;
+	u8 *payload;
+	mlan_buffer mbuf;
+	t_u8 drop = 0;
+	t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] =
+		{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+	wifi_timeval t1, t2;
+	t_s32 delay;
+	t_u32 in_ts_sec = 0;
+	t_u32 in_ts_usec = 0;
+
+	ENTER();
+	memset(&mbuf, 0, sizeof(mlan_buffer));
+	mbuf.bss_index = pmbuf->bss_index;
+
+	priv = woal_bss_index_to_priv(pmoal, pmbuf->bss_index);
+	if (priv == NULL) {
+		PRINTM(MERROR, "%s: priv is null\n", __func__);
+		goto done;
+	}
+	netdev = priv->netdev;
+	skb = (struct sk_buff *)pmbuf->pdesc;
+	if (!skb)
+		goto done;
+
+	skb_reserve(skb, pmbuf->data_offset);
+	if (skb_tailroom(skb) < (int)pmbuf->data_len) {
+		PRINTM(MERROR, "skb overflow: tail room=%d, data_len=%d\n",
+		       skb_tailroom(skb), pmbuf->data_len);
+		goto done;
+	}
+	skb_put(skb, pmbuf->data_len);
+
+	//rx_trace 8
+	if (handle->tp_acnt.on) {
+		moal_tp_accounting(pmoal, skb, RX_DROP_P4);
+		woal_get_monotonic_time(&t1);
+		in_ts_sec = t1.time_sec;
+		in_ts_usec = t1.time_usec;
+		if (pmbuf && pmbuf->in_ts_sec) {
+			pmbuf->out_ts_sec = t1.time_sec;
+			pmbuf->out_ts_usec = t1.time_usec;
+		}
+	}
+	if (handle->tp_acnt.drop_point == RX_DROP_P4) {
+		status = MLAN_STATUS_PENDING;
+		dev_kfree_skb(skb);
+		goto done;
+	}
+
+	while (skb != frame) {
+		__be16 len;
+		u8 padding;
+		unsigned int subframe_len;
+		eth = (struct ethhdr *)skb->data;
+		len = ntohs(eth->h_proto);
+		subframe_len = sizeof(struct ethhdr) + len;
+		remaining = skb->len;
+
+		if (subframe_len > remaining) {
+			PRINTM(MERROR,
+			       "Error in len: remaining = %d, subframe_len = %d\n",
+			       remaining, subframe_len);
+			break;
+		}
+		memcpy(dst, eth->h_dest, ETH_ALEN);
+		memcpy(src, eth->h_source, ETH_ALEN);
+
+		padding = (4 - subframe_len) & 0x3;
+
+		skb_pull(skb, sizeof(struct ethhdr));
+
+		if (remaining <= (subframe_len + padding)) {
+			frame = skb;
+			status = MLAN_STATUS_PENDING;
+		} else {
+			frame = skb_clone(skb, GFP_ATOMIC);
+			skb_trim(frame, len);
+			eth = (struct ethhdr *)skb_pull(skb, len + padding);
+			if (!eth) {
+				PRINTM(MERROR, "Invalid amsdu packet\n");
+				break;
+			}
+		}
+		skb_reset_network_header(frame);
+		frame->dev = netdev;
+		frame->priority = skb->priority;
+		payload = frame->data;
+		if (ether_addr_equal(payload, rfc1042_eth_hdr)) {
+			/* Remove RFC1042 */
+			skb_pull(frame, 6);
+			memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
+			memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+		} else {
+			memcpy(skb_push(frame, sizeof(__be16)), &len,
+			       sizeof(__be16));
+			memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
+			memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+		}
+		mbuf.pbuf = frame->data;
+		mbuf.data_len = frame->len;
+		mlan_process_deaggr_pkt(handle->pmlan_adapter, &mbuf, &drop);
+		if (drop) {
+			dev_kfree_skb(frame);
+			continue;
+		}
+		frame->protocol = eth_type_trans(frame, netdev);
+		frame->ip_summed = CHECKSUM_NONE;
+		if (in_interrupt())
+			netif_rx(frame);
+		else {
+			if (atomic_read(&handle->rx_pending) >
+			    MAX_RX_PENDING_THRHLD)
+				netif_rx(frame);
+			else {
+				if (handle->params.net_rx == MTRUE) {
+					local_bh_disable();
+					netif_receive_skb(frame);
+					local_bh_enable();
+				} else {
+					netif_rx_ni(frame);
+				}
+			}
+		}
+	}
+	if (handle->tp_acnt.on) {
+		if (pmbuf && pmbuf->in_ts_sec)
+			moal_tp_accounting(handle, pmbuf, RX_TIME_PKT);
+
+		woal_get_monotonic_time(&t2);
+		delay = (t_s32)(t2.time_sec - in_ts_sec) * 1000000;
+		delay += (t_s32)(t2.time_usec - in_ts_usec);
+		moal_amsdu_tp_accounting(pmoal, delay, 0);
+	}
+done:
+	if (status == MLAN_STATUS_PENDING)
+		atomic_dec(&handle->mbufalloc_count);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function uploads the packet to the network stack
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmbuf    Pointer to the mlan buffer structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_private *priv = NULL;
+	struct sk_buff *skb = NULL;
+	moal_handle *handle = (moal_handle *)pmoal;
+#if defined(USB) || defined(PCIE)
+	t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;
+#endif
+	dot11_rxcontrol rxcontrol;
+	t_u8 rx_info_flag = MFALSE;
+	int j;
+	struct ethhdr *ethh = NULL;
+	struct net_device *netdev = NULL;
+
+	ENTER();
+	if (pmbuf) {
+#ifdef USB
+#ifdef STA_SUPPORT
+		if (IS_USB(handle->card_type)) {
+			struct usb_card_rec *cardp =
+				(struct usb_card_rec *)handle->card;
+			if (cardp->rx_deaggr_ctrl.enable) {
+				max_rx_data_size =
+					cardp->rx_deaggr_ctrl.aggr_max;
+				if (cardp->rx_deaggr_ctrl.aggr_mode ==
+				    MLAN_USB_AGGR_MODE_NUM) {
+					max_rx_data_size *=
+						MAX(MLAN_USB_MAX_PKT_SIZE,
+						    cardp->rx_deaggr_ctrl.
+						    aggr_align);
+					max_rx_data_size =
+						MAX(max_rx_data_size,
+						    MLAN_RX_DATA_BUF_SIZE);
+				}
+			}
+		}
+#endif
+#endif
+
+		priv = woal_bss_index_to_priv(pmoal, pmbuf->bss_index);
+		skb = (struct sk_buff *)pmbuf->pdesc;
+		if (priv) {
+			if (skb) {
+				skb_reserve(skb, pmbuf->data_offset);
+				if (skb_tailroom(skb) < (int)pmbuf->data_len) {
+					PRINTM(MERROR,
+					       "skb overflow: tail room=%d, data_len=%d\n",
+					       skb_tailroom(skb),
+					       pmbuf->data_len);
+					status = MLAN_STATUS_FAILURE;
+					priv->stats.rx_dropped++;
+					goto done;
+				}
+				skb_put(skb, pmbuf->data_len);
+				pmbuf->pdesc = NULL;
+				pmbuf->pbuf = NULL;
+				pmbuf->data_offset = pmbuf->data_len = 0;
+				/* pkt been submit to kernel, no need to
+				 * free by mlan*/
+				status = MLAN_STATUS_PENDING;
+				atomic_dec(&handle->mbufalloc_count);
+			} else {
+				PRINTM(MERROR,
+				       "%s without skb attach!!!\n", __func__);
+				skb = dev_alloc_skb(pmbuf->data_len +
+						    MLAN_NET_IP_ALIGN);
+				if (!skb) {
+					PRINTM(MERROR,
+					       "%s fail to alloc skb\n",
+					       __func__);
+					status = MLAN_STATUS_FAILURE;
+					priv->stats.rx_dropped++;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+					woal_packet_fate_monitor(priv,
+								 PACKET_TYPE_RX,
+								 RX_PKT_FATE_DRV_DROP_NOBUFS,
+								 FRAME_TYPE_ETHERNET_II,
+								 0, 0,
+								 (t_u8
+								  *)(pmbuf->
+								     pbuf +
+								     pmbuf->
+								     data_offset),
+								 pmbuf->
+								 data_len);
+#endif
+					goto done;
+				}
+				skb_reserve(skb, MLAN_NET_IP_ALIGN);
+				moal_memcpy_ext(handle, skb->data,
+						(t_u8 *)(pmbuf->pbuf +
+							 pmbuf->data_offset),
+						pmbuf->data_len,
+						pmbuf->data_len);
+				skb_put(skb, pmbuf->data_len);
+			}
+			ethh = (struct ethhdr *)(skb->data);
+			if (ntohs(ethh->h_proto) == ETH_P_PAE)
+				PRINTM(MEVENT,
+				       "wlan: %s Rx EAPOL pkt from " MACSTR
+				       "\n",
+				       priv->netdev->name,
+				       MAC2STR(ethh->h_source));
+			if (!netdev)
+				netdev = priv->netdev;
+			skb->dev = netdev;
+			skb->protocol = eth_type_trans(skb, netdev);
+			skb->ip_summed = CHECKSUM_NONE;
+
+#if defined(USB) || defined(PCIE)
+			/* This is only required only in case of 11n and
+			   USB as we alloc if(skb_tailroom(skb) <
+			   pmbuf->data_len){ PRINTM(MERROR,"skb overflow:
+			   tail room=%d, data_len\n", skb_tailroom(skb),
+			   pmbuf->data_len); status = MLAN_STATUS_FAILURE;
+			   priv->stats.rx_dropped++;
+			   goto done;
+			   }
+			   * a buffer of 4K only if its 11N (to be able to
+			   receive 4K AMSDU
+			   * packets). In case of SD we allocate buffers
+			   based on the size
+			   * of packet and hence this is not needed.
+			 */
+			/* Modifying the truesize here as our allocation
+			 * for each skb is 4K but we only receive 2K
+			 * packets and this cause the kernel to start
+			 * dropping packets in case where application
+			 * has allocated buffer based on 2K size i.e. if
+			 * there a 64K packet received (in IP fragments
+			 * and application allocates 64K to receive this
+			 * packet but this packet would almost double up
+			 * because we allocate each 1.5K fragment in 4K
+			 * and pass it up. As soon as the 64K limit hits
+			 * kernel will start to drop rest of the
+			 * fragments. Currently we fail the
+			 * Filesndl-ht.scr script for UDP, hence this
+			 * fix
+			 */
+			if (!IS_SD(priv->phandle->card_type)) {
+				if (skb->truesize > max_rx_data_size)
+					skb->truesize +=
+						(skb->len - max_rx_data_size);
+			}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (!woal_filter_packet(priv, skb->data, skb->len, 0)) {
+				PRINTM(MEVENT,
+				       "drop filtered packet %s\n",
+				       priv->netdev->name);
+				status = MLAN_STATUS_FAILURE;
+				priv->stats.rx_dropped++;
+				woal_packet_fate_monitor(priv, PACKET_TYPE_RX,
+							 RX_PKT_FATE_DRV_DROP_FILTER,
+							 FRAME_TYPE_ETHERNET_II,
+							 0, 0, skb->data,
+							 skb->len);
+				dev_kfree_skb(skb);
+				goto done;
+			}
+#endif
+			priv->stats.rx_bytes += skb->len;
+			priv->stats.rx_packets++;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			woal_packet_fate_monitor(priv, PACKET_TYPE_RX,
+						 RX_PKT_FATE_SUCCESS,
+						 FRAME_TYPE_ETHERNET_II,
+						 0, 0, skb->data, skb->len);
+#endif
+#ifdef ANDROID_KERNEL
+			if (handle->params.wakelock_timeout) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+				__pm_wakeup_event(&handle->ws,
+						  handle->params.
+						  wakelock_timeout);
+#else
+				wake_lock_timeout(&handle->wake_lock,
+						  msecs_to_jiffies(handle->
+								   params.
+								   wakelock_timeout));
+#endif
+			}
+#endif
+			if (priv->rx_protocols.protocol_num) {
+				for (j = 0;
+				     j < priv->rx_protocols.protocol_num; j++) {
+					if (htons((__force t_u16)skb->protocol)
+					    == priv->rx_protocols.protocols[j])
+						rx_info_flag = MTRUE;
+				}
+			}
+			if (rx_info_flag &&
+			    (skb_tailroom(skb) > (int)sizeof(rxcontrol))) {
+				memset(&rxcontrol, 0, sizeof(dot11_rxcontrol));
+				rxcontrol.datarate = pmbuf->u.rx_info.data_rate;
+				rxcontrol.channel = pmbuf->u.rx_info.channel;
+				rxcontrol.antenna = pmbuf->u.rx_info.antenna;
+				rxcontrol.rssi = pmbuf->u.rx_info.rssi;
+				skb_put(skb, sizeof(dot11_rxcontrol));
+				memmove(skb->data +
+					sizeof(dot11_rxcontrol),
+					skb->data,
+					skb->len - sizeof(dot11_rxcontrol));
+				moal_memcpy_ext(handle, skb->data, &rxcontrol,
+						sizeof(dot11_rxcontrol),
+						sizeof(dot11_rxcontrol));
+			}
+			//rx_trace 8
+			if (priv->phandle->tp_acnt.on) {
+				wifi_timeval t;
+				moal_tp_accounting(handle, skb, RX_DROP_P4);
+				if (pmbuf && pmbuf->in_ts_sec) {
+					woal_get_monotonic_time(&t);
+					pmbuf->out_ts_sec = t.time_sec;
+					pmbuf->out_ts_usec = t.time_usec;
+				}
+			}
+			if (priv->phandle->tp_acnt.drop_point == RX_DROP_P4) {
+				status = MLAN_STATUS_PENDING;
+				dev_kfree_skb(skb);
+			} else if (in_interrupt())
+				netif_rx(skb);
+			else {
+				if (atomic_read(&handle->rx_pending) >
+				    MAX_RX_PENDING_THRHLD)
+					netif_rx(skb);
+				else {
+					if (handle->params.net_rx == MTRUE) {
+						local_bh_disable();
+						netif_receive_skb(skb);
+						local_bh_enable();
+					} else {
+						netif_rx_ni(skb);
+					}
+				}
+			}
+			if (priv->phandle->tp_acnt.on) {
+				if (pmbuf && pmbuf->in_ts_sec)
+					moal_tp_accounting(handle, pmbuf,
+							   RX_TIME_PKT);
+			}
+		}
+	}
+done:
+	LEAVE();
+	return status;
+}
+
+#if defined(PCIE) || defined(SDIO)
+void
+woal_request_busfreq_pmqos_add(t_void *handle)
+{
+	moal_handle *pmhandle = (moal_handle *)handle;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
+#ifdef IMX_SUPPORT
+	if (IS_PCIE(pmhandle->card_type)) {
+		request_bus_freq(BUS_FREQ_HIGH);
+	}
+#endif
+#endif
+	if (moal_extflg_isset(pmhandle, EXT_PMQOS)) {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+#ifdef IMX_SUPPORT
+		pm_qos_add_request(&pmhandle->woal_pm_qos_req,
+				   PM_QOS_CPU_DMA_LATENCY, 0);
+#endif
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
+#ifdef IMX_SUPPORT
+		cpu_latency_qos_add_request(&pmhandle->woal_pm_qos_req, 0);
+#endif
+#endif
+	}
+	return;
+}
+
+void
+woal_release_busfreq_pmqos_remove(t_void *handle)
+{
+
+	moal_handle *pmhandle = (moal_handle *)handle;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
+#ifdef IMX_SUPPORT
+	if (IS_PCIE(pmhandle->card_type)) {
+		release_bus_freq(BUS_FREQ_HIGH);
+	}
+#endif
+#endif
+
+	if (moal_extflg_isset(pmhandle, EXT_PMQOS)) {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+#ifdef IMX_SUPPORT
+		pm_qos_remove_request(&pmhandle->woal_pm_qos_req);
+#endif
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
+#ifdef IMX_SUPPORT
+		cpu_latency_qos_remove_request(&pmhandle->woal_pm_qos_req);
+#endif
+#endif
+	}
+	return;
+}
+#endif /*defined(PCIE) || defined(SDIO) */
+
+/**
+ *  @brief This function checks media_connected state for
+ *  BSS types UAP/STA/P2P_GO/GC
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *
+ */
+int
+woal_check_media_connected(t_void *pmoal)
+{
+	int i;
+	moal_handle *pmhandle = (moal_handle *)pmoal;
+	moal_private *pmpriv = NULL;
+	for (i = 0; i < pmhandle->priv_num && (pmpriv = pmhandle->priv[i]); i++) {
+		if (!pmpriv)
+			continue;
+		if (pmpriv->media_connected == MTRUE) {
+			return MTRUE;
+		}
+	}
+	return MFALSE;
+}
+
+/**
+ *  @brief This function checks connect and disconnect
+ *  events for BSS types UAP/STA/P2P_GO/GC
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *
+ */
+static void
+moal_connection_status_check_pmqos(t_void *pmoal)
+{
+	moal_handle *pmhandle = (moal_handle *)pmoal;
+	if ((woal_check_media_connected(pmoal) == MTRUE)) {
+
+		if (pmhandle->request_pm == MFALSE) {
+			pmhandle->request_pm = MTRUE;
+#if defined(PCIE) || defined(SDIO)
+			woal_request_busfreq_pmqos_add(pmhandle);
+#endif
+		}
+	} else {
+		if (pmhandle->request_pm == MTRUE) {
+			pmhandle->request_pm = MFALSE;
+#if defined(PCIE) || defined(SDIO)
+			woal_release_busfreq_pmqos_remove(pmhandle);
+#endif
+		}
+	}
+
+}
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+/**
+ * @brief   Handle RX MGMT PKT event
+ *
+ * @param priv          A pointer moal_private structure
+ * @param pkt        A pointer to pkt
+ * @param len        length of pkt
+ *
+ * @return          N/A
+ */
+static void
+woal_rx_mgmt_pkt_event(moal_private *priv, t_u8 *pkt, t_u16 len)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (evt) {
+		evt->priv = priv;
+		evt->type = WOAL_EVENT_RX_MGMT_PKT;
+		evt->evt.event_len = len;
+		moal_memcpy_ext(priv->phandle, evt->evt.event_buf, pkt,
+				evt->evt.event_len, sizeof(evt->evt.event_buf));
+		INIT_LIST_HEAD(&evt->link);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+		list_add_tail(&evt->link, &handle->evt_queue);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		queue_work(handle->evt_workqueue, &handle->evt_work);
+	}
+}
+#endif
+#endif
+
+/**
+ *  @brief This function handles event receive
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param pmevent  Pointer to the mlan event structure
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_recv_event(t_void *pmoal, pmlan_event pmevent)
+{
+#ifdef STA_SUPPORT
+	int custom_len = 0;
+#ifdef STA_CFG80211
+	unsigned long flags;
+#endif
+#endif
+	moal_private *priv = NULL;
+#if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
+	moal_private *pmpriv = NULL;
+#endif
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+#if defined(STA_SUPPORT) || defined(UAP_WEXT)
+#if defined(UAP_SUPPORT) || defined(STA_WEXT)
+	union iwreq_data wrqu;
+#endif
+#endif
+#endif
+	mlan_ds_ps_info pm_info;
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_handle *ref_handle = NULL;
+
+#ifdef STA_CFG80211
+	t_u8 hw_test;
+#endif
+	int cfg80211_wext;
+
+#ifdef STA_CFG80211
+	t_u8 channel_status;
+	moal_private *remain_priv = NULL;
+#endif
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+	chan_band_info *pchan_info = NULL;
+#endif
+	t_u8 radar_detected;
+
+	t_u8 auto_fw_dump = MFALSE;
+	ENTER();
+	if (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) {
+		if (!handle->is_fw_dump_timer_set) {
+			PRINTM(MMSG, "FW trigger fw dump\n");
+			handle->is_fw_dump_timer_set = MTRUE;
+			woal_mod_timer(&handle->fw_dump_timer, MOAL_TIMER_5S);
+		}
+		woal_store_firmware_dump(pmoal, pmevent);
+		handle->driver_status = MTRUE;
+		ref_handle = (moal_handle *)handle->pref_mac;
+		if (ref_handle)
+			ref_handle->driver_status = MTRUE;
+		goto done;
+	}
+	if ((pmevent->event_id != MLAN_EVENT_ID_DRV_DEFER_RX_WORK) &&
+	    (pmevent->event_id != MLAN_EVENT_ID_DRV_DEFER_HANDLING) &&
+	    (pmevent->event_id != MLAN_EVENT_ID_DRV_MGMT_FRAME))
+		PRINTM(MEVENT, "event id:0x%x\n", pmevent->event_id);
+#if defined(PCIE)
+	if (pmevent->event_id == MLAN_EVENT_ID_SSU_DUMP_FILE) {
+		goto done;
+	}
+#endif /* SSU_SUPPORT */
+	if (pmevent->event_id == MLAN_EVENT_ID_STORE_HOST_CMD_RESP) {
+		goto done;
+	}
+	priv = woal_bss_index_to_priv(pmoal, pmevent->bss_index);
+	if (priv == NULL) {
+		PRINTM(MERROR, "%s: priv is null\n", __func__);
+		goto done;
+	}
+	if (priv->netdev == NULL) {
+		PRINTM(MERROR, "%s: netdev is null\n", __func__);
+		goto done;
+	}
+
+	cfg80211_wext = priv->phandle->params.cfg80211_wext;
+#ifdef STA_CFG80211
+	hw_test = moal_extflg_isset(pmoal, EXT_HW_TEST);
+#endif
+	switch (pmevent->event_id) {
+#ifdef STA_SUPPORT
+	case MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED:
+		priv->is_adhoc_link_sensed = MTRUE;
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_wake_queue(priv->netdev);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_ADHOC_LINK_SENSED);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_SENSED,
+				     strlen(CUS_EVT_ADHOC_LINK_SENSED));
+		break;
+
+	case MLAN_EVENT_ID_FW_ADHOC_LINK_LOST:
+		woal_stop_queue(priv->netdev);
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		priv->is_adhoc_link_sensed = MFALSE;
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_ADHOC_LINK_LOST);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_LOST,
+				     strlen(CUS_EVT_ADHOC_LINK_LOST));
+		break;
+
+	case MLAN_EVENT_ID_DRV_CONNECTED:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext) &&
+		    pmevent->event_len == ETH_ALEN) {
+			memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
+			moal_memcpy_ext(priv->phandle, wrqu.ap_addr.sa_data,
+					pmevent->event_buf, ETH_ALEN,
+					sizeof(wrqu.ap_addr.sa_data));
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu,
+					    NULL);
+		}
+#endif
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			moal_memcpy_ext(priv->phandle, priv->cfg_bssid,
+					pmevent->event_buf, ETH_ALEN, ETH_ALEN);
+			woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME,
+					   PASSIVE_SCAN_CHAN_TIME,
+					   MIN_SPECIFIC_SCAN_CHAN_TIME);
+		}
+#endif
+		custom_len = strlen(CUS_EVT_AP_CONNECTED);
+		memmove(pmevent->event_buf + custom_len, pmevent->event_buf,
+			pmevent->event_len);
+		moal_memcpy_ext(priv->phandle, pmevent->event_buf,
+				CUS_EVT_AP_CONNECTED, custom_len, custom_len);
+		pmevent->event_len += custom_len;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		woal_update_dscp_mapping(priv);
+		priv->media_connected = MTRUE;
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_wake_queue(priv->netdev);
+		moal_connection_status_check_pmqos(pmoal);
+		break;
+
+	case MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER:
+	case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER:
+	case MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER:
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		if (IS_STA_CFG80211(cfg80211_wext))
+			woal_ring_event_logger(priv, VERBOSE_RING_ID, pmevent);
+#endif
+#endif
+		break;
+
+	case MLAN_EVENT_ID_DRV_SCAN_REPORT:
+		PRINTM(MINFO, "Scan report\n");
+
+		if (priv->report_scan_result) {
+			priv->report_scan_result = MFALSE;
+#ifdef STA_CFG80211
+			if (IS_STA_CFG80211(cfg80211_wext)) {
+				if (priv->phandle->scan_request) {
+					PRINTM(MINFO,
+					       "Reporting scan results\n");
+					woal_inform_bss_from_scan_result(priv,
+									 NULL,
+									 MOAL_NO_WAIT);
+					if (!priv->phandle->first_scan_done) {
+						priv->phandle->first_scan_done =
+							MTRUE;
+						woal_set_scan_time(priv,
+								   ACTIVE_SCAN_CHAN_TIME,
+								   PASSIVE_SCAN_CHAN_TIME,
+								   SPECIFIC_SCAN_CHAN_TIME);
+					}
+					spin_lock_irqsave(&priv->phandle->
+							  scan_req_lock, flags);
+					if (priv->phandle->scan_request) {
+						cancel_delayed_work(
+							&priv->phandle->scan_timeout_work);
+						woal_cfg80211_scan_done(priv->
+									phandle->
+									scan_request,
+									MFALSE);
+						priv->phandle->scan_request =
+							NULL;
+					}
+					spin_unlock_irqrestore(&priv->phandle->
+							       scan_req_lock,
+							       flags);
+				}
+			}
+#endif /* STA_CFG80211 */
+
+#ifdef STA_WEXT
+			if (IS_STA_WEXT(cfg80211_wext)) {
+				memset(&wrqu, 0, sizeof(union iwreq_data));
+				wireless_send_event(priv->netdev, SIOCGIWSCAN,
+						    &wrqu, NULL);
+			}
+#endif
+			woal_broadcast_event(priv, (t_u8 *)&pmevent->event_id,
+					     sizeof(mlan_event_id));
+		}
+
+		if (!is_zero_timeval(priv->phandle->scan_time_start)) {
+			woal_get_monotonic_time(&priv->phandle->scan_time_end);
+			priv->phandle->scan_time +=
+				(t_u64)(timeval_to_usec
+					(priv->phandle->scan_time_end) -
+					timeval_to_usec(priv->phandle->
+							scan_time_start));
+			PRINTM(MINFO,
+			       "%s : start_timeval=%d:%d end_timeval=%d:%d inter=%llu scan_time=%llu\n",
+			       __func__,
+			       priv->phandle->scan_time_start.time_sec,
+			       priv->phandle->scan_time_start.time_usec,
+			       priv->phandle->scan_time_end.time_sec,
+			       priv->phandle->scan_time_end.time_usec,
+			       (t_u64)(timeval_to_usec
+				       (priv->phandle->scan_time_end) -
+				       timeval_to_usec(priv->phandle->
+						       scan_time_start)),
+			       priv->phandle->scan_time);
+			priv->phandle->scan_time_start.time_sec = 0;
+			priv->phandle->scan_time_start.time_usec = 0;
+		}
+
+		if (priv->phandle->scan_pending_on_block == MTRUE) {
+			priv->phandle->scan_pending_on_block = MFALSE;
+			priv->phandle->scan_priv = NULL;
+			MOAL_REL_SEMAPHORE(&priv->phandle->async_sem);
+		}
+		break;
+
+	case MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM:
+		memmove((pmevent->event_buf + strlen(CUS_EVT_OBSS_SCAN_PARAM) +
+			 1), pmevent->event_buf, pmevent->event_len);
+		moal_memcpy_ext(priv->phandle, pmevent->event_buf,
+				(t_u8 *)CUS_EVT_OBSS_SCAN_PARAM,
+				strlen(CUS_EVT_OBSS_SCAN_PARAM),
+				strlen(CUS_EVT_OBSS_SCAN_PARAM));
+		pmevent->event_buf[strlen(CUS_EVT_OBSS_SCAN_PARAM)] = 0;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len +
+				     strlen(CUS_EVT_OBSS_SCAN_PARAM));
+
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext)) {
+			memset(&wrqu, 0, sizeof(union iwreq_data));
+			wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
+			wrqu.data.length = pmevent->event_len +
+				strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1;
+			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
+					    pmevent->event_buf);
+		}
+#endif
+		break;
+	case MLAN_EVENT_ID_FW_BW_CHANGED:
+		memmove((pmevent->event_buf + strlen(CUS_EVT_BW_CHANGED) + 1),
+			pmevent->event_buf, pmevent->event_len);
+		moal_memcpy_ext(priv->phandle, pmevent->event_buf,
+				(t_u8 *)CUS_EVT_BW_CHANGED,
+				strlen(CUS_EVT_BW_CHANGED),
+				strlen(CUS_EVT_BW_CHANGED));
+		pmevent->event_buf[strlen(CUS_EVT_BW_CHANGED)] = 0;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len +
+				     strlen(CUS_EVT_BW_CHANGED));
+
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext)) {
+			memset(&wrqu, 0, sizeof(union iwreq_data));
+			wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
+			wrqu.data.length = pmevent->event_len +
+				strlen(CUS_EVT_BW_CHANGED) + 1;
+			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
+					    pmevent->event_buf);
+		}
+#endif
+		break;
+
+	case MLAN_EVENT_ID_FW_DISCONNECTED:
+		woal_send_disconnect_to_system(priv,
+					       (t_u16)*pmevent->event_buf);
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		priv->auth_flag = 0;
+		priv->host_mlme = MFALSE;
+		priv->auth_alg = 0xFFFF;
+#endif
+#endif
+#ifdef STA_WEXT
+		/* Reset wireless stats signal info */
+		if (IS_STA_WEXT(cfg80211_wext)) {
+			priv->w_stats.qual.level = 0;
+			priv->w_stats.qual.noise = 0;
+		}
+#endif
+#ifdef REASSOCIATION
+		if (priv->reassoc_on == MTRUE) {
+			PRINTM(MINFO, "Reassoc: trigger the timer\n");
+			priv->reassoc_required = MTRUE;
+			priv->phandle->is_reassoc_timer_set = MTRUE;
+			woal_mod_timer(&priv->phandle->reassoc_timer,
+				       REASSOC_TIMER_DEFAULT);
+		} else {
+			priv->rate_index = AUTO_RATE;
+		}
+#endif /* REASSOCIATION */
+		moal_connection_status_check_pmqos(pmoal);
+		break;
+
+	case MLAN_EVENT_ID_FW_MIC_ERR_UNI:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext)) {
+#if WIRELESS_EXT >= 18
+			woal_send_mic_error_event(priv,
+						  MLAN_EVENT_ID_FW_MIC_ERR_UNI);
+#else
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_MLME_MIC_ERR_UNI);
+#endif
+		}
+#endif /* STA_WEXT */
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			cfg80211_michael_mic_failure(priv->netdev,
+						     priv->cfg_bssid,
+						     NL80211_KEYTYPE_PAIRWISE,
+						     -1, NULL, GFP_KERNEL);
+		}
+#endif
+		woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_UNI,
+				     strlen(CUS_EVT_MLME_MIC_ERR_UNI));
+		break;
+	case MLAN_EVENT_ID_FW_MIC_ERR_MUL:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext)) {
+#if WIRELESS_EXT >= 18
+			woal_send_mic_error_event(priv,
+						  MLAN_EVENT_ID_FW_MIC_ERR_MUL);
+#else
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_MLME_MIC_ERR_MUL);
+#endif
+		}
+#endif /* STA_WEXT */
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			cfg80211_michael_mic_failure(priv->netdev,
+						     priv->cfg_bssid,
+						     NL80211_KEYTYPE_GROUP, -1,
+						     NULL, GFP_KERNEL);
+		}
+#endif
+		woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_MUL,
+				     strlen(CUS_EVT_MLME_MIC_ERR_MUL));
+		break;
+	case MLAN_EVENT_ID_FW_BCN_RSSI_LOW:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_BEACON_RSSI_LOW);
+#endif
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+			cfg80211_cqm_rssi_notify(priv->netdev,
+						 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+						 *(t_s16 *)pmevent->event_buf,
+#endif
+						 GFP_KERNEL);
+			priv->last_event |= EVENT_BCN_RSSI_LOW;
+#endif
+			if (!hw_test && priv->roaming_enabled)
+				woal_config_bgscan_and_rssi(priv, MTRUE);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			woal_cfg80211_rssi_monitor_event(priv,
+							 *(t_s16 *)pmevent->
+							 event_buf);
+#endif
+		}
+#endif
+		woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_LOW,
+				     strlen(CUS_EVT_BEACON_RSSI_LOW));
+		break;
+	case MLAN_EVENT_ID_FW_BCN_RSSI_HIGH:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_BEACON_RSSI_HIGH);
+#endif
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			if (!priv->mrvl_rssi_low) {
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+				cfg80211_cqm_rssi_notify(priv->netdev,
+							 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+							 *(t_s16 *)pmevent->
+							 event_buf,
+#endif
+							 GFP_KERNEL);
+#endif
+				woal_set_rssi_threshold(priv,
+							MLAN_EVENT_ID_FW_BCN_RSSI_HIGH,
+							MOAL_NO_WAIT);
+			}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			woal_cfg80211_rssi_monitor_event(priv,
+							 *(t_s16 *)pmevent->
+							 event_buf);
+#endif
+		}
+#endif
+		woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_HIGH,
+				     strlen(CUS_EVT_BEACON_RSSI_HIGH));
+		break;
+	case MLAN_EVENT_ID_FW_BCN_SNR_LOW:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_BEACON_SNR_LOW);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_LOW,
+				     strlen(CUS_EVT_BEACON_SNR_LOW));
+		break;
+	case MLAN_EVENT_ID_FW_BCN_SNR_HIGH:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_BEACON_SNR_HIGH);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_HIGH,
+				     strlen(CUS_EVT_BEACON_SNR_HIGH));
+		break;
+	case MLAN_EVENT_ID_FW_MAX_FAIL:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_MAX_FAIL);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_MAX_FAIL,
+				     strlen(CUS_EVT_MAX_FAIL));
+		break;
+	case MLAN_EVENT_ID_FW_DATA_RSSI_LOW:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_LOW);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_LOW,
+				     strlen(CUS_EVT_DATA_RSSI_LOW));
+		break;
+	case MLAN_EVENT_ID_FW_DATA_SNR_LOW:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_LOW);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_DATA_SNR_LOW,
+				     strlen(CUS_EVT_DATA_SNR_LOW));
+		break;
+	case MLAN_EVENT_ID_FW_DATA_RSSI_HIGH:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_DATA_RSSI_HIGH);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_HIGH,
+				     strlen(CUS_EVT_DATA_RSSI_HIGH));
+		break;
+	case MLAN_EVENT_ID_FW_DATA_SNR_HIGH:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_HIGH);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_DATA_SNR_HIGH,
+				     strlen(CUS_EVT_DATA_SNR_HIGH));
+		break;
+	case MLAN_EVENT_ID_FW_LINK_QUALITY:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_LINK_QUALITY);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_LINK_QUALITY,
+				     strlen(CUS_EVT_LINK_QUALITY));
+		break;
+	case MLAN_EVENT_ID_FW_PORT_RELEASE:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_PORT_RELEASE);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_PORT_RELEASE,
+				     strlen(CUS_EVT_PORT_RELEASE));
+		break;
+	case MLAN_EVENT_ID_FW_PRE_BCN_LOST:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_PRE_BEACON_LOST);
+#endif
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			struct cfg80211_bss *bss = NULL;
+			bss = cfg80211_get_bss(priv->wdev->wiphy, NULL,
+					       priv->cfg_bssid, NULL, 0,
+					       WLAN_CAPABILITY_ESS,
+					       WLAN_CAPABILITY_ESS);
+			if (bss) {
+				cfg80211_unlink_bss(priv->wdev->wiphy, bss);
+				cfg80211_put_bss(priv->wdev->wiphy, bss);
+			}
+			if (!hw_test && priv->roaming_enabled)
+				woal_config_bgscan_and_rssi(priv, MFALSE);
+			else {
+				cfg80211_cqm_rssi_notify(priv->netdev,
+							 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+							 0,
+#endif
+							 GFP_KERNEL);
+			}
+			priv->last_event |= EVENT_PRE_BCN_LOST;
+		}
+#endif
+#endif
+		woal_broadcast_event(priv, CUS_EVT_PRE_BEACON_LOST,
+				     strlen(CUS_EVT_PRE_BEACON_LOST));
+		break;
+	case MLAN_EVENT_ID_FW_DEBUG_INFO:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, pmevent->event_buf);
+#endif
+		memmove((pmevent->event_buf + strlen(FW_DEBUG_INFO) + 1),
+			pmevent->event_buf, pmevent->event_len);
+		moal_memcpy_ext(priv->phandle, pmevent->event_buf,
+				(t_u8 *)FW_DEBUG_INFO, strlen(FW_DEBUG_INFO),
+				strlen(FW_DEBUG_INFO));
+		pmevent->event_buf[strlen(FW_DEBUG_INFO)] = 0;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len +
+				     strlen(FW_DEBUG_INFO) + 1);
+		break;
+	case MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   WMM_CONFIG_CHANGE_INDICATION);
+#endif
+		woal_broadcast_event(priv, WMM_CONFIG_CHANGE_INDICATION,
+				     strlen(WMM_CONFIG_CHANGE_INDICATION));
+		break;
+
+	case MLAN_EVENT_ID_DRV_REPORT_STRING:
+		PRINTM(MINFO, "Report string %s\n", pmevent->event_buf);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, pmevent->event_buf);
+#endif
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     strlen(pmevent->event_buf));
+		break;
+	case MLAN_EVENT_ID_FW_WEP_ICV_ERR:
+		DBG_HEXDUMP(MCMD_D, "WEP ICV error", pmevent->event_buf,
+			    pmevent->event_len);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv, CUS_EVT_WEP_ICV_ERR);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_WEP_ICV_ERR,
+				     strlen(CUS_EVT_WEP_ICV_ERR));
+		break;
+
+	case MLAN_EVENT_ID_DRV_DEFER_HANDLING:
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_EVENT_ID_DRV_FLUSH_RX_WORK:
+		if (moal_extflg_isset(priv->phandle, EXT_NAPI)) {
+			napi_synchronize(&priv->phandle->napi_rx);
+			break;
+		}
+		flush_workqueue(priv->phandle->rx_workqueue);
+		break;
+	case MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK:
+		flush_workqueue(priv->phandle->workqueue);
+		break;
+	case MLAN_EVENT_ID_DRV_DEFER_RX_WORK:
+		if (moal_extflg_isset(priv->phandle, EXT_NAPI)) {
+			napi_schedule(&priv->phandle->napi_rx);
+			break;
+		}
+		queue_work(priv->phandle->rx_workqueue,
+			   &priv->phandle->rx_work);
+		break;
+	case MLAN_EVENT_ID_DRV_DBG_DUMP:
+		priv->phandle->driver_status = MTRUE;
+		ref_handle = (moal_handle *)priv->phandle->pref_mac;
+		if (ref_handle)
+			ref_handle->driver_status = MTRUE;
+		if (drvdbg & MFW_D)
+			auto_fw_dump = MTRUE;
+
+		woal_moal_debug_info(priv, NULL, MFALSE);
+		if (!auto_fw_dump && !handle->fw_dump)
+			woal_process_hang(priv->phandle);
+		wifi_status = 2;
+		break;
+	case MLAN_EVENT_ID_DRV_WIFI_STATUS:
+		wifi_status = *(t_u16 *)(pmevent->event_buf + sizeof(t_u32));
+		break;
+	case MLAN_EVENT_ID_FW_BG_SCAN:
+		if (priv->media_connected == MTRUE)
+			priv->bg_scan_start = MFALSE;
+		priv->bg_scan_reported = MTRUE;
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext)) {
+			memset(&wrqu, 0, sizeof(union iwreq_data));
+			wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu,
+					    NULL);
+		}
+#endif
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			priv->last_event |= EVENT_BG_SCAN_REPORT;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			if (priv->sched_scanning &&
+			    !priv->phandle->cfg80211_suspend) {
+				mlan_scan_resp scan_resp;
+				if (MLAN_STATUS_SUCCESS ==
+				    woal_get_scan_table(priv, MOAL_NO_WAIT,
+							&scan_resp))
+					PRINTM(MIOCTL,
+					       "Triggered mlan get bgscan result\n");
+			}
+#endif
+			if (!hw_test && priv->roaming_enabled
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+			    && !priv->phandle->cfg80211_suspend
+#endif
+				) {
+				priv->roaming_required = MTRUE;
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+				__pm_wakeup_event(&priv->phandle->ws,
+						  ROAMING_WAKE_LOCK_TIMEOUT);
+#else
+				wake_lock_timeout(&priv->phandle->wake_lock,
+						  msecs_to_jiffies
+						  (ROAMING_WAKE_LOCK_TIMEOUT));
+#endif
+#endif
+				wake_up_interruptible(&priv->phandle->
+						      reassoc_thread.wait_q);
+			} else {
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+				if (priv->mrvl_rssi_low) {
+					cfg80211_cqm_rssi_notify(priv->netdev,
+								 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+								 0,
+#endif
+								 GFP_KERNEL);
+				}
+#endif
+			}
+		}
+#endif
+		break;
+	case MLAN_EVENT_ID_FW_BG_SCAN_STOPPED:
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			if (priv->sched_scanning)
+				woal_bgscan_stop_event(priv);
+		}
+#endif
+#endif
+		break;
+	case MLAN_EVENT_ID_DRV_BGSCAN_RESULT:
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			if (priv->sched_scanning &&
+			    !priv->phandle->cfg80211_suspend) {
+				woal_inform_bss_from_scan_result(priv, NULL,
+								 MOAL_NO_WAIT);
+				PRINTM(MMSG,
+				       "wlan: Report sched_scan result\n");
+				woal_report_sched_scan_result(priv);
+				priv->last_event = 0;
+				PRINTM(MEVENT,
+				       "Reporting Sched_Scan results\n");
+			}
+		}
+#endif
+#endif
+		break;
+#endif /* STA_SUPPORT */
+
+	case MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY:
+		radar_detected = pmevent->event_buf[0];
+
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		if (!IS_STA_OR_UAP_CFG80211(cfg80211_wext))
+			break;
+
+		if (priv->phandle->is_cac_timer_set) {
+			PRINTM(MEVENT, "%s radar found when CAC \n",
+			       radar_detected ? "" : "No");
+			moal_stop_timer(priv->phandle,
+					&priv->phandle->cac_timer);
+			priv->phandle->is_cac_timer_set = MFALSE;
+			if (radar_detected) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+				cfg80211_cac_event(priv->netdev,
+						   &priv->phandle->dfs_channel,
+						   NL80211_RADAR_CAC_ABORTED,
+						   GFP_KERNEL);
+#else
+				cfg80211_cac_event(priv->netdev,
+						   NL80211_RADAR_CAC_ABORTED,
+						   GFP_KERNEL);
+#endif
+				cfg80211_radar_event(priv->wdev->wiphy,
+						     &priv->phandle->
+						     dfs_channel, GFP_KERNEL);
+			} else {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+				cfg80211_cac_event(priv->netdev,
+						   &priv->phandle->dfs_channel,
+						   NL80211_RADAR_CAC_FINISHED,
+						   GFP_KERNEL);
+#else
+				cfg80211_cac_event(priv->netdev,
+						   NL80211_RADAR_CAC_FINISHED,
+						   GFP_KERNEL);
+#endif
+			}
+			memset(&priv->phandle->dfs_channel, 0,
+			       sizeof(struct cfg80211_chan_def));
+			priv->phandle->cac_bss_index = 0xff;
+		}
+#endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
+#endif /* UAP_CFG80211 */
+		break;
+	case MLAN_EVENT_ID_FW_RADAR_DETECTED:
+
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		if (!IS_STA_OR_UAP_CFG80211(cfg80211_wext))
+			break;
+		if (priv->phandle->is_cac_timer_set) {
+			if (priv->bss_index == priv->phandle->cac_bss_index) {
+				PRINTM(MEVENT, "radar detected during CAC \n");
+				woal_cancel_timer(&priv->phandle->cac_timer);
+				priv->phandle->is_cac_timer_set = MFALSE;
+				/* downstream: cancel the unfinished CAC in
+				 * Firmware*/
+				woal_11h_cancel_chan_report_ioctl(priv,
+								  MOAL_NO_WAIT);
+				/* upstream: inform cfg80211 */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+				cfg80211_cac_event(priv->netdev,
+						   &priv->phandle->dfs_channel,
+						   NL80211_RADAR_CAC_ABORTED,
+						   GFP_KERNEL);
+#else
+				cfg80211_cac_event(priv->netdev,
+						   NL80211_RADAR_CAC_ABORTED,
+						   GFP_KERNEL);
+#endif
+				cfg80211_radar_event(priv->wdev->wiphy,
+						     &priv->phandle->
+						     dfs_channel, GFP_KERNEL);
+
+				memset(&priv->phandle->dfs_channel, 0,
+				       sizeof(priv->phandle->dfs_channel));
+				priv->phandle->cac_bss_index = 0xff;
+			} else {
+				PRINTM(MERROR,
+				       " Radar event for incorrect inferface \n");
+			}
+		} else {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+				woal_cfg80211_dfs_vendor_event(priv,
+							       event_dfs_radar_detected,
+							       &priv->chan);
+			else {
+#endif
+				if (priv->uap_host_based && priv->bss_started)
+					cfg80211_radar_event(priv->wdev->wiphy,
+							     &priv->chan,
+							     GFP_KERNEL);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			}
+#endif
+		}
+#endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0 */
+#endif /* UAP_CFG80211 */
+		break;
+	case MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN:
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext))
+			woal_send_iwevcustom_event(priv,
+						   CUS_EVT_CHANNEL_SWITCH_ANN);
+#endif
+		woal_broadcast_event(priv, CUS_EVT_CHANNEL_SWITCH_ANN,
+				     strlen(CUS_EVT_CHANNEL_SWITCH_ANN));
+		break;
+
+	case MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE:
+#if defined(UAP_CFG80211) || defined(STA_CFG80211)
+		pchan_info = (chan_band_info *) pmevent->event_buf;
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
+			PRINTM(MMSG,
+			       "CSA/ECSA: Switch to new channel %d complete!\n",
+			       pchan_info->channel);
+			priv->channel = pchan_info->channel;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+			if (priv->csa_chan.chan &&
+			    (pchan_info->channel ==
+			     priv->csa_chan.chan->hw_value)) {
+				moal_memcpy_ext(priv->phandle, &priv->chan,
+						&priv->csa_chan,
+						sizeof(struct
+						       cfg80211_chan_def),
+						sizeof(struct
+						       cfg80211_chan_def));
+			}
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (MFALSE
+#ifdef UAP_CFG80211
+			    || priv->uap_host_based
+#endif
+#ifdef STA_CFG80211
+			    || priv->sme_current.ssid_len
+#endif
+				) {
+				PRINTM(MEVENT,
+				       "CHAN_SWITCH: 11n=%d, chan=%d, center_chan=%d, band=%d, width=%d, 2Offset=%d\n",
+				       pchan_info->is_11n_enabled,
+				       pchan_info->channel,
+				       pchan_info->center_chan,
+				       pchan_info->bandcfg.chanBand,
+				       pchan_info->bandcfg.chanWidth,
+				       pchan_info->bandcfg.chan2Offset);
+				woal_cfg80211_notify_channel(priv, pchan_info);
+			}
+#endif
+		}
+#endif
+#ifdef UAP_SUPPORT
+		if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
+			if (priv->uap_tx_blocked) {
+				if (!netif_carrier_ok(priv->netdev))
+					netif_carrier_on(priv->netdev);
+				woal_start_queue(priv->netdev);
+				priv->uap_tx_blocked = MFALSE;
+			}
+			priv->phandle->chsw_wait_q_woken = MTRUE;
+			wake_up_interruptible(&priv->phandle->chsw_wait_q);
+		}
+#endif
+		break;
+	case MLAN_EVENT_ID_FW_STOP_TX:
+		woal_stop_queue(priv->netdev);
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		break;
+	case MLAN_EVENT_ID_FW_START_TX:
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_wake_queue(priv->netdev);
+		break;
+	case MLAN_EVENT_ID_FW_HS_WAKEUP:
+		/* simulate HSCFG_CANCEL command */
+		woal_cancel_hs(priv, MOAL_NO_WAIT);
+#ifdef STA_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
+			woal_send_iwevcustom_event(pmpriv, CUS_EVT_HS_WAKEUP);
+#endif /* STA_WEXT */
+		if (pmpriv)
+			woal_broadcast_event(pmpriv, CUS_EVT_HS_WAKEUP,
+					     strlen(CUS_EVT_HS_WAKEUP));
+#endif /*STA_SUPPORT */
+#ifdef UAP_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_UAP);
+		if (pmpriv) {
+			pmevent->event_id = UAP_EVENT_ID_HS_WAKEUP;
+			woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
+					     sizeof(t_u32));
+		}
+#endif /* UAP_SUPPORT */
+		break;
+	case MLAN_EVENT_ID_DRV_HS_ACTIVATED:
+#ifdef STA_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
+			woal_send_iwevcustom_event(pmpriv,
+						   CUS_EVT_HS_ACTIVATED);
+#endif /* STA_WEXT */
+		if (pmpriv)
+			woal_broadcast_event(pmpriv, CUS_EVT_HS_ACTIVATED,
+					     strlen(CUS_EVT_HS_ACTIVATED));
+#endif /* STA_SUPPORT */
+#if defined(UAP_SUPPORT)
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_UAP);
+		if (pmpriv) {
+			pmevent->event_id = UAP_EVENT_ID_DRV_HS_ACTIVATED;
+			woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
+					     sizeof(t_u32));
+		}
+#endif
+		memset(&pm_info, 0, sizeof(mlan_ds_ps_info));
+		if (priv->phandle->suspend_fail == MFALSE) {
+			woal_get_pm_info(priv, &pm_info);
+			if (pm_info.is_suspend_allowed == MTRUE) {
+				priv->phandle->hs_activated = MTRUE;
+#ifdef MMC_PM_FUNC_SUSPENDED
+				woal_wlan_is_suspended(priv->phandle);
+#endif
+			}
+			priv->phandle->hs_activate_wait_q_woken = MTRUE;
+			wake_up(&priv->phandle->hs_activate_wait_q);
+		}
+		break;
+	case MLAN_EVENT_ID_DRV_HS_DEACTIVATED:
+#ifdef STA_SUPPORT
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
+			woal_send_iwevcustom_event(pmpriv,
+						   CUS_EVT_HS_DEACTIVATED);
+#endif /* STA_WEXT */
+		if (pmpriv)
+			woal_broadcast_event(pmpriv, CUS_EVT_HS_DEACTIVATED,
+					     strlen(CUS_EVT_HS_DEACTIVATED));
+#endif /* STA_SUPPORT */
+#if defined(UAP_SUPPORT)
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_UAP);
+		if (pmpriv) {
+			pmevent->event_id = UAP_EVENT_ID_DRV_HS_DEACTIVATED;
+			woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
+					     sizeof(t_u32));
+		}
+#endif
+		priv->phandle->hs_activated = MFALSE;
+		break;
+#ifdef UAP_SUPPORT
+	case MLAN_EVENT_ID_UAP_FW_BSS_START:
+		woal_hist_data_reset(priv);
+		priv->bss_started = MTRUE;
+		priv->skip_cac = MFALSE;
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_start_queue(priv->netdev);
+		moal_memcpy_ext(priv->phandle, priv->current_addr,
+				pmevent->event_buf + 6, ETH_ALEN, ETH_ALEN);
+		moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
+				priv->current_addr, ETH_ALEN, ETH_ALEN);
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+#ifdef STA_SUPPORT
+#ifdef STA_CFG80211
+		pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
+		if (IS_STA_CFG80211(cfg80211_wext) && pmpriv)
+			woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
+					   PASSIVE_SCAN_CHAN_TIME,
+					   MIN_SPECIFIC_SCAN_CHAN_TIME);
+#endif
+#endif
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		if (priv->chan_under_nop) {
+			PRINTM(MMSG,
+			       "Channel Under Nop: notify cfg80211 new channel=%d\n",
+			       priv->channel);
+			cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
+			priv->chan_under_nop = MFALSE;
+		}
+#endif
+#endif
+		break;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	case MLAN_EVENT_ID_DRV_UAP_CHAN_INFO:
+#ifdef UAP_CFG80211
+		if (IS_UAP_CFG80211(cfg80211_wext)) {
+			pchan_info = (chan_band_info *) pmevent->event_buf;
+			PRINTM(MEVENT,
+			       "UAP: 11n=%d, chan=%d, center_chan=%d, band=%d, width=%d, 2Offset=%d\n",
+			       pchan_info->is_11n_enabled, pchan_info->channel,
+			       pchan_info->center_chan,
+			       pchan_info->bandcfg.chanBand,
+			       pchan_info->bandcfg.chanWidth,
+			       pchan_info->bandcfg.chan2Offset);
+			if (priv->uap_host_based &&
+			    (priv->channel != pchan_info->channel))
+				woal_channel_switch_event(priv, pchan_info);
+		}
+#endif
+		break;
+#endif
+	case MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE:
+		priv->media_connected = MTRUE;
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_wake_queue(priv->netdev);
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		moal_connection_status_check_pmqos(pmoal);
+		break;
+	case MLAN_EVENT_ID_UAP_FW_BSS_IDLE:
+		priv->media_connected = MFALSE;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		moal_connection_status_check_pmqos(pmoal);
+		break;
+	case MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES:{
+			t_u16 status = 0;
+			status = *(t_u16 *)(pmevent->event_buf + 4);
+			if (status) {
+				priv->media_connected = MFALSE;
+				woal_stop_queue(priv->netdev);
+				if (netif_carrier_ok(priv->netdev))
+					netif_carrier_off(priv->netdev);
+			} else {
+				priv->media_connected = MTRUE;
+				if (!netif_carrier_ok(priv->netdev))
+					netif_carrier_on(priv->netdev);
+				woal_wake_queue(priv->netdev);
+			}
+			woal_broadcast_event(priv, pmevent->event_buf,
+					     pmevent->event_len);
+		}
+		break;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	case MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED:
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
+			PRINTM(MEVENT,
+			       "FW_REMAIN_ON_CHANNEL_EXPIRED cookie = %#llx\n",
+			       priv->phandle->cookie);
+			if (priv->host_mlme &&
+			    (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {
+				priv->auth_flag = 0;
+				priv->host_mlme = MFALSE;
+				priv->auth_alg = 0xFFFF;
+			}
+			priv->phandle->remain_on_channel = MFALSE;
+			if (priv->phandle->cookie &&
+			    !priv->phandle->is_remain_timer_set) {
+				cfg80211_remain_on_channel_expired(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+									  priv->
+									  netdev,
+#else
+									  priv->
+									  wdev,
+#endif
+									  priv->
+									  phandle->
+									  cookie,
+									  &priv->
+									  phandle->
+									  chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+									  priv->
+									  phandle->
+									  channel_type,
+#endif
+									  GFP_ATOMIC);
+				priv->phandle->cookie = 0;
+			}
+		}
+		break;
+#endif
+#endif
+	case MLAN_EVENT_ID_UAP_FW_STA_CONNECT:
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
+			struct station_info *sinfo = NULL;
+			t_u8 addr[ETH_ALEN];
+			sinfo = kzalloc(sizeof(struct station_info),
+					GFP_ATOMIC);
+			if (sinfo) {
+				sinfo->filled = 0;
+				sinfo->generation = 0;
+				/* copy the station mac address */
+				memset(addr, 0xFF, ETH_ALEN);
+				moal_memcpy_ext(priv->phandle, addr,
+						pmevent->event_buf, ETH_ALEN,
+						ETH_ALEN);
+			    /** these field add in kernel 3.2, but some
+			    * kernel do have the pacth to support it,
+			    * like T3T and pxa978T 3.0.31 JB, these
+			    * patch are needed to support
+			    * wpa_supplicant 2.x */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 31)
+				if (pmevent->event_len > ETH_ALEN) {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+					/* set station info filled flag */
+					sinfo->filled |=
+						STATION_INFO_ASSOC_REQ_IES;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
+					sinfo->pertid = NULL;
+#endif
+					/* get the assoc request ies and length */
+					sinfo->assoc_req_ies =
+						(const t_u8 *)(pmevent->
+							       event_buf +
+							       ETH_ALEN);
+					sinfo->assoc_req_ies_len =
+						pmevent->event_len - ETH_ALEN;
+				}
+#endif /* KERNEL_VERSION */
+				if (priv->netdev && priv->wdev)
+					cfg80211_new_sta(priv->netdev,
+							 (t_u8 *)addr, sinfo,
+							 GFP_KERNEL);
+				kfree(sinfo);
+			}
+		}
+#endif /* UAP_CFG80211 */
+		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) +
+			 1), pmevent->event_buf, pmevent->event_len);
+		moal_memcpy_ext(priv->phandle, pmevent->event_buf,
+				(t_u8 *)CUS_EVT_STA_CONNECTED,
+				strlen(CUS_EVT_STA_CONNECTED),
+				strlen(CUS_EVT_STA_CONNECTED));
+		pmevent->event_buf[strlen(CUS_EVT_STA_CONNECTED)] = 0;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len +
+				     strlen(CUS_EVT_STA_CONNECTED));
+#ifdef UAP_WEXT
+		if (IS_UAP_WEXT(cfg80211_wext)) {
+			memset(&wrqu, 0, sizeof(union iwreq_data));
+			wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
+			if ((pmevent->event_len +
+			     strlen(CUS_EVT_STA_CONNECTED) + 1) > IW_CUSTOM_MAX)
+				wrqu.data.length =
+					ETH_ALEN +
+					strlen(CUS_EVT_STA_CONNECTED) + 1;
+			else
+				wrqu.data.length =
+					pmevent->event_len +
+					strlen(CUS_EVT_STA_CONNECTED) + 1;
+			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
+					    pmevent->event_buf);
+		}
+#endif /* UAP_WEXT */
+		break;
+	case MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT:
+#ifdef UAP_CFG80211
+		if (IS_UAP_CFG80211(cfg80211_wext)) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			/**Forward Deauth, Auth and disassoc frame to Host*/
+			if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) {
+				t_u16 reason_code =
+					woal_le16_to_cpu(*(t_u16 *)pmevent->
+							 event_buf);
+				PRINTM(MCMND, "deauth reason code =0x%x\n",
+				       reason_code);
+				/** BIT 14 indicate deauth is initiated by FW */
+				if (reason_code & MBIT(14))
+					woal_host_mlme_disconnect(priv, 0,
+								  pmevent->
+								  event_buf +
+								  2);
+			} else
+#endif
+			if (priv->netdev && priv->wdev)
+				cfg80211_del_sta(priv->netdev,
+						 pmevent->event_buf + 2,
+						 GFP_KERNEL);
+
+#endif /* KERNEL_VERSION */
+		}
+#endif /* UAP_CFG80211 */
+		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_DISCONNECTED) +
+			 1), pmevent->event_buf, pmevent->event_len);
+		moal_memcpy_ext(priv->phandle, pmevent->event_buf,
+				(t_u8 *)CUS_EVT_STA_DISCONNECTED,
+				strlen(CUS_EVT_STA_DISCONNECTED),
+				strlen(CUS_EVT_STA_DISCONNECTED));
+		pmevent->event_buf[strlen(CUS_EVT_STA_DISCONNECTED)] = 0;
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len +
+				     strlen(CUS_EVT_STA_DISCONNECTED));
+
+#ifdef UAP_WEXT
+		if (IS_UAP_WEXT(cfg80211_wext)) {
+			memset(&wrqu, 0, sizeof(union iwreq_data));
+			wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
+			wrqu.data.length = pmevent->event_len +
+				strlen(CUS_EVT_STA_DISCONNECTED) + 1;
+			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
+					    pmevent->event_buf);
+		}
+#endif /* UAP_WEXT */
+		break;
+	case MLAN_EVENT_ID_DRV_MGMT_FRAME:
+#ifdef UAP_WEXT
+		if (IS_UAP_WEXT(cfg80211_wext)) {
+			woal_broadcast_event(priv, pmevent->event_buf,
+					     pmevent->event_len);
+		}
+#endif /* UAP_WEXT */
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+			if (priv->netdev &&
+			    priv->netdev->ieee80211_ptr->wiphy->mgmt_stypes &&
+			    priv->mgmt_subtype_mask) {
+				/* frmctl + durationid + addr1 + addr2 + addr3 +
+				 * seqctl */
+#define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2)
+				t_u8 *pkt;
+				int freq =
+					priv->phandle->remain_on_channel ?
+					priv->phandle->chan.center_freq :
+					woal_get_active_intf_freq(priv);
+				if (!freq) {
+					if (!priv->phandle->chan.center_freq) {
+						PRINTM(MINFO,
+						       "Skip to report mgmt packet to cfg80211\n");
+						break;
+					}
+					freq = priv->phandle->chan.center_freq;
+				}
+
+				pkt = ((t_u8 *)pmevent->event_buf +
+				       sizeof(pmevent->event_id));
+
+				/* move addr4 */
+				memmove(pkt + PACKET_ADDR4_POS,
+					pkt + PACKET_ADDR4_POS + ETH_ALEN,
+					pmevent->event_len -
+					sizeof(pmevent->event_id) -
+					PACKET_ADDR4_POS - ETH_ALEN);
+#ifdef WIFI_DIRECT_SUPPORT
+				if (ieee80211_is_action(((struct ieee80211_mgmt
+							  *)pkt)
+							->frame_control))
+					woal_cfg80211_display_p2p_actframe(pkt,
+									   pmevent->
+									   event_len
+									   -
+									   sizeof
+									   (pmevent->
+									    event_id)
+									   -
+									   MLAN_MAC_ADDR_LENGTH,
+									   ieee80211_get_channel
+									   (priv->
+									    wdev->
+									    wiphy,
+									    freq),
+									   MFALSE);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+				/**Forward Deauth, Auth and disassoc frame to
+				 * Host*/
+				if (priv->host_mlme &&
+				    (GET_BSS_ROLE(priv) != MLAN_BSS_ROLE_UAP) &&
+				    (ieee80211_is_deauth(((struct ieee80211_mgmt
+							   *)pkt)
+							 ->frame_control) ||
+				     ieee80211_is_auth(((struct ieee80211_mgmt
+							 *)pkt)
+						       ->frame_control) ||
+				     ieee80211_is_disassoc(((struct
+							     ieee80211_mgmt *)
+							    pkt)
+							   ->frame_control))) {
+					if (ieee80211_is_auth(((struct
+								ieee80211_mgmt
+								*)
+							       pkt)
+							      ->frame_control)) {
+						PRINTM(MEVENT,
+						       "HostMlme %s: Received auth frame type = 0x%x\n",
+						       priv->netdev->name,
+						       priv->auth_alg);
+
+						if (priv->
+						    auth_flag &
+						    HOST_MLME_AUTH_PENDING) {
+							if (priv->auth_alg !=
+							    WLAN_AUTH_SAE) {
+								priv->auth_flag
+									&=
+									~HOST_MLME_AUTH_PENDING;
+								priv->auth_flag
+									|=
+									HOST_MLME_AUTH_DONE;
+								priv->phandle->
+									host_mlme_priv
+									= priv;
+								queue_work
+									(priv->
+									 phandle->
+									 evt_workqueue,
+									 &priv->
+									 phandle->
+									 host_mlme_work);
+							}
+						} else {
+							PRINTM(MERROR,
+							       "HostMlme %s: Drop auth frame, auth_flag=0x%x auth_alg=0x%x\n",
+							       priv->netdev->
+							       name,
+							       priv->auth_flag,
+							       priv->auth_alg);
+							break;
+						}
+					} else {
+						PRINTM(MEVENT,
+						       "HostMlme %s: Receive deauth/disassociate\n",
+						       priv->netdev->name);
+						if (!priv->wdev->current_bss) {
+							PRINTM(MEVENT,
+							       "HostMlme: Drop deauth/disassociate, current_bss = null\n");
+							break;
+						}
+						priv->cfg_disconnect = MTRUE;
+						woal_mgmt_frame_register(priv,
+									 IEEE80211_STYPE_DEAUTH,
+									 MFALSE);
+						woal_mgmt_frame_register(priv,
+									 IEEE80211_STYPE_DISASSOC,
+									 MFALSE);
+						woal_send_disconnect_to_system
+							(priv,
+							 DEF_DEAUTH_REASON_CODE);
+						priv->host_mlme = MFALSE;
+						priv->auth_flag = 0;
+						priv->auth_alg = 0xFFFF;
+					}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+					woal_rx_mgmt_pkt_event(priv, pkt,
+							       pmevent->
+							       event_len -
+							       sizeof(pmevent->
+								      event_id)
+							       -
+							       MLAN_MAC_ADDR_LENGTH);
+#else
+					if (ieee80211_is_deauth(((struct
+								  ieee80211_mgmt
+								  *)
+								 pkt)
+								->
+								frame_control))
+						cfg80211_send_deauth(priv->
+								     netdev,
+								     pkt,
+								     pmevent->
+								     event_len -
+								     sizeof
+								     (pmevent->
+								      event_id)
+								     -
+								     MLAN_MAC_ADDR_LENGTH);
+					else if (ieee80211_is_auth
+						 (((struct ieee80211_mgmt *)pkt)
+						  ->frame_control))
+						cfg80211_send_rx_auth(priv->
+								      netdev,
+								      pkt,
+								      pmevent->
+								      event_len
+								      -
+								      sizeof
+								      (pmevent->
+								       event_id)
+								      -
+								      MLAN_MAC_ADDR_LENGTH);
+					else if (ieee80211_is_disassoc
+						 (((struct ieee80211_mgmt *)pkt)
+						  ->frame_control))
+						cfg80211_send_disassoc(priv->
+								       netdev,
+								       pkt,
+								       pmevent->
+								       event_len
+								       -
+								       sizeof
+								       (pmevent->
+									event_id)
+								       -
+								       MLAN_MAC_ADDR_LENGTH);
+
+#endif
+				} else
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+					cfg80211_rx_mgmt(
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+								priv->wdev,
+#else
+								priv->netdev,
+#endif
+								freq, 0,
+								((const t_u8 *)
+								 pmevent->
+								 event_buf) +
+								sizeof(pmevent->
+								       event_id),
+								pmevent->
+								event_len -
+								sizeof(pmevent->
+								       event_id)
+								-
+								MLAN_MAC_ADDR_LENGTH
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+								, 0
+#endif
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
+								, GFP_ATOMIC
+#endif
+						);
+#else
+					cfg80211_rx_mgmt(priv->netdev, freq,
+							 ((const t_u8 *)
+							  pmevent->event_buf) +
+							 sizeof(pmevent->
+								event_id),
+							 pmevent->event_len -
+							 sizeof(pmevent->
+								event_id) -
+							 MLAN_MAC_ADDR_LENGTH,
+							 GFP_ATOMIC);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+				woal_packet_fate_monitor(priv, PACKET_TYPE_RX,
+							 RX_PKT_FATE_SUCCESS,
+							 FRAME_TYPE_80211_MGMT,
+							 0, 0,
+							 ((t_u8 *)pmevent->
+							  event_buf) +
+							 sizeof(pmevent->
+								event_id),
+							 pmevent->event_len -
+							 sizeof(pmevent->
+								event_id) -
+							 MLAN_MAC_ADDR_LENGTH);
+#endif
+			}
+#endif /* KERNEL_VERSION */
+		}
+#endif /* STA_CFG80211 || UAP_CFG80211 */
+		break;
+#endif /* UAP_SUPPORT */
+	case MLAN_EVENT_ID_DRV_PASSTHRU:
+		woal_broadcast_event(priv, pmevent->event_buf,
+				     pmevent->event_len);
+		break;
+	case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT:
+		PRINTM(MINFO, "Assoc result\n");
+
+		if (priv->media_connected) {
+			PRINTM(MINFO, "Assoc_Rpt: Media Connected\n");
+			if (!netif_carrier_ok(priv->netdev)) {
+				PRINTM(MINFO, "Assoc_Rpt: Carrier On\n");
+				netif_carrier_on(priv->netdev);
+			}
+			PRINTM(MINFO, "Assoc_Rpt: Queue Start\n");
+			woal_wake_queue(priv->netdev);
+		}
+		break;
+	case MLAN_EVENT_ID_DRV_MEAS_REPORT:
+		/* We have received measurement report, wakeup measurement wait
+		 * queue */
+		PRINTM(MINFO, "Measurement Report\n");
+		/* Going out of CAC checking period */
+		if (priv->phandle->cac_period == MTRUE) {
+			priv->phandle->cac_period = MFALSE;
+			if (priv->phandle->meas_wait_q_woken == MFALSE) {
+				priv->phandle->meas_wait_q_woken = MTRUE;
+				wake_up_interruptible(&priv->phandle->
+						      meas_wait_q);
+			}
+
+			/* Execute delayed BSS START command */
+			if (priv->phandle->delay_bss_start == MTRUE) {
+				mlan_ioctl_req *req = NULL;
+				mlan_ds_bss *bss = NULL;
+
+				/* Clear flag */
+				priv->phandle->delay_bss_start = MFALSE;
+
+				PRINTM(MMSG,
+				       "Now CAC measure period end. Execute delayed BSS Start command.\n");
+
+				req = woal_alloc_mlan_ioctl_req(sizeof
+								(mlan_ds_bss));
+				if (!req) {
+					PRINTM(MERROR,
+					       "Failed to allocate ioctl request buffer\n");
+					goto done;
+				}
+				bss = (mlan_ds_bss *)req->pbuf;
+				req->req_id = MLAN_IOCTL_BSS;
+				req->action = MLAN_ACT_SET;
+				bss->sub_command = MLAN_OID_BSS_START;
+				moal_memcpy_ext(priv->phandle,
+						&bss->param.ssid_bssid,
+						&priv->phandle->
+						delay_ssid_bssid,
+						sizeof(mlan_ssid_bssid),
+						sizeof(mlan_ssid_bssid));
+
+				if (woal_request_ioctl(priv, req,
+						       MOAL_NO_WAIT) !=
+				    MLAN_STATUS_PENDING) {
+					PRINTM(MERROR,
+					       "Delayed BSS Start operation failed!\n");
+					kfree(req);
+				}
+
+				PRINTM(MMSG, "BSS START Complete!\n");
+			}
+#ifdef UAP_SUPPORT
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			if (priv->uap_host_based &&
+			    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+				woal_cfg80211_dfs_vendor_event(priv,
+							       event_dfs_cac_finished,
+							       &priv->chan);
+#endif
+#endif
+#endif
+		}
+		break;
+	case MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ:
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			tdls_tear_down_event *tdls_event =
+				(tdls_tear_down_event *)pmevent->event_buf;
+			cfg80211_tdls_oper_request(priv->netdev,
+						   tdls_event->peer_mac_addr,
+						   NL80211_TDLS_TEARDOWN,
+						   tdls_event->reason_code,
+						   GFP_KERNEL);
+		}
+#endif
+#endif
+		break;
+	case MLAN_EVENT_ID_FW_TX_STATUS:{
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+			unsigned long flag;
+			tx_status_event *tx_status =
+				(tx_status_event *)(pmevent->event_buf + 4);
+			struct tx_status_info *tx_info = NULL;
+			PRINTM(MINFO,
+			       "Receive Tx status: tx_token=%d, pkt_type=0x%x, status=%d tx_seq_num=%d\n",
+			       tx_status->tx_token_id, tx_status->packet_type,
+			       tx_status->status, priv->tx_seq_num);
+			spin_lock_irqsave(&priv->tx_stat_lock, flag);
+			tx_info =
+				woal_get_tx_info(priv, tx_status->tx_token_id);
+			if (tx_info) {
+				bool ack;
+				struct sk_buff *skb =
+					(struct sk_buff *)tx_info->tx_skb;
+				list_del(&tx_info->link);
+				spin_unlock_irqrestore(&priv->tx_stat_lock,
+						       flag);
+				if (!tx_status->status)
+					ack = true;
+				else
+					ack = false;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+				if (priv->phandle->remain_on_channel &&
+				    tx_info->cancel_remain_on_channel) {
+					remain_priv =
+						priv->phandle->priv
+						[priv->phandle->
+						 remain_bss_index];
+					if (remain_priv) {
+						woal_cfg80211_remain_on_channel_cfg
+							(remain_priv,
+							 MOAL_NO_WAIT, MTRUE,
+							 &channel_status, NULL,
+							 0, 0);
+						priv->phandle->
+							remain_on_channel =
+							MFALSE;
+					}
+				}
+#endif
+				PRINTM(MEVENT, "Wlan: Tx status=%d\n", ack);
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+				if (tx_info->tx_cookie) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+					cfg80211_mgmt_tx_status(priv->netdev,
+								tx_info->
+								tx_cookie,
+								skb->data,
+								skb->len, ack,
+								GFP_ATOMIC);
+#else
+					cfg80211_mgmt_tx_status(priv->wdev,
+								tx_info->
+								tx_cookie,
+								skb->data,
+								skb->len, ack,
+								GFP_ATOMIC);
+#endif
+#endif
+				}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+				woal_packet_fate_monitor(priv, PACKET_TYPE_TX,
+							 ack ? TX_PKT_FATE_ACKED
+							 : TX_PKT_FATE_SENT,
+							 FRAME_TYPE_80211_MGMT,
+							 0, 0, skb->data,
+							 skb->len);
+#endif
+#endif
+				dev_kfree_skb_any(skb);
+				kfree(tx_info);
+			} else {
+
+				spin_unlock_irqrestore(&priv->tx_stat_lock,
+						       flag);
+			}
+#endif
+		}
+		break;
+	case MLAN_EVENT_ID_DRV_FT_RESPONSE:
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(cfg80211_wext)) {
+			struct cfg80211_ft_event_params ft_event;
+			if (priv->ft_pre_connect)
+				break;
+			memset(&ft_event, 0,
+			       sizeof(struct cfg80211_ft_event_params));
+			PRINTM(MMSG,
+			       "wlan : FT response  target AP " MACSTR "\n",
+			       MAC2STR((t_u8 *)pmevent->event_buf));
+			DBG_HEXDUMP(MDAT_D, "FT-event ", pmevent->event_buf,
+				    pmevent->event_len);
+			moal_memcpy_ext(priv->phandle, priv->target_ap_bssid,
+					pmevent->event_buf, ETH_ALEN, ETH_ALEN);
+			ft_event.target_ap = priv->target_ap_bssid;
+			ft_event.ies = pmevent->event_buf + ETH_ALEN;
+			ft_event.ies_len = pmevent->event_len - ETH_ALEN;
+			/*TSPEC info is needed by RIC, However the TS operation
+			 * is configured by mlanutl*/
+			/*So do not add RIC temporally */
+			/*when add RIC, 1. query TS status, 2. copy tspec from
+			 * addts command*/
+			ft_event.ric_ies = NULL;
+			ft_event.ric_ies_len = 0;
+
+			cfg80211_ft_event(priv->netdev, &ft_event);
+			priv->ft_pre_connect = MTRUE;
+
+			if (priv->ft_roaming_triggered_by_driver ||
+			    !(priv->ft_cap & MBIT(0))) {
+				priv->ft_wait_condition = MTRUE;
+				wake_up(&priv->ft_wait_q);
+			}
+		}
+#endif
+#endif
+		break;
+	default:
+		break;
+	}
+done:
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prints the debug message in mlan
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param level    debug level
+ *  @param pformat  point to string format buf
+ *
+ *  @return         N/A
+ */
+__attribute__ ((format(printf, 3, 4)))
+     t_void moal_print(t_void *pmoal, t_u32 level, char *pformat, IN ...)
+{
+#ifdef DEBUG_LEVEL1
+	va_list args;
+
+	if (level & MHEX_DUMP) {
+		t_u8 *buf = NULL;
+		int len = 0;
+
+		va_start(args, pformat);
+		buf = (t_u8 *)va_arg(args, t_u8 *);
+		len = (int)va_arg(args, int);
+		va_end(args);
+
+#ifdef DEBUG_LEVEL2
+		if (level & MINFO)
+			HEXDUMP((char *)pformat, buf, len);
+		else
+#endif /* DEBUG_LEVEL2 */
+		{
+			if (level & MERROR)
+				DBG_HEXDUMP(MERROR, (char *)pformat, buf, len);
+			if (level & MCMD_D)
+				DBG_HEXDUMP(MCMD_D, (char *)pformat, buf, len);
+			if (level & MDAT_D)
+				DBG_HEXDUMP(MDAT_D, (char *)pformat, buf, len);
+			if (level & MIF_D)
+				DBG_HEXDUMP(MIF_D, (char *)pformat, buf, len);
+			if (level & MFW_D)
+				DBG_HEXDUMP(MFW_D, (char *)pformat, buf, len);
+			if (level & MEVT_D)
+				DBG_HEXDUMP(MEVT_D, (char *)pformat, buf, len);
+		}
+	} else {
+		if (drvdbg & level) {
+			va_start(args, pformat);
+			vprintk(pformat, args);
+			va_end(args);
+		}
+	}
+#endif /* DEBUG_LEVEL1 */
+}
+
+/**
+ *  @brief This function prints the network interface name
+ *
+ *  @param pmoal Pointer to the MOAL context
+ *  @param bss_index    BSS index
+ *  @param level        debug level
+ *
+ *  @return            N/A
+ */
+t_void
+moal_print_netintf(t_void *pmoal, t_u32 bss_index, t_u32 level)
+{
+#ifdef DEBUG_LEVEL1
+	moal_handle *phandle = (moal_handle *)pmoal;
+
+	if (phandle) {
+		if ((bss_index < MLAN_MAX_BSS_NUM) &&
+		    phandle->priv[bss_index] &&
+		    phandle->priv[bss_index]->netdev) {
+			if (drvdbg & level)
+				printk("%s: ",
+				       phandle->priv[bss_index]->netdev->name);
+		}
+	}
+#endif /* DEBUG_LEVEL1 */
+}
+
+/**
+ *  @brief This function asserts the existence of the passed argument
+ *
+ *  @param pmoal     A pointer to moal_private structure
+ *  @param cond             Condition to check
+ *
+ *  @return                 N/A
+ */
+t_void
+moal_assert(t_void *pmoal, t_u32 cond)
+{
+	if (!cond) {
+		panic("Assert failed: Panic!");
+	}
+}
+
+/**
+ *  @brief This function save the histogram data
+ *
+ *  @param pmoal     A pointer to moal_private structure
+ *  @param bss_index        BSS index
+ *  @param rx_rate          rx rate index
+ *  @param snr              snr
+ *  @param nflr             noise floor
+ *  @param antenna          antenna
+ *
+ *  @return                 N/A
+ */
+t_void
+moal_hist_data_add(t_void *pmoal, t_u32 bss_index,
+		   t_u16 rx_rate, t_s8 snr, t_s8 nflr, t_u8 antenna)
+{
+	moal_private *priv = NULL;
+	priv = woal_bss_index_to_priv(pmoal, bss_index);
+	if (priv && antenna >= priv->phandle->card_info->histogram_table_num)
+		antenna = 0;
+	if (priv && priv->hist_data[antenna])
+		woal_hist_data_add(priv, rx_rate, snr, nflr, antenna);
+}
+
+/**
+ *  @brief This function update the peer signal
+ *
+ *  @param pmoal     A pointer to moal_private structure
+ *  @param bss_index        BSS index
+ *  @param peer_addr        peer address
+ *  @param snr              snr
+ *  @param nflr             noise floor
+ *
+ *  @return                 N/A
+ */
+t_void
+moal_updata_peer_signal(t_void *pmoal, t_u32 bss_index,
+			t_u8 *peer_addr, t_s8 snr, t_s8 nflr)
+{
+	moal_private *priv = NULL;
+	struct tdls_peer *peer = NULL;
+	unsigned long flags;
+	priv = woal_bss_index_to_priv(pmoal, bss_index);
+	if (priv && priv->enable_auto_tdls) {
+		spin_lock_irqsave(&priv->tdls_lock, flags);
+		list_for_each_entry(peer, &priv->tdls_list, link) {
+			if (!memcmp(peer->peer_addr, peer_addr, ETH_ALEN)) {
+				peer->rssi = nflr - snr;
+				peer->rssi_jiffies = jiffies;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&priv->tdls_lock, flags);
+	}
+}
+
+/**
+ *  @brief Performs division of 64-bit num with base
+ *  @brief do_div does two things
+ *  @brief 1. modifies the 64-bit num in place with
+ *  @brief the quotient, i.e., num becomes quotient
+ *  @brief 2. do_div() returns the 32-bit reminder
+ *
+ *  @param num   dividend
+ *  @param base  divisor
+ *  @return      returns 64-bit quotient
+ */
+t_u64
+moal_do_div(t_u64 num, t_u32 base)
+{
+	t_u64 val = num;
+	do_div(val, base);
+	return val;
+}
+
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+/**
+ *  @brief Performs wait event
+ *
+ *  @param pmoal   t_void
+ *  @param bss_index      index of priv
+ *  @return      MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_wait_hostcmd_complete(t_void *pmoal, t_u32 bss_index)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_private *priv = woal_bss_index_to_priv(handle, bss_index);
+	long time_left = 0;
+
+	ENTER();
+
+	if (!priv) {
+		PRINTM(MERROR, "moal_wait_event: priv is null!\n");
+		goto done;
+	}
+
+	priv->hostcmd_wait_condition = MFALSE;
+	time_left = wait_event_timeout(priv->hostcmd_wait_q,
+				       priv->hostcmd_wait_condition,
+				       MOAL_IOCTL_TIMEOUT);
+
+	if (!time_left) {
+		PRINTM(MERROR, "moal_wait_event: wait timeout ");
+		status = MLAN_STATUS_FAILURE;
+	}
+
+done:
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief wake up esa wait_q
+ *
+ *  @param pmoal   t_void
+ *  @param bss_index      index of priv
+ *  @return      MLAN_STATUS_SUCCESS
+ */
+mlan_status
+moal_notify_hostcmd_complete(t_void *pmoal, t_u32 bss_index)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = (moal_handle *)pmoal;
+	moal_private *priv = woal_bss_index_to_priv(handle, bss_index);
+
+	ENTER();
+
+	priv->hostcmd_wait_condition = MTRUE;
+	wake_up(&priv->hostcmd_wait_q);
+
+	LEAVE();
+	return status;
+}
+#endif
diff --git a/wlan_sd8987/mlinux/moal_shim.h b/wlan_sd8987/mlinux/moal_shim.h
new file mode 100755
index 0000000..9667cd0
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_shim.h
@@ -0,0 +1,133 @@
+/** @file moal_shim.h
+ *
+ * @brief This file contains declaration referring to
+ * functions defined in moal module
+ *
+ *
+ * Copyright 2008-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/*************************************************************
+ * Change Log:
+ *	10/21/2008: initial version
+ ************************************************************/
+
+#ifndef _MOAL_H
+#define _MOAL_H
+
+mlan_status moal_get_fw_data(t_void *pmoal, t_u32 offset,
+			     t_u32 len, t_u8 *pbuf);
+mlan_status moal_get_vdll_data(t_void *pmoal, t_u32 len, t_u8 *pbuf);
+mlan_status moal_get_hw_spec_complete(t_void *pmoal,
+				      mlan_status status,
+				      mlan_hw_info * phw, pmlan_bss_tbl ptbl);
+mlan_status moal_init_fw_complete(t_void *pmoal, mlan_status status);
+mlan_status moal_shutdown_fw_complete(t_void *pmoal, mlan_status status);
+mlan_status moal_ioctl_complete(t_void *pmoal,
+				pmlan_ioctl_req pioctl_req, mlan_status status);
+mlan_status moal_alloc_mlan_buffer(t_void *pmoal, t_u32 size,
+				   pmlan_buffer *pmbuf);
+mlan_status moal_free_mlan_buffer(t_void *pmoal, pmlan_buffer pmbuf);
+mlan_status moal_send_packet_complete(t_void *pmoal,
+				      pmlan_buffer pmbuf, mlan_status status);
+#ifdef USB
+mlan_status moal_recv_complete(t_void *pmoal, pmlan_buffer pmbuf,
+			       t_u32 port, mlan_status status);
+mlan_status moal_write_data_async(t_void *pmoal,
+				  pmlan_buffer pmbuf, t_u32 port);
+#endif
+
+#if defined(SDIO) || defined(PCIE)
+/** moal_write_reg */
+mlan_status moal_write_reg(t_void *pmoal, t_u32 reg, t_u32 data);
+/** moal_read_reg */
+mlan_status moal_read_reg(t_void *pmoal, t_u32 reg, t_u32 *data);
+#endif /* SDIO || PCIE */
+mlan_status moal_write_data_sync(t_void *pmoal,
+				 pmlan_buffer pmbuf, t_u32 port, t_u32 timeout);
+mlan_status moal_read_data_sync(t_void *pmoal,
+				pmlan_buffer pmbuf, t_u32 port, t_u32 timeout);
+mlan_status moal_recv_amsdu_packet(t_void *pmoal, pmlan_buffer pmbuf);
+mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf);
+mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent);
+mlan_status moal_malloc(t_void *pmoal, t_u32 size, t_u32 flag, t_u8 **ppbuf);
+mlan_status moal_mfree(t_void *pmoal, t_u8 *pbuf);
+mlan_status moal_vmalloc(t_void *pmoal, t_u32 size, t_u8 **ppbuf);
+mlan_status moal_vfree(t_void *pmoal, t_u8 *pbuf);
+#ifdef PCIE
+mlan_status moal_malloc_consistent(t_void *pmoal, t_u32 size,
+				   t_u8 **ppbuf, t_pu64 pbuf_pa);
+mlan_status moal_mfree_consistent(t_void *pmoal, t_u32 size,
+				  t_u8 *pbuf, t_u64 buf_pa);
+mlan_status moal_map_memory(t_void *pmoal, t_u8 *pbuf,
+			    t_u64 *pbuf_pa, t_u32 size, t_u32 flag);
+mlan_status moal_unmap_memory(t_void *pmoal, t_u8 *pbuf,
+			      t_u64 buf_pa, t_u32 size, t_u32 flag);
+#endif /* PCIE */
+t_void *moal_memset(t_void *pmoal, t_void *pmem, t_u8 byte, t_u32 num);
+t_void *moal_memcpy(t_void *pmoal, t_void *pdest,
+		    const t_void *psrc, t_u32 num);
+t_void *moal_memcpy_ext(t_void *pmoal, t_void *pdest,
+			const t_void *psrc, t_u32 num, t_u32 dest_size);
+
+t_void *moal_memmove(t_void *pmoal, t_void *pdest,
+		     const t_void *psrc, t_u32 num);
+t_s32 moal_memcmp(t_void *pmoal, const t_void *pmem1,
+		  const t_void *pmem2, t_u32 num);
+/** moal_udelay */
+t_void moal_udelay(t_void *pmoal, t_u32 udelay);
+t_void moal_usleep_range(t_void *pmoal, t_u32 min_delay, t_u32 max_delay);
+mlan_status moal_get_boot_ktime(t_void *pmoal, t_u64 *pnsec);
+mlan_status moal_get_system_time(t_void *pmoal, t_u32 *psec, t_u32 *pusec);
+mlan_status moal_init_lock(t_void *pmoal, t_void **pplock);
+mlan_status moal_free_lock(t_void *pmoal, t_void *plock);
+mlan_status moal_spin_lock(t_void *pmoal, t_void *plock);
+mlan_status moal_spin_unlock(t_void *pmoal, t_void *plock);
+#if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
+mlan_status moal_wait_hostcmd_complete(t_void *pmoal, t_u32 bss_index);
+mlan_status moal_notify_hostcmd_complete(t_void *pmoal, t_u32 bss_index);
+#endif
+t_void moal_print(t_void *pmoal, t_u32 level, char *pformat, IN ...);
+t_void moal_print_netintf(t_void *pmoal, t_u32 bss_index, t_u32 level);
+t_void moal_assert(t_void *pmoal, t_u32 cond);
+t_void moal_hist_data_add(t_void *pmoal, t_u32 bss_index,
+			  t_u16 rx_rate, t_s8 snr, t_s8 nflr, t_u8 antenna);
+
+t_void moal_updata_peer_signal(t_void *pmoal, t_u32 bss_index,
+			       t_u8 *peer_addr, t_s8 snr, t_s8 nflr);
+t_u64 moal_do_div(t_u64 num, t_u32 base);
+
+mlan_status moal_init_timer(t_void *pmoal, t_void **pptimer,
+			    IN t_void (*callback) (t_void *pcontext),
+			    t_void *pcontext);
+mlan_status moal_free_timer(t_void *pmoal, t_void *ptimer);
+mlan_status moal_start_timer(t_void *pmoal, t_void *ptimer,
+			     t_u8 periodic, t_u32 msec);
+mlan_status moal_stop_timer(t_void *pmoal, t_void *ptimer);
+void moal_tp_accounting(t_void *pmoal, void *buf, t_u32 drop_point);
+void moal_tp_accounting_rx_param(t_void *pmoal, unsigned int type,
+				 unsigned int rsvd1);
+void moal_amsdu_tp_accounting(t_void *pmoal, t_s32 amsdu_process_delay,
+			      t_s32 amsdu_copy_delay);
+
+#if defined(PCIE) || defined(SDIO)
+/* pmqos busfreq add request handler*/
+void woal_request_busfreq_pmqos_add(t_void *pmhandle);
+/* pmqos busfreq remove handler*/
+void woal_release_busfreq_pmqos_remove(t_void *pmhandle);
+#endif
+
+#endif /*_MOAL_H */
diff --git a/wlan_sd8987/mlinux/moal_sta_cfg80211.c b/wlan_sd8987/mlinux/moal_sta_cfg80211.c
new file mode 100755
index 0000000..2184a68
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sta_cfg80211.c
@@ -0,0 +1,9931 @@
+/** @file moal_sta_cfg80211.c
+ *
+ * @brief This file contains the functions for STA CFG80211.
+ *
+ *
+ * Copyright 2011-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include "moal_cfg80211.h"
+#include "moal_cfg80211_util.h"
+#include "moal_sta_cfg80211.h"
+#include "moal_eth_ioctl.h"
+#ifdef UAP_SUPPORT
+#include "moal_uap.h"
+#endif
+#include <linux/sort.h>
+
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+extern int fw_region;
+#endif
+#endif
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+static const u32 cfg80211_cipher_suites[] = {
+	WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104,
+	WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP,
+	WLAN_CIPHER_SUITE_SMS4,
+	WLAN_CIPHER_SUITE_AES_CMAC,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	WLAN_CIPHER_SUITE_BIP_GMAC_128,
+	WLAN_CIPHER_SUITE_BIP_GMAC_256,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	WLAN_CIPHER_SUITE_GCMP,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	WLAN_CIPHER_SUITE_GCMP_256,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	WLAN_CIPHER_SUITE_CCMP_256,
+#endif
+};
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+static void
+#else
+static int
+#endif
+
+woal_cfg80211_reg_notifier(struct wiphy *wiphy,
+			   struct regulatory_request *request);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+static int woal_cfg80211_scan(struct wiphy *wiphy,
+			      struct cfg80211_scan_request *request);
+#else
+static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
+			      struct cfg80211_scan_request *request);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+static void woal_cfg80211_abort_scan(struct wiphy *wiphy,
+				     struct wireless_dev *wdev);
+#endif
+static int woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_connect_params *sme);
+
+static int woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+				    t_u16 reason_code);
+
+static int woal_cfg80211_get_station(struct wiphy *wiphy,
+				     struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+				     const u8 *mac,
+#else
+				     u8 *mac,
+#endif
+				     struct station_info *sinfo);
+
+static int woal_cfg80211_dump_station(struct wiphy *wiphy,
+				      struct net_device *dev, int idx,
+				      t_u8 *mac, struct station_info *sinfo);
+
+static int woal_cfg80211_dump_survey(struct wiphy *wiphy,
+				     struct net_device *dev, int idx,
+				     struct survey_info *survey);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int woal_cfg80211_get_channel(struct wiphy *wiphy,
+				     struct wireless_dev *wdev,
+				     struct cfg80211_chan_def *chandef);
+#endif
+static int woal_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+					struct net_device *dev, bool enabled,
+					int timeout);
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+static int woal_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
+					     struct net_device *dev,
+					     s32 rssi_thold, u32 rssi_hyst);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+static int woal_cfg80211_get_tx_power(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+				      struct wireless_dev *wdev,
+#endif
+				      int *dbm);
+
+static int woal_cfg80211_set_tx_power(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+				      struct wireless_dev *wdev,
+#endif
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+				      enum tx_power_setting type,
+#else
+				      enum nl80211_tx_power_setting type,
+#endif
+				      int dbm);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+static int woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+					     struct wireless_dev *wdev,
+#else
+					     struct net_device *dev,
+#endif
+					     u64 cookie);
+
+static int
+ woal_cfg80211_remain_on_channel(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+				 struct wireless_dev *wdev,
+#else
+				 struct net_device *dev,
+#endif
+				 struct ieee80211_channel *chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+				 enum nl80211_channel_type channel_type,
+#endif
+				 unsigned int duration, u64 * cookie);
+
+static int woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+						  struct wireless_dev *wdev,
+#else
+						  struct net_device *dev,
+#endif
+						  u64 cookie);
+#endif /* KERNEL_VERSION */
+
+#ifdef CONFIG_NL80211_TESTMODE
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+static int woal_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
+			     void *data, int len);
+#else
+static int woal_testmode_cmd(struct wiphy *wiphy, void *data, int len);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+int woal_cfg80211_sched_scan_start(struct wiphy *wiphy, struct net_device *dev,
+				   struct cfg80211_sched_scan_request *request);
+int woal_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+				  , u64 reqid
+#endif
+	);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+int woal_cfg80211_resume(struct wiphy *wiphy);
+int woal_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+static void woal_cfg80211_set_wakeup(struct wiphy *wiphy, bool enabled);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+void woal_check_auto_tdls(struct wiphy *wiphy, struct net_device *dev);
+int woal_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			    const u8 *peer,
+#else
+			    u8 *peer,
+#endif
+			    enum nl80211_tdls_operation oper);
+int woal_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			    const u8 *peer,
+#else
+			    u8 *peer,
+#endif
+			    u8 action_code, u8 dialog_token, u16 status_code,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+			    u32 peer_capability,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+			    bool initiator,
+#endif
+			    const u8 *extra_ies, size_t extra_ies_len);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+static int woal_cfg80211_tdls_channel_switch(struct wiphy *wiphy,
+					     struct net_device *dev,
+					     const u8 *addr, u8 oper_class,
+					     struct cfg80211_chan_def *chandef);
+
+void woal_cfg80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
+					      struct net_device *dev,
+					      const u8 *addr);
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+static int woal_cfg80211_change_station(struct wiphy *wiphy,
+					struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+					const u8 *mac,
+#else
+					u8 *mac,
+#endif
+					struct station_parameters *params);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+int woal_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
+				struct cfg80211_update_ft_ies_params *ftie);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int woal_cfg80211_authenticate(struct wiphy *wiphy,
+				      struct net_device *dev,
+				      struct cfg80211_auth_request *req);
+
+static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
+				   struct cfg80211_assoc_request *req);
+#ifdef UAP_SUPPORT
+int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev,
+				  u8 *mac, struct station_parameters *params);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#ifdef UAP_SUPPORT
+static int woal_cfg80211_add_station(struct wiphy *wiphy,
+				     struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+				     const u8 *mac,
+#else
+				     u8 *mac,
+#endif
+				     struct station_parameters *params);
+#endif
+#endif
+
+static int woal_cfg80211_deauthenticate(struct wiphy *wiphy,
+					struct net_device *dev,
+					struct cfg80211_deauth_request *req);
+
+static int woal_cfg80211_disassociate(struct wiphy *wiphy,
+				      struct net_device *dev,
+				      struct cfg80211_disassoc_request *req);
+
+/** cfg80211 operations */
+static struct cfg80211_ops woal_cfg80211_ops = {
+	.change_virtual_intf = woal_cfg80211_change_virtual_intf,
+	.scan = woal_cfg80211_scan,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+	.abort_scan = woal_cfg80211_abort_scan,
+#endif
+	.connect = woal_cfg80211_connect,
+	.disconnect = woal_cfg80211_disconnect,
+	.deauth = woal_cfg80211_deauthenticate,
+	.disassoc = woal_cfg80211_disassociate,
+	.get_station = woal_cfg80211_get_station,
+	.dump_station = woal_cfg80211_dump_station,
+	.dump_survey = woal_cfg80211_dump_survey,
+	.set_wiphy_params = woal_cfg80211_set_wiphy_params,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
+	.set_channel = woal_cfg80211_set_channel,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	.get_channel = woal_cfg80211_get_channel,
+#endif
+	.add_key = woal_cfg80211_add_key,
+	.del_key = woal_cfg80211_del_key,
+	.set_default_key = woal_cfg80211_set_default_key,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+	.set_default_mgmt_key = woal_cfg80211_set_default_mgmt_key,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+	.set_default_beacon_key = woal_cfg80211_set_default_beacon_key,
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+	.set_rekey_data = woal_cfg80211_set_rekey_data,
+#endif
+	.set_pmksa = woal_cfg80211_set_pmksa,
+	.del_pmksa = woal_cfg80211_del_pmksa,
+	.flush_pmksa = woal_cfg80211_flush_pmksa,
+	.set_power_mgmt = woal_cfg80211_set_power_mgmt,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+	.set_tx_power = woal_cfg80211_set_tx_power,
+	.get_tx_power = woal_cfg80211_get_tx_power,
+#endif
+	.set_bitrate_mask = woal_cfg80211_set_bitrate_mask,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.sched_scan_start = woal_cfg80211_sched_scan_start,
+	.sched_scan_stop = woal_cfg80211_sched_scan_stop,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.suspend = woal_cfg80211_suspend,
+	.resume = woal_cfg80211_resume,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	.set_wakeup = woal_cfg80211_set_wakeup,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	.set_antenna = woal_cfg80211_set_antenna,
+	.get_antenna = woal_cfg80211_get_antenna,
+#endif
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+	.set_cqm_rssi_config = woal_cfg80211_set_cqm_rssi_config,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	.tdls_oper = woal_cfg80211_tdls_oper,
+	.tdls_mgmt = woal_cfg80211_tdls_mgmt,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	.tdls_channel_switch =
+		woal_cfg80211_tdls_channel_switch,.tdls_cancel_channel_switch =
+		woal_cfg80211_tdls_cancel_channel_switch,
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		.change_station = woal_cfg80211_change_station,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+		.update_ft_ies = woal_cfg80211_update_ft_ies,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		.set_qos_map = woal_cfg80211_set_qos_map,
+#endif
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		.set_coalesce = woal_cfg80211_set_coalesce,
+#endif
+		.add_virtual_intf =
+		woal_cfg80211_add_virtual_intf,.del_virtual_intf =
+		woal_cfg80211_del_virtual_intf,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		.start_ap = woal_cfg80211_add_beacon,.change_beacon =
+		woal_cfg80211_set_beacon,.stop_ap = woal_cfg80211_del_beacon,
+#else
+		.add_beacon = woal_cfg80211_add_beacon,.set_beacon =
+		woal_cfg80211_set_beacon,.del_beacon = woal_cfg80211_del_beacon,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		.change_bss = woal_cfg80211_change_bss,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+		.add_station = woal_cfg80211_add_station,
+#endif
+		.del_station = woal_cfg80211_del_station,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+		.set_txq_params = woal_cfg80211_set_txq_params,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+		.set_mac_acl = woal_cfg80211_set_mac_acl,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		.start_radar_detection =
+		woal_cfg80211_start_radar_detection,.channel_switch =
+		woal_cfg80211_channel_switch,
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
+		.update_mgmt_frame_registrations =
+		woal_cfg80211_mgmt_frame_register,
+#else
+		.mgmt_frame_register = woal_cfg80211_mgmt_frame_register,
+#endif
+		.mgmt_tx = woal_cfg80211_mgmt_tx,
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		.mgmt_tx_cancel_wait =
+		woal_cfg80211_mgmt_tx_cancel_wait,.remain_on_channel =
+		woal_cfg80211_remain_on_channel,.cancel_remain_on_channel =
+		woal_cfg80211_cancel_remain_on_channel,
+#endif
+#ifdef CONFIG_NL80211_TESTMODE
+		.testmode_cmd = woal_testmode_cmd,
+#endif
+};
+
+/** Region code mapping */
+typedef struct _region_code_t {
+	/** Region */
+	t_u8 region[COUNTRY_CODE_LEN];
+} region_code_t;
+
+static const struct ieee80211_regdomain mrvl_regdom = {
+	.n_reg_rules = 4,
+	.alpha2 = "99",
+	.reg_rules = {
+		      /* IEEE 802.11b/g, channels 1..11 */
+		      REG_RULE(2412 - 10, 2472 + 10, 40, 6, 20, 0),
+		      /* If any */
+		      /* IEEE 802.11 channel 14 - Only JP enables
+		       * this and for 802.11b only
+		       */
+		      REG_RULE(2484 - 10, 2484 + 10, 20, 6, 20, 0),
+		      /* IEEE 802.11a, channel 36..64 */
+		      REG_RULE(5150 - 10, 5350 + 10, 80, 6, 20, 0),
+		      /* IEEE 802.11a, channel 100..165 */
+		      REG_RULE(5470 - 10, 5850 + 10, 80, 6, 20, 0),
+		      }
+};
+
+#define AUTH_TX_DEFAULT_WAIT_TIME 2400
+/********************************************************
+				Local Variables
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+// clang-format off
+static const struct ieee80211_txrx_stypes
+ ieee80211_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_STATION] = {
+				    .tx = MBIT(IEEE80211_STYPE_ACTION >> 4) |
+				    MBIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				    .rx = MBIT(IEEE80211_STYPE_ACTION >> 4) |
+				    MBIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				    },
+	[NL80211_IFTYPE_AP] = {
+			       .tx = 0xffff,
+			       .rx = MBIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			       MBIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			       MBIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			       MBIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			       MBIT(IEEE80211_STYPE_AUTH >> 4) |
+			       MBIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			       MBIT(IEEE80211_STYPE_ACTION >> 4),
+			       },
+	[NL80211_IFTYPE_AP_VLAN] = {
+				    .tx = 0x0000,
+				    .rx = 0x0000,
+				    },
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+				       .tx = MBIT(IEEE80211_STYPE_ACTION >> 4) |
+				       MBIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				       .rx = MBIT(IEEE80211_STYPE_ACTION >> 4) |
+				       MBIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+				       },
+	[NL80211_IFTYPE_P2P_GO] = {
+				   .tx = MBIT(IEEE80211_STYPE_ACTION >> 4) |
+				   MBIT(IEEE80211_STYPE_AUTH >> 4) |
+				   MBIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
+				   MBIT(IEEE80211_STYPE_REASSOC_RESP >> 4) |
+				   MBIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+				   .rx = MBIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+				   MBIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+				   MBIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+				   MBIT(IEEE80211_STYPE_DISASSOC >> 4) |
+				   MBIT(IEEE80211_STYPE_AUTH >> 4) |
+				   MBIT(IEEE80211_STYPE_DEAUTH >> 4) |
+				   MBIT(IEEE80211_STYPE_ACTION >> 4),
+				   },
+#endif
+#endif
+	[NL80211_IFTYPE_MESH_POINT] = {
+				       .tx = 0x0000,
+				       .rx = 0x0000,
+				       },
+
+};
+
+// clang-format on
+#endif
+
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
+/**
+ * NOTE: types in all the sets must be equals to the
+ * initial value of wiphy->interface_modes
+ */
+static const struct ieee80211_iface_limit cfg80211_ap_sta_limits[] = {
+	{.max = 4,
+	 .types = MBIT(NL80211_IFTYPE_STATION)
+#ifdef UAP_CFG80211
+	 | MBIT(NL80211_IFTYPE_AP)
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	 | MBIT(NL80211_IFTYPE_P2P_GO) | MBIT(NL80211_IFTYPE_P2P_CLIENT)
+#endif
+#endif
+	 }
+};
+
+static struct ieee80211_iface_combination cfg80211_iface_comb_ap_sta = {
+	.limits = cfg80211_ap_sta_limits,
+	.num_different_channels = 1,
+	.n_limits = ARRAY_SIZE(cfg80211_ap_sta_limits),
+	.max_interfaces = 4,
+	.beacon_int_infra_match = MTRUE,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	.radar_detect_widths =
+		MBIT(NL80211_CHAN_WIDTH_20_NOHT) | MBIT(NL80211_CHAN_WIDTH_20),
+#endif
+};
+#endif
+
+extern pmoal_handle m_handle[];
+
+#ifdef CONFIG_PM
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+static const struct wiphy_wowlan_support wowlan_support = {
+	.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT,
+	.n_patterns = MAX_NUM_FILTERS,
+	.pattern_min_len = 1,
+	.pattern_max_len = WOWLAN_MAX_PATTERN_LEN,
+	.max_pkt_offset = WOWLAN_MAX_OFFSET_LEN,
+};
+
+static const struct wiphy_wowlan_support wowlan_support_with_gtk = {
+	.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT |
+		WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+		WIPHY_WOWLAN_GTK_REKEY_FAILURE,
+	.n_patterns = MAX_NUM_FILTERS,
+	.pattern_min_len = 1,
+	.pattern_max_len = WOWLAN_MAX_PATTERN_LEN,
+	.max_pkt_offset = WOWLAN_MAX_OFFSET_LEN,
+};
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+static const struct wiphy_coalesce_support coalesce_support = {
+	.n_rules = COALESCE_MAX_RULES,
+	.max_delay = MAX_COALESCING_DELAY,
+	.n_patterns = COALESCE_MAX_FILTERS,
+	.pattern_min_len = 1,
+	.pattern_max_len = MAX_PATTERN_LEN,
+	.max_pkt_offset = MAX_OFFSET_LEN,
+};
+#endif
+
+/********************************************************
+				Global Variables
+********************************************************/
+
+/********************************************************
+				Local Functions
+********************************************************/
+
+/**
+ *  @brief This function check cfg80211 special region code.
+ *
+ *  @param region_string         Region string
+ *
+ *  @return     MTRUE/MFALSE
+ */
+t_u8
+is_cfg80211_special_region_code(t_u8 *region_string)
+{
+	t_u8 i;
+	region_code_t cfg80211_special_region_code[] = {
+		{"00 "}, {"99 "}, {"98 "}, {"97 "}
+	};
+
+	for (i = 0; i < COUNTRY_CODE_LEN && region_string[i]; i++)
+		region_string[i] = toupper(region_string[i]);
+
+	for (i = 0; i < ARRAY_SIZE(cfg80211_special_region_code); i++) {
+		if (!memcmp(region_string,
+			    cfg80211_special_region_code[i].region,
+			    COUNTRY_CODE_LEN)) {
+			PRINTM(MIOCTL, "special region code=%s\n",
+			       region_string);
+			return MTRUE;
+		}
+	}
+	return MFALSE;
+}
+
+/**
+ * @brief Get the encryption mode from cipher
+ *
+ * @param cipher        Cipher cuite
+ * @param wpa_enabled   WPA enable or disable
+ *
+ * @return              MLAN_ENCRYPTION_MODE_*
+ */
+static int
+woal_cfg80211_get_encryption_mode(t_u32 cipher, int *wpa_enabled)
+{
+	int encrypt_mode;
+
+	ENTER();
+
+	*wpa_enabled = 0;
+	switch (cipher) {
+	case MW_AUTH_CIPHER_NONE:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_NONE;
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_WEP40;
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_WEP104;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_TKIP;
+		*wpa_enabled = 1;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_CCMP;
+		*wpa_enabled = 1;
+		break;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	case WLAN_CIPHER_SUITE_CCMP_256:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_CCMP_256;
+		*wpa_enabled = 1;
+		break;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	case WLAN_CIPHER_SUITE_GCMP:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_GCMP;
+		*wpa_enabled = 1;
+		break;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	case WLAN_CIPHER_SUITE_GCMP_256:
+		encrypt_mode = MLAN_ENCRYPTION_MODE_GCMP_256;
+		*wpa_enabled = 1;
+		break;
+#endif
+	default:
+		encrypt_mode = -1;
+	}
+
+	LEAVE();
+	return encrypt_mode;
+}
+
+/**
+ *  @brief get associate failure status code
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *
+ *  @return         IEEE status code
+ */
+static int
+woal_get_assoc_status(moal_private *priv)
+{
+	int ret = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	t_u16 status = (t_u16)(priv->assoc_status & 0xffff);
+	t_u16 cap = (t_u16)(priv->assoc_status >> 16);
+
+	switch (cap) {
+	case 0xfffd:
+	case 0xfffe:
+		ret = status;
+		break;
+	case 0xfffc:
+		ret = WLAN_STATUS_AUTH_TIMEOUT;
+		break;
+	default:
+		break;
+	}
+	PRINTM(MCMND, "Assoc fail: status=%d, cap=0x%x, IEEE status=%d\n",
+	       status, cap, ret);
+	return ret;
+}
+
+/**
+ *  @brief Check the pairwise or group cipher for
+ *  WEP enabled or not
+ *
+ *  @param cipher       MLAN Cipher cuite
+ *
+ *  @return             1 -- enable or 0 -- disable
+ */
+static int
+woal_cfg80211_is_alg_wep(t_u32 cipher)
+{
+	int alg = 0;
+	ENTER();
+
+	if (cipher == MLAN_ENCRYPTION_MODE_WEP40 ||
+	    cipher == MLAN_ENCRYPTION_MODE_WEP104)
+		alg = 1;
+
+	LEAVE();
+	return alg;
+}
+
+/**
+ *  @brief Convert NL80211 interface type to MLAN_BSS_MODE_*
+ *
+ *  @param iftype   Interface type of NL80211
+ *
+ *  @return         Driver bss mode
+ */
+static t_u32
+woal_nl80211_iftype_to_mode(enum nl80211_iftype iftype)
+{
+	switch (iftype) {
+	case NL80211_IFTYPE_STATION:
+		return MLAN_BSS_MODE_INFRA;
+	case NL80211_IFTYPE_UNSPECIFIED:
+	default:
+		return MLAN_BSS_MODE_AUTO;
+	}
+}
+
+/**
+ *  @brief Control WPS Session Enable/Disable
+ *
+ *  @param priv     Pointer to the moal_private driver data struct
+ *  @param enable   enable/disable flag
+ *
+ *  @return          0 --success, otherwise fail
+ */
+static int
+woal_wps_cfg(moal_private *priv, int enable)
+{
+	int ret = 0;
+	mlan_ds_wps_cfg *pwps = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	PRINTM(MINFO, "WOAL_WPS_SESSION\n");
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pwps = (mlan_ds_wps_cfg *)req->pbuf;
+	req->req_id = MLAN_IOCTL_WPS_CFG;
+	req->action = MLAN_ACT_SET;
+	pwps->sub_command = MLAN_OID_WPS_CFG_SESSION;
+	if (enable)
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START;
+	else
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_END;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief configure ASSOC IE
+ *
+ * @param priv				A pointer to moal private structure
+ * @param ie				A pointer to ie data
+ * @param ie_len			The length of ie data
+ * @param wait_option       wait option
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_assoc_ies_cfg(moal_private *priv, t_u8 *ie, int ie_len,
+			    t_u8 wait_option)
+{
+	int bytes_left = ie_len;
+	t_u8 *pcurrent_ptr = ie;
+	int total_ie_len;
+	t_u8 element_len;
+	int ret = MLAN_STATUS_SUCCESS;
+	IEEEtypes_ElementId_e element_id;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	t_u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
+	t_u8 hs20_oui[] = { 0x50, 0x6f, 0x9a, 0x10 };
+
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR,
+			       "InterpretIE: Error in processing IE, bytes left < IE length\n");
+			bytes_left = 0;
+			continue;
+		}
+		switch (element_id) {
+		case RSN_IE:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR, "Fail to set RSN IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL, "Set RSN IE\n");
+			break;
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    (pvendor_ie->vend_hdr.oui_type == wps_oui[3])) {
+				PRINTM(MIOCTL, "Enable WPS session\n");
+				woal_wps_cfg(priv, MTRUE);
+			}
+
+			if (!memcmp(pvendor_ie->vend_hdr.oui, hs20_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    (pvendor_ie->vend_hdr.oui_type == hs20_oui[3])) {
+				PRINTM(MIOCTL,
+				       "Hotspot2.0 is enabled for this bss\n");
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_set_hotspotcfg(priv, wait_option,
+							(HOTSPOT_BY_SUPPLICANT |
+							 HOTSPOT_ENABLED))) {
+					PRINTM(MERROR,
+					       "Fail to enable hotspot 2.0\n");
+					ret = -EFAULT;
+					goto done;
+				}
+			}
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR,
+				       "Fail to Set VENDOR SPECIFIC IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL,
+			       "Set VENDOR SPECIFIC IE, OUI: %02x:%02x:%02x:%02x\n",
+			       pvendor_ie->vend_hdr.oui[0],
+			       pvendor_ie->vend_hdr.oui[1],
+			       pvendor_ie->vend_hdr.oui[2],
+			       pvendor_ie->vend_hdr.oui_type);
+			break;
+		case MOBILITY_DOMAIN:
+			break;
+		case FAST_BSS_TRANSITION:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR, "Fail to set"
+				       "FAST_BSS_TRANSITION IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL, "Set FAST_BSS_TRANSITION IE\n");
+			break;
+		case RIC:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR,
+				       "Fail to set"
+				       "RESOURCE INFORMATION CONTAINER IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL,
+			       "Set RESOURCE INFORMATION CONTAINER IE\n");
+			break;
+		case EXT_CAPABILITY:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR,
+				       "Fail to set Extended Capabilites IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL, "Set Extended Capabilities IE\n");
+			break;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		case EXTENSION:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR, "Fail to set Extension IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL, "Set Extension IE\n");
+			break;
+		case FRAGMENT:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR, "Fail to set Fragmented IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL, "Set Fragmented IE\n");
+			break;
+#endif
+		default:
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						pcurrent_ptr, &total_ie_len,
+						wait_option)) {
+				PRINTM(MERROR, "Fail to set GEN IE\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			PRINTM(MIOCTL, "Set GEN IE\n");
+			break;
+		}
+		pcurrent_ptr += element_len + 2;
+		/* Need to account for IE ID and IE Len */
+		bytes_left -= (element_len + 2);
+	}
+done:
+	return ret;
+}
+
+#ifdef CONFIG_NL80211_TESTMODE
+enum moal_tm_attr {
+	__MOAL_TM_ATTR_INVALID = 0,
+	MOAL_TM_ATTR_CMD = 1,
+	MOAL_TM_ATTR_DATA = 2,
+
+	/* keep last */
+	__MOAL_TM_ATTR_AFTER_LAST,
+	MOAL_TM_ATTR_MAX = __MOAL_TM_ATTR_AFTER_LAST - 1,
+};
+
+static const struct nla_policy moal_tm_policy[MOAL_TM_ATTR_MAX + 1] = {
+	[MOAL_TM_ATTR_CMD] = {.type = NLA_U32},
+	[MOAL_TM_ATTR_DATA] = {.type = NLA_BINARY,
+			       .len = MRVDRV_SIZE_OF_CMD_BUFFER},
+};
+
+enum moal_tm_command {
+	MOAL_TM_CMD_HOSTCMD = 0,
+};
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+static int
+woal_testmode_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
+		  void *data, int len)
+#else
+static int
+woal_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+#endif
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv =
+		(moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct nlattr *tb[MOAL_TM_ATTR_MAX + 1];
+	struct sk_buff *skb;
+	int err;
+
+	if (!priv)
+		return -EINVAL;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	err = nla_parse(tb, MOAL_TM_ATTR_MAX, data, len, moal_tm_policy, NULL);
+#else
+	err = nla_parse(tb, MOAL_TM_ATTR_MAX, data, len, moal_tm_policy);
+#endif
+	if (err)
+		return err;
+
+	if (!tb[MOAL_TM_ATTR_CMD])
+		return -EINVAL;
+
+	switch (nla_get_u32(tb[MOAL_TM_ATTR_CMD])) {
+	case MOAL_TM_CMD_HOSTCMD:
+		if (!tb[MOAL_TM_ATTR_DATA])
+			return -EINVAL;
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+		if (req == NULL)
+			return -ENOMEM;
+		misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+		misc_cfg->sub_command = MLAN_OID_MISC_HOST_CMD;
+		req->req_id = MLAN_IOCTL_MISC_CFG;
+		req->action = MLAN_ACT_SET;
+		misc_cfg->param.hostcmd.len = nla_len(tb[MOAL_TM_ATTR_DATA]);
+		moal_memcpy_ext(priv->phandle, misc_cfg->param.hostcmd.cmd,
+				nla_data(tb[MOAL_TM_ATTR_DATA]),
+				misc_cfg->param.hostcmd.len,
+				MRVDRV_SIZE_OF_CMD_BUFFER);
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			err = -EFAULT;
+			goto error;
+		}
+		/* process hostcmd response */
+		skb = cfg80211_testmode_alloc_reply_skb(wiphy,
+							misc_cfg->param.hostcmd.
+							len);
+		if (!skb) {
+			kfree(req);
+			return -ENOMEM;
+		}
+		err = nla_put(skb, MOAL_TM_ATTR_DATA,
+			      misc_cfg->param.hostcmd.len,
+			      misc_cfg->param.hostcmd.cmd);
+		if (err) {
+			kfree(req);
+			kfree_skb(skb);
+			return -EMSGSIZE;
+		}
+		err = cfg80211_testmode_reply(skb);
+		kfree(req);
+		return err;
+	default:
+		return -EOPNOTSUPP;
+	}
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	return err;
+}
+#endif
+
+/**
+ * @brief Send domain info command to FW
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param wait_option  wait option
+ *
+ * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_send_domain_info_cmd_fw(moal_private *priv, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband = NULL;
+	struct ieee80211_channel *channel = NULL;
+	t_u8 no_of_sub_band = 0;
+	t_u8 no_of_parsed_chan = 0;
+	t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
+	t_u8 i, flag = 0;
+	mlan_ds_11d_cfg *cfg_11d = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "No wdev or wiphy in priv\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	band = priv->phandle->band;
+	if (!priv->wdev->wiphy->bands[band]) {
+		PRINTM(MERROR, "11D: setting domain info in FW failed band=%d",
+		       band);
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(MCMD_D, "Send domain info: country=%c%c band=%d\n",
+	       priv->phandle->country_code[0], priv->phandle->country_code[1],
+	       band);
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
+	cfg_11d->sub_command = MLAN_OID_11D_DOMAIN_INFO_EXT;
+	req->req_id = MLAN_IOCTL_11D_CFG;
+	req->action = MLAN_ACT_SET;
+
+	if (is_cfg80211_special_region_code(priv->phandle->country_code)) {
+		/* Set country code */
+		cfg_11d->param.domain_info.country_code[0] = 'W';
+		cfg_11d->param.domain_info.country_code[1] = 'W';
+	} else {
+		/* Set country code */
+		cfg_11d->param.domain_info.country_code[0] =
+			priv->phandle->country_code[0];
+		cfg_11d->param.domain_info.country_code[1] =
+			priv->phandle->country_code[1];
+	}
+	cfg_11d->param.domain_info.country_code[2] = ' ';
+	cfg_11d->param.domain_info.band = band;
+
+	sband = priv->wdev->wiphy->bands[band];
+	for (i = 0; (i < sband->n_channels) &&
+	     (no_of_sub_band < MRVDRV_MAX_SUBBAND_802_11D); i++) {
+		channel = &sband->channels[i];
+		if (channel->flags & IEEE80211_CHAN_DISABLED)
+			continue;
+
+		if (!flag) {
+			flag = 1;
+			next_chan = first_chan = (t_u32)channel->hw_value;
+			max_pwr = channel->max_power;
+			no_of_parsed_chan = 1;
+			continue;
+		}
+
+		if (channel->hw_value == next_chan + 1 &&
+		    channel->max_power == max_pwr) {
+			next_chan++;
+			no_of_parsed_chan++;
+		} else {
+			cfg_11d->param.domain_info.sub_band[no_of_sub_band]
+				.first_chan = first_chan;
+			cfg_11d->param.domain_info.sub_band[no_of_sub_band]
+				.no_of_chan = no_of_parsed_chan;
+			cfg_11d->param.domain_info.sub_band[no_of_sub_band]
+				.max_tx_pwr = max_pwr;
+			no_of_sub_band++;
+			next_chan = first_chan = (t_u32)channel->hw_value;
+			max_pwr = channel->max_power;
+			no_of_parsed_chan = 1;
+		}
+	}
+
+	if (flag && (no_of_sub_band < MRVDRV_MAX_SUBBAND_802_11D)) {
+		cfg_11d->param.domain_info.sub_band[no_of_sub_band].first_chan =
+			first_chan;
+		cfg_11d->param.domain_info.sub_band[no_of_sub_band].no_of_chan =
+			no_of_parsed_chan;
+		cfg_11d->param.domain_info.sub_band[no_of_sub_band].max_tx_pwr =
+			max_pwr;
+		no_of_sub_band++;
+	}
+	cfg_11d->param.domain_info.no_of_sub_band = no_of_sub_band;
+
+	PRINTM(MCMND, "CFG80211: Country=%c%c, band=%d, no_of_sub_band=%d\n",
+	       priv->phandle->country_code[0], priv->phandle->country_code[1],
+	       priv->phandle->band, cfg_11d->param.domain_info.no_of_sub_band);
+	/* Send domain info command to FW */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		PRINTM(MERROR, "11D: Error setting domain info in FW\n");
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to change the channel and
+ * change domain info according to that channel
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param chan            A pointer to ieee80211_channel structure
+ * @param channel_type    Channel type of nl80211_channel_type
+ * @param wait_option     wait option
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_set_rf_channel(moal_private *priv, struct ieee80211_channel *chan,
+		    enum nl80211_channel_type channel_type, t_u8 wait_option)
+{
+	int ret = 0;
+	t_u32 mode, config_bands = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!chan) {
+		LEAVE();
+		return -EINVAL;
+	}
+	mode = woal_nl80211_iftype_to_mode(priv->wdev->iftype);
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	/* Get config_bands, adhoc_start_band and adhoc_channel values from MLAN
+	 */
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	req->action = MLAN_ACT_SET;
+	priv->phandle->band = chan->band;
+	/* Set appropriate bands */
+	if (chan->band == IEEE80211_BAND_2GHZ)
+		config_bands = BAND_B | BAND_G | BAND_GN;
+	else {
+		config_bands = BAND_AN | BAND_A;
+	}
+	if (mode == MLAN_BSS_MODE_IBSS) {
+		radio_cfg->param.band_cfg.adhoc_start_band = config_bands;
+		radio_cfg->param.band_cfg.adhoc_channel =
+			ieee80211_frequency_to_channel(chan->center_freq);
+	}
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	woal_send_domain_info_cmd_fw(priv, wait_option);
+
+	PRINTM(MINFO, "Setting band %d, and mode = %d channel=%d\n",
+	       config_bands, mode,
+	       ieee80211_frequency_to_channel(chan->center_freq));
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_change_adhoc_chan(priv,
+				   ieee80211_frequency_to_channel(chan->
+								  center_freq),
+				   wait_option)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set ewpa mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param ssid_bssid           A pointer to mlan_ssid_bssid structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+static mlan_status
+woal_set_ewpa_mode(moal_private *priv, t_u8 wait_option,
+		   mlan_ssid_bssid *ssid_bssid)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv->phandle->card_info->embedded_supp)
+		goto error;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto error;
+	}
+
+	/* Fill request buffer */
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Try Get All */
+	memset(&sec->param.passphrase, 0, sizeof(mlan_ds_passphrase));
+	moal_memcpy_ext(priv->phandle, &sec->param.passphrase.ssid,
+			&ssid_bssid->ssid, sizeof(sec->param.passphrase.ssid),
+			sizeof(sec->param.passphrase.ssid));
+	moal_memcpy_ext(priv->phandle, &sec->param.passphrase.bssid,
+			&ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH,
+			sizeof(sec->param.passphrase.bssid));
+	sec->param.passphrase.psk_type = MLAN_PSK_QUERY;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto error;
+	sec->param.ewpa_enabled = MFALSE;
+	if (sec->param.passphrase.psk_type == MLAN_PSK_PASSPHRASE) {
+		if (sec->param.passphrase.psk.passphrase.passphrase_len > 0)
+			sec->param.ewpa_enabled = MTRUE;
+	} else if (sec->param.passphrase.psk_type == MLAN_PSK_PMK)
+		sec->param.ewpa_enabled = MTRUE;
+
+	sec->sub_command = MLAN_OID_SEC_CFG_EWPA_ENABLED;
+	req->action = MLAN_ACT_SET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, wait_option);
+
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ * @brief Set encryption mode and enable WPA
+ *
+ * @param priv          A pointer to moal_private structure
+ * @param encrypt_mode  Encryption mode
+ * @param wpa_enabled   WPA enable or not
+ * @param wait_option   wait option
+ *
+ * @return              0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_set_auth(moal_private *priv, int encrypt_mode,
+		       int wpa_enabled, t_u8 wait_option)
+{
+	int ret = 0;
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_encrypt_mode(priv, wait_option, encrypt_mode))
+		ret = -EFAULT;
+
+	if (wpa_enabled) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wpa_enable(priv, wait_option, 1))
+			ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Informs the CFG802.11 subsystem of a new BSS connection.
+ *
+ * The following information are sent to the CFG802.11 subsystem
+ * to register the new BSS connection. If we do not register the new BSS,
+ * a kernel panic will result.
+ *      - MAC address
+ *      - Capabilities
+ *      - Beacon period
+ *      - RSSI value
+ *      - Channel
+ *      - Supported rates IE
+ *      - Extended capabilities IE
+ *      - DS parameter set IE
+ *      - HT Capability IE
+ *      - Vendor Specific IE (221)
+ *      - WPA IE
+ *      - RSN IE
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param ssid_bssid      A pointer to A pointer to mlan_ssid_bssid structure
+ * @param wait_option     wait_option
+ *
+ * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_inform_bss_from_scan_result(moal_private *priv,
+				 mlan_ssid_bssid *ssid_bssid, t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct ieee80211_channel *chan;
+	mlan_scan_resp scan_resp;
+	BSSDescriptor_t *scan_table;
+	t_u64 ts = 0;
+	u16 cap_info = 0;
+	int i = 0;
+	struct cfg80211_bss *pub = NULL;
+
+	ENTER();
+	if (!priv->wdev || !priv->wdev->wiphy) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	memset(&scan_resp, 0, sizeof(scan_resp));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, wait_option, &scan_resp)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (scan_resp.num_in_scan_table) {
+		scan_table = (BSSDescriptor_t *)scan_resp.pscan_table;
+		for (i = 0; i < (int)scan_resp.num_in_scan_table; i++) {
+			if (ssid_bssid) {
+				/* Inform specific BSS only */
+				if (memcmp(ssid_bssid->ssid.ssid,
+					   scan_table[i].ssid.ssid,
+					   ssid_bssid->ssid.ssid_len) ||
+				    memcmp(ssid_bssid->bssid,
+					   scan_table[i].mac_address, ETH_ALEN))
+					continue;
+			}
+			if (!scan_table[i].freq) {
+				scan_table[i].freq =
+					ieee80211_channel_to_frequency((int)
+								       scan_table
+								       [i].
+								       channel
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								       ,
+								       woal_band_cfg_to_ieee_band
+								       (scan_table
+									[i].
+									bss_band)
+#endif
+					);
+			}
+			chan = ieee80211_get_channel(priv->wdev->wiphy,
+						     scan_table[i].freq);
+			if (!chan) {
+				PRINTM(MCMND,
+				       "Fail to get chan with freq: channel=%d freq=%d\n",
+				       (int)scan_table[i].channel,
+				       (int)scan_table[i].freq);
+				continue;
+			}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+			    !ssid_bssid) {
+				if (!strncmp(scan_table[i].ssid.ssid, "DIRECT-",
+					     strlen("DIRECT-"))) {
+					PRINTM(MCMND,
+					       "wlan: P2P device " MACSTR
+					       " found, channel=%d\n",
+					       MAC2STR(scan_table[i]
+						       .mac_address),
+					       (int)chan->hw_value);
+				}
+			}
+#endif
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+			/** Andorid's Location service is expecting timestamp to
+			 * be local time (in microsecond) since boot; and not
+			 * the TSF found in the beacon. */
+			ts = ktime_to_us(ktime_get_boottime());
+#else
+			moal_memcpy_ext(priv->phandle, &ts,
+					scan_table[i].time_stamp, sizeof(ts),
+					sizeof(ts));
+#endif
+			moal_memcpy_ext(priv->phandle, &cap_info,
+					&scan_table[i].cap_info,
+					sizeof(cap_info), sizeof(cap_info));
+			pub = cfg80211_inform_bss(priv->wdev->wiphy, chan,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+						  CFG80211_BSS_FTYPE_UNKNOWN,
+#endif
+						  scan_table[i].mac_address, ts,
+						  cap_info,
+						  scan_table[i].beacon_period,
+						  scan_table[i].pbeacon_buf +
+						  WLAN_802_11_FIXED_IE_SIZE,
+						  scan_table[i].
+						  beacon_buf_size -
+						  WLAN_802_11_FIXED_IE_SIZE,
+						  -RSSI_DBM_TO_MDM(scan_table
+								   [i].rssi),
+						  GFP_KERNEL);
+			if (pub) {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+				pub->len_information_elements =
+					pub->len_beacon_ies;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+				cfg80211_put_bss(priv->wdev->wiphy, pub);
+#else
+				cfg80211_put_bss(pub);
+#endif
+			}
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Informs the CFG802.11 subsystem of a new IBSS connection.
+ *
+ * The following information are sent to the CFG802.11 subsystem
+ * to register the new IBSS connection. If we do not register the
+ * new IBSS, a kernel panic will result.
+ *      - MAC address
+ *      - Capabilities
+ *      - Beacon period
+ *      - RSSI value
+ *      - Channel
+ *      - Supported rates IE
+ *      - Extended capabilities IE
+ *      - DS parameter set IE
+ *      - HT Capability IE
+ *      - Vendor Specific IE (221)
+ *      - WPA IE
+ *      - RSN IE
+ *
+ * @param priv              A pointer to moal_private structure
+ * @param cahn              A pointer to ieee80211_channel structure
+ * @param beacon_interval   Beacon interval
+ *
+ * @return                  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_cfg80211_inform_ibss_bss(moal_private *priv,
+			      struct ieee80211_channel *chan,
+			      t_u16 beacon_interval)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_bss_info bss_info;
+	mlan_ds_get_signal signal;
+	t_u8 ie_buf[MLAN_MAX_SSID_LENGTH + sizeof(IEEEtypes_Header_t)];
+	int ie_len = 0;
+	struct cfg80211_bss *bss = NULL;
+
+	ENTER();
+
+	ret = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (ret)
+		goto done;
+
+	memset(ie_buf, 0, sizeof(ie_buf));
+	ie_buf[0] = WLAN_EID_SSID;
+	ie_buf[1] = bss_info.ssid.ssid_len;
+
+	moal_memcpy_ext(priv->phandle, &ie_buf[sizeof(IEEEtypes_Header_t)],
+			&bss_info.ssid.ssid, bss_info.ssid.ssid_len,
+			sizeof(ie_buf) - sizeof(IEEEtypes_Header_t));
+	ie_len = ie_buf[1] + sizeof(IEEEtypes_Header_t);
+
+	/* Get signal information from the firmware */
+	memset(&signal, 0, sizeof(mlan_ds_get_signal));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_signal_info(priv, MOAL_IOCTL_WAIT, &signal)) {
+		PRINTM(MERROR, "Error getting signal information\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+				  CFG80211_BSS_FTYPE_UNKNOWN,
+#endif
+				  bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
+				  beacon_interval, ie_buf, ie_len,
+				  signal.bcn_rssi_avg, GFP_KERNEL);
+	if (bss)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+		cfg80211_put_bss(priv->wdev->wiphy, bss);
+#else
+		cfg80211_put_bss(bss);
+#endif
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Process country IE before assoicate
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param bss             A pointer to cfg80211_bss structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_process_country_ie(moal_private *priv, struct cfg80211_bss *bss)
+{
+	u8 *country_ie, country_ie_len;
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11d_cfg *cfg_11d = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	rcu_read_lock();
+	country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+	if (!country_ie) {
+		rcu_read_unlock();
+		PRINTM(MIOCTL, "No country IE found!\n");
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		LEAVE();
+		return 0;
+	}
+
+	country_ie_len = country_ie[1];
+	if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
+		rcu_read_unlock();
+		PRINTM(MIOCTL, "Wrong Country IE length!\n");
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		LEAVE();
+		return 0;
+	}
+	priv->phandle->country_code[0] = country_ie[2];
+	priv->phandle->country_code[1] = country_ie[3];
+	priv->phandle->country_code[2] = ' ';
+	if (is_cfg80211_special_region_code(priv->phandle->country_code)) {
+		rcu_read_unlock();
+		PRINTM(MIOCTL, "Skip special region code in CountryIE");
+		LEAVE();
+		return 0;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_region_code(priv, priv->phandle->country_code))
+		PRINTM(MERROR, "Set country code failed!\n");
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (req == NULL) {
+		rcu_read_unlock();
+		PRINTM(MERROR, "Fail to allocate mlan_ds_11d_cfg buffer\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
+	cfg_11d->sub_command = MLAN_OID_11D_DOMAIN_INFO_EXT;
+	req->req_id = MLAN_IOCTL_11D_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Set country code */
+	cfg_11d->param.domain_info.country_code[0] =
+		priv->phandle->country_code[0];
+	cfg_11d->param.domain_info.country_code[1] =
+		priv->phandle->country_code[1];
+	cfg_11d->param.domain_info.country_code[2] = ' ';
+
+	/** IEEE80211_BAND_2GHZ or IEEE80211_BAND_5GHZ */
+	cfg_11d->param.domain_info.band = priv->phandle->band;
+
+	country_ie_len -= COUNTRY_CODE_LEN;
+	cfg_11d->param.domain_info.no_of_sub_band =
+		MIN(MRVDRV_MAX_SUBBAND_802_11D,
+		    (country_ie_len /
+		     sizeof(struct ieee80211_country_ie_triplet)));
+	moal_memcpy_ext(priv->phandle,
+			(u8 *)cfg_11d->param.domain_info.sub_band,
+			&country_ie[2] + COUNTRY_CODE_LEN,
+			cfg_11d->param.domain_info.no_of_sub_band *
+			sizeof(mlan_ds_subband_set_t),
+			sizeof(cfg_11d->param.domain_info.sub_band));
+
+	PRINTM(MCMND, "11D: Country IE: %c%c band=%d no_of_sub_band=%d\n",
+	       country_ie[2], country_ie[3], priv->phandle->band,
+	       cfg_11d->param.domain_info.no_of_sub_band);
+	rcu_read_unlock();
+
+	/* Send domain info command to FW */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = MLAN_STATUS_FAILURE;
+		PRINTM(MERROR, "11D: Error setting domain info in FW\n");
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request scan based on connect parameter
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param conn_param      A pointer to connect parameters
+ * @param wait_option     wait option
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_connect_scan(moal_private *priv,
+			   struct cfg80211_connect_params *conn_param,
+			   t_u8 wait_option)
+{
+	moal_handle *handle = priv->phandle;
+	int ret = 0;
+	wlan_user_scan_cfg scan_req;
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int chan_idx = 0, i;
+
+	ENTER();
+	if (handle->scan_pending_on_block == MTRUE) {
+		PRINTM(MINFO, "scan already in processing...\n");
+		LEAVE();
+		return ret;
+	}
+#ifdef REASSOCIATION
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#endif /* REASSOCIATION */
+	priv->report_scan_result = MTRUE;
+	memset(&scan_req, 0x00, sizeof(scan_req));
+	moal_memcpy_ext(priv->phandle, scan_req.ssid_list[0].ssid,
+			conn_param->ssid, conn_param->ssid_len,
+			sizeof(scan_req.ssid_list[0].ssid));
+	scan_req.ssid_list[0].max_len = 0;
+	if (conn_param->channel) {
+		scan_req.chan_list[0].chan_number =
+			conn_param->channel->hw_value;
+		scan_req.chan_list[0].radio_type = conn_param->channel->band;
+		if (conn_param->channel->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+			scan_req.chan_list[0].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		else if (conn_param->channel->flags & IEEE80211_CHAN_RADAR)
+			scan_req.chan_list[0].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+		else
+			scan_req.chan_list[0].scan_type = MLAN_SCAN_TYPE_ACTIVE;
+		scan_req.chan_list[0].scan_time = 0;
+	} else {
+		for (band = 0; (band < IEEE80211_NUM_BANDS); band++) {
+			if (!priv->wdev->wiphy->bands[band])
+				continue;
+			sband = priv->wdev->wiphy->bands[band];
+			for (i = 0; (i < sband->n_channels); i++) {
+				ch = &sband->channels[i];
+				if (ch->flags & IEEE80211_CHAN_DISABLED)
+					continue;
+				scan_req.chan_list[chan_idx].radio_type = band;
+				if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_PASSIVE;
+				else if (ch->flags & IEEE80211_CHAN_RADAR)
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+				else
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_ACTIVE;
+				scan_req.chan_list[chan_idx].chan_number =
+					(u32)ch->hw_value;
+				chan_idx++;
+			}
+		}
+	}
+	moal_memcpy_ext(priv->phandle, scan_req.random_mac, priv->random_mac,
+			ETH_ALEN, sizeof(scan_req.random_mac));
+	ret = woal_request_userscan(priv, wait_option, &scan_req);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @brief Save assoc parameters for roaming
+ *
+ * @param priv            A pointer to moal_private
+ * @param req             A pointer to cfg80211_assoc_request structure
+ */
+static void
+woal_save_assoc_params(moal_private *priv,
+		       struct cfg80211_assoc_request *req,
+		       mlan_ssid_bssid *ssid_bssid)
+{
+	ENTER();
+
+	priv->assoc_bss = req->bss;
+	if (req->bss->channel) {
+		priv->sme_current.channel = &priv->conn_chan;
+		moal_memcpy_ext(priv->phandle, priv->sme_current.channel,
+				req->bss->channel,
+				sizeof(struct ieee80211_channel),
+				sizeof(struct ieee80211_channel));
+	}
+	priv->sme_current.bssid = priv->conn_bssid;
+	moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.bssid,
+			req->bss->bssid, MLAN_MAC_ADDR_LENGTH,
+			MLAN_MAC_ADDR_LENGTH);
+	if (req->ie && req->ie_len) {
+		priv->sme_current.ie = kzalloc(req->ie_len, GFP_KERNEL);
+		priv->sme_current.ie_len = req->ie_len;
+		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.ie,
+				req->ie, req->ie_len, priv->sme_current.ie_len);
+	}
+	moal_memcpy_ext(priv->phandle, &priv->sme_current.crypto, &req->crypto,
+			sizeof(struct cfg80211_crypto_settings),
+			sizeof(struct cfg80211_crypto_settings));
+	priv->sme_current.flags = req->flags;
+	moal_memcpy_ext(priv->phandle, &priv->sme_current.ht_capa,
+			&req->ht_capa, sizeof(struct ieee80211_ht_cap),
+			sizeof(struct ieee80211_ht_cap));
+	moal_memcpy_ext(priv->phandle, &priv->sme_current.ht_capa_mask,
+			&req->ht_capa_mask, sizeof(struct ieee80211_ht_cap),
+			sizeof(struct ieee80211_ht_cap));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+	moal_memcpy_ext(priv->phandle, &priv->sme_current.vht_capa,
+			&req->vht_capa, sizeof(struct ieee80211_vht_cap),
+			sizeof(struct ieee80211_vht_cap));
+	moal_memcpy_ext(priv->phandle, &priv->sme_current.vht_capa_mask,
+			&req->vht_capa_mask, sizeof(struct ieee80211_vht_cap),
+			sizeof(struct ieee80211_vht_cap));
+#endif
+	if (ssid_bssid && ssid_bssid->ssid.ssid_len) {
+		priv->sme_current.ssid = priv->conn_ssid;
+		memset(priv->conn_ssid, 0, MLAN_MAX_SSID_LENGTH);
+		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.ssid,
+				ssid_bssid->ssid.ssid,
+				ssid_bssid->ssid.ssid_len,
+				sizeof(priv->conn_ssid));
+		priv->conn_ssid_len = ssid_bssid->ssid.ssid_len;
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Save auth parameters for roaming
+ *
+ * @param priv            A pointer to moal_private
+ * @param req             A pointer to struct cfg80211_auth_request
+ */
+static void
+woal_save_auth_params(moal_private *priv, struct cfg80211_auth_request *req)
+{
+	ENTER();
+	woal_clear_conn_params(priv);
+	priv->sme_current.auth_type = req->auth_type;
+	priv->sme_current.key_idx = req->key_idx;
+	priv->sme_current.key_len = req->key_len;
+	if (req->key && req->key_len && (req->key_len <= MAX_WEP_KEY_SIZE)) {
+		priv->sme_current.key = priv->conn_wep_key;
+		moal_memcpy_ext(priv->phandle, (t_u8 *)priv->sme_current.key,
+				req->key, req->key_len,
+				sizeof(priv->conn_wep_key));
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Request scan based on auth_request parameter
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param req             A pointer to cfg80211_auth_request
+ * @param wait_option     wait option
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_auth_scan(moal_private *priv,
+			struct cfg80211_auth_request *req, t_u8 wait_option)
+{
+	moal_handle *handle = priv->phandle;
+	int ret = 0;
+	wlan_user_scan_cfg scan_req;
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int chan_idx = 0, i;
+	const u8 *ssid;
+
+	ENTER();
+	if (handle->scan_pending_on_block == MTRUE) {
+		PRINTM(MINFO, "scan already in processing...\n");
+		LEAVE();
+		return ret;
+	}
+#ifdef REASSOCIATION
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#endif /* REASSOCIATION */
+	priv->report_scan_result = MTRUE;
+	memset(&scan_req, 0x00, sizeof(scan_req));
+	rcu_read_lock();
+	ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
+	if (ssid) {
+		moal_memcpy_ext(priv->phandle, scan_req.ssid_list[0].ssid,
+				ssid + 2, ssid[1],
+				sizeof(scan_req.ssid_list[0].ssid));
+		scan_req.ssid_list[0].max_len = 0;
+	}
+	rcu_read_unlock();
+	moal_memcpy_ext(priv->phandle, scan_req.specific_bssid, req->bss->bssid,
+			ETH_ALEN, ETH_ALEN);
+	if (req->bss->channel) {
+		scan_req.chan_list[0].chan_number = req->bss->channel->hw_value;
+		scan_req.chan_list[0].radio_type = req->bss->channel->band;
+		if (req->bss->channel->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+			scan_req.chan_list[0].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		else if (req->bss->channel->flags & IEEE80211_CHAN_RADAR)
+			scan_req.chan_list[0].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+		else
+			scan_req.chan_list[0].scan_type = MLAN_SCAN_TYPE_ACTIVE;
+		scan_req.chan_list[0].scan_time = 0;
+	} else {
+		for (band = 0; (band < IEEE80211_NUM_BANDS); band++) {
+			if (!priv->wdev->wiphy->bands[band])
+				continue;
+			sband = priv->wdev->wiphy->bands[band];
+			for (i = 0; (i < sband->n_channels); i++) {
+				ch = &sband->channels[i];
+				if (ch->flags & IEEE80211_CHAN_DISABLED)
+					continue;
+				scan_req.chan_list[chan_idx].radio_type = band;
+				if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_PASSIVE;
+				else if (ch->flags & IEEE80211_CHAN_RADAR)
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+				else
+					scan_req.chan_list[chan_idx].scan_type =
+						MLAN_SCAN_TYPE_ACTIVE;
+				scan_req.chan_list[chan_idx].chan_number =
+					(u32)ch->hw_value;
+				chan_idx++;
+			}
+		}
+	}
+	moal_memcpy_ext(priv->phandle, scan_req.random_mac, priv->random_mac,
+			ETH_ALEN, sizeof(scan_req.random_mac));
+	ret = woal_request_userscan(priv, wait_option, &scan_req);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function is authentication handler when host MLME
+ *          enable.
+ *          In this case driver will prepare and send Auth Req.
+ *
+ *  @param wiphy       A pointer to wiphy.
+ *
+ *  @param dev         A pointer to net_device
+ *
+ *  @param req         A pointer to cfg80211_auth_request
+ *
+ *  @return            0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_authenticate(struct wiphy *wiphy,
+			   struct net_device *dev,
+			   struct cfg80211_auth_request *req)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	IEEE80211_MGMT *mgmt = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_buffer pmbuf = NULL;
+	t_u32 pkt_type, tx_control;
+	t_u16 packet_len = 0, auth_alg;
+	t_u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	int ret = 0;
+
+	t_u8 trans = 1, status_code = 0;
+	t_u8 *varptr = NULL;
+	mlan_ssid_bssid *ssid_bssid;
+	moal_handle *handle = priv->phandle;
+	int i;
+
+	ENTER();
+
+	priv->cfg_disconnect = MFALSE;
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		PRINTM(MERROR, "Role is AP\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#endif
+	if (priv->wdev->iftype != NL80211_IFTYPE_STATION
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+#endif /* WIFI_DIRECT_SUPPORT */
+		) {
+		PRINTM(MERROR,
+		       "Received infra auth request when interface not in infra mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+	ssid_bssid = kzalloc(sizeof(mlan_ssid_bssid), GFP_ATOMIC);
+	if (!ssid_bssid) {
+		PRINTM(MERROR, "Fail to allocate ssid_bssid buffer\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+	moal_memcpy_ext(priv->phandle, ssid_bssid->bssid, req->bss->bssid,
+			ETH_ALEN, sizeof(ssid_bssid->bssid));
+	/* Not allowed to connect to the same AP which is already connected
+	   with other interface */
+	for (i = 0; i < handle->priv_num; i++) {
+		if (handle->priv[i] != priv &&
+		    MTRUE == woal_is_connected(handle->priv[i], ssid_bssid)) {
+			PRINTM(MMSG,
+			       "wlan: already connected with other interface, bssid "
+			       MACSTR "\n",
+			       MAC2STR(handle->priv[i]->cfg_bssid));
+			kfree(ssid_bssid);
+			LEAVE();
+			return -EINVAL;
+		}
+	}
+	if (MLAN_STATUS_SUCCESS != woal_find_bssid(priv, req->bss->bssid)) {
+		woal_cfg80211_auth_scan(priv, req, MOAL_IOCTL_WAIT);
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_find_bssid(priv, req->bss->bssid)) {
+			PRINTM(MMSG, "bssid not find in scan list\n");
+			kfree(ssid_bssid);
+			LEAVE();
+			return -EFAULT;
+		}
+	}
+	kfree(ssid_bssid);
+
+	if ((priv->auth_alg != WLAN_AUTH_SAE) &&
+	    (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {
+		PRINTM(MERROR, "pending auth on going\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+	    (priv->wdev->iftype == NL80211_IFTYPE_STATION ||
+	     priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
+		/* if bsstype == wifi direct, and iftype == station or p2p
+		 * client, that means wpa_supplicant wants to enable wifi direct
+		 * functionality, so we should init p2p client.
+		 *
+		 * Note that due to kernel iftype check, ICS wpa_supplicant
+		 * could not updaet iftype to init p2p client, so we have to
+		 * done it here.
+		 * */
+		if (MLAN_STATUS_SUCCESS != woal_cfg80211_init_p2p_client(priv)) {
+			PRINTM(MERROR,
+			       "Init p2p client for wpa_supplicant failed.\n");
+			ret = -EFAULT;
+			LEAVE();
+			return ret;
+		}
+	}
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		/* WAR for P2P connection with vendor TV */
+		woal_sched_timeout(200);
+	}
+#endif
+
+	/*enable auth register frame */
+	if (priv->auth_flag == 0) {
+		woal_mgmt_frame_register(priv, IEEE80211_STYPE_AUTH, MTRUE);
+		woal_mgmt_frame_register(priv, IEEE80211_STYPE_DEAUTH, MTRUE);
+		woal_mgmt_frame_register(priv, IEEE80211_STYPE_DISASSOC, MTRUE);
+	}
+#define HEADER_SIZE 8
+	// frmctl + durationid + addr1 + addr2 + addr3 + seqctl + addr4
+#define MGMT_HEADER_LEN (2 + 2 + 6 + 6 + 6 + 2 + 6)
+	// 6   = auth_alg + auth_transaction +auth_status
+#define AUTH_BODY_LEN 6
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+	packet_len = (t_u16)req->ie_len + req->auth_data_len + MGMT_HEADER_LEN +
+		AUTH_BODY_LEN;
+#else
+	packet_len = (t_u16)req->ie_len + req->sae_data_len + MGMT_HEADER_LEN +
+		AUTH_BODY_LEN;
+#endif
+	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
+				       MLAN_MIN_DATA_HEADER_LEN + HEADER_SIZE +
+				       packet_len + sizeof(packet_len));
+
+	if (!pmbuf) {
+		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0,
+				  KEY_INDEX_CLEAR_ALL, NULL, 1,
+				  MOAL_IOCTL_WAIT)) {
+		/* Disable keys and clear all previous security settings */
+		PRINTM(MERROR, "Fail to clear previous keys\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	switch (req->auth_type) {
+	case NL80211_AUTHTYPE_OPEN_SYSTEM:
+		auth_alg = WLAN_AUTH_OPEN;
+		break;
+	case NL80211_AUTHTYPE_SHARED_KEY:
+		auth_alg = WLAN_AUTH_SHARED_KEY;
+		break;
+	case NL80211_AUTHTYPE_FT:
+		auth_alg = WLAN_AUTH_FT;
+		break;
+	case NL80211_AUTHTYPE_NETWORK_EAP:
+		auth_alg = WLAN_AUTH_LEAP;
+		break;
+	case NL80211_AUTHTYPE_SAE:
+		auth_alg = WLAN_AUTH_SAE;
+		break;
+	default:
+		PRINTM(MERROR, "Unsupported auth type=%d\n", req->auth_type);
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	if (ret)
+		goto done;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_alg)) {
+		PRINTM(MERROR, "Fail to set auth mode\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (req->key &&
+	    ((auth_alg == WLAN_AUTH_OPEN) ||
+	     (auth_alg == WLAN_AUTH_SHARED_KEY))) {
+		PRINTM(MMSG, "Setting wep encryption with key len %d\n",
+		       req->key_len);
+		/* Set the WEP key */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_set_wep_keys(priv, req->key, req->key_len,
+					       req->key_idx, MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Fail to set wep key idx %d\n", req->key_idx);
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Enable the WEP key by key index */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_set_wep_keys(priv, NULL, 0, req->key_idx,
+					       MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Fail to enable wep key idx %d\n", req->key_idx);
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (priv->auth_flag == 0) {
+		if (woal_cfg80211_remain_on_channel_cfg
+		    (priv, MOAL_IOCTL_WAIT, MFALSE, (t_u8 *)&status,
+		     req->bss->channel, 0, AUTH_TX_DEFAULT_WAIT_TIME)) {
+			PRINTM(MERROR, "Fail to configure remain on channel\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (status == MLAN_STATUS_SUCCESS) {
+			priv->phandle->remain_on_channel = MTRUE;
+			moal_memcpy_ext(priv->phandle, &(priv->phandle->chan),
+					req->bss->channel,
+					sizeof(struct ieee80211_channel),
+					sizeof(priv->phandle->chan));
+		} else {
+			PRINTM(MERROR,
+			       "HostMlme %s: Set remain on Channel: with status=%d\n",
+			       dev->name, status);
+		}
+	}
+
+	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
+	pkt_type = MRVL_PKT_TYPE_MGMT_FRAME;
+	tx_control = 0;
+	/* Add pkt_type and tx_control */
+	moal_memcpy_ext(priv->phandle, pmbuf->pbuf + pmbuf->data_offset,
+			&pkt_type, sizeof(pkt_type), sizeof(pkt_type));
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+			&tx_control, sizeof(tx_control), sizeof(tx_control));
+
+	mgmt = (IEEE80211_MGMT *)(pmbuf->pbuf + pmbuf->data_offset +
+				  HEADER_SIZE + sizeof(packet_len));
+	memset(mgmt, 0, MGMT_HEADER_LEN);
+	/**Authentication Frame: Frame Control*/
+	mgmt->frame_control =
+		woal_cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
+	/**Authentication Frame: Destination Address*/
+	moal_memcpy_ext(priv->phandle, mgmt->da, req->bss->bssid, ETH_ALEN,
+			sizeof(mgmt->da));
+	/**Authentication Frame: Source Address*/
+	moal_memcpy_ext(priv->phandle, mgmt->sa, priv->current_addr, ETH_ALEN,
+			sizeof(mgmt->sa));
+	/**Authentication Frame: BSSID*/
+	moal_memcpy_ext(priv->phandle, mgmt->bssid, req->bss->bssid, ETH_ALEN,
+			sizeof(mgmt->bssid));
+	moal_memcpy_ext(priv->phandle, mgmt->addr4, addr, ETH_ALEN,
+			sizeof(mgmt->addr4));
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+	if (req->auth_data_len >= 4) {
+		if (req->auth_type == NL80211_AUTHTYPE_SAE) {
+			__le16 *pos = (__le16 *) req->auth_data;
+
+			trans = le16_to_cpu(pos[0]);
+			status_code = le16_to_cpu(pos[1]);
+		}
+		moal_memcpy_ext(priv->phandle, (t_u8 *)(&mgmt->u.auth.variable),
+				req->auth_data + 4, req->auth_data_len - 4,
+				req->auth_data_len - 4);
+		varptr = (t_u8 *)&mgmt->u.auth.variable +
+			(req->auth_data_len - 4);
+		packet_len -= 4;
+	}
+#else
+	if (req->sae_data_len >= 4) {
+		if (req->auth_type == NL80211_AUTHTYPE_SAE) {
+			__le16 *pos = (__le16 *) req->sae_data;
+
+			trans = le16_to_cpu(pos[0]);
+			status_code = le16_to_cpu(pos[1]);
+		}
+		moal_memcpy_ext(priv->phandle, (t_u8 *)(&mgmt->u.auth.variable),
+				req->sae_data + 4, req->sae_data_len - 4,
+				req->sae_data_len - 4);
+		varptr = (t_u8 *)&mgmt->u.auth.variable +
+			(req->sae_data_len - 4);
+		packet_len -= 4;
+	}
+#endif
+	/*Add packet len */
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE,
+			&packet_len, sizeof(packet_len), sizeof(packet_len));
+
+	/**Authentication Frame: Authentication Alg*/
+	mgmt->u.auth.auth_alg = woal_cpu_to_le16(auth_alg);
+	mgmt->u.auth.auth_transaction = trans;
+	/**Authentication Frame: Status code*/
+	mgmt->u.auth.status_code = status_code;
+
+	if (req->ie && req->ie_len) {
+		if (!varptr) {
+			varptr = (t_u8 *)&mgmt->u.auth.variable;
+		}
+		moal_memcpy_ext(priv->phandle, (t_u8 *)varptr, req->ie,
+				req->ie_len, req->ie_len);
+	}
+
+	pmbuf->data_len = HEADER_SIZE + packet_len + sizeof(packet_len);
+	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
+	pmbuf->bss_index = priv->bss_index;
+	pmbuf->priority = 7;
+
+	priv->host_mlme = MTRUE;
+	priv->auth_flag = HOST_MLME_AUTH_PENDING;
+	priv->auth_alg = woal_cpu_to_le16(auth_alg);
+
+	PRINTM(MMSG, "wlan: HostMlme %s send auth to bssid " MACSTR "\n",
+	       dev->name, MAC2STR(req->bss->bssid));
+	DBG_HEXDUMP(MDAT_D, "Auth:", pmbuf->pbuf + pmbuf->data_offset,
+		    pmbuf->data_len);
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_save_auth_params(priv, req);
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		priv->host_mlme = MFALSE;
+		priv->auth_flag = 0;
+		priv->auth_alg = 0xFFFF;
+		PRINTM(MERROR, "Fail to send packet status=%d\n", status);
+		ret = -EFAULT;
+		break;
+	}
+done:
+	if (ret) {
+		woal_mgmt_frame_register(priv, IEEE80211_STYPE_AUTH, MFALSE);
+		if (priv->phandle->remain_on_channel) {
+			woal_cfg80211_remain_on_channel_cfg(priv,
+							    MOAL_IOCTL_WAIT,
+							    MTRUE,
+							    (t_u8 *)&status,
+							    NULL, 0, 0);
+			priv->phandle->remain_on_channel = MFALSE;
+		}
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This workqueue function handles association response in host mlme
+ * case
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+void
+woal_host_mlme_work_queue(struct work_struct *work)
+{
+	moal_handle *handle = container_of(work, moal_handle, host_mlme_work);
+	moal_private *priv = (moal_private *)handle->host_mlme_priv;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	if (priv) {
+		if (priv->auth_flag & HOST_MLME_AUTH_DONE) {
+			priv->auth_flag = 0;
+			woal_mgmt_frame_register(priv, IEEE80211_STYPE_AUTH,
+						 MFALSE);
+
+			if (priv->phandle->remain_on_channel) {
+				woal_cfg80211_remain_on_channel_cfg(priv,
+								    MOAL_IOCTL_WAIT,
+								    MTRUE,
+								    (t_u8 *)
+								    &status,
+								    NULL, 0, 0);
+				priv->phandle->remain_on_channel = MFALSE;
+			}
+			PRINTM(MCMND, "wlan: HostMlme %s auth success\n",
+			       priv->netdev->name);
+		}
+	}
+}
+
+/**
+ *  @brief This workqueue function handles association response in event queue
+ * case
+ *
+ *  @param priv  	pointer to moal_private
+ *  @param assoc_rsp	pointer to mlan_ds_misc_assoc_rsp
+ *
+ *  @return        N/A
+ */
+void
+woal_host_mlme_process_assoc_resp(moal_private *priv,
+				  mlan_ds_misc_assoc_rsp *assoc_rsp)
+{
+	struct cfg80211_bss *bss = NULL;
+	unsigned long flags;
+
+	if (priv) {
+		if (priv->auth_flag & HOST_MLME_ASSOC_DONE) {
+			priv->auth_flag = 0;
+			bss = priv->assoc_bss;
+			if (!bss) {
+				PRINTM(MERROR,
+				       "HostMlme %s:assoc_bss is null\n",
+				       priv->netdev->name);
+				return;
+			}
+
+			if (assoc_rsp->assoc_resp_len) {
+				PRINTM(MCMND,
+				       "HostMlme: %s assoc_resp_len=%d, frame_control=0x%x\n",
+				       priv->netdev->name,
+				       assoc_rsp->assoc_resp_len,
+				       ((struct ieee80211_mgmt *)
+					assoc_rsp->assoc_resp_buf)
+				       ->frame_control);
+				if (ieee80211_is_assoc_resp(((struct
+							      ieee80211_mgmt *)
+							     assoc_rsp->
+							     assoc_resp_buf)
+							    ->frame_control) ||
+				    ieee80211_is_reassoc_resp(((struct
+								ieee80211_mgmt
+								*)
+							       assoc_rsp->
+							       assoc_resp_buf)
+							      ->frame_control)) {
+					spin_lock_irqsave(&priv->connect_lock,
+							  flags);
+					if (le16_to_cpu(((struct ieee80211_mgmt
+							  *)assoc_rsp->
+							 assoc_resp_buf)
+							->u.assoc_resp.
+							status_code) !=
+					    WLAN_STATUS_SUCCESS) {
+						memset(priv->cfg_bssid, 0,
+						       ETH_ALEN);
+						if (priv->bss_type ==
+						    MLAN_BSS_TYPE_STA)
+							woal_clear_conn_params
+								(priv);
+					} else {
+						priv->cfg_disconnect = MFALSE;
+					}
+					spin_unlock_irqrestore(&priv->
+							       connect_lock,
+							       flags);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
+					cfg80211_rx_assoc_resp(priv->netdev,
+							       bss,
+							       assoc_rsp->
+							       assoc_resp_buf,
+							       assoc_rsp->
+							       assoc_resp_len,
+							       -1, NULL, 0);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+					cfg80211_rx_assoc_resp(priv->netdev,
+							       bss,
+							       assoc_rsp->
+							       assoc_resp_buf,
+							       assoc_rsp->
+							       assoc_resp_len,
+							       -1);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+					cfg80211_rx_assoc_resp(priv->netdev,
+							       bss,
+							       assoc_rsp->
+							       assoc_resp_buf,
+							       assoc_rsp->
+							       assoc_resp_len);
+#else
+					cfg80211_send_rx_assoc(priv->netdev,
+							       bss,
+							       assoc_rsp->
+							       assoc_resp_buf,
+							       assoc_rsp->
+							       assoc_resp_len);
+#endif
+#endif
+#endif
+				}
+			}
+		}
+	}
+}
+
+/**
+ * @brief   Handle assoc response event
+ *
+ * @param priv          A pointer moal_private structure
+ * @param pchan_info    A pointer to mlan_ds_misc_assoc_rsp structure
+ *
+ * @return          N/A
+ */
+
+static void
+woal_assoc_resp_event(moal_private *priv, mlan_ds_misc_assoc_rsp *passoc_rsp)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (evt) {
+		evt->priv = priv;
+		evt->type = WOAL_EVENT_ASSOC_RESP;
+		moal_memcpy_ext(priv->phandle, &evt->assoc_resp, passoc_rsp,
+				sizeof(mlan_ds_misc_assoc_rsp),
+				sizeof(mlan_ds_misc_assoc_rsp));
+		INIT_LIST_HEAD(&evt->link);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+		list_add_tail(&evt->link, &handle->evt_queue);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		queue_work(handle->evt_workqueue, &handle->evt_work);
+	}
+}
+
+/**
+ *  @brief This function is association handler when host MLME
+ *          enable.
+ *          In this case driver will prepare and send Assoc Req.
+ *
+ *  @param wiphy       A pointer to wiphy.
+ *
+ *  @param dev         A pointer to net_device
+ *
+ *  @param req         A pointer to cfg80211_assoc_request
+ *
+ *  @return            0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_assoc_request *req)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+	mlan_ssid_bssid ssid_bssid;
+	unsigned long flags;
+	const u8 *ssid_ie;
+	int wpa_enabled = 0, group_enc_mode = 0, pairwise_enc_mode = 0;
+	mlan_bss_info bss_info;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (priv->auth_alg == WLAN_AUTH_SAE) {
+
+		priv->auth_flag = HOST_MLME_AUTH_DONE;
+
+		woal_mgmt_frame_register(priv, IEEE80211_STYPE_AUTH, MFALSE);
+		PRINTM(MINFO, "wlan: HostMlme %s auth exchange successful\n",
+		       priv->netdev->name);
+
+		if (priv->phandle->remain_on_channel) {
+			if (woal_cfg80211_remain_on_channel_cfg
+			    (priv, MOAL_IOCTL_WAIT, MTRUE, (t_u8 *)&status,
+			     NULL, 0, 0)) {
+				PRINTM(MERROR,
+				       "Failed to cancel remain on channel\n");
+				ret = -EFAULT;
+				goto done;
+			}
+			priv->phandle->remain_on_channel = MFALSE;
+		}
+	}
+
+	if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE)) {
+		LEAVE();
+		return -EBUSY;
+	}
+
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+	priv->cfg_connect = MTRUE;
+	priv->assoc_status = 0;
+	priv->auth_alg = 0xFFFF;
+
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	rcu_read_lock();
+	ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
+	moal_memcpy_ext(priv->phandle, ssid_bssid.bssid, req->bss->bssid,
+			ETH_ALEN, sizeof(ssid_bssid.bssid));
+
+	if (!ssid_ie) {
+		rcu_read_unlock();
+		ret = -EINVAL;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, ssid_bssid.ssid.ssid, ssid_ie + 2,
+			ssid_ie[1], sizeof(ssid_bssid.ssid.ssid));
+	ssid_bssid.ssid.ssid_len = ssid_ie[1];
+	rcu_read_unlock();
+
+	if (ssid_bssid.ssid.ssid_len > MW_ESSID_MAX_SIZE) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (!ssid_bssid.ssid.ssid_len || ssid_bssid.ssid.ssid[0] < 0x20) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+#ifdef STA_WEXT
+	if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
+		switch (req->crypto.wpa_versions) {
+		case NL80211_WPA_VERSION_2:
+			priv->wpa_version = IW_AUTH_WPA_VERSION_WPA2;
+			break;
+		case NL80211_WPA_VERSION_1:
+			priv->wpa_version = IW_AUTH_WPA_VERSION_WPA;
+			break;
+		default:
+			priv->wpa_version = 0;
+			break;
+		}
+		if (req->crypto.n_akm_suites) {
+			switch (req->crypto.akm_suites[0]) {
+			case WLAN_AKM_SUITE_PSK:
+				priv->key_mgmt = IW_AUTH_KEY_MGMT_PSK;
+				break;
+			case WLAN_AKM_SUITE_8021X:
+				priv->key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
+				break;
+			default:
+				priv->key_mgmt = 0;
+				break;
+			}
+		}
+	}
+#endif
+
+	if (req->ie && req->ie_len) {	/* Set the IE */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_assoc_ies_cfg(priv, (t_u8 *)req->ie,
+						req->ie_len, MOAL_IOCTL_WAIT)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (req->crypto.n_ciphers_pairwise) {
+		pairwise_enc_mode =
+			woal_cfg80211_get_encryption_mode(req->crypto.
+							  ciphers_pairwise[0],
+							  &wpa_enabled);
+		ret = woal_cfg80211_set_auth(priv, pairwise_enc_mode,
+					     wpa_enabled, MOAL_IOCTL_WAIT);
+		if (ret)
+			goto done;
+	}
+
+	if (req->crypto.cipher_group) {
+		group_enc_mode =
+			woal_cfg80211_get_encryption_mode(req->crypto.
+							  cipher_group,
+							  &wpa_enabled);
+		ret = woal_cfg80211_set_auth(priv, group_enc_mode, wpa_enabled,
+					     MOAL_IOCTL_WAIT);
+		if (ret)
+			goto done;
+	}
+	ssid_bssid.host_mlme = priv->host_mlme;
+
+	if (req->bss->channel) {
+		ssid_bssid.channel_flags = req->bss->channel->flags;
+		ssid_bssid.channel_flags |= CHAN_FLAGS_MAX;
+		PRINTM(MCMND, "channel flags=0x%x\n", req->bss->channel->flags);
+	}
+	if (req->prev_bssid) {
+		moal_memcpy_ext(priv->phandle, ssid_bssid.prev_bssid,
+				req->prev_bssid, ETH_ALEN,
+				sizeof(ssid_bssid.prev_bssid));
+
+	}
+
+	PRINTM(MCMND, "wlan: HostMlme %s send assoicate to bssid " MACSTR "\n",
+	       priv->netdev->name, MAC2STR(req->bss->bssid));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT_TIMEOUT, &ssid_bssid)) {
+		PRINTM(MERROR, "HostMlme %s: bss_start Fails\n",
+		       priv->netdev->name);
+		priv->host_mlme = MFALSE;
+		priv->auth_flag = 0;
+		ret = -EFAULT;
+	}
+
+done:
+
+	if (!ret) {
+		priv->rssi_low = DEFAULT_RSSI_LOW_THRESHOLD;
+		if (priv->bss_type == MLAN_BSS_TYPE_STA
+#ifdef WIFI_DIRECT_SUPPORT
+		    || priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+			)
+			woal_save_assoc_params(priv, req, &ssid_bssid);
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		priv->channel = bss_info.bss_chan;
+	}
+
+	spin_lock_irqsave(&priv->connect_lock, flags);
+	priv->cfg_connect = MFALSE;
+	if (!ret && priv->media_connected) {
+		PRINTM(MMSG,
+		       "wlan: HostMlme %s Connected to bssid " MACSTR
+		       " successfully\n",
+		       priv->netdev->name, MAC2STR(priv->cfg_bssid));
+		spin_unlock_irqrestore(&priv->connect_lock, flags);
+	} else {
+		PRINTM(MERROR,
+		       "wlan: HostMlme %s Failed to connect to bssid " MACSTR
+		       "\n", priv->netdev->name, MAC2STR(req->bss->bssid));
+		if (ssid_bssid.assoc_rsp.assoc_resp_len &&
+		    ssid_bssid.assoc_rsp.assoc_resp_len >
+		    sizeof(IEEEtypes_MgmtHdr_t)) {
+			// save the connection param when send assoc_resp to
+			// kernel
+			woal_save_assoc_params(priv, req, &ssid_bssid);
+			ret = 0;
+		} else {
+			ssid_bssid.assoc_rsp.assoc_resp_len = 0;
+			ret = -EFAULT;
+			memset(priv->cfg_bssid, 0, ETH_ALEN);
+			if (priv->bss_type == MLAN_BSS_TYPE_STA)
+				woal_clear_conn_params(priv);
+		}
+		priv->host_mlme = MFALSE;
+		priv->auth_flag = 0;
+		spin_unlock_irqrestore(&priv->connect_lock, flags);
+	}
+	/*Association Response should also be send when ret is non-zero.
+	   We also need to return success when we have association response
+	   available */
+	if (ssid_bssid.assoc_rsp.assoc_resp_len) {
+		priv->auth_flag |= HOST_MLME_ASSOC_DONE;
+		woal_assoc_resp_event(priv, &ssid_bssid.assoc_rsp);
+	}
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Request the driver for (re)association
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param sme             A pointer to connect parameters
+ * @param wait_option     wait option
+ * @param assoc_resp      A pointer to assoc_rsp structure;
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_assoc(moal_private *priv, void *sme, t_u8 wait_option,
+		    mlan_ds_misc_assoc_rsp *assoc_rsp)
+{
+	struct cfg80211_ibss_params *ibss_param = NULL;
+	struct cfg80211_connect_params *conn_param = NULL;
+	mlan_802_11_ssid req_ssid;
+	mlan_ssid_bssid ssid_bssid;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	t_u32 auth_type = 0, mode;
+	int wpa_enabled = 0;
+	int group_enc_mode = 0, pairwise_enc_mode = 0;
+	int alg_is_wep = 0;
+
+	t_u8 *ssid, ssid_len = 0, *bssid;
+	t_u8 *ie = NULL;
+	int ie_len = 0;
+	struct ieee80211_channel *channel = NULL;
+	t_u16 beacon_interval = 0;
+	bool privacy;
+	struct cfg80211_bss *pub = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!sme) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	mode = woal_nl80211_iftype_to_mode(priv->wdev->iftype);
+
+	if (mode == MLAN_BSS_MODE_IBSS) {
+		ibss_param = (struct cfg80211_ibss_params *)sme;
+		ssid = (t_u8 *)ibss_param->ssid;
+		ssid_len = ibss_param->ssid_len;
+		bssid = (t_u8 *)ibss_param->bssid;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+		channel = ibss_param->channel;
+#else
+		channel = ibss_param->chandef.chan;
+#endif
+		if (channel)
+			priv->phandle->band = channel->band;
+		if (ibss_param->ie_len)
+			ie = (t_u8 *)ibss_param->ie;
+		ie_len = ibss_param->ie_len;
+		beacon_interval = ibss_param->beacon_interval;
+		privacy = ibss_param->privacy;
+
+	} else {
+		conn_param = (struct cfg80211_connect_params *)sme;
+		ssid = (t_u8 *)conn_param->ssid;
+		ssid_len = conn_param->ssid_len;
+		bssid = (t_u8 *)conn_param->bssid;
+		channel = conn_param->channel;
+		if (channel)
+			priv->phandle->band = channel->band;
+		if (conn_param->ie_len)
+			ie = (t_u8 *)conn_param->ie;
+		ie_len = conn_param->ie_len;
+		privacy = conn_param->privacy;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+		pub = cfg80211_get_bss(priv->wdev->wiphy, channel,
+				       bssid, ssid, ssid_len,
+				       IEEE80211_BSS_TYPE_ESS,
+				       IEEE80211_PRIVACY_ANY);
+#else
+		pub = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid,
+				       ssid_len, WLAN_CAPABILITY_ESS,
+				       WLAN_CAPABILITY_ESS);
+#endif
+		if (pub) {
+			if ((!priv->phandle->params.reg_alpha2 ||
+			     strncmp(priv->phandle->params.reg_alpha2,
+				     "99", strlen("99")))
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			    &&
+			    (!moal_extflg_isset(priv->phandle,
+						EXT_COUNTRY_IE_IGNORE))
+#endif
+				)
+				woal_process_country_ie(priv, pub);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+			cfg80211_put_bss(priv->wdev->wiphy, pub);
+#else
+			cfg80211_put_bss(pub);
+#endif
+		} else
+			woal_send_domain_info_cmd_fw(priv, wait_option);
+#ifdef STA_WEXT
+		if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
+			switch (conn_param->crypto.wpa_versions) {
+			case NL80211_WPA_VERSION_2:
+				priv->wpa_version = IW_AUTH_WPA_VERSION_WPA2;
+				break;
+			case NL80211_WPA_VERSION_1:
+				priv->wpa_version = IW_AUTH_WPA_VERSION_WPA;
+				break;
+			default:
+				priv->wpa_version = 0;
+				break;
+			}
+			if (conn_param->crypto.n_akm_suites) {
+				switch (conn_param->crypto.akm_suites[0]) {
+				case WLAN_AKM_SUITE_PSK:
+					priv->key_mgmt = IW_AUTH_KEY_MGMT_PSK;
+					break;
+				case WLAN_AKM_SUITE_8021X:
+					priv->key_mgmt =
+						IW_AUTH_KEY_MGMT_802_1X;
+					break;
+				default:
+					priv->key_mgmt = 0;
+					break;
+				}
+			}
+		}
+#endif
+	}
+
+	memset(&req_ssid, 0, sizeof(mlan_802_11_ssid));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+	req_ssid.ssid_len = ssid_len;
+	if (ssid_len > MW_ESSID_MAX_SIZE) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, req_ssid.ssid, ssid, ssid_len,
+			sizeof(req_ssid.ssid));
+	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
+		PRINTM(MERROR, "Invalid SSID - aborting\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (priv->phandle->card_info->embedded_supp)
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_ewpa_mode(priv, wait_option, &ssid_bssid)) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0,
+				  KEY_INDEX_CLEAR_ALL, NULL, 1, wait_option)) {
+		/* Disable keys and clear all previous security settings */
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef STA_CFG80211
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext)) {
+		/** Check if current roaming support OKC offload roaming */
+		if (conn_param && conn_param->crypto.n_akm_suites &&
+		    conn_param->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X) {
+			if (priv->okc_roaming_ie && priv->okc_ie_len) {
+				ie = priv->okc_roaming_ie;
+				ie_len = priv->okc_ie_len;
+			}
+		}
+	}
+#endif
+
+	if ((priv->ft_pre_connect ||
+	     (conn_param && conn_param->auth_type == NL80211_AUTHTYPE_FT)) &&
+	    priv->ft_ie_len) {
+		ie = priv->ft_ie;
+		ie_len = priv->ft_ie_len;
+		priv->ft_ie_len = 0;
+	}
+	if (ie && ie_len) {	/* Set the IE */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_assoc_ies_cfg(priv, ie, ie_len,
+						wait_option)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (conn_param && mode != MLAN_BSS_MODE_IBSS) {
+		/* These parameters are only for managed mode */
+		if (conn_param->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
+			auth_type = MLAN_AUTH_MODE_OPEN;
+		else if (conn_param->auth_type == NL80211_AUTHTYPE_SHARED_KEY)
+			auth_type = MLAN_AUTH_MODE_SHARED;
+		else if (conn_param->auth_type == NL80211_AUTHTYPE_NETWORK_EAP)
+			auth_type = MLAN_AUTH_MODE_NETWORKEAP;
+		else if (conn_param->auth_type == NL80211_AUTHTYPE_FT)
+			auth_type = MLAN_AUTH_MODE_FT;
+		else
+			auth_type = MLAN_AUTH_MODE_AUTO;
+		if (priv->ft_pre_connect)
+			auth_type = MLAN_AUTH_MODE_FT;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_auth_mode(priv, wait_option, auth_type)) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		if (conn_param->crypto.n_ciphers_pairwise) {
+			pairwise_enc_mode =
+				woal_cfg80211_get_encryption_mode(conn_param->
+								  crypto.
+								  ciphers_pairwise
+								  [0],
+								  &wpa_enabled);
+			ret = woal_cfg80211_set_auth(priv, pairwise_enc_mode,
+						     wpa_enabled, wait_option);
+			if (ret)
+				goto done;
+		}
+
+		if (conn_param->crypto.cipher_group) {
+			group_enc_mode =
+				woal_cfg80211_get_encryption_mode(conn_param->
+								  crypto.
+								  cipher_group,
+								  &wpa_enabled);
+			ret = woal_cfg80211_set_auth(priv, group_enc_mode,
+						     wpa_enabled, wait_option);
+			if (ret)
+				goto done;
+		}
+
+		if (conn_param->key) {
+			alg_is_wep =
+				woal_cfg80211_is_alg_wep(pairwise_enc_mode) |
+				woal_cfg80211_is_alg_wep(group_enc_mode);
+			if (alg_is_wep) {
+				PRINTM(MINFO,
+				       "Setting wep encryption with key len %d\n",
+				       conn_param->key_len);
+				/* Set the WEP key */
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_cfg80211_set_wep_keys(priv,
+							       conn_param->key,
+							       conn_param->
+							       key_len,
+							       conn_param->
+							       key_idx,
+							       wait_option)) {
+					ret = -EFAULT;
+					goto done;
+				}
+				/* Enable the WEP key by key index */
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_cfg80211_set_wep_keys(priv, NULL, 0,
+							       conn_param->
+							       key_idx,
+							       wait_option)) {
+					ret = -EFAULT;
+					goto done;
+				}
+			}
+		}
+	}
+
+	if (mode == MLAN_BSS_MODE_IBSS) {
+		mlan_ds_bss *bss = NULL;
+		/* Change beacon interval */
+		if ((beacon_interval < MLAN_MIN_BEACON_INTERVAL) ||
+		    (beacon_interval > MLAN_MAX_BEACON_INTERVAL)) {
+			ret = -EINVAL;
+			goto done;
+		}
+		kfree(req);
+		req = NULL;
+
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+		if (req == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		bss = (mlan_ds_bss *)req->pbuf;
+		req->req_id = MLAN_IOCTL_BSS;
+		req->action = MLAN_ACT_SET;
+		bss->sub_command = MLAN_OID_IBSS_BCN_INTERVAL;
+		bss->param.bcn_interval = beacon_interval;
+		status = woal_request_ioctl(priv, req, wait_option);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		/* "privacy" is set only for ad-hoc mode */
+		if (privacy) {
+			/*
+			 * Keep MLAN_ENCRYPTION_MODE_WEP40 for now so that
+			 * the firmware can find a matching network from the
+			 * scan. cfg80211 does not give us the encryption
+			 * mode at this stage so just setting it to wep here
+			 */
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_auth_mode(priv, wait_option,
+					       MLAN_AUTH_MODE_OPEN)) {
+				ret = -EFAULT;
+				goto done;
+			}
+
+			wpa_enabled = 0;
+			ret = woal_cfg80211_set_auth(priv,
+						     MLAN_ENCRYPTION_MODE_WEP104,
+						     wpa_enabled, wait_option);
+			if (ret)
+				goto done;
+		}
+	}
+	moal_memcpy_ext(priv->phandle, &ssid_bssid.ssid, &req_ssid,
+			sizeof(mlan_802_11_ssid), sizeof(ssid_bssid.ssid));
+	if (bssid)
+		moal_memcpy_ext(priv->phandle, &ssid_bssid.bssid, bssid,
+				ETH_ALEN, sizeof(ssid_bssid.bssid));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_find_essid(priv, &ssid_bssid, wait_option)) {
+		/* Do specific SSID scanning */
+		if (mode != MLAN_BSS_MODE_IBSS)
+			ret = woal_cfg80211_connect_scan(priv, conn_param,
+							 wait_option);
+		else
+			ret = woal_request_scan(priv, wait_option, &req_ssid);
+		if (ret) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	/* Disconnect before try to associate */
+	if (mode == MLAN_BSS_MODE_IBSS)
+		woal_disconnect(priv, wait_option, NULL,
+				DEF_DEAUTH_REASON_CODE);
+
+	if (mode != MLAN_BSS_MODE_IBSS) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_find_best_network(priv, wait_option, &ssid_bssid)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Inform the BSS information to kernel, otherwise
+		 * kernel will give a panic after successful assoc */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_inform_bss_from_scan_result(priv, &ssid_bssid,
+						     wait_option)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (MLAN_STATUS_SUCCESS !=
+		   woal_find_best_network(priv, wait_option, &ssid_bssid))
+		/* Adhoc start, Check the channel command */
+		woal_11h_channel_check_ioctl(priv, wait_option);
+
+	PRINTM(MINFO, "Trying to associate to %s and bssid " MACSTR "\n",
+	       (char *)req_ssid.ssid, MAC2STR(ssid_bssid.bssid));
+
+	/* Zero SSID implies use BSSID to connect */
+	if (bssid)
+		memset(&ssid_bssid.ssid, 0, sizeof(mlan_802_11_ssid));
+	else			/* Connect to BSS by ESSID */
+		memset(&ssid_bssid.bssid, 0, MLAN_MAC_ADDR_LENGTH);
+	if (channel) {
+		ssid_bssid.channel_flags = channel->flags;
+		ssid_bssid.channel_flags |= CHAN_FLAGS_MAX;
+		PRINTM(MCMND, "channel flags=0x%x\n", channel->flags);
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+	if (conn_param && conn_param->prev_bssid) {
+		moal_memcpy_ext(priv->phandle, ssid_bssid.prev_bssid,
+				conn_param->prev_bssid, ETH_ALEN,
+				sizeof(ssid_bssid.prev_bssid));
+
+	}
+#endif
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT_TIMEOUT, &ssid_bssid)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Inform the IBSS information to kernel, otherwise
+	 * kernel will give a panic after successful assoc */
+	if (mode == MLAN_BSS_MODE_IBSS) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_inform_ibss_bss(priv, channel,
+						  beacon_interval)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (assoc_rsp) {
+		moal_memcpy_ext(priv->phandle, assoc_rsp, &ssid_bssid.assoc_rsp,
+				sizeof(mlan_ds_misc_assoc_rsp),
+				sizeof(mlan_ds_misc_assoc_rsp));
+		PRINTM(MCMND, "assoc_rsp ie len=%d\n",
+		       assoc_rsp->assoc_resp_len);
+	}
+done:
+	if (ret) {
+		/* clear the encryption mode */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_set_auth(priv, MLAN_ENCRYPTION_MODE_NONE,
+					   MFALSE, wait_option)) {
+			PRINTM(MERROR, "Could not clear encryption \n");
+			ret = -EFAULT;
+		}
+		/* clear IE */
+		ie_len = 0;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_gen_ie(priv, MLAN_ACT_SET, NULL, &ie_len,
+					wait_option)) {
+			PRINTM(MERROR, "Could not clear RSN IE\n");
+			ret = -EFAULT;
+		}
+	}
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to fill the tx/rx rate info
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param sinfo           A pointer to station_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static void
+woal_cfg80211_fill_rate_info(moal_private *priv, struct station_info *sinfo)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_rate *rate = NULL;
+	t_u16 Rates[12] = { 0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12,
+		0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+	};
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	rate = (mlan_ds_rate *)req->pbuf;
+	rate->sub_command = MLAN_OID_GET_DATA_RATE;
+	req->req_id = MLAN_IOCTL_RATE;
+	req->action = MLAN_ACT_GET;
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (rate->param.data_rate.tx_rate_format != MLAN_RATE_FORMAT_LG) {
+		if (rate->param.data_rate.tx_rate_format == MLAN_RATE_FORMAT_HT) {
+			sinfo->txrate.flags = RATE_INFO_FLAGS_MCS;
+			if (rate->param.data_rate.tx_ht_bw == MLAN_HT_BW40)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+				sinfo->txrate.bw = RATE_INFO_BW_40;
+#else
+				sinfo->txrate.flags |=
+					RATE_INFO_FLAGS_40_MHZ_WIDTH;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+			else
+				sinfo->txrate.bw = RATE_INFO_BW_20;
+#endif
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		else if (rate->param.data_rate.tx_rate_format ==
+			 MLAN_RATE_FORMAT_VHT) {
+			sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
+			sinfo->txrate.nss = rate->param.data_rate.tx_nss + 1;
+			if (rate->param.data_rate.tx_ht_bw == MLAN_VHT_BW80)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+				sinfo->txrate.bw = RATE_INFO_BW_80;
+#else
+				sinfo->txrate.flags |=
+					RATE_INFO_FLAGS_80_MHZ_WIDTH;
+#endif
+			else if (rate->param.data_rate.tx_ht_bw == MLAN_HT_BW40)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+				sinfo->txrate.bw = RATE_INFO_BW_40;
+#else
+				sinfo->txrate.flags |=
+					RATE_INFO_FLAGS_40_MHZ_WIDTH;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+			else
+				sinfo->txrate.bw = RATE_INFO_BW_20;
+#endif
+		}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 1, 18)
+		else if (rate->param.data_rate.tx_rate_format ==
+			 MLAN_RATE_FORMAT_HE) {
+			sinfo->txrate.flags = RATE_INFO_FLAGS_HE_MCS;
+			sinfo->txrate.nss = rate->param.data_rate.tx_nss + 1;
+			sinfo->txrate.mcs = rate->param.data_rate.tx_mcs_index;
+			sinfo->txrate.he_gi = rate->param.data_rate.tx_ht_gi;
+			if (rate->param.data_rate.tx_ht_bw == MLAN_VHT_BW80)
+				sinfo->txrate.bw = RATE_INFO_BW_80;
+			else if (rate->param.data_rate.tx_ht_bw == MLAN_HT_BW40)
+				sinfo->txrate.bw = RATE_INFO_BW_40;
+			else
+				sinfo->txrate.bw = RATE_INFO_BW_20;
+		}
+#endif
+		if (rate->param.data_rate.tx_ht_gi == MLAN_HT_SGI)
+			sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+		sinfo->txrate.mcs = rate->param.data_rate.tx_mcs_index;
+	} else {
+		/* Bit rate is in 500 kb/s units. Convert it to 100kb/s units */
+		sinfo->txrate.legacy =
+			Rates[rate->param.data_rate.tx_data_rate] * 5;
+	}
+	//Fill Rx rate
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	if (rate->param.data_rate.rx_rate_format != MLAN_RATE_FORMAT_LG) {
+		if (rate->param.data_rate.rx_rate_format == MLAN_RATE_FORMAT_HT) {
+			sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS;
+			if (rate->param.data_rate.rx_ht_bw == MLAN_HT_BW40)
+				sinfo->rxrate.bw = RATE_INFO_BW_40;
+			else
+				sinfo->rxrate.bw = RATE_INFO_BW_20;
+		} else if (rate->param.data_rate.rx_rate_format ==
+			   MLAN_RATE_FORMAT_VHT) {
+			sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS;
+			sinfo->rxrate.nss = rate->param.data_rate.rx_nss + 1;
+			if (rate->param.data_rate.rx_ht_bw == MLAN_VHT_BW80)
+				sinfo->rxrate.bw = RATE_INFO_BW_80;
+			else if (rate->param.data_rate.rx_ht_bw == MLAN_HT_BW40)
+				sinfo->rxrate.bw = RATE_INFO_BW_40;
+			else
+				sinfo->rxrate.bw = RATE_INFO_BW_20;
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 1, 18)
+		else if (rate->param.data_rate.rx_rate_format ==
+			 MLAN_RATE_FORMAT_HE) {
+			sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS;
+			sinfo->rxrate.nss = rate->param.data_rate.rx_nss + 1;
+			sinfo->rxrate.mcs = rate->param.data_rate.rx_mcs_index;
+			sinfo->rxrate.he_gi = rate->param.data_rate.rx_ht_gi;
+			if (rate->param.data_rate.rx_ht_bw == MLAN_VHT_BW80)
+				sinfo->rxrate.bw = RATE_INFO_BW_80;
+			else if (rate->param.data_rate.rx_ht_bw == MLAN_HT_BW40)
+				sinfo->rxrate.bw = RATE_INFO_BW_40;
+			else
+				sinfo->rxrate.bw = RATE_INFO_BW_20;
+		}
+#endif
+		if (rate->param.data_rate.rx_ht_gi == MLAN_HT_SGI)
+			sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+		sinfo->rxrate.mcs = rate->param.data_rate.rx_mcs_index;
+	} else {
+		/* Bit rate is in 500 kb/s units. Convert it to 100kb/s units */
+		sinfo->rxrate.legacy =
+			Rates[rate->param.data_rate.rx_data_rate] * 5;
+	}
+#endif
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Request the driver to dump the station information
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param sinfo           A pointer to station_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static mlan_status
+woal_cfg80211_dump_station_info(moal_private *priv, struct station_info *sinfo)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_signal signal;
+	mlan_ds_get_stats stats;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	mlan_bss_info bss_info;
+	t_u8 dtim_period = 0;
+#endif
+
+	ENTER();
+
+	if (priv->phandle->scan_pending_on_block) {
+		if (priv->sinfo)
+			moal_memcpy_ext(priv->phandle, sinfo, priv->sinfo,
+					sizeof(struct station_info),
+					sizeof(struct station_info));
+		LEAVE();
+		return ret;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled = MBIT(NL80211_STA_INFO_RX_BYTES) |
+		MBIT(NL80211_STA_INFO_TX_BYTES) |
+		MBIT(NL80211_STA_INFO_RX_PACKETS) |
+		MBIT(NL80211_STA_INFO_TX_PACKETS) |
+		MBIT(NL80211_STA_INFO_SIGNAL) |
+		MBIT(NL80211_STA_INFO_TX_BITRATE) |
+		MBIT(NL80211_STA_INFO_RX_BITRATE);
+#else
+	sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES |
+		STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS |
+		STATION_INFO_SIGNAL | STATION_INFO_TX_BITRATE;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled |= MBIT(NL80211_STA_INFO_TX_FAILED);
+#else
+	sinfo->filled |= STATION_INFO_TX_FAILED;
+#endif
+#endif
+
+	/* Get signal information from the firmware */
+	memset(&signal, 0, sizeof(mlan_ds_get_signal));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_signal_info(priv, MOAL_IOCTL_WAIT, &signal)) {
+		PRINTM(MERROR, "Error getting signal information\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Get stats information from the firmware */
+	memset(&stats, 0, sizeof(mlan_ds_get_stats));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, &stats)) {
+		PRINTM(MERROR, "Error getting stats information\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	sinfo->rx_bytes = priv->stats.rx_bytes;
+	sinfo->tx_bytes = priv->stats.tx_bytes;
+	sinfo->rx_packets = priv->stats.rx_packets;
+	sinfo->tx_packets = priv->stats.tx_packets;
+	sinfo->signal = signal.bcn_rssi_avg;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+	sinfo->tx_failed = stats.failed;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	/* Update BSS information */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled |= MBIT(NL80211_STA_INFO_BSS_PARAM);
+#else
+	sinfo->filled |= STATION_INFO_BSS_PARAM;
+#endif
+	sinfo->bss_param.flags = 0;
+	ret = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (ret)
+		goto done;
+	if (bss_info.capability_info & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+	if (bss_info.capability_info & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+	sinfo->bss_param.beacon_interval = bss_info.beacon_interval;
+	/* Get DTIM period */
+	ret = woal_set_get_dtim_period(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
+				       &dtim_period);
+	if (ret) {
+		PRINTM(MERROR, "Get DTIM period failed\n");
+		goto done;
+	}
+	sinfo->bss_param.dtim_period = dtim_period;
+#endif
+	woal_cfg80211_fill_rate_info(priv, sinfo);
+	if (priv->sinfo)
+		moal_memcpy_ext(priv->phandle, priv->sinfo, sinfo,
+				sizeof(struct station_info),
+				sizeof(struct station_info));
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+				Global Functions
+********************************************************/
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+/**
+ * @brief Set all radar channel's dfs_state
+ *
+ * @param wiphy           A pointer to wiphy structure
+ *
+ * @return                N/A
+ */
+void
+woal_update_radar_chans_dfs_state(struct wiphy *wiphy)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	int i;
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		sband = wiphy->bands[band];
+		if (!sband)
+			continue;
+		for (i = 0; i < sband->n_channels; i++) {
+			if (sband->channels[i].flags & IEEE80211_CHAN_RADAR) {
+				if (moal_extflg_isset(handle, EXT_DFS_OFFLOAD))
+					sband->channels[i].dfs_state =
+						NL80211_DFS_AVAILABLE;
+				else
+					sband->channels[i].dfs_state =
+						NL80211_DFS_USABLE;
+			}
+		}
+	}
+	PRINTM(MCMND, "Set radar dfs_state: dfs_offload=%d\n",
+	       moal_extflg_isset(handle, EXT_DFS_OFFLOAD));
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+
+/**
+ *  @brief This function will be used by sort, to compare LHS & RHS
+ *
+ *  @param lhs              LHS value
+ *  @param rhs              RHS value
+ *  @return                 0
+ */
+static int
+compare(const void *lhs, const void *rhs)
+{
+	const chan_freq_power_t *lhs_cfp = (const chan_freq_power_t *)(lhs);
+	const chan_freq_power_t *rhs_cfp = (const chan_freq_power_t *)(rhs);
+
+	if (lhs_cfp->channel < rhs_cfp->channel)
+		return -1;
+	if (lhs_cfp->channel > rhs_cfp->channel)
+		return 1;
+
+	return 0;
+}
+
+/**
+ *  @brief This function get channel reg_rule flags
+ *
+ *  @param buf              Buffer containing channel region config
+ *  @param num_chan         Length of buffer
+ *  @param regd             ieee80211_regdomain to be updated
+ *
+ *  @return                 N/A
+ */
+t_u32
+woal_get_chan_rule_flags(mlan_ds_custom_reg_domain * custom_reg, t_u8 channel)
+{
+	t_u16 num_chan = 0;
+	t_u32 flags = 0;
+	int idx;
+	t_u16 chflags;
+
+	num_chan = custom_reg->num_bg_chan;
+	num_chan += custom_reg->num_a_chan;
+	for (idx = 0; idx < num_chan; idx++) {
+		chflags = custom_reg->cfp_tbl[idx].dynamic.flags;
+		if (chflags & NXP_CHANNEL_DISABLED)
+			continue;
+		if (custom_reg->cfp_tbl[idx].channel == channel) {
+			if (chflags & NXP_CHANNEL_PASSIVE)
+				flags |= NL80211_RRF_NO_IR;
+			if (chflags & NXP_CHANNEL_DFS)
+				flags |= NL80211_RRF_DFS;
+			if (chflags & NXP_CHANNEL_NO_OFDM)
+				flags |= NL80211_RRF_NO_OFDM;
+			break;
+		}
+	}
+	return flags;
+}
+
+/**
+ *  @brief This function update the beaconng flags of channel
+ *
+ *  @param custom_reg       pointer to mlan_ds_custom_reg_domain
+ *
+ *  @return                 pointer to ieee80211_regdomain
+ */
+
+static void
+woal_reg_apply_beaconing_flags(struct wiphy *wiphy,
+			       mlan_ds_custom_reg_domain * custom_reg)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int band, i;
+	t_u32 rule_flags = 0;
+
+	for (band = 0; band < NUM_NL80211_BANDS; band++) {
+		sband = wiphy->bands[band];
+		if (!sband)
+			continue;
+
+		for (i = 0; i < sband->n_channels; i++) {
+			ch = &sband->channels[i];
+
+			if (ch->flags &
+			    (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
+				continue;
+
+			rule_flags =
+				woal_get_chan_rule_flags(custom_reg,
+							 ch->hw_value);
+
+			if (!(rule_flags & NL80211_RRF_NO_IR))
+				ch->flags &= ~IEEE80211_CHAN_NO_IR;
+		}
+	}
+}
+
+/**
+ *  @brief This function create the custom regdomain
+ *
+ *  @param custom_reg       pointer to mlan_ds_custom_reg_domain
+ *
+ *  @return                 pointer to ieee80211_regdomain
+ */
+static struct ieee80211_regdomain *
+create_custom_regdomain(mlan_ds_custom_reg_domain * custom_reg)
+{
+	struct ieee80211_reg_rule *rule;
+	bool new_rule;
+	int idx, freq, prev_freq = 0;
+	t_u8 chan;
+	t_u16 num_chan = 0;
+	t_u32 bw, prev_bw = 0;
+	t_u16 chflags, prev_chflags = 0, valid_rules = 0;
+	struct ieee80211_regdomain *regd = NULL;
+	int regd_size;
+	const struct ieee80211_freq_range *freq_range = NULL;
+
+	num_chan = custom_reg->num_bg_chan;
+	num_chan += custom_reg->num_a_chan;
+
+	sort(&custom_reg->cfp_tbl[custom_reg->num_bg_chan],
+	     custom_reg->num_a_chan, sizeof(chan_freq_power_t), &compare, NULL);
+
+	regd_size = sizeof(struct ieee80211_regdomain) +
+		num_chan * sizeof(struct ieee80211_reg_rule);
+
+	regd = kzalloc(regd_size, GFP_KERNEL);
+	if (!regd) {
+		return NULL;
+	}
+	for (idx = 0; idx < num_chan; idx++) {
+		enum ieee80211_band band;
+
+		chan = custom_reg->cfp_tbl[idx].channel;
+		if (!chan) {
+			if (regd)
+				kfree(regd);
+			return NULL;
+		}
+		chflags = custom_reg->cfp_tbl[idx].dynamic.flags;
+		band = (chan <= 14) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+		freq = ieee80211_channel_to_frequency(chan, band);
+		PRINTM(MINFO, "chan=%d freq=%d chan_flag=0x%x\n", chan, freq,
+		       chflags);
+		new_rule = false;
+
+		if (chflags & NXP_CHANNEL_DISABLED)
+			continue;
+
+		if (band == IEEE80211_BAND_5GHZ) {
+			if (!(chflags & NXP_CHANNEL_NOHT80))
+				bw = MHZ_TO_KHZ(80);
+			else if (!(chflags & NXP_CHANNEL_NOHT40))
+				bw = MHZ_TO_KHZ(40);
+			else
+				bw = MHZ_TO_KHZ(20);
+		} else {
+			if (!(chflags & NXP_CHANNEL_NOHT40))
+				bw = MHZ_TO_KHZ(40);
+			else
+				bw = MHZ_TO_KHZ(20);
+		}
+
+		if (idx == 0 || prev_chflags != chflags || prev_bw != bw ||
+		    freq - prev_freq > 20) {
+			valid_rules++;
+			new_rule = true;
+		}
+
+		rule = &regd->reg_rules[valid_rules - 1];
+
+		rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10);
+
+		prev_chflags = chflags;
+		prev_freq = freq;
+		prev_bw = bw;
+
+		if (!new_rule)
+			continue;
+
+		rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10);
+		rule->power_rule.max_eirp = DBM_TO_MBM(19);
+		rule->flags = 0;
+
+		if (chflags & NXP_CHANNEL_PASSIVE)
+			rule->flags |= NL80211_RRF_NO_IR;
+		if (chflags & NXP_CHANNEL_DFS)
+			rule->flags |= NL80211_RRF_DFS;
+		if (chflags & NXP_CHANNEL_NO_OFDM)
+			rule->flags |= NL80211_RRF_NO_OFDM;
+		rule->freq_range.max_bandwidth_khz = bw;
+	}
+
+	regd->n_reg_rules = valid_rules;
+
+	if (custom_reg->region.country_code[0] == 'W' &&
+	    custom_reg->region.country_code[1] == 'W') {
+		regd->alpha2[0] = '0';
+		regd->alpha2[1] = '0';
+	} else {
+		/* set alpha2 from FW. */
+		regd->alpha2[0] = custom_reg->region.country_code[0];
+		regd->alpha2[1] = custom_reg->region.country_code[1];
+	}
+
+	switch (custom_reg->region.dfs_region) {
+	case 1:
+		regd->dfs_region = NL80211_DFS_FCC;
+		break;
+	case 2:
+		regd->dfs_region = NL80211_DFS_ETSI;
+		break;
+	case 3:
+		regd->dfs_region = NL80211_DFS_JP;
+		break;
+	default:
+		regd->dfs_region = NL80211_DFS_UNSET;
+		break;
+	}
+
+	PRINTM(MCMND, "create_custom_regdomain: %c%c rules=%d dfs_region=%d\n",
+	       regd->alpha2[0], regd->alpha2[1], valid_rules, regd->dfs_region);
+	for (idx = 0; idx < (int)regd->n_reg_rules; idx++) {
+		rule = &regd->reg_rules[idx];
+		freq_range = &rule->freq_range;
+		PRINTM(MCMND,
+		       "flags=0x%x star_freq=%d end_freq=%d freq_diff=%d max_bandwidth=%d\n",
+		       rule->flags, freq_range->start_freq_khz,
+		       freq_range->end_freq_khz,
+		       freq_range->end_freq_khz - freq_range->start_freq_khz,
+		       freq_range->max_bandwidth_khz);
+	}
+	if (!regd->n_reg_rules) {
+		kfree(regd);
+		regd = NULL;
+	}
+	return regd;
+}
+
+/**
+ *  @brief create custom channel regulatory config
+ *
+ *  @param priv         A pointer to moal_private structure
+ *
+ *  @return		        0-success, otherwise failure
+ */
+static int
+woal_update_custom_regdomain(moal_private *priv, struct wiphy *wiphy)
+{
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u8 country_code[COUNTRY_CODE_LEN];
+
+	int ret = 0;
+	struct ieee80211_regdomain *regd = NULL;
+
+	ENTER();
+
+	if (!priv || !wiphy) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -EFAULT;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GET_CHAN_REGION_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+	memset(&misc->param.custom_reg_domain, 0,
+	       sizeof(misc->param.custom_reg_domain));
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(country_code, 0, sizeof(country_code));
+	if (MTRUE ==
+	    is_cfg80211_special_region_code(priv->phandle->country_code)) {
+		country_code[0] = 'W';
+		country_code[1] = 'W';
+	} else {
+		country_code[0] = priv->phandle->country_code[0];
+		country_code[1] = priv->phandle->country_code[1];
+	}
+	if (misc->param.custom_reg_domain.region.country_code[0] == '\0'
+	    || misc->param.custom_reg_domain.region.country_code[1] == '\0') {
+		PRINTM(MCMND, "FW country code not valid\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (misc->param.custom_reg_domain.region.country_code[0] !=
+	    country_code[0] ||
+	    misc->param.custom_reg_domain.region.country_code[1] !=
+	    country_code[1]) {
+		PRINTM(MCMND, "FW country code %c%c not match %c%c\n",
+		       misc->param.custom_reg_domain.region.country_code[0],
+		       misc->param.custom_reg_domain.region.country_code[1],
+		       country_code[0], country_code[1]);
+	}
+	regd = create_custom_regdomain(&misc->param.custom_reg_domain);
+	if (regd) {
+		PRINTM(MMSG, "call regulatory_set_wiphy_regd %c%c",
+		       misc->param.custom_reg_domain.region.country_code[0],
+		       misc->param.custom_reg_domain.region.country_code[1]);
+		wiphy->regulatory_flags &=
+			~(REGULATORY_STRICT_REG | REGULATORY_CUSTOM_REG);
+		wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
+		rtnl_lock();
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
+		ret = regulatory_set_wiphy_regd_sync(wiphy, regd);
+#else
+		ret = regulatory_set_wiphy_regd_sync_rtnl(wiphy, regd);
+#endif
+		rtnl_unlock();
+		kfree(regd);
+		if (!ret)
+			woal_reg_apply_beaconing_flags(wiphy,
+						       &misc->param.
+						       custom_reg_domain);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This workqueue handles create customer regulatory
+ * case
+ *
+ *  @param work    A pointer to work_struct
+ *
+ *  @return        N/A
+ */
+void
+woal_regulatory_work_queue(struct work_struct *work)
+{
+	moal_handle *handle = container_of(work, moal_handle, regulatory_work);
+	struct wiphy *wiphy = handle->wiphy;
+	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	enum ieee80211_band band;
+
+	if (priv && wiphy) {
+		woal_update_custom_regdomain(priv, wiphy);
+		band = priv->phandle->band;
+		priv->phandle->band = IEEE80211_BAND_2GHZ;
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->band = band;
+	}
+}
+#endif
+
+/**
+ * @brief Request the driver to change regulatory domain
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param request         A pointer to regulatory_request structure
+ *
+ * @return                0
+ */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+static void
+#else
+static int
+#endif
+woal_cfg80211_reg_notifier(struct wiphy *wiphy,
+			   struct regulatory_request *request)
+{
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	t_u8 region[COUNTRY_CODE_LEN];
+	enum ieee80211_band band;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+	int ret = 0;
+#endif
+	t_u8 load_power_table = MFALSE;
+	mlan_fw_info fw_info;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	char *reg_alpha2 = NULL;
+#endif
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		PRINTM(MFATAL, "Unable to get priv in %s()\n", __func__);
+		LEAVE();
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+		return -EINVAL;
+#else
+		return;
+#endif
+	}
+
+	PRINTM(MCMND,
+	       "cfg80211 regulatory domain callback "
+	       "%c%c initiator=%d\n",
+	       request->alpha2[0], request->alpha2[1], request->initiator);
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (fw_info.force_reg) {
+		PRINTM(MINFO,
+		       "Regulatory domain is enforced in the on-chip OTP\n");
+		LEAVE();
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+		return -EINVAL;
+#else
+		return;
+#endif
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (moal_extflg_isset(handle, EXT_DFS_OFFLOAD))
+		woal_update_radar_chans_dfs_state(wiphy);
+#endif
+	memset(region, 0, sizeof(region));
+	moal_memcpy_ext(priv->phandle, region, request->alpha2,
+			sizeof(request->alpha2), sizeof(region));
+	region[2] = ' ';
+	if ((handle->country_code[0] != request->alpha2[0]) ||
+	    (handle->country_code[1] != request->alpha2[1])) {
+		if (handle->params.cntry_txpwr &&
+		    !handle->params.txpwrlimit_cfg) {
+			t_u8 country_code[COUNTRY_CODE_LEN];
+			handle->country_code[0] = request->alpha2[0];
+			handle->country_code[1] = request->alpha2[1];
+			handle->country_code[2] = ' ';
+			memset(country_code, 0, sizeof(country_code));
+			if (MTRUE == is_cfg80211_special_region_code(region)) {
+				country_code[0] = 'W';
+				country_code[1] = 'W';
+			} else {
+				country_code[0] = request->alpha2[0];
+				country_code[1] = request->alpha2[1];
+			}
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_request_country_power_table(priv,
+							     country_code)) {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+				return -EFAULT;
+#else
+				return;
+#endif
+			}
+			load_power_table = MTRUE;
+		}
+	}
+	if (MTRUE != is_cfg80211_special_region_code(region)) {
+		if (!handle->params.cntry_txpwr) {
+			handle->country_code[0] = request->alpha2[0];
+			handle->country_code[1] = request->alpha2[1];
+			handle->country_code[2] = ' ';
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_region_code(priv, handle->country_code))
+			PRINTM(MERROR, "Set country code failed!\n");
+	}
+	switch (request->initiator) {
+	case NL80211_REGDOM_SET_BY_DRIVER:
+		PRINTM(MCMND, "Regulatory domain BY_DRIVER\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+		reg_alpha2 = priv->phandle->params.reg_alpha2;
+		if ((handle->params.cntry_txpwr == CNTRY_RGPOWER_MODE)
+		    && !handle->params.txpwrlimit_cfg
+		    && load_power_table
+		    && reg_alpha2 && woal_is_valid_alpha2(reg_alpha2))
+			queue_work(handle->evt_workqueue,
+				   &handle->regulatory_work);
+#endif
+		break;
+	case NL80211_REGDOM_SET_BY_CORE:
+		PRINTM(MCMND, "Regulatory domain BY_CORE\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+		if (handle->params.cntry_txpwr == CNTRY_RGPOWER_MODE
+		    && load_power_table && !handle->params.txpwrlimit_cfg)
+			queue_work(handle->evt_workqueue,
+				   &handle->regulatory_work);
+#endif
+		break;
+	case NL80211_REGDOM_SET_BY_USER:
+		PRINTM(MCMND, "Regulatory domain BY_USER\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+		if (handle->params.cntry_txpwr == CNTRY_RGPOWER_MODE
+		    && load_power_table && !handle->params.txpwrlimit_cfg)
+			queue_work(handle->evt_workqueue,
+				   &handle->regulatory_work);
+#endif
+		break;
+	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		PRINTM(MCMND, "Regulatory domain BY_COUNTRY_IE\n");
+		break;
+	}
+	if (priv->wdev && priv->wdev->wiphy &&
+	    (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+		band = priv->phandle->band;
+		priv->phandle->band = IEEE80211_BAND_2GHZ;
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->band = band;
+	}
+
+	LEAVE();
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+	return ret;
+#endif
+}
+
+#ifdef UAP_CFG80211
+/**
+ * @brief Swithces BSS role of interface
+ *
+ * @param priv          A pointer to moal_private structure
+ * @param wait_option   Wait option (MOAL_WAIT or MOAL_NO_WAIT)
+ * @param bss_role      bss role
+ *
+ * @return         0 --success, otherwise fail
+ */
+static mlan_status
+woal_role_switch(moal_private *priv, t_u8 wait_option, t_u8 bss_role)
+{
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_ROLE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+	bss->param.bss_role = bss_role;
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set/get bandcfg
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               get or set action
+ *  @param band_cfg             A pointer to mlan_ds_band_cfg structure
+ *
+ *  @return                     0 -- success, otherwise fail
+ */
+static int
+woal_setget_bandcfg(moal_private *priv, t_u8 action, mlan_ds_band_cfg *band_cfg)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_radio_cfg *radio_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
+	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	req->action = action;
+
+	if (req->action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &radio_cfg->param.band_cfg,
+				band_cfg, sizeof(mlan_ds_band_cfg),
+				sizeof(radio_cfg->param.band_cfg));
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto error;
+	}
+	moal_memcpy_ext(priv->phandle, band_cfg, &radio_cfg->param.band_cfg,
+			sizeof(mlan_ds_band_cfg), sizeof(mlan_ds_band_cfg));
+error:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief request scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param scan_cfg             A pointer to wlan_user_scan_cfg structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+static mlan_status
+woal_uap_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_handle *handle = priv->phandle;
+	moal_private *tmp_priv;
+	u8 role;
+	mlan_ds_band_cfg org_bandcfg;
+	mlan_ds_band_cfg bandcfg;
+	u8 band_change = MFALSE;
+	ENTER();
+	if (priv->bss_index > 0)
+		tmp_priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	else
+		tmp_priv = priv;
+	if (!tmp_priv) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	role = GET_BSS_ROLE(tmp_priv);
+	if (role == MLAN_BSS_ROLE_UAP)
+		woal_role_switch(tmp_priv, MOAL_IOCTL_WAIT, MLAN_BSS_ROLE_STA);
+	if (tmp_priv != priv) {
+		woal_setget_bandcfg(priv, MLAN_ACT_GET, &bandcfg);
+		woal_setget_bandcfg(tmp_priv, MLAN_ACT_GET, &org_bandcfg);
+		if (bandcfg.config_bands != org_bandcfg.config_bands) {
+			woal_setget_bandcfg(tmp_priv, MLAN_ACT_SET, &bandcfg);
+			band_change = MTRUE;
+		}
+	}
+#ifdef REASSOCIATION
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
+		goto done;
+	}
+#endif /* REASSOCIATION */
+	tmp_priv->report_scan_result = MTRUE;
+	ret = woal_request_userscan(tmp_priv, MOAL_IOCTL_WAIT, scan_cfg);
+	woal_sched_timeout(5);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+done:
+	if (role == MLAN_BSS_ROLE_UAP)
+		woal_role_switch(tmp_priv, MOAL_IOCTL_WAIT, MLAN_BSS_ROLE_UAP);
+	if (band_change)
+		woal_setget_bandcfg(tmp_priv, MLAN_ACT_SET, &org_bandcfg);
+	LEAVE();
+	return ret;
+}
+#endif
+
+static int
+woal_find_wps_ie_in_probereq(const t_u8 *ie, int len)
+{
+	int left_len = len;
+	const t_u8 *pos = ie;
+	t_u8 ie_id, ie_len;
+	IEEEtypes_VendorSpecific_t *pvendor_ie = NULL;
+	const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };
+
+	while (left_len >= 2) {
+		ie_id = *pos;
+		ie_len = *(pos + 1);
+		if ((ie_len + 2) > left_len)
+			break;
+		if (ie_id == VENDOR_SPECIFIC_221) {
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pos;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    pvendor_ie->vend_hdr.oui_type == wps_oui[3])
+				return MTRUE;
+		}
+
+		pos += (ie_len + 2);
+		left_len -= (ie_len + 2);
+	}
+
+	return MFALSE;
+}
+
+/** scan result expired value */
+#define SCAN_RESULT_EXPIRTED 1
+/**
+ *  @brief check if the scan result expired
+ *
+ *  @param priv         A pointer to moal_private
+ *
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+static t_u8
+woal_is_uap_scan_result_expired(moal_private *priv)
+{
+	mlan_scan_resp scan_resp;
+	wifi_timeval t;
+	ENTER();
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		LEAVE();
+		return MTRUE;
+	}
+	if (!scan_resp.num_in_scan_table) {
+		LEAVE();
+		return MTRUE;
+	}
+	woal_get_monotonic_time(&t);
+	if (t.time_sec > (scan_resp.age_in_secs + SCAN_RESULT_EXPIRTED)) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief check if the scan result expired
+ *
+ *  @param priv         A pointer to moal_private
+ *
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+static t_u8
+woal_is_scan_result_expired(moal_private *priv)
+{
+	mlan_scan_resp scan_resp;
+	wifi_timeval t;
+	ENTER();
+	// Don't block ACS scan
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return MTRUE;
+	}
+	//Don't block scan when non any interface active
+	if (!woal_is_any_interface_active(priv->phandle)) {
+		LEAVE();
+		return MTRUE;
+	}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	//Do not skip p2p interface connect scan
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		LEAVE();
+		return MTRUE;
+	}
+#endif
+#endif
+	if (!priv->media_connected) {
+		LEAVE();
+		return MTRUE;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		LEAVE();
+		return MTRUE;
+	}
+	if (!scan_resp.num_in_scan_table) {
+		LEAVE();
+		return MTRUE;
+	}
+	woal_get_monotonic_time(&t);
+	if (t.time_sec > (scan_resp.age_in_secs + SCAN_RESULT_EXPIRTED)) {
+		LEAVE();
+		return MTRUE;
+	}
+	LEAVE();
+	return MFALSE;
+}
+
+/**
+ *  @brief check if the scan result ageout
+ *
+ *  @param priv         A pointer to moal_private
+ *
+ *
+ *  @return             MTRUE/MFALSE;
+ */
+t_u8
+wlan_check_scan_table_ageout(moal_private *priv)
+{
+	mlan_scan_resp scan_resp;
+	wifi_timeval t;
+	ENTER();
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		LEAVE();
+		return MFALSE;
+	}
+	woal_get_monotonic_time(&t);
+#define CFG80211_SCAN_RESULT_AGEOUT 10
+	if (t.time_sec > (scan_resp.age_in_secs + CFG80211_SCAN_RESULT_AGEOUT)) {
+		LEAVE();
+		return MFALSE;
+	}
+	PRINTM(MCMND, "Scan: Keep Previous result\n");
+	LEAVE();
+	return MTRUE;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ * @brief Request the driver to do a scan. Always returning
+ * zero meaning that the scan request is given to driver,
+ * and will be valid until passed to cfg80211_scan_done().
+ * To inform scan results, call cfg80211_inform_bss().
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param request         A pointer to cfg80211_scan_request structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+#else
+/**
+ * @brief Request the driver to do a scan. Always returning
+ * zero meaning that the scan request is given to driver,
+ * and will be valid until passed to cfg80211_scan_done().
+ * To inform scan results, call cfg80211_inform_bss().
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param request         A pointer to cfg80211_scan_request structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
+		   struct cfg80211_scan_request *request)
+#endif
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = request->wdev->netdev;
+#endif
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	wlan_user_scan_cfg *scan_req = NULL;
+	mlan_bss_info bss_info;
+	mlan_scan_cfg scan_cfg;
+	struct ieee80211_channel *chan;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	t_u8 buf[ETH_ALEN];
+#endif
+	int ret = 0, i;
+	unsigned long flags;
+
+	ENTER();
+
+	PRINTM(MINFO, "Received scan request on %s\n", dev->name);
+#if defined(WIFI_LATENCY_MODE_SUPPORT)
+	if (MTRUE == priv->scan_suppressed) {
+		PRINTM(MINFO, "Suppress scan request per config\n");
+		ret = -EAGAIN;
+		goto done;
+	}
+#endif  // defined(WIFI_LATENCY_MODE_SUPPORT)
+
+	if (priv->phandle->scan_pending_on_block == MTRUE) {
+		PRINTM(MCMND, "scan already in processing...\n");
+		LEAVE();
+		return -EAGAIN;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (priv->last_event & EVENT_BG_SCAN_REPORT) {
+		PRINTM(MCMND, "block scan while pending BGSCAN result\n");
+		priv->last_event = 0;
+		LEAVE();
+		return -EAGAIN;
+	}
+#endif
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (priv->phandle->is_go_timer_set &&
+	    priv->wdev->iftype != NL80211_IFTYPE_P2P_GO) {
+		PRINTM(MCMND, "block scan in go timer....\n");
+		LEAVE();
+		return -EAGAIN;
+	}
+#endif
+#endif
+#endif
+	cancel_delayed_work_sync(&priv->phandle->scan_timeout_work);
+	priv->phandle->fake_scan_complete = priv->fake_scan_complete;
+	if (priv->fake_scan_complete || !woal_is_scan_result_expired(priv)) {
+		priv->phandle->fake_scan_complete = MTRUE;
+		PRINTM(MEVENT,
+		       "fake scan complete flag is on\n");
+		priv->phandle->scan_request = request;
+		queue_delayed_work(priv->phandle->evt_workqueue,
+                    &priv->phandle->scan_timeout_work, msecs_to_jiffies(1000));
+		return MLAN_STATUS_SUCCESS;
+	}
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		if (bss_info.scan_block) {
+			PRINTM(MEVENT, "Block scan in mlan module\n");
+			return -EAGAIN;
+		}
+	}
+	if (priv->phandle->scan_request &&
+	    priv->phandle->scan_request != request) {
+		PRINTM(MCMND,
+		       "different scan_request is coming before previous one is finished on %s...\n",
+		       dev->name);
+		LEAVE();
+		return -EBUSY;
+	}
+
+	spin_lock_irqsave(&priv->phandle->scan_req_lock, flags);
+	priv->phandle->scan_request = request;
+	spin_unlock_irqrestore(&priv->phandle->scan_req_lock, flags);
+	if (is_zero_timeval(priv->phandle->scan_time_start)) {
+		woal_get_monotonic_time(&priv->phandle->scan_time_start);
+		PRINTM(MINFO, "%s : start_timeval=%d:%d \n", __func__,
+		       priv->phandle->scan_time_start.time_sec,
+		       priv->phandle->scan_time_start.time_usec);
+	}
+	scan_req = kmalloc(sizeof(wlan_user_scan_cfg), GFP_KERNEL);
+	memset(scan_req, 0x00, sizeof(wlan_user_scan_cfg));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+	if (!is_broadcast_ether_addr(request->bssid)) {
+		moal_memcpy_ext(priv->phandle, scan_req->specific_bssid,
+				request->bssid, ETH_ALEN,
+				sizeof(scan_req->specific_bssid));
+		PRINTM(MIOCTL, "scan: bssid=" MACSTR "\n",
+		       MAC2STR(scan_req->specific_bssid));
+	}
+#endif
+
+	memset(&scan_cfg, 0, sizeof(mlan_scan_cfg));
+	woal_get_scan_config(priv, &scan_cfg);
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->phandle->miracast_mode)
+		scan_req->scan_chan_gap = priv->phandle->scan_chan_gap;
+	else {
+#endif
+		if (scan_cfg.scan_chan_gap)
+			scan_req->scan_chan_gap = scan_cfg.scan_chan_gap;
+		else if (woal_is_any_interface_active(priv->phandle))
+			scan_req->scan_chan_gap = priv->phandle->scan_chan_gap;
+		else
+			scan_req->scan_chan_gap = 0;
+#ifdef WIFI_DIRECT_SUPPORT
+	}
+#endif
+	/** indicate FW, gap is optional */
+	if (scan_req->scan_chan_gap && priv->phandle->pref_mac)
+		scan_req->scan_chan_gap |= GAP_FLAG_OPTIONAL;
+
+	if (priv->phandle->scan_request->n_channels <= 38) {
+		if (scan_cfg.ext_scan == 3)
+			scan_req->ext_scan_type = EXT_SCAN_ENHANCE;
+	}
+
+	for (i = 0; i < priv->phandle->scan_request->n_ssids; i++) {
+		moal_memcpy_ext(priv->phandle, scan_req->ssid_list[i].ssid,
+				priv->phandle->scan_request->ssids[i].ssid,
+				priv->phandle->scan_request->ssids[i].ssid_len,
+				sizeof(scan_req->ssid_list[i].ssid));
+		if (priv->phandle->scan_request->ssids[i].ssid_len)
+			scan_req->ssid_list[i].max_len = 0;
+		else
+			scan_req->ssid_list[i].max_len = 0xff;
+		PRINTM(MIOCTL, "scan: ssid=%s\n", scan_req->ssid_list[i].ssid);
+	}
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+	    priv->phandle->scan_request->n_ssids) {
+		if (!memcmp(scan_req->ssid_list[0].ssid, "DIRECT-", 7))
+			scan_req->ssid_list[0].max_len = 0xfe;
+	}
+#endif
+#endif
+	for (i = 0; i < (int)MIN(WLAN_USER_SCAN_CHAN_MAX,
+				 priv->phandle->scan_request->n_channels);
+	     i++) {
+		chan = priv->phandle->scan_request->channels[i];
+		scan_req->chan_list[i].chan_number = chan->hw_value;
+		scan_req->chan_list[i].radio_type = chan->band;
+		if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) ||
+		    !priv->phandle->scan_request->n_ssids)
+			scan_req->chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		else if (chan->flags & IEEE80211_CHAN_RADAR)
+			scan_req->chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
+		else
+			scan_req->chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_ACTIVE;
+		PRINTM(MCMD_D, "cfg80211_scan: chan=%d chan->flag=0x%x\n",
+		       chan->hw_value, chan->flags);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+		scan_req->chan_list[i].scan_time =
+			priv->phandle->scan_request->duration;
+#else
+		scan_req->chan_list[i].scan_time = 0;
+#endif
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+		if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+		    priv->phandle->scan_request->n_ssids) {
+			if (!memcmp(scan_req->ssid_list[0].ssid, "DIRECT-", 7))
+				scan_req->chan_list[i].scan_time =
+					MIN_SPECIFIC_SCAN_CHAN_TIME;
+		}
+#endif
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+		if (priv->phandle->miracast_mode)
+			scan_req->chan_list[i].scan_time =
+				priv->phandle->miracast_scan_time;
+		else if (woal_is_any_interface_active(priv->phandle)) {
+			if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+				scan_req->chan_list[i].scan_time =
+					INIT_PASSIVE_SCAN_CHAN_TIME;
+			else
+				scan_req->chan_list[i].scan_time =
+					MIN_SPECIFIC_SCAN_CHAN_TIME;
+		}
+#endif
+#ifdef UAP_CFG80211
+		if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+			if (!woal_is_uap_scan_result_expired(priv))
+				scan_req->chan_list[i].scan_time =
+					MIN_SPECIFIC_SCAN_CHAN_TIME;
+
+			else
+				scan_req->chan_list[i].scan_time =
+					PASSIVE_SCAN_CHAN_TIME;
+		}
+#endif
+	}
+	if (priv->phandle->scan_request->ie &&
+	    priv->phandle->scan_request->ie_len) {
+		if (woal_find_wps_ie_in_probereq((t_u8 *)priv->phandle->
+						 scan_request->ie,
+						 priv->phandle->scan_request->
+						 ie_len)) {
+			PRINTM(MIOCTL,
+			       "Notify firmware only keep probe response\n");
+			scan_req->proberesp_only = MTRUE;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0,
+						(t_u8 *)priv->phandle->
+						scan_request->ie,
+						priv->phandle->scan_request->
+						ie_len, MGMT_MASK_PROBE_REQ,
+						MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Fail to set scan request IE\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		/** Clear SCAN IE in Firmware */
+		if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+			woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0,
+						    NULL, 0, NULL, 0,
+						    MGMT_MASK_PROBE_REQ,
+						    MOAL_IOCTL_WAIT);
+	}
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		/** use sync scan for uap */
+		ret = woal_uap_scan(priv, scan_req);
+		if (!ret) {
+			kfree(scan_req);
+			LEAVE();
+			return ret;
+		} else {
+			PRINTM(MERROR, "Uap SCAN failure\n");
+			goto done;
+		}
+	}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+		PRINTM(MIOCTL, "NL80211_SCAN_FLAG_RANDOM_ADDR is set\n");
+		get_random_bytes(buf, ETH_ALEN);
+		for (i = 0; i < ETH_ALEN; i++) {
+			buf[i] &= ~request->mac_addr_mask[i];
+			buf[i] |= request->mac_addr[i] &
+				request->mac_addr_mask[i];
+		}
+		moal_memcpy_ext(priv->phandle, scan_req->random_mac, buf,
+				ETH_ALEN, sizeof(scan_req->random_mac));
+	} else
+#endif
+		moal_memcpy_ext(priv->phandle, scan_req->random_mac,
+				priv->random_mac, ETH_ALEN,
+				sizeof(scan_req->random_mac));
+
+	PRINTM(MCMND, "wlan:random_mac " MACSTR "\n",
+	       MAC2STR(scan_req->random_mac));
+	scan_req->keep_previous_scan = wlan_check_scan_table_ageout(priv);
+
+	if (MLAN_STATUS_SUCCESS != woal_do_scan(priv, scan_req)) {
+		PRINTM(MERROR, "woal_do_scan fails!\n");
+		ret = -EAGAIN;
+		goto done;
+	}
+done:
+	if (ret) {
+		spin_lock_irqsave(&priv->phandle->scan_req_lock, flags);
+		woal_cfg80211_scan_done(request, MTRUE);
+		priv->phandle->scan_request = NULL;
+		priv->phandle->scan_priv = NULL;
+		spin_unlock_irqrestore(&priv->phandle->scan_req_lock, flags);
+	} else{
+		PRINTM(MMSG, "wlan: %s START SCAN\n", dev->name);
+		queue_delayed_work(priv->phandle->evt_workqueue,
+			&priv->phandle->scan_timeout_work,
+			msecs_to_jiffies(priv->phandle->scan_timeout));
+    }
+	kfree(scan_req);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+static void
+woal_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(wdev->netdev);
+	ENTER();
+	PRINTM(MMSG, "wlan: ABORT SCAN start\n");
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+	LEAVE();
+	return;
+}
+#endif
+/**
+ * @brief construct and send ft action request
+ *
+ *  @param priv     A pointer to moal_private structure
+ * @param ie       A pointer to ft ie
+ * @param le       Value of ie len
+ * @param bssid    A pointer to target ap bssid
+ * @
+ * @return         0 -- success, otherwise fail
+ */
+static int
+woal_send_ft_action_requst(moal_private *priv, t_u8 *ie, t_u8 len,
+			   t_u8 *bssid, t_u8 *target_ap)
+{
+	IEEE80211_MGMT *mgmt = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_buffer pmbuf = NULL;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+	t_u16 packet_len = 0;
+	t_u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	int ret = 0;
+
+	ENTER();
+
+	/* pkt_type + tx_control */
+#define HEADER_SIZE 8
+	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl + addr4 */
+#define MGMT_HEADER_LEN (2 + 2 + 6 + 6 + 6 + 2 + 6)
+	/* 14   = category + action + sta addr + target ap */
+#define FT_REQUEST_LEN 14
+	packet_len = (t_u16)len + MGMT_HEADER_LEN + FT_REQUEST_LEN;
+	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
+				       MLAN_MIN_DATA_HEADER_LEN + HEADER_SIZE +
+				       packet_len + sizeof(packet_len));
+	if (!pmbuf) {
+		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
+	pkt_type = MRVL_PKT_TYPE_MGMT_FRAME;
+	tx_control = 0;
+	/* Add pkt_type and tx_control */
+	moal_memcpy_ext(priv->phandle, pmbuf->pbuf + pmbuf->data_offset,
+			&pkt_type, sizeof(pkt_type), sizeof(pkt_type));
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+			&tx_control, sizeof(tx_control), sizeof(tx_control));
+	/*Add packet len */
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE,
+			&packet_len, sizeof(packet_len), sizeof(packet_len));
+
+	mgmt = (IEEE80211_MGMT *)(pmbuf->pbuf + pmbuf->data_offset +
+				  HEADER_SIZE + sizeof(packet_len));
+	memset(mgmt, 0, MGMT_HEADER_LEN);
+	mgmt->frame_control =
+		woal_cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
+	moal_memcpy_ext(priv->phandle, mgmt->da, bssid, ETH_ALEN,
+			sizeof(mgmt->da));
+	moal_memcpy_ext(priv->phandle, mgmt->sa, priv->current_addr, ETH_ALEN,
+			sizeof(mgmt->sa));
+	moal_memcpy_ext(priv->phandle, mgmt->bssid, bssid, ETH_ALEN,
+			sizeof(mgmt->bssid));
+	moal_memcpy_ext(priv->phandle, mgmt->addr4, addr, ETH_ALEN,
+			sizeof(mgmt->addr4));
+
+	mgmt->u.ft_req.category = 0x06;	/**ft action code 0x6*/
+	mgmt->u.ft_req.action = 0x1; /**ft action request*/
+	moal_memcpy_ext(priv->phandle, mgmt->u.ft_req.sta_addr,
+			priv->current_addr, ETH_ALEN,
+			sizeof(mgmt->u.ft_req.sta_addr));
+	moal_memcpy_ext(priv->phandle, mgmt->u.ft_req.target_ap_addr, target_ap,
+			ETH_ALEN, sizeof(mgmt->u.ft_req.target_ap_addr));
+
+	if (ie && len)
+		moal_memcpy_ext(priv->phandle,
+				(t_u8 *)(&mgmt->u.ft_req.variable), ie, len,
+				len);
+
+	pmbuf->data_len = HEADER_SIZE + packet_len + sizeof(packet_len);
+	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
+	pmbuf->bss_index = priv->bss_index;
+	pmbuf->priority = 7;
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		ret = -EFAULT;
+		break;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief construct and send ft auth request
+ *
+ *  @param priv     A pointer to moal_private structure
+ * @param ie       A pointer to ft ie
+ * @param le       Value of ie len
+ * @param bssid    A pointer to target ap bssid
+ * @
+ * @return         0 -- success, otherwise fail
+ */
+static int
+woal_send_ft_auth_requst(moal_private *priv, t_u8 *ie, t_u8 len, t_u8 *bssid)
+{
+	IEEE80211_MGMT *mgmt = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	pmlan_buffer pmbuf = NULL;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+	t_u16 packet_len = 0;
+	t_u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	int ret = 0;
+
+	ENTER();
+	/* pkt_type + tx_control */
+#define HEADER_SIZE 8
+	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl + addr4 */
+#define MGMT_HEADER_LEN (2 + 2 + 6 + 6 + 6 + 2 + 6)
+	/* 6   = auth_alg + auth_transaction +auth_status */
+#define AUTH_BODY_LEN 6
+	packet_len = (t_u16)len + MGMT_HEADER_LEN + AUTH_BODY_LEN;
+	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
+				       MLAN_MIN_DATA_HEADER_LEN + HEADER_SIZE +
+				       packet_len + sizeof(packet_len));
+	if (!pmbuf) {
+		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
+	pkt_type = MRVL_PKT_TYPE_MGMT_FRAME;
+	tx_control = 0;
+	/* Add pkt_type and tx_control */
+	moal_memcpy_ext(priv->phandle, pmbuf->pbuf + pmbuf->data_offset,
+			&pkt_type, sizeof(pkt_type), sizeof(pkt_type));
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
+			&tx_control, sizeof(tx_control), sizeof(tx_control));
+	/*Add packet len */
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE,
+			&packet_len, sizeof(packet_len), sizeof(packet_len));
+
+	mgmt = (IEEE80211_MGMT *)(pmbuf->pbuf + pmbuf->data_offset +
+				  HEADER_SIZE + sizeof(packet_len));
+	memset(mgmt, 0, MGMT_HEADER_LEN);
+	mgmt->frame_control =
+		woal_cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
+	moal_memcpy_ext(priv->phandle, mgmt->da, bssid, ETH_ALEN,
+			sizeof(mgmt->da));
+	moal_memcpy_ext(priv->phandle, mgmt->sa, priv->current_addr, ETH_ALEN,
+			sizeof(mgmt->sa));
+	moal_memcpy_ext(priv->phandle, mgmt->bssid, bssid, ETH_ALEN,
+			sizeof(mgmt->bssid));
+	moal_memcpy_ext(priv->phandle, mgmt->addr4, addr, ETH_ALEN,
+			sizeof(mgmt->addr4));
+
+	mgmt->u.auth.auth_alg = woal_cpu_to_le16(WLAN_AUTH_FT);
+	mgmt->u.auth.auth_transaction = woal_cpu_to_le16(1);
+	mgmt->u.auth.status_code = woal_cpu_to_le16(0);
+	if (ie && len)
+		moal_memcpy_ext(priv->phandle, (t_u8 *)(&mgmt->u.auth.variable),
+				ie, len, len);
+
+	pmbuf->data_len = HEADER_SIZE + packet_len + sizeof(packet_len);
+	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
+	pmbuf->bss_index = priv->bss_index;
+	pmbuf->priority = 7;
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		ret = -EFAULT;
+		break;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief connect the AP through ft over air.
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param bssid           A pointer to bssid
+ * @param chan            struct ieee80211_channel
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_connect_ft_over_air(moal_private *priv, t_u8 *bssid,
+			 struct ieee80211_channel *chan)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	t_u8 status = 0;
+#endif
+
+	t_u8 wait_option = MOAL_IOCTL_WAIT;
+	int ret = 0;
+	long timeout = 0;
+
+	ENTER();
+
+	if (!bssid) {
+		PRINTM(MERROR,
+		       "Invalid bssid, unable to connect AP to through FT\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	/*enable auth register frame */
+	woal_mgmt_frame_register(priv, IEEE80211_STYPE_AUTH, MTRUE);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MFALSE, &status,
+					    chan, 0, AUTH_TX_DEFAULT_WAIT_TIME);
+#endif
+
+	/*construct auth request and send out */
+	woal_send_ft_auth_requst(priv, priv->ft_ie, priv->ft_ie_len, bssid);
+	PRINTM(MMSG, "wlan: send out FT auth,wait for auth response\n");
+	/*wait until received auth response */
+	priv->ft_wait_condition = MFALSE;
+	timeout = wait_event_timeout(priv->ft_wait_q, priv->ft_wait_condition,
+				     1 * HZ);
+	if (!timeout) {
+		/*connet fail */
+		if (!priv->ft_roaming_triggered_by_driver) {
+			woal_inform_bss_from_scan_result(priv, NULL,
+							 wait_option);
+			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+						NULL, 0, NULL, 0,
+						WLAN_STATUS_SUCCESS,
+						GFP_KERNEL);
+		}
+		priv->ft_roaming_triggered_by_driver = MFALSE;
+		PRINTM(MMSG, "wlan: keep connected to bssid " MACSTR "\n",
+		       MAC2STR(priv->cfg_bssid));
+	} else {
+		PRINTM(MMSG, "wlan: FT auth received \n");
+		moal_memcpy_ext(priv->phandle, priv->target_ap_bssid, bssid,
+				ETH_ALEN, sizeof(priv->target_ap_bssid));
+	}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MTRUE, &status,
+					    NULL, 0, 0);
+#endif
+
+	woal_mgmt_frame_register(priv, IEEE80211_STYPE_AUTH, MFALSE);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief connect the AP through ft over DS.
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param bssid           A pointer to bssid
+ * @param chan            struct ieee80211_channel
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_connect_ft_over_ds(moal_private *priv, t_u8 *bssid,
+			struct ieee80211_channel *pchan)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	t_u8 status = 0;
+#endif
+	t_u8 wait_option = MOAL_IOCTL_WAIT;
+	int ret = 0;
+	long timeout = 0;
+
+	ENTER();
+
+	if (priv->media_connected) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MFALSE,
+						    &status, pchan, 0, 1200);
+#endif
+		/*construct ft action request and send out */
+		woal_send_ft_action_requst(priv, priv->ft_ie, priv->ft_ie_len,
+					   (t_u8 *)priv->cfg_bssid, bssid);
+		PRINTM(MMSG,
+		       "wlan: send out FT request,wait for FT response\n");
+		/*wait until received auth response */
+		priv->ft_wait_condition = MFALSE;
+		timeout = wait_event_timeout(priv->ft_wait_q,
+					     priv->ft_wait_condition, 1 * HZ);
+		if (!timeout) {
+			/*go over air, as current AP may be unreachable */
+			PRINTM(MMSG, "wlan: go over air\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+			woal_cfg80211_remain_on_channel_cfg(priv, wait_option,
+							    MTRUE, &status,
+							    NULL, 0, 0);
+#endif
+			woal_connect_ft_over_air(priv, bssid, pchan);
+			LEAVE();
+			return ret;
+		} else {
+			PRINTM(MMSG, "wlan: received FT response\n");
+			moal_memcpy_ext(priv->phandle, priv->target_ap_bssid,
+					bssid, ETH_ALEN,
+					sizeof(priv->target_ap_bssid));
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MTRUE,
+						    &status, NULL, 0, 0);
+#endif
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief start FT Roaming.
+ *
+ * @param priv               A pointer to moal_private structure
+ * @param ssid_bssid         A pointer to mlan_ssid_bssid structure
+ *
+ *
+ * @return                   0 -- success, otherwise fail
+ */
+static int
+woal_start_ft_roaming(moal_private *priv, mlan_ssid_bssid *ssid_bssid)
+{
+	struct ieee80211_channel chan;
+	int ret = 0;
+
+	ENTER();
+
+	PRINTM(MEVENT, "Try to start FT roaming......\n");
+	chan.band = (ssid_bssid->channel < 36) ? IEEE80211_BAND_2GHZ :
+		IEEE80211_BAND_5GHZ;
+	chan.center_freq = ieee80211_channel_to_frequency(ssid_bssid->channel
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+							  , chan.band
+#endif
+		);
+
+	if (!(priv->last_event & EVENT_PRE_BCN_LOST) &&
+	    (ssid_bssid->ft_cap & MBIT(0))) {
+		woal_connect_ft_over_ds(priv, (t_u8 *)&ssid_bssid->bssid,
+					&chan);
+	} else {
+		/*if pre beacon lost, it need to send auth request instead ft
+		 * action request when ft over ds */
+		woal_connect_ft_over_air(priv, (t_u8 *)&ssid_bssid->bssid,
+					 &chan);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to connect to the ESS with
+ * the specified parameters from kernel
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param sme             A pointer to cfg80211_connect_params structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+		      struct cfg80211_connect_params *sme)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+	mlan_bss_info bss_info;
+	unsigned long flags;
+	mlan_ds_misc_assoc_rsp *assoc_rsp = NULL;
+	IEEEtypes_AssocRsp_t *passoc_rsp = NULL;
+	mlan_ssid_bssid ssid_bssid;
+	moal_handle *handle = priv->phandle;
+	int i;
+
+	ENTER();
+
+	PRINTM(MINFO, "Received association request on %s\n", dev->name);
+	priv->cfg_disconnect = MFALSE;
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return 0;
+	}
+#endif
+	if (priv->wdev->iftype != NL80211_IFTYPE_STATION
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+	    && priv->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT
+#endif /* KERNEL_VERSION */
+#endif /* WIFI_DIRECT_SUPPORT */
+		) {
+		PRINTM(MERROR,
+		       "Received infra assoc request when station not in infra mode\n");
+		LEAVE();
+		return -EINVAL;
+	}
+	memset(&ssid_bssid, 0, sizeof(ssid_bssid));
+	moal_memcpy_ext(priv->phandle, &ssid_bssid.ssid.ssid, sme->ssid,
+			sme->ssid_len, sizeof(ssid_bssid.ssid.ssid));
+	ssid_bssid.ssid.ssid_len = sme->ssid_len;
+	if (sme->bssid)
+		moal_memcpy_ext(priv->phandle, &ssid_bssid.bssid, sme->bssid,
+				ETH_ALEN, sizeof(ssid_bssid.bssid));
+	/* Not allowed to connect to the same AP which is already connected
+	   with other interface */
+	for (i = 0; i < handle->priv_num; i++) {
+		if (handle->priv[i] != priv &&
+		    MTRUE == woal_is_connected(handle->priv[i], &ssid_bssid)) {
+			PRINTM(MMSG,
+			       "wlan: already connected with other interface, bssid "
+			       MACSTR "\n",
+			       MAC2STR(handle->priv[i]->cfg_bssid));
+			LEAVE();
+			return -EINVAL;
+		}
+	}
+
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT &&
+	    (priv->wdev->iftype == NL80211_IFTYPE_STATION ||
+	     priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
+		/* if bsstype == wifi direct, and iftype == station or p2p
+		 * client, that means wpa_supplicant wants to enable wifi direct
+		 * functionality, so we should init p2p client.
+		 *
+		 * Note that due to kernel iftype check, ICS wpa_supplicant
+		 * could not updaet iftype to init p2p client, so we have to
+		 * done it here.
+		 * */
+		if (MLAN_STATUS_SUCCESS != woal_cfg80211_init_p2p_client(priv)) {
+			PRINTM(MERROR,
+			       "Init p2p client for wpa_supplicant failed.\n");
+			ret = -EFAULT;
+
+			LEAVE();
+			return ret;
+		}
+	}
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		/* WAR for P2P connection with vendor TV */
+		woal_sched_timeout(200);
+	}
+#endif
+#endif
+	/*11r roaming triggered by supplicant */
+	if (priv->media_connected && priv->ft_ie_len &&
+	    !(priv->ft_cap & MBIT(0))) {
+		/** get current bss info */
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		/** get target bss info */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_find_essid(priv, &ssid_bssid, MOAL_IOCTL_WAIT)) {
+			ret = woal_cfg80211_connect_scan(priv, sme,
+							 MOAL_IOCTL_WAIT);
+			if (!ret) {
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_find_best_network(priv,
+							   MOAL_IOCTL_WAIT,
+							   &ssid_bssid)) {
+					PRINTM(MERROR,
+					       "can't find targe AP \n");
+					// LEAVE();
+					// return -EFAULT;
+				}
+			}
+		}
+		if (bss_info.mdid == ssid_bssid.ft_md &&
+		    bss_info.ft_cap == ssid_bssid.ft_cap) {
+			ret = woal_start_ft_roaming(priv, &ssid_bssid);
+			LEAVE();
+			return 0;
+		}
+	}
+
+	priv->cfg_connect = MTRUE;
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
+	priv->assoc_status = 0;
+	assoc_rsp = kzalloc(sizeof(mlan_ds_misc_assoc_rsp), GFP_ATOMIC);
+	if (!assoc_rsp) {
+		PRINTM(MERROR, "Failed to allocate memory for assoc_rsp\n");
+		ret = -ENOMEM;
+		LEAVE();
+		return ret;
+	}
+	ret = woal_cfg80211_assoc(priv, (void *)sme, MOAL_IOCTL_WAIT,
+				  assoc_rsp);
+
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+	if (!ret) {
+		passoc_rsp = (IEEEtypes_AssocRsp_t *)assoc_rsp->assoc_resp_buf;
+		priv->rssi_low = DEFAULT_RSSI_LOW_THRESHOLD;
+		if (priv->bss_type == MLAN_BSS_TYPE_STA)
+			woal_save_conn_params(priv, sme);
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		priv->channel = bss_info.bss_chan;
+		if (!ssid_bssid.ft_md) {
+			priv->ft_ie_len = 0;
+			priv->ft_pre_connect = MFALSE;
+			priv->ft_md = 0;
+			priv->ft_cap = 0;
+		}
+	}
+	spin_lock_irqsave(&priv->connect_lock, flags);
+	priv->cfg_connect = MFALSE;
+	if (!ret && priv->media_connected) {
+		PRINTM(MMSG,
+		       "wlan: Connected to bssid " MACSTR " successfully\n",
+		       MAC2STR(priv->cfg_bssid));
+		spin_unlock_irqrestore(&priv->connect_lock, flags);
+		cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
+					passoc_rsp->ie_buffer,
+					assoc_rsp->assoc_resp_len -
+					ASSOC_RESP_FIXED_SIZE,
+					WLAN_STATUS_SUCCESS, GFP_KERNEL);
+	} else {
+		PRINTM(MINFO, "wlan: Failed to connect to bssid " MACSTR "\n",
+		       MAC2STR(priv->cfg_bssid));
+		memset(priv->cfg_bssid, 0, ETH_ALEN);
+		spin_unlock_irqrestore(&priv->connect_lock, flags);
+		cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
+					NULL, 0, woal_get_assoc_status(priv),
+					GFP_KERNEL);
+	}
+
+	kfree(assoc_rsp);
+	assoc_rsp = NULL;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief This function will print diconnect reason code according
+ *  to IEEE 802.11 spec
+ *
+ *  @param reason_code    reason code for the deauth/disaccoc
+ *                        received from firmware
+ *  @return        N/A
+ */
+static void
+woal_print_disconnect_reason(t_u16 reason_code)
+{
+	ENTER();
+
+	switch (reason_code) {
+	case MLAN_REASON_UNSPECIFIED:
+		PRINTM(MMSG, "wlan: REASON: Unspecified reason\n");
+		break;
+	case MLAN_REASON_PREV_AUTH_NOT_VALID:
+		PRINTM(MMSG,
+		       "wlan: REASON: Previous authentication no longer valid\n");
+		break;
+	case MLAN_REASON_DEAUTH_LEAVING:
+		PRINTM(MMSG,
+		       "wlan: REASON: (Deauth) Sending STA is leaving (or has left) IBSS or ESS\n");
+		break;
+	case MLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
+		PRINTM(MMSG,
+		       "wlan: REASON: Disassociated due to inactivity \n");
+		break;
+	case MLAN_REASON_DISASSOC_AP_BUSY:
+		PRINTM(MMSG,
+		       "wlan: REASON: (Disassociated) AP unable to handle all connected STAs\n");
+		break;
+	case MLAN_REASON_CLASS2_FRAME_FROM_NOAUTH_STA:
+		PRINTM(MMSG,
+		       "wlan: REASON: Class 2 frame was received from nonauthenticated STA\n");
+		break;
+	case MLAN_REASON_CLASS3_FRAME_FROM_NOASSOC_STA:
+		PRINTM(MMSG,
+		       "wlan: REASON: Class 3 frame was received from nonassociated STA\n");
+		break;
+	case MLAN_REASON_DISASSOC_STA_HAS_LEFT:
+		PRINTM(MMSG,
+		       "wlan: REASON: (Disassocated) Sending STA is leaving (or has left) BSS\n");
+		break;
+	case MLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
+		PRINTM(MMSG,
+		       "wlan: REASON: STA requesting (re)assoc is not authenticated with responding STA\n");
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Request the driver to disconnect
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param reason_code     Reason code
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+			 t_u16 reason_code)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+	PRINTM(MMSG,
+	       "wlan: Received disassociation request on %s, reason: %u\n",
+	       dev->name, reason_code);
+	woal_print_disconnect_reason(reason_code);
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return 0;
+	}
+#endif
+	if (priv->phandle->driver_status) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_disconnect in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MMSG, " Already disconnected\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+		if (priv->wdev->current_bss &&
+		    (priv->wdev->iftype == NL80211_IFTYPE_STATION ||
+		     priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
+			priv->cfg_disconnect = MTRUE;
+			cfg80211_disconnected(priv->netdev, 0, NULL, 0,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+					      true,
+#endif
+					      GFP_KERNEL);
+		}
+#endif
+		LEAVE();
+		return 0;
+	}
+
+	if (priv->cfg_disconnect) {
+		PRINTM(MERROR, "Disassociation already in progress\n");
+		LEAVE();
+		return 0;
+	}
+
+	/** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+	priv->cfg_disconnect = MTRUE;
+	if (woal_disconnect(priv, MOAL_IOCTL_WAIT_TIMEOUT, priv->cfg_bssid,
+			    reason_code) != MLAN_STATUS_SUCCESS) {
+		priv->cfg_disconnect = MFALSE;
+		LEAVE();
+		return -EFAULT;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+	if (priv->wdev->iftype == NL80211_IFTYPE_STATION ||
+	    priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)
+		cfg80211_disconnected(priv->netdev, 0, NULL, 0,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+				      true,
+#endif
+				      GFP_KERNEL);
+#endif
+
+	memset(priv->cfg_bssid, 0, ETH_ALEN);
+	if (priv->bss_type == MLAN_BSS_TYPE_STA)
+		woal_clear_conn_params(priv);
+	priv->channel = 0;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief This function is deauthentication handler when host MLME
+ *          enable.
+ *          In this case driver will prepare and send Deauth Req.
+ *
+ *  @param wiphy       A pointer to wiphy.
+ *
+ *  @param dev         A pointer to net_device
+ *
+ *  @param req         A pointer to cfg80211_deauth_request
+ *
+ *  @return            0 -- success, otherwise fail
+ */
+
+static int
+woal_cfg80211_deauthenticate(struct wiphy *wiphy,
+			     struct net_device *dev,
+			     struct cfg80211_deauth_request *req)
+{
+	int ret = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (priv->host_mlme) {
+		priv->host_mlme = MFALSE;
+		priv->auth_flag = 0;
+		priv->auth_alg = 0xFFFF;
+		/*send deauth packet to notify disconnection to wpa_supplicant */
+		woal_deauth_event(priv, req->reason_code);
+	}
+#endif
+
+	ret = woal_cfg80211_disconnect(wiphy, dev, req->reason_code);
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
+	if (priv->wdev->iftype == NL80211_IFTYPE_STATION ||
+	    priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)
+		cfg80211_disconnected(priv->netdev, 0, NULL, 0, GFP_KERNEL);
+#endif
+	return ret;
+}
+
+/**
+ *  @brief This function is disassociation handler when host MLME
+ *          enable.
+ *          In this case driver will prepare and send Disassoc frame.
+ *
+ *  @param wiphy       A pointer to wiphy.
+ *
+ *  @param dev         A pointer to net_device
+ *
+ *  @param req         A pointer to cfg80211_disassoc_request
+ *
+ *  @return            0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_disassociate(struct wiphy *wiphy,
+			   struct net_device *dev,
+			   struct cfg80211_disassoc_request *req)
+{
+	int ret = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (priv->host_mlme) {
+		priv->host_mlme = MFALSE;
+		priv->auth_flag = 0;
+		priv->auth_alg = 0xFFFF;
+		/*send deauth packet to notify disconnection to wpa_supplicant */
+		woal_deauth_event(priv, req->reason_code);
+	}
+#endif
+
+	ret = woal_cfg80211_disconnect(wiphy, dev, req->reason_code);
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
+	if (priv->wdev->iftype == NL80211_IFTYPE_STATION ||
+	    priv->wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)
+		cfg80211_disconnected(priv->netdev, 0, NULL, 0, GFP_KERNEL);
+#endif
+	return ret;
+}
+
+/**
+ * @brief Request the driver to get the station information
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param mac             MAC address of the station
+ * @param sinfo           A pointer to station_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			  const u8 *mac,
+#else
+			  u8 *mac,
+#endif
+			  struct station_info *sinfo)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return woal_uap_cfg80211_get_station(wiphy, dev, mac, sinfo);
+	}
+#endif
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MINFO, "cfg80211: Media not connected!\n");
+		LEAVE();
+		return -ENOENT;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_cfg80211_dump_station_info(priv, sinfo)) {
+		PRINTM(MERROR, "cfg80211: Failed to get station info\n");
+		ret = -EFAULT;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	woal_check_auto_tdls(wiphy, dev);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to dump the station information
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param idx             Station index
+ * @param mac             MAC address of the station
+ * @param sinfo           A pointer to station_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_dump_station(struct wiphy *wiphy,
+			   struct net_device *dev, int idx,
+			   t_u8 *mac, struct station_info *sinfo)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return woal_uap_cfg80211_dump_station(wiphy, dev, idx, mac,
+						      sinfo);
+	}
+#endif
+
+	if (!priv->media_connected || idx != 0) {
+		PRINTM(MINFO,
+		       "cfg80211: Media not connected or not for this station!\n");
+		LEAVE();
+		return -ENOENT;
+	}
+
+	moal_memcpy_ext(priv->phandle, mac, priv->cfg_bssid, ETH_ALEN,
+			ETH_ALEN);
+
+	if (MLAN_STATUS_SUCCESS != woal_cfg80211_dump_station_info(priv, sinfo)) {
+		PRINTM(MERROR, "cfg80211: Failed to get station info\n");
+		ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Convert driver band configuration to IEEE band type
+ *
+ *  @param band     Driver band configuration
+ *
+ *  @return         IEEE band type
+ */
+static t_u8
+woal_bandcfg_to_ieee_band(Band_Config_t bandcfg)
+{
+	t_u8 ret_radio_type = 0;
+
+	ENTER();
+
+	switch (bandcfg.chanBand) {
+	case BAND_5GHZ:
+		ret_radio_type = IEEE80211_BAND_5GHZ;
+		break;
+	case BAND_2GHZ:
+	default:
+		ret_radio_type = IEEE80211_BAND_2GHZ;
+		break;
+	}
+	LEAVE();
+	return ret_radio_type;
+}
+
+/**
+ * @brief Request the driver to dump survey info
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param idx             Station index
+ * @param survey          A pointer to survey_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_dump_survey(struct wiphy *wiphy,
+			  struct net_device *dev, int idx,
+			  struct survey_info *survey)
+{
+	int ret = -ENOENT;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	enum ieee80211_band band;
+	ChanStatistics_t *pchan_stats = NULL;
+	mlan_scan_resp scan_resp;
+
+	ENTER();
+	PRINTM(MIOCTL, "dump_survey idx=%d\n", idx);
+
+	memset(&scan_resp, 0, sizeof(scan_resp));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	pchan_stats = (ChanStatistics_t *)scan_resp.pchan_stats;
+	if (idx > (int)scan_resp.num_in_chan_stats || idx < 0) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (idx == (int)scan_resp.num_in_chan_stats ||
+	    !pchan_stats[idx].cca_scan_duration)
+		goto done;
+	ret = 0;
+	memset(survey, 0, sizeof(*survey));
+	band = woal_bandcfg_to_ieee_band(pchan_stats[idx].bandcfg);
+	survey->channel =
+		ieee80211_get_channel(wiphy,
+				      ieee80211_channel_to_frequency(pchan_stats
+								     [idx].
+								     chan_num
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+								     , band
+#endif
+				      ));
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = pchan_stats[idx].noise;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	survey->filled |= SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY;
+	survey->time = pchan_stats[idx].cca_scan_duration;
+	survey->time_busy = pchan_stats[idx].cca_busy_duration;
+#else
+	survey->filled |=
+		SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY;
+	survey->channel_time = pchan_stats[idx].cca_scan_duration;
+	survey->channel_time_busy = pchan_stats[idx].cca_busy_duration;
+#endif
+#endif
+done:
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static int
+woal_cfg80211_get_channel(struct wiphy *wiphy,
+			  struct wireless_dev *wdev,
+			  struct cfg80211_chan_def *chandef)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(wdev->netdev);
+	chan_band_info channel;
+
+	memset(&channel, 0x00, sizeof(channel));
+
+#ifdef UAP_SUPPORT
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		if (priv->bss_started == MTRUE) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_ap_channel(priv, MLAN_ACT_GET,
+						    MOAL_IOCTL_WAIT,
+						    &channel)) {
+				PRINTM(MERROR, "Fail to get ap channel \n");
+				return -EFAULT;
+			}
+		} else {
+			PRINTM(MIOCTL, "get_channel when AP is not started\n");
+			return -EFAULT;
+		}
+	} else
+#endif
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		if (priv->media_connected == MTRUE) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_get_sta_channel(priv, MOAL_IOCTL_WAIT,
+						 &channel)) {
+				PRINTM(MERROR, "Fail to get sta channel \n");
+				return -EFAULT;
+			}
+		} else {
+			PRINTM(MIOCTL,
+			       "get_channel when STA is not connected\n");
+			return -EFAULT;
+		}
+	} else {
+		PRINTM(MERROR, "BssRole not support %d.\n", GET_BSS_ROLE(priv));
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_FAILURE == woal_chandef_create(priv, chandef, &channel))
+		return -EFAULT;
+	else
+		return 0;
+}
+#endif
+
+/**
+ * @brief Request the driver to change the IEEE power save
+ * mdoe
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param enabled         Enable or disable
+ * @param timeout         Timeout value
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+			     struct net_device *dev, bool enabled, int timeout)
+{
+	int ret = 0, disabled;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+	if (moal_extflg_isset(priv->phandle, EXT_HW_TEST) ||
+	    (priv->phandle->params.ps_mode == MLAN_INIT_PARA_DISABLED)) {
+		PRINTM(MIOCTL, "block set power hw_test=%d ps_mode=%d\n",
+		       moal_extflg_isset(priv->phandle, EXT_HW_TEST),
+		       priv->phandle->params.ps_mode);
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (priv->phandle->driver_status) {
+		PRINTM(MERROR,
+		       "Block woal_cfg80211_set_power_mgmt in abnormal driver state\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
+		PRINTM(MIOCTL, "skip set power for p2p interface\n");
+		LEAVE();
+		return ret;
+	}
+#endif
+#endif
+	if (enabled)
+		disabled = 0;
+	else
+		disabled = 1;
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_SET,
+							   &disabled, timeout,
+							   MOAL_IOCTL_WAIT)) {
+		ret = -EOPNOTSUPP;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+/**
+ * @brief Request the driver to get the transmit power info
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param type            TX power adjustment type
+ * @param dbm             TX power in dbm
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_get_tx_power(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			   struct wireless_dev *wdev,
+#endif
+			   int *dbm)
+{
+	int ret = 0;
+	moal_private *priv = NULL;
+	mlan_power_cfg_t power_cfg;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+
+	ENTER();
+
+	if (!handle) {
+		PRINTM(MFATAL, "Unable to get handle\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+
+	if (!priv) {
+		PRINTM(MFATAL, "Unable to get priv in %s()\n", __func__);
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_tx_power(priv, MLAN_ACT_GET, &power_cfg)) {
+		LEAVE();
+		return -EFAULT;
+	}
+
+	*dbm = power_cfg.power_level;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to change the transmit power
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param type            TX power adjustment type
+ * @param dbm             TX power in dbm
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_set_tx_power(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			   struct wireless_dev *wdev,
+#endif
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
+			   enum tx_power_setting type,
+#else
+			   enum nl80211_tx_power_setting type,
+#endif
+			   int dbm)
+{
+	int ret = 0;
+	moal_private *priv = NULL;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	mlan_power_cfg_t power_cfg;
+
+	ENTER();
+
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		PRINTM(MFATAL, "Unable to get priv in %s()\n", __func__);
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (type) {
+		power_cfg.is_power_auto = 0;
+		power_cfg.power_level = dbm;
+	} else
+		power_cfg.is_power_auto = 1;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_tx_power(priv, MLAN_ACT_SET, &power_cfg))
+		ret = -EFAULT;
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+/**
+ * CFG802.11 operation handler for connection quality monitoring.
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param rssi_thold	  rssi threshold
+ * @param rssi_hyst		  rssi hysteresis
+ */
+static int
+woal_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
+				  struct net_device *dev,
+				  s32 rssi_thold, u32 rssi_hyst)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	ENTER();
+	priv->cqm_rssi_thold = rssi_thold;
+	priv->cqm_rssi_high_thold = rssi_thold;
+	priv->cqm_rssi_hyst = rssi_hyst;
+
+	PRINTM(MIOCTL, "rssi_thold=%d rssi_hyst=%d\n", (int)rssi_thold,
+	       (int)rssi_hyst);
+	woal_set_rssi_threshold(priv, 0, MOAL_IOCTL_WAIT);
+	LEAVE();
+	return 0;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+/**
+ * @brief remain on channel config
+ *
+ * @param priv              A pointer to moal_private structure
+ * @param wait_option       Wait option
+ * @param cancel			cancel remain on channel flag
+ * @param status            A pointer to status, success, in process or reject
+ * @param chan              A pointer to ieee80211_channel structure
+ * @param channel_type      channel_type,
+ * @param duration          Duration wait to receive frame
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_remain_on_channel_cfg(moal_private *priv, t_u8 wait_option,
+				    t_u8 remove, t_u8 *status,
+				    struct ieee80211_channel *chan,
+				    enum mlan_channel_type channel_type,
+				    t_u32 duration)
+{
+	mlan_ds_remain_chan chan_cfg;
+	int ret = 0;
+
+	ENTER();
+
+	if (!status || (!chan && !remove)) {
+		PRINTM(MERROR,
+		       "Invalid parameter status=%p, chan=%p, remove=%d\n",
+		       status, chan, remove);
+		LEAVE();
+		return -EFAULT;
+	}
+	memset(&chan_cfg, 0, sizeof(mlan_ds_remain_chan));
+	if (remove) {
+		chan_cfg.remove = MTRUE;
+	} else {
+#ifdef WIFI_DIRECT_SUPPORT
+		if (priv->phandle->is_go_timer_set) {
+			PRINTM(MINFO,
+			       "block remain on channel while go timer is on\n");
+			LEAVE();
+			return -EBUSY;
+		}
+#endif
+		if (chan->band == IEEE80211_BAND_2GHZ)
+			chan_cfg.bandcfg.chanBand = BAND_2GHZ;
+		else if (chan->band == IEEE80211_BAND_5GHZ)
+			chan_cfg.bandcfg.chanBand = BAND_5GHZ;
+		switch (channel_type) {
+		case CHAN_HT40MINUS:
+			chan_cfg.bandcfg.chan2Offset = SEC_CHAN_BELOW;
+			chan_cfg.bandcfg.chanWidth = CHAN_BW_40MHZ;
+			break;
+		case CHAN_HT40PLUS:
+			chan_cfg.bandcfg.chan2Offset = SEC_CHAN_ABOVE;
+			chan_cfg.bandcfg.chanWidth = CHAN_BW_40MHZ;
+			break;
+		case CHAN_VHT80:
+			chan_cfg.bandcfg.chanWidth = CHAN_BW_80MHZ;
+			break;
+		case CHAN_NO_HT:
+		case CHAN_HT20:
+		default:
+			break;
+		}
+		chan_cfg.channel =
+			ieee80211_frequency_to_channel(chan->center_freq);
+		chan_cfg.remain_period = duration;
+		PRINTM(MCMND,
+		       "Remain on Channel: chan=%d, offset=%d width=%d\n",
+		       chan_cfg.channel, chan_cfg.bandcfg.chan2Offset,
+		       chan_cfg.bandcfg.chanWidth);
+	}
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_set_remain_channel_ioctl(priv, wait_option, &chan_cfg))
+		*status = chan_cfg.status;
+	else
+		ret = -EFAULT;
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wdev                  A pointer to wireless_dev structure
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+				  struct wireless_dev *wdev, u64 cookie)
+#else
+/**
+ * @brief tx mgmt frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param cookie                A pointer to frame cookie
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
+				  struct net_device *dev, u64 cookie)
+#endif
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+	t_u8 status = 1;
+	moal_private *remain_priv = NULL;
+
+	ENTER();
+
+	if (priv->phandle->remain_on_channel) {
+		remain_priv =
+			priv->phandle->priv[priv->phandle->remain_bss_index];
+		if (!remain_priv) {
+			PRINTM(MERROR,
+			       "mgmt_tx_cancel_wait: Wrong remain_bss_index=%d\n",
+			       priv->phandle->remain_bss_index);
+			ret = -EFAULT;
+			goto done;
+		}
+		if (woal_cfg80211_remain_on_channel_cfg(remain_priv,
+							MOAL_IOCTL_WAIT, MTRUE,
+							&status, NULL, 0, 0)) {
+			PRINTM(MERROR,
+			       "mgmt_tx_cancel_wait: Fail to cancel remain on channel\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (priv->phandle->cookie) {
+			cfg80211_remain_on_channel_expired(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+								  remain_priv->
+								  netdev,
+#else
+								  remain_priv->
+								  wdev,
+#endif
+								  priv->
+								  phandle->
+								  cookie,
+								  &priv->
+								  phandle->chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+								  priv->
+								  phandle->
+								  channel_type,
+#endif
+								  GFP_ATOMIC);
+			priv->phandle->cookie = 0;
+		}
+		priv->phandle->remain_on_channel = MFALSE;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ * @brief Make chip remain on channel
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wdev                  A pointer to wireless_dev structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param channel_type          Channel type
+ * @param duration              Duration for timer
+ * @param cookie                A pointer to timer cookie
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
+				struct ieee80211_channel *chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+				enum nl80211_channel_type channel_type,
+#endif
+				unsigned int duration, u64 * cookie)
+#else
+/**
+ * @brief Make chip remain on channel
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param chan                  A pointer to ieee80211_channel structure
+ * @param channel_type          Channel type
+ * @param duration              Duration for timer
+ * @param cookie                A pointer to timer cookie
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
+				struct ieee80211_channel *chan,
+				enum nl80211_channel_type channel_type,
+				unsigned int duration, u64 * cookie)
+#endif
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+	t_u8 status = 1;
+	moal_private *remain_priv = NULL;
+
+	ENTER();
+
+	if (!chan || !cookie) {
+		PRINTM(MERROR, "Invalid parameter for remain on channel\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/** cancel previous remain on channel */
+	if (priv->phandle->remain_on_channel &&
+	    ((priv->phandle->chan.center_freq != chan->center_freq))) {
+		remain_priv =
+			priv->phandle->priv[priv->phandle->remain_bss_index];
+		if (!remain_priv) {
+			PRINTM(MERROR,
+			       "remain_on_channel: Wrong remain_bss_index=%d\n",
+			       priv->phandle->remain_bss_index);
+			ret = -EFAULT;
+			goto done;
+		}
+		if (woal_cfg80211_remain_on_channel_cfg(remain_priv,
+							MOAL_IOCTL_WAIT, MTRUE,
+							&status, NULL, 0, 0)) {
+			PRINTM(MERROR,
+			       "remain_on_channel: Fail to cancel remain on channel\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->phandle->cookie = 0;
+		priv->phandle->remain_on_channel = MFALSE;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE,
+						&status, chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+						channel_type,
+#else
+						0,
+#endif
+						(t_u32)duration)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (status) {
+		PRINTM(MMSG,
+		       "%s: Set remain on Channel: channel=%d with status=%d\n",
+		       dev->name,
+		       ieee80211_frequency_to_channel(chan->center_freq),
+		       status);
+		if (!priv->phandle->remain_on_channel) {
+			priv->phandle->is_remain_timer_set = MTRUE;
+			woal_mod_timer(&priv->phandle->remain_timer, duration);
+		}
+	}
+
+	/* remain on channel operation success */
+	/* we need update the value cookie */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+	*cookie = (u64) random32() | 1;
+#else
+	*cookie = (u64) prandom_u32() | 1;
+#endif
+	priv->phandle->remain_on_channel = MTRUE;
+	priv->phandle->remain_bss_index = priv->bss_index;
+	priv->phandle->cookie = *cookie;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+	priv->phandle->channel_type = channel_type;
+#endif
+	moal_memcpy_ext(priv->phandle, &priv->phandle->chan, chan,
+			sizeof(struct ieee80211_channel),
+			sizeof(priv->phandle->chan));
+
+	if (status == 0)
+		PRINTM(MIOCTL,
+		       "%s: Set remain on Channel: channel=%d cookie = %#llx\n",
+		       dev->name,
+		       ieee80211_frequency_to_channel(chan->center_freq),
+		       priv->phandle->cookie);
+
+	cfg80211_ready_on_channel(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+					 dev,
+#else
+					 priv->wdev,
+#endif
+					 *cookie, chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+					 channel_type,
+#endif
+					 duration, GFP_KERNEL);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+/**
+ * @brief Cancel remain on channel
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wdev                  A pointer to wireless_dev structure
+ * @param cookie                A pointer to timer cookie
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
+				       struct wireless_dev *wdev, u64 cookie)
+#else
+/**
+ * @brief Cancel remain on channel
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param cookie                A pointer to timer cookie
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
+				       struct net_device *dev, u64 cookie)
+#endif
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	moal_private *remain_priv = NULL;
+	int ret = 0;
+	t_u8 status = 1;
+
+	ENTER();
+	PRINTM(MIOCTL, "Cancel remain on Channel: cookie = %#llx\n", cookie);
+	remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index];
+	if (!remain_priv) {
+		PRINTM(MERROR,
+		       "cancel_remain_on_channel: Wrong remain_bss_index=%d\n",
+		       priv->phandle->remain_bss_index);
+		ret = -EFAULT;
+		goto done;
+	}
+	if (woal_cfg80211_remain_on_channel_cfg(remain_priv, MOAL_IOCTL_WAIT,
+						MTRUE, &status, NULL, 0, 0)) {
+		PRINTM(MERROR,
+		       "cancel_remain_on_channel: Fail to cancel remain on channel\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	priv->phandle->remain_on_channel = MFALSE;
+	if (priv->phandle->cookie)
+		priv->phandle->cookie = 0;
+done:
+	LEAVE();
+	return ret;
+}
+#endif /* KERNEL_VERSION */
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+/**
+ * @brief start sched scan
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param request               A pointer to struct cfg80211_sched_scan_request
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_sched_scan_start(struct wiphy *wiphy, struct net_device *dev,
+			       struct cfg80211_sched_scan_request *request)
+{
+	struct ieee80211_channel *chan = NULL;
+	int i = 0;
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	struct cfg80211_ssid *ssid = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	t_u8 buf[ETH_ALEN];
+#endif
+	ENTER();
+
+#ifdef UAP_CFG80211
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		LEAVE();
+		return -EFAULT;
+	}
+#endif
+
+	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
+	if (!request) {
+		PRINTM(MERROR, "Invalid sched_scan req parameter\n");
+		LEAVE();
+		return -EINVAL;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
+	PRINTM(MIOCTL,
+	       "%s sched scan: n_ssids=%d n_match_sets=%d n_channels=%d interval=%d ie_len=%d\n",
+	       priv->netdev->name, request->n_ssids, request->n_match_sets,
+	       request->n_channels, request->scan_plans[0].interval,
+	       (int)request->ie_len);
+#else
+	PRINTM(MIOCTL,
+	       "%s sched scan: n_ssids=%d n_match_sets=%d n_channels=%d interval=%d ie_len=%d\n",
+	       priv->netdev->name, request->n_ssids, request->n_match_sets,
+	       request->n_channels, request->interval, (int)request->ie_len);
+#endif
+	/** We have pending scan, start bgscan later */
+	if (priv->phandle->scan_pending_on_block)
+		priv->scan_cfg.start_later = MTRUE;
+	for (i = 0; i < request->n_match_sets; i++) {
+		ssid = &request->match_sets[i].ssid;
+		strncpy(priv->scan_cfg.ssid_list[i].ssid, ssid->ssid,
+			ssid->ssid_len);
+		priv->scan_cfg.ssid_list[i].max_len = 0;
+		PRINTM(MIOCTL, "sched scan: ssid=%s\n", ssid->ssid);
+	}
+	/** Add broadcast scan, when n_match_sets = 0 */
+	if (!request->n_match_sets)
+		priv->scan_cfg.ssid_list[0].max_len = 0xff;
+	for (i = 0; i < (int)MIN(WLAN_BG_SCAN_CHAN_MAX, request->n_channels);
+	     i++) {
+		chan = request->channels[i];
+		priv->scan_cfg.chan_list[i].chan_number = chan->hw_value;
+		priv->scan_cfg.chan_list[i].radio_type = chan->band;
+		if (chan->flags &
+		    (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR))
+			priv->scan_cfg.chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_PASSIVE;
+		else
+			priv->scan_cfg.chan_list[i].scan_type =
+				MLAN_SCAN_TYPE_ACTIVE;
+		priv->scan_cfg.chan_list[i].scan_time = 0;
+#ifdef WIFI_DIRECT_SUPPORT
+		if (priv->phandle->miracast_mode)
+			priv->scan_cfg.chan_list[i].scan_time =
+				priv->phandle->miracast_scan_time;
+#endif
+	}
+	priv->scan_cfg.chan_per_scan =
+		MIN(WLAN_BG_SCAN_CHAN_MAX, request->n_channels);
+
+	/** set scan request IES */
+	if (request->ie && request->ie_len) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0,
+						(t_u8 *)request->ie,
+						request->ie_len,
+						MGMT_MASK_PROBE_REQ,
+						MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Fail to set sched scan IE\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		/** Clear SCAN IE in Firmware */
+		if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK)
+			woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0,
+						    NULL, 0, NULL, 0,
+						    MGMT_MASK_PROBE_REQ,
+						    MOAL_IOCTL_WAIT);
+	}
+
+	/* Interval between scan cycles in milliseconds,supplicant set to 10
+	 * second */
+	/* We want to use 30 second for per scan cycle */
+	priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
+	if (request->scan_plans[0].interval * 1000 > MIN_BGSCAN_INTERVAL)
+		priv->scan_cfg.scan_interval =
+			request->scan_plans[0].interval * 1000;
+	if (request->n_scan_plans >= 2) {
+		priv->scan_cfg.config_ees = MTRUE;
+		priv->scan_cfg.ees_mode =
+			MBIT(EES_MODE_HIGH) | MBIT(EES_MODE_MID);
+		priv->scan_cfg.high_period =
+			request->scan_plans[0].interval * 1000;
+		priv->scan_cfg.high_period_count =
+			request->scan_plans[0].iterations;
+		priv->scan_cfg.mid_period = request->scan_plans[1].interval;
+		if (request->scan_plans[1].iterations == 0)
+			priv->scan_cfg.mid_period_count = DEF_REPEAT_COUNT;
+		else
+			priv->scan_cfg.mid_period_count =
+				request->scan_plans[1].iterations;
+		if (request->n_scan_plans == 3) {
+			priv->scan_cfg.ees_mode |= MBIT(EES_MODE_LOW);
+			priv->scan_cfg.low_period =
+				request->scan_plans[2].interval;
+			priv->scan_cfg.low_period_count = DEF_REPEAT_COUNT;
+		}
+	}
+#else
+	if (request->interval > MIN_BGSCAN_INTERVAL)
+		priv->scan_cfg.scan_interval = request->interval;
+#endif
+	priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT;
+	priv->scan_cfg.report_condition =
+		BG_SCAN_SSID_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
+	priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
+	priv->scan_cfg.action = BG_SCAN_ACT_SET;
+	priv->scan_cfg.enable = MTRUE;
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->phandle->miracast_mode)
+		priv->scan_cfg.scan_chan_gap = priv->phandle->scan_chan_gap;
+	else
+		priv->scan_cfg.scan_chan_gap = 0;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+		PRINTM(MIOCTL, "NL80211_SCAN_FLAG_RANDOM_ADDR is set\n");
+		get_random_bytes(buf, ETH_ALEN);
+		for (i = 0; i < ETH_ALEN; i++) {
+			buf[i] &= ~request->mac_addr_mask[i];
+			buf[i] |= request->mac_addr[i] &
+				request->mac_addr_mask[i];
+		}
+		moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac, buf,
+				ETH_ALEN, sizeof(priv->scan_cfg.random_mac));
+	} else
+#endif
+		moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
+				priv->random_mac, ETH_ALEN,
+				sizeof(priv->scan_cfg.random_mac));
+
+	PRINTM(MCMND, "wlan:random_mac " MACSTR "\n",
+	       MAC2STR(priv->scan_cfg.random_mac));
+	if (MLAN_STATUS_SUCCESS ==
+	    woal_request_bgscan(priv, MOAL_IOCTL_WAIT, &priv->scan_cfg)) {
+		PRINTM(MMSG, "wlan: sched scan start\n");
+		priv->sched_scanning = MTRUE;
+		priv->bg_scan_start = MTRUE;
+		priv->bg_scan_reported = MFALSE;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+		priv->bg_scan_reqid = request->reqid;
+#endif
+	} else
+		ret = -EFAULT;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief stop sched scan
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			      , u64 reqid
+#endif
+	)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	ENTER();
+	PRINTM(MMSG, "wlan: sched scan stop\n");
+	priv->sched_scanning = MFALSE;
+	woal_stop_bg_scan(priv, MOAL_NO_WAIT);
+	priv->bg_scan_start = MFALSE;
+	priv->bg_scan_reported = MFALSE;
+	LEAVE();
+	return 0;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+/**
+ * @brief cfg80211_resume handler
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_resume(struct wiphy *wiphy)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) && defined(CONFIG_PM)
+	struct cfg80211_wowlan_wakeup wakeup_report;
+#endif
+	mlan_ds_hs_wakeup_reason wakeup_reason;
+	int i;
+
+	PRINTM(MCMND, "<--- Enter woal_cfg80211_resume --->\n");
+
+	if (!priv) {
+		PRINTM(MERROR, "woal_cfg80211_resume: priv is NULL\n");
+		goto done;
+	}
+
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
+			if (handle->priv[i]->last_event & EVENT_BG_SCAN_REPORT) {
+				if (handle->priv[i]->sched_scanning) {
+					woal_inform_bss_from_scan_result
+						(handle->priv[i], NULL,
+						 MOAL_IOCTL_WAIT);
+					woal_report_sched_scan_result(handle->
+								      priv[i]);
+					handle->priv[i]->last_event = 0;
+					PRINTM(MCMND,
+					       "Report sched scan result in cfg80211 resume\n");
+				}
+				if (!moal_extflg_isset(handle, EXT_HW_TEST) &&
+				    handle->priv[i]->roaming_enabled) {
+					handle->priv[i]->roaming_required =
+						MTRUE;
+#ifdef ANDROID_KERNEL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+					__pm_wakeup_event(&handle->ws,
+							  ROAMING_WAKE_LOCK_TIMEOUT);
+#else
+					wake_lock_timeout(&handle->wake_lock,
+							  msecs_to_jiffies
+							  (ROAMING_WAKE_LOCK_TIMEOUT));
+#endif
+#endif
+					wake_up_interruptible(&handle->
+							      reassoc_thread.
+							      wait_q);
+				}
+			}
+		}
+	}
+
+	woal_get_wakeup_reason(priv, &wakeup_reason);
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext))
+		woal_wake_reason_logger(priv, wakeup_reason);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) && defined(CONFIG_PM)
+	memset(&wakeup_report, 0, sizeof(struct cfg80211_wowlan_wakeup));
+	wakeup_report.pattern_idx = -1;
+
+	switch (wakeup_reason.hs_wakeup_reason) {
+	case NO_HSWAKEUP_REASON:
+		break;
+	case BCAST_DATA_MATCHED:
+		break;
+	case MCAST_DATA_MATCHED:
+		break;
+	case UCAST_DATA_MATCHED:
+		break;
+	case MASKTABLE_EVENT_MATCHED:
+		break;
+	case NON_MASKABLE_EVENT_MATCHED:
+		break;
+	case NON_MASKABLE_CONDITION_MATCHED:
+		if (wiphy->wowlan_config && wiphy->wowlan_config->disconnect)
+			wakeup_report.disconnect = true;
+		break;
+	case MAGIC_PATTERN_MATCHED:
+		if (wiphy->wowlan_config && wiphy->wowlan_config->magic_pkt)
+			wakeup_report.magic_pkt = true;
+		if (wiphy->wowlan_config && wiphy->wowlan_config->n_patterns)
+			wakeup_report.pattern_idx = 1;
+		break;
+	case CONTROL_FRAME_MATCHED:
+		break;
+	case MANAGEMENT_FRAME_MATCHED:
+		break;
+	case GTK_REKEY_FAILURE:
+		if (wiphy->wowlan_config &&
+		    wiphy->wowlan_config->gtk_rekey_failure)
+			wakeup_report.gtk_rekey_failure = true;
+		break;
+	default:
+		break;
+	}
+
+	if ((wakeup_reason.hs_wakeup_reason > 0) &&
+	    (wakeup_reason.hs_wakeup_reason <= 10)) {
+		cfg80211_report_wowlan_wakeup(priv->wdev, &wakeup_report,
+					      GFP_KERNEL);
+	}
+#endif
+
+done:
+	handle->cfg80211_suspend = MFALSE;
+	PRINTM(MCMND, "<--- Leave woal_cfg80211_resume --->\n");
+	return 0;
+}
+
+/**
+ * @brief is_wowlan_pattern_supported
+ *
+ * @param priv                 A pointer to moal_private
+ * @param pat                 A pointer to wowlan pattern
+ * @param byte_seq       A pointer to byte_seq
+ *
+ * @return                      1 -- support, 0 -- not support
+ */
+static t_bool
+is_wowlan_pattern_supported(moal_private *priv,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+			    struct cfg80211_pkt_pattern *pat,
+#else
+			    struct cfg80211_wowlan_trig_pkt_pattern
+			    *pat,
+#endif
+			    s8 * byte_seq)
+{
+	int j, k, valid_byte_cnt = 0;
+	t_bool dont_care_byte = MFALSE;
+
+	for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
+		for (k = 0; k < 8; k++) {
+			if (pat->mask[j] & 1 << k) {
+				moal_memcpy_ext(priv->phandle,
+						byte_seq + valid_byte_cnt,
+						&pat->pattern[j * 8 + k], 1, 1);
+				valid_byte_cnt++;
+				if (dont_care_byte)
+					return MFALSE;
+			} else {
+				if (valid_byte_cnt)
+					dont_care_byte = MTRUE;
+			}
+
+			if (valid_byte_cnt > MAX_NUM_BYTE_SEQ)
+				return MFALSE;
+		}
+	}
+
+	byte_seq[MAX_NUM_BYTE_SEQ] = valid_byte_cnt;
+
+	return MTRUE;
+}
+
+/**
+ * @brief cfg80211_suspend handler
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param wow                   A pointer to cfg80211_wowlan
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	int i;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_mef_flt_cfg mef_cfg;
+	mef_entry_t *mef_entry = NULL;
+	int filt_num = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	t_bool first_pat = MTRUE;
+#endif
+	t_u8 byte_seq[MAX_NUM_BYTE_SEQ + 1];
+	const t_u8 ipv4_mc_mac[] = { 0x33, 0x33 };
+	const t_u8 ipv6_mc_mac[] = { 0x01, 0x00, 0x5e };
+	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	mlan_ds_hs_cfg hscfg;
+
+	PRINTM(MCMND, "<--- Enter woal_cfg80211_suspend --->\n");
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
+			if (handle->scan_request) {
+				PRINTM(MIOCTL,
+				       "Cancel pending scan in woal_cfg80211_suspend\n");
+				woal_cancel_scan(handle->priv[i],
+						 MOAL_IOCTL_WAIT);
+			}
+			handle->priv[i]->last_event = 0;
+		}
+	}
+
+	handle->cfg80211_suspend = MTRUE;
+	if (!wow) {
+		PRINTM(MERROR, "None of the WOWLAN triggers enabled\n");
+		ret = 0;
+		goto done;
+	}
+
+	if (!priv || !priv->media_connected) {
+		PRINTM(MERROR,
+		       "Can not configure WOWLAN in disconnected state\n");
+		ret = 0;
+		goto done;
+	}
+
+	PRINTM(MCMND, "wow->n_patterns=%d\n", wow->n_patterns);
+	PRINTM(MCMND, "wow->any=%d\n", wow->any);
+	PRINTM(MCMND, "wow->disconnect=%d\n", wow->disconnect);
+	PRINTM(MCMND, "wow->magic_pkt=%d\n", wow->magic_pkt);
+	PRINTM(MCMND, "wow->gtk_rekey_failure=%d\n", wow->gtk_rekey_failure);
+	PRINTM(MCMND, "wow->eap_identity_req=%d\n", wow->eap_identity_req);
+	PRINTM(MCMND, "wow->four_way_handshake=%d\n", wow->four_way_handshake);
+	PRINTM(MCMND, "wow->rfkill_release=%d\n", wow->rfkill_release);
+
+	if (!(wow->n_patterns) && !(wow->magic_pkt)) {
+		PRINTM(MCMND, "No pattern or magic packet configured\n");
+		ret = 0;
+		goto done;
+	}
+
+	memset(&mef_cfg, 0, sizeof(mef_cfg));
+	mef_cfg.mef_act_type = MEF_ACT_WOWLAN;
+	mef_entry = &mef_cfg.mef_entry;
+
+	mef_entry->mode = MEF_MODE_HOST_SLEEP;
+	mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
+
+	for (i = 0; i < wow->n_patterns; i++) {
+		memset(byte_seq, 0, sizeof(byte_seq));
+		if (!is_wowlan_pattern_supported(priv, &wow->patterns[i],
+						 byte_seq)) {
+			PRINTM(MERROR, "Pattern not supported\n");
+			ret = -EOPNOTSUPP;
+			goto done;
+		}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+		if (!wow->patterns[i].pkt_offset) {
+#endif
+			if (!(byte_seq[0] & 0x01) &&
+			    (byte_seq[MAX_NUM_BYTE_SEQ] == 1)) {
+				mef_cfg.criteria |= CRITERIA_UNICAST;
+				continue;
+			} else if (is_broadcast_ether_addr(byte_seq)) {
+				mef_cfg.criteria |= CRITERIA_BROADCAST;
+				continue;
+			} else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
+				    (byte_seq[MAX_NUM_BYTE_SEQ] == 2)) ||
+				   (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
+				    (byte_seq[MAX_NUM_BYTE_SEQ] == 3))) {
+				mef_cfg.criteria |= CRITERIA_MULTICAST;
+				continue;
+			}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+		}
+
+		mef_entry->filter_item[filt_num].fill_flag =
+			(FILLING_TYPE | FILLING_REPEAT | FILLING_BYTE_SEQ |
+			 FILLING_OFFSET);
+		mef_entry->filter_item[filt_num].repeat = 1;
+		mef_entry->filter_item[filt_num].offset =
+			wow->patterns[i].pkt_offset;
+		moal_memcpy_ext(priv->phandle,
+				mef_entry->filter_item[filt_num].byte_seq,
+				byte_seq, MAX_NUM_BYTE_SEQ,
+				sizeof(mef_entry->filter_item[filt_num].
+				       byte_seq));
+		mef_entry->filter_item[filt_num].num_byte_seq =
+			byte_seq[MAX_NUM_BYTE_SEQ];
+		mef_entry->filter_item[filt_num].type = TYPE_BYTE_EQ;
+
+		if (first_pat)
+			first_pat = MFALSE;
+		else
+			mef_entry->rpn[filt_num] = RPN_TYPE_OR;
+
+		filt_num++;
+#endif
+	}
+
+	if (wow->magic_pkt) {
+		mef_cfg.criteria |= CRITERIA_UNICAST | CRITERIA_BROADCAST |
+			CRITERIA_MULTICAST;
+		mef_entry->filter_item[filt_num].fill_flag =
+			(FILLING_TYPE | FILLING_REPEAT | FILLING_BYTE_SEQ |
+			 FILLING_OFFSET);
+		mef_entry->filter_item[filt_num].repeat = 16;
+		moal_memcpy_ext(priv->phandle,
+				mef_entry->filter_item[filt_num].byte_seq,
+				priv->current_addr, ETH_ALEN,
+				sizeof(mef_entry->filter_item[filt_num].
+				       byte_seq));
+		mef_entry->filter_item[filt_num].num_byte_seq = ETH_ALEN;
+		mef_entry->filter_item[filt_num].offset = 56;
+		mef_entry->filter_item[filt_num].type = TYPE_BYTE_EQ;
+		if (filt_num)
+			mef_entry->rpn[filt_num] = RPN_TYPE_OR;
+		filt_num++;
+		mef_entry->filter_item[filt_num].fill_flag =
+			(FILLING_TYPE | FILLING_REPEAT | FILLING_BYTE_SEQ |
+			 FILLING_OFFSET);
+		mef_entry->filter_item[filt_num].repeat = 16;
+		moal_memcpy_ext(priv->phandle,
+				mef_entry->filter_item[filt_num].byte_seq,
+				priv->current_addr, ETH_ALEN,
+				sizeof(mef_entry->filter_item[filt_num].
+				       byte_seq));
+		mef_entry->filter_item[filt_num].num_byte_seq = ETH_ALEN;
+		mef_entry->filter_item[filt_num].offset = 28;
+		mef_entry->filter_item[filt_num].type = TYPE_BYTE_EQ;
+		if (filt_num)
+			mef_entry->rpn[filt_num] = RPN_TYPE_OR;
+		filt_num++;
+	}
+
+	mef_entry->filter_num = filt_num;
+
+	if (!mef_cfg.criteria)
+		mef_cfg.criteria = CRITERIA_BROADCAST | CRITERIA_UNICAST |
+			CRITERIA_MULTICAST;
+
+	status = woal_set_get_wowlan_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					    &mef_cfg);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "woal_set_get_wowlan_config fail!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
+	status = woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
+					&hscfg);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Fail to get HS parameter in woal_cfg80211_suspend: 0x%x 0x%x 0x%x\n",
+		       hscfg.conditions, hscfg.gap, hscfg.gpio);
+		ret = -EFAULT;
+		goto done;
+	}
+	hscfg.is_invoke_hostcmd = MFALSE;
+	if (wow->n_patterns || wow->magic_pkt)
+		hscfg.conditions = 0;
+	status = woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					&hscfg);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Fail to set HS parameter in woal_cfg80211_suspend: 0x%x 0x%x 0x%x\n",
+		       hscfg.conditions, hscfg.gap, hscfg.gpio);
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	PRINTM(MCMND, "<--- Leave woal_cfg80211_suspend --->\n");
+	return ret;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+static void
+woal_cfg80211_set_wakeup(struct wiphy *wiphy, bool enabled)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+
+	device_set_wakeup_enable(handle->hotplug_device, enabled);
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+/**
+ *  @brief TDLS operation ioctl handler
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param peer     A pointer to peer mac
+ *  @apram action   action for TDLS
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_tdls_oper(moal_private *priv, u8 *peer, t_u8 action)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TDLS_OPER;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+	misc->param.tdls_oper.tdls_action = action;
+	moal_memcpy_ext(priv->phandle, misc->param.tdls_oper.peer_mac, peer,
+			ETH_ALEN, sizeof(misc->param.tdls_oper.peer_mac));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief TDLS operation ioctl handler
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param peer         A pointer to peer mac
+ *  @param tdls_ies     A pointer to mlan_ds_misc_tdls_ies structure
+ *  @param flags        TDLS ie flags
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_tdls_get_ies(moal_private *priv, u8 *peer,
+		  mlan_ds_misc_tdls_ies *tdls_ies, t_u16 flags)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GET_TDLS_IES;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_GET;
+	misc->param.tdls_ies.flags = flags;
+	moal_memcpy_ext(priv->phandle, misc->param.tdls_ies.peer_mac, peer,
+			ETH_ALEN, sizeof(misc->param.tdls_ies.peer_mac));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (tdls_ies)
+		moal_memcpy_ext(priv->phandle, tdls_ies, &misc->param.tdls_ies,
+				sizeof(mlan_ds_misc_tdls_ies),
+				sizeof(mlan_ds_misc_tdls_ies));
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief append tdls ext_capability
+ *
+ * @param skb                   A pointer to sk_buff structure
+ *
+ * @return                      N/A
+ */
+static void
+woal_tdls_add_ext_capab(moal_private *priv, struct sk_buff *skb,
+			mlan_ds_misc_tdls_ies *tdls_ies)
+{
+	u8 *pos = NULL;
+	if (tdls_ies->ext_cap[0] == WLAN_EID_EXT_CAPABILITY) {
+		pos = (void *)skb_put(skb, sizeof(IEEEtypes_ExtCap_t));
+		moal_memcpy_ext(priv->phandle, pos, tdls_ies->ext_cap,
+				sizeof(IEEEtypes_ExtCap_t),
+				sizeof(IEEEtypes_ExtCap_t));
+	} else {
+		PRINTM(MERROR, "Fail to append tdls ext_capability\n");
+	}
+}
+
+/**
+ * @brief append supported rates
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param skb                   A pointer to sk_buff structure
+ * @param band                  AP's band
+ *
+ * @return                      N/A
+ */
+static void
+woal_add_supported_rates_ie(moal_private *priv, struct sk_buff *skb,
+			    enum ieee80211_band band)
+{
+	t_u8 basic_rates[] = { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24 };
+	t_u8 basic_rates_5G[] = { 0x0c, 0x12, 0x18, 0x24,
+		0x30, 0x48, 0x60, 0x6c
+	};
+	t_u8 *pos;
+	t_u8 rate_num = 0;
+	if (band == IEEE80211_BAND_2GHZ)
+		rate_num = sizeof(basic_rates);
+	else
+		rate_num = sizeof(basic_rates_5G);
+
+	if (skb_tailroom(skb) < rate_num + 2)
+		return;
+
+	pos = skb_put(skb, rate_num + 2);
+	*pos++ = WLAN_EID_SUPP_RATES;
+	*pos++ = rate_num;
+	if (band == IEEE80211_BAND_2GHZ)
+		moal_memcpy_ext(priv->phandle, pos, basic_rates, rate_num,
+				rate_num);
+	else
+		moal_memcpy_ext(priv->phandle, pos, basic_rates_5G, rate_num,
+				rate_num);
+	return;
+}
+
+/**
+ * @brief append ext_supported rates
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param skb                   A pointer to sk_buff structure
+ * @param band                  AP's band
+ *
+ * @return                      N/A
+ */
+static void
+woal_add_ext_supported_rates_ie(moal_private *priv,
+				struct sk_buff *skb, enum ieee80211_band band)
+{
+	t_u8 ext_rates[] = { 0x0c, 0x12, 0x18, 0x60 };
+	t_u8 *pos;
+	t_u8 rate_num = sizeof(ext_rates);
+
+	if (band != IEEE80211_BAND_2GHZ)
+		return;
+
+	if (skb_tailroom(skb) < rate_num + 2)
+		return;
+
+	pos = skb_put(skb, rate_num + 2);
+	*pos++ = WLAN_EID_EXT_SUPP_RATES;
+	*pos++ = rate_num;
+	moal_memcpy_ext(priv->phandle, pos, ext_rates, rate_num, rate_num);
+	return;
+}
+
+/**
+ * @brief append wmm ie
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param skb                   A pointer to sk_buff structure
+ * @param wmm_type         WMM_TYPE_INFO/WMM_TYPE_PARAMETER
+ * @param pQosInfo           A pointer to qos info
+ *
+ * @return                      N/A
+ */
+static void
+woal_add_wmm_ie(moal_private *priv, struct sk_buff *skb,
+		t_u8 wmm_type, t_u8 *pQosInfo)
+{
+	t_u8 wmmInfoElement[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
+	t_u8 wmmParamElement[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
+	t_u8 ac_vi[] = { 0x42, 0x43, 0x5e, 0x00 };
+	t_u8 ac_vo[] = { 0x62, 0x32, 0x2f, 0x00 };
+	t_u8 ac_be[] = { 0x03, 0xa4, 0x00, 0x00 };
+	t_u8 ac_bk[] = { 0x27, 0xa4, 0x00, 0x00 };
+	t_u8 qosInfo = 0x0;
+	t_u8 reserved = 0;
+	t_u8 wmm_id = 221;
+	t_u8 wmmParamIe_len = 25;
+	t_u8 wmmInfoIe_len = 7;
+	t_u8 len = 0;
+	t_u8 *pos;
+
+	qosInfo = (pQosInfo == NULL) ? 0xf : (*pQosInfo);
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		if (skb_tailroom(skb) < (wmmParamIe_len + 2))
+			return;
+		pos = skb_put(skb, wmmParamIe_len + 2);
+		len = wmmParamIe_len;
+	} else {
+		if (skb_tailroom(skb) < (wmmInfoIe_len + 2))
+			return;
+		pos = skb_put(skb, wmmInfoIe_len + 2);
+		len = wmmInfoIe_len;
+	}
+
+	*pos++ = wmm_id;
+	*pos++ = len;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		moal_memcpy_ext(priv->phandle, pos, wmmParamElement,
+				sizeof(wmmParamElement),
+				sizeof(wmmParamElement));
+		pos += sizeof(wmmParamElement);
+	} else {
+		moal_memcpy_ext(priv->phandle, pos, wmmInfoElement,
+				sizeof(wmmInfoElement), sizeof(wmmInfoElement));
+		pos += sizeof(wmmInfoElement);
+	}
+	*pos++ = qosInfo;
+	/*wmm parameter */
+	if (wmm_type == WMM_TYPE_PARAMETER) {
+		*pos++ = reserved;
+		moal_memcpy_ext(priv->phandle, pos, ac_be, sizeof(ac_be),
+				sizeof(ac_be));
+		pos += sizeof(ac_be);
+		moal_memcpy_ext(priv->phandle, pos, ac_bk, sizeof(ac_bk),
+				sizeof(ac_bk));
+		pos += sizeof(ac_bk);
+		moal_memcpy_ext(priv->phandle, pos, ac_vi, sizeof(ac_vi),
+				sizeof(ac_vi));
+		pos += sizeof(ac_vi);
+		moal_memcpy_ext(priv->phandle, pos, ac_vo, sizeof(ac_vo),
+				sizeof(ac_vo));
+	}
+	return;
+}
+
+/**
+ * @brief update tdls peer status
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param peer_addr             A point to peer mac address
+ * @param link_status           link status
+ *
+ * @return                      N/A
+ */
+static t_void
+woal_updata_peer_status(moal_private *priv, t_u8 *peer_addr,
+			tdlsStatus_e link_status)
+{
+	struct tdls_peer *peer = NULL;
+	unsigned long flags;
+	if (priv && priv->enable_auto_tdls) {
+		spin_lock_irqsave(&priv->tdls_lock, flags);
+		list_for_each_entry(peer, &priv->tdls_list, link) {
+			if (!memcmp(peer->peer_addr, peer_addr, ETH_ALEN)) {
+				if ((link_status == TDLS_NOT_SETUP) &&
+				    (peer->link_status ==
+				     TDLS_SETUP_INPROGRESS))
+					peer->num_failure++;
+				else if (link_status == TDLS_SETUP_COMPLETE)
+					peer->num_failure = 0;
+				peer->link_status = link_status;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&priv->tdls_lock, flags);
+	}
+}
+
+/**
+ * @brief add tdls peer
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param peer                  A point to peer address
+ *
+ * @return                      N/A
+ */
+static t_void
+woal_add_tdls_peer(moal_private *priv, t_u8 *peer)
+{
+	struct tdls_peer *tdls_peer = NULL;
+	unsigned long flags;
+	t_u8 find_peer = MFALSE;
+	if (priv && priv->enable_auto_tdls) {
+		spin_lock_irqsave(&priv->tdls_lock, flags);
+		list_for_each_entry(tdls_peer, &priv->tdls_list, link) {
+			if (!memcmp(tdls_peer->peer_addr, peer, ETH_ALEN)) {
+				tdls_peer->link_status = TDLS_SETUP_INPROGRESS;
+				tdls_peer->rssi_jiffies = jiffies;
+				find_peer = MTRUE;
+				break;
+			}
+		}
+		if (!find_peer) {
+			/* create new TDLS peer */
+			tdls_peer =
+				kzalloc(sizeof(struct tdls_peer), GFP_ATOMIC);
+			if (tdls_peer) {
+				moal_memcpy_ext(priv->phandle,
+						tdls_peer->peer_addr, peer,
+						ETH_ALEN,
+						sizeof(tdls_peer->peer_addr));
+				tdls_peer->link_status = TDLS_SETUP_INPROGRESS;
+				tdls_peer->rssi_jiffies = jiffies;
+				INIT_LIST_HEAD(&tdls_peer->link);
+				list_add_tail(&tdls_peer->link,
+					      &priv->tdls_list);
+				PRINTM(MCMND,
+				       "Add to TDLS list: peer=" MACSTR "\n",
+				       MAC2STR(peer));
+			}
+		}
+		spin_unlock_irqrestore(&priv->tdls_lock, flags);
+	}
+}
+
+/**
+ * @brief check auto tdls
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ *
+ * @return                      N/A
+ */
+void
+woal_check_auto_tdls(struct wiphy *wiphy, struct net_device *dev)
+{
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	struct tdls_peer *tdls_peer = NULL;
+	unsigned long flags;
+	t_u8 tdls_discovery = MFALSE;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+	if (priv && priv->enable_auto_tdls) {
+		priv->tdls_check_tx = MFALSE;
+		spin_lock_irqsave(&priv->tdls_lock, flags);
+		list_for_each_entry(tdls_peer, &priv->tdls_list, link) {
+			if ((jiffies - tdls_peer->rssi_jiffies) >
+			    TDLS_IDLE_TIME) {
+				tdls_peer->rssi = 0;
+				if (tdls_peer->num_failure <
+				    TDLS_MAX_FAILURE_COUNT)
+					tdls_discovery = MTRUE;
+			}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (tdls_peer->rssi &&
+			    (tdls_peer->rssi >= TDLS_RSSI_LOW_THRESHOLD)) {
+				if (tdls_peer->link_status ==
+				    TDLS_SETUP_COMPLETE) {
+					tdls_peer->link_status = TDLS_TEAR_DOWN;
+					PRINTM(MMSG,
+					       "Wlan: Tear down TDLS link, peer="
+					       MACSTR " rssi=%d\n",
+					       MAC2STR(tdls_peer->peer_addr),
+					       -tdls_peer->rssi);
+					cfg80211_tdls_oper_request(dev,
+								   tdls_peer->
+								   peer_addr,
+								   NL80211_TDLS_TEARDOWN,
+								   TDLS_TEARN_DOWN_REASON_UNSPECIFIC,
+								   GFP_ATOMIC);
+				}
+			} else if (tdls_peer->rssi &&
+				   (tdls_peer->rssi <=
+				    TDLS_RSSI_HIGH_THRESHOLD)) {
+				if ((tdls_peer->link_status ==
+				     TDLS_NOT_SETUP) &&
+				    (tdls_peer->num_failure <
+				     TDLS_MAX_FAILURE_COUNT)) {
+					priv->tdls_check_tx = MTRUE;
+					PRINTM(MCMND,
+					       "Wlan: Find TDLS peer=" MACSTR
+					       " rssi=%d\n",
+					       MAC2STR(tdls_peer->peer_addr),
+					       -tdls_peer->rssi);
+				}
+			}
+#endif
+		}
+		spin_unlock_irqrestore(&priv->tdls_lock, flags);
+	}
+	if (tdls_discovery)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+		woal_cfg80211_tdls_mgmt(wiphy, dev, bcast_addr,
+					TDLS_DISCOVERY_REQUEST, 1, 0, 0, 0,
+					NULL, 0);
+#else
+		woal_cfg80211_tdls_mgmt(wiphy, dev, bcast_addr,
+					TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL,
+					0);
+#endif
+#else
+		woal_cfg80211_tdls_mgmt(wiphy, dev, bcast_addr,
+					TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
+#endif
+	LEAVE();
+}
+
+/**
+ * @brief woal construct tdls data frame
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param skb                   skb buffer
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+static int
+woal_construct_tdls_data_frame(moal_private *priv, t_u8 *peer,
+			       t_u8 action_code, t_u8 dialog_token,
+			       t_u16 status_code, struct sk_buff *skb)
+{
+	struct ieee80211_tdls_data *tdata;
+	t_u16 capability;
+	IEEEtypes_HTCap_t *HTcap;
+	IEEEtypes_HTInfo_t *HTInfo;
+	IEEEtypes_2040BSSCo_t *BSSCo;
+	IEEEtypes_VHTCap_t *VHTcap;
+	IEEEtypes_VHTOprat_t *vht_oprat;
+	IEEEtypes_AID_t *AidInfo;
+	IEEEtypes_Generic_t *pSupp_chan = NULL, *pRegulatory_class = NULL;
+	mlan_ds_misc_tdls_ies *tdls_ies = NULL;
+	int ret = 0;
+	mlan_bss_info bss_info;
+	enum ieee80211_band band;
+	mlan_fw_info fw_info;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		PRINTM(MERROR, "Fail to get bss info\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	band = woal_band_cfg_to_ieee_band(bss_info.bss_band);
+	tdls_ies = kzalloc(sizeof(mlan_ds_misc_tdls_ies), GFP_KERNEL);
+	if (!tdls_ies) {
+		PRINTM(MERROR, "Fail to alloc memory for tdls_ies\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	capability = 0x2421;
+
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	tdata = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+	moal_memcpy_ext(priv->phandle, tdata->da, peer, ETH_ALEN,
+			sizeof(tdata->da));
+	moal_memcpy_ext(priv->phandle, tdata->sa, priv->current_addr, ETH_ALEN,
+			sizeof(tdata->sa));
+	tdata->ether_type = cpu_to_be16(MLAN_ETHER_PKT_TYPE_TDLS_ACTION);
+	tdata->payload_type = WLAN_TDLS_SNAP_RFTYPE;
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+		if (fw_info.fw_bands & BAND_AAC)
+			woal_tdls_get_ies(priv, peer, tdls_ies,
+					  TDLS_IE_FLAGS_SETUP |
+					  TDLS_IE_FLAGS_EXTCAP |
+					  TDLS_IE_FLAGS_HTCAP |
+					  TDLS_IE_FLAGS_VHTCAP |
+					  TDLS_IE_FLAGS_AID |
+					  TDLS_IE_FLAGS_SUPP_CS_IE);
+		else
+			woal_tdls_get_ies(priv, peer, tdls_ies,
+					  TDLS_IE_FLAGS_SETUP |
+					  TDLS_IE_FLAGS_EXTCAP |
+					  TDLS_IE_FLAGS_HTCAP |
+					  TDLS_IE_FLAGS_SUPP_CS_IE);
+
+		tdata->category = WLAN_CATEGORY_TDLS;
+		tdata->action_code = WLAN_TDLS_SETUP_REQUEST;
+		skb_put(skb, sizeof(tdata->u.setup_req));
+		tdata->u.setup_req.dialog_token = dialog_token;
+		tdata->u.setup_req.capability = cpu_to_le16(capability);
+		woal_add_supported_rates_ie(priv, skb, band);
+		woal_add_ext_supported_rates_ie(priv, skb, band);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		if (fw_info.fw_bands & BAND_AAC)
+			woal_tdls_get_ies(priv, peer, tdls_ies,
+					  TDLS_IE_FLAGS_EXTCAP |
+					  TDLS_IE_FLAGS_HTCAP |
+					  TDLS_IE_FLAGS_VHTCAP |
+					  TDLS_IE_FLAGS_AID |
+					  TDLS_IE_FLAGS_SUPP_CS_IE);
+		else
+			woal_tdls_get_ies(priv, peer, tdls_ies,
+					  TDLS_IE_FLAGS_EXTCAP |
+					  TDLS_IE_FLAGS_HTCAP |
+					  TDLS_IE_FLAGS_SUPP_CS_IE);
+
+		tdata->category = WLAN_CATEGORY_TDLS;
+		tdata->action_code = WLAN_TDLS_SETUP_RESPONSE;
+
+		skb_put(skb, sizeof(tdata->u.setup_resp));
+		tdata->u.setup_resp.status_code = cpu_to_le16(status_code);
+		tdata->u.setup_resp.dialog_token = dialog_token;
+		tdata->u.setup_resp.capability = cpu_to_le16(capability);
+
+		woal_add_supported_rates_ie(priv, skb, band);
+		woal_add_ext_supported_rates_ie(priv, skb, band);
+		break;
+	case WLAN_TDLS_SETUP_CONFIRM:
+		if (fw_info.fw_bands & BAND_AAC)
+			woal_tdls_get_ies(priv, peer, tdls_ies,
+					  TDLS_IE_FLAGS_EXTCAP |
+					  TDLS_IE_FLAGS_HTINFO |
+					  TDLS_IE_FLAGS_VHTOPRAT |
+					  TDLS_IE_FLAGS_QOS_INFO);
+		else
+			woal_tdls_get_ies(priv, peer, tdls_ies,
+					  TDLS_IE_FLAGS_EXTCAP |
+					  TDLS_IE_FLAGS_HTINFO |
+					  TDLS_IE_FLAGS_QOS_INFO);
+
+		tdata->category = WLAN_CATEGORY_TDLS;
+		tdata->action_code = WLAN_TDLS_SETUP_CONFIRM;
+
+		skb_put(skb, sizeof(tdata->u.setup_cfm));
+		tdata->u.setup_cfm.status_code = cpu_to_le16(status_code);
+		tdata->u.setup_cfm.dialog_token = dialog_token;
+
+		break;
+	case WLAN_TDLS_TEARDOWN:
+		tdata->category = WLAN_CATEGORY_TDLS;
+		tdata->action_code = WLAN_TDLS_TEARDOWN;
+
+		skb_put(skb, sizeof(tdata->u.teardown));
+		tdata->u.teardown.reason_code = cpu_to_le16(status_code);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		tdata->category = WLAN_CATEGORY_TDLS;
+		tdata->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+
+		skb_put(skb, sizeof(tdata->u.discover_req));
+		tdata->u.discover_req.dialog_token = dialog_token;
+		break;
+	default:
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (action_code == WLAN_TDLS_SETUP_REQUEST ||
+	    action_code == WLAN_TDLS_SETUP_RESPONSE) {
+		/* supported chanel ie */
+		if (tdls_ies->supp_chan[0] == SUPPORTED_CHANNELS) {
+			pSupp_chan =
+				(void *)skb_put(skb,
+						sizeof(IEEEtypes_Header_t) +
+						tdls_ies->supp_chan[1]);
+			memset(pSupp_chan, 0,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->supp_chan[1]);
+			moal_memcpy_ext(priv->phandle, pSupp_chan,
+					tdls_ies->supp_chan,
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->supp_chan[1],
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->supp_chan[1]);
+		}
+		/* supported regulatory class ie */
+		if (tdls_ies->regulatory_class[0] == REGULATORY_CLASS) {
+			pRegulatory_class =
+				(void *)skb_put(skb,
+						sizeof(IEEEtypes_Header_t) +
+						tdls_ies->regulatory_class[1]);
+			memset(pRegulatory_class, 0,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->regulatory_class[1]);
+			moal_memcpy_ext(priv->phandle, pRegulatory_class,
+					tdls_ies->regulatory_class,
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->regulatory_class[1],
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->regulatory_class[1]);
+		}
+		woal_tdls_add_ext_capab(priv, skb, tdls_ies);
+	}
+
+	/* TODO we should fill in ht_cap and htinfo with correct value */
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_RESPONSE:
+		/*HT capability */
+		if (tdls_ies->ht_cap[0] == HT_CAPABILITY) {
+			HTcap = (void *)skb_put(skb, sizeof(IEEEtypes_HTCap_t));
+			memset(HTcap, 0, sizeof(IEEEtypes_HTCap_t));
+			moal_memcpy_ext(priv->phandle, HTcap, tdls_ies->ht_cap,
+					sizeof(IEEEtypes_HTCap_t),
+					sizeof(IEEEtypes_HTCap_t));
+		} else {
+			PRINTM(MIOCTL, "No TDLS HT capability\n");
+		}
+
+		/*20_40_bss_coexist */
+		BSSCo = (void *)skb_put(skb, sizeof(IEEEtypes_2040BSSCo_t));
+		memset(BSSCo, 0, sizeof(IEEEtypes_2040BSSCo_t));
+		BSSCo->ieee_hdr.element_id = BSSCO_2040;
+		BSSCo->ieee_hdr.len = sizeof(IEEEtypes_2040BSSCo_t) -
+			sizeof(IEEEtypes_Header_t);
+		BSSCo->bss_co_2040.bss_co_2040_value = 0x01;
+
+		/* VHT capability */
+		if (tdls_ies->vht_cap[0] == VHT_CAPABILITY) {
+			VHTcap = (void *)skb_put(skb,
+						 sizeof(IEEEtypes_VHTCap_t));
+			memset(VHTcap, 0, sizeof(IEEEtypes_VHTCap_t));
+			moal_memcpy_ext(priv->phandle, VHTcap,
+					tdls_ies->vht_cap,
+					sizeof(IEEEtypes_VHTCap_t),
+					sizeof(IEEEtypes_VHTCap_t));
+		} else {
+			PRINTM(MIOCTL, "NO TDLS VHT capability\n");
+		}
+		/* AID info */
+		if (tdls_ies->aid_info[0] == AID_INFO) {
+			AidInfo = (void *)skb_put(skb, sizeof(IEEEtypes_AID_t));
+			memset(AidInfo, 0, sizeof(IEEEtypes_AID_t));
+			moal_memcpy_ext(priv->phandle, AidInfo,
+					tdls_ies->aid_info,
+					sizeof(IEEEtypes_AID_t),
+					sizeof(IEEEtypes_AID_t));
+		} else {
+			PRINTM(MIOCTL, "No TDLS AID info\n");
+		}
+		break;
+	case WLAN_TDLS_SETUP_CONFIRM:
+		/*HT information */
+		if (tdls_ies->ht_info[0] == HT_OPERATION) {
+			HTInfo = (void *)skb_put(skb,
+						 sizeof(IEEEtypes_HTInfo_t));
+			memset(HTInfo, 0, sizeof(IEEEtypes_HTInfo_t));
+			moal_memcpy_ext(priv->phandle, HTInfo,
+					tdls_ies->ht_info,
+					sizeof(IEEEtypes_HTInfo_t),
+					sizeof(IEEEtypes_HTInfo_t));
+		} else
+			PRINTM(MIOCTL, "No TDLS HT information\n");
+		/** VHT operation */
+		if (tdls_ies->vht_oprat[0] == VHT_OPERATION) {
+			vht_oprat =
+				(void *)skb_put(skb,
+						sizeof(IEEEtypes_VHTOprat_t));
+			memset(vht_oprat, 0, sizeof(IEEEtypes_VHTOprat_t));
+			moal_memcpy_ext(priv->phandle, vht_oprat,
+					tdls_ies->vht_oprat,
+					sizeof(IEEEtypes_VHTOprat_t),
+					sizeof(IEEEtypes_VHTOprat_t));
+		} else
+			PRINTM(MIOCTL, "NO TDLS VHT Operation IE\n");
+		break;
+	default:
+		break;
+	}
+
+	if (action_code == WLAN_TDLS_SETUP_REQUEST ||
+	    action_code == WLAN_TDLS_SETUP_RESPONSE) {
+		/*wmm info */
+		woal_add_wmm_ie(priv, skb, WMM_TYPE_INFO, NULL);
+	} else if (action_code == WLAN_TDLS_SETUP_CONFIRM) {
+		/*wmm parameter */
+		woal_add_wmm_ie(priv, skb, WMM_TYPE_PARAMETER,
+				&tdls_ies->QosInfo);
+	}
+
+done:
+	kfree(tdls_ies);
+	return ret;
+}
+
+/**
+ * @brief woal construct tdls action frame
+ *
+ * @param priv                  A pointer to moal_private structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param skb                   skb buffer
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+static int
+woal_construct_tdls_action_frame(moal_private *priv, t_u8 *peer,
+				 t_u8 action_code, t_u8 dialog_token,
+				 t_u16 status_code, struct sk_buff *skb)
+{
+	struct ieee80211_mgmt *mgmt;
+	t_u8 addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	t_u16 capability;
+	t_u8 *pos = NULL;
+	mlan_ds_misc_tdls_ies *tdls_ies = NULL;
+	mlan_bss_info bss_info;
+	enum ieee80211_band band;
+	IEEEtypes_Generic_t *pSupp_chan = NULL, *pRegulatory_class = NULL;
+
+	int ret = 0;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		PRINTM(MERROR, "Fail to get bss info\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	band = woal_band_cfg_to_ieee_band(bss_info.bss_band);
+
+	tdls_ies = kzalloc(sizeof(mlan_ds_misc_tdls_ies), GFP_KERNEL);
+	if (!tdls_ies) {
+		PRINTM(MERROR, "Fail to alloc memory for tdls_ies\n");
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	mgmt = (void *)skb_put(skb, 24);
+	memset(mgmt, 0, 24);
+	moal_memcpy_ext(priv->phandle, mgmt->da, peer, ETH_ALEN,
+			sizeof(mgmt->da));
+	moal_memcpy_ext(priv->phandle, mgmt->sa, priv->current_addr, ETH_ALEN,
+			sizeof(mgmt->sa));
+	moal_memcpy_ext(priv->phandle, mgmt->bssid, priv->cfg_bssid, ETH_ALEN,
+			sizeof(mgmt->bssid));
+
+	mgmt->frame_control =
+		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
+	/* add address 4 */
+	pos = skb_put(skb, ETH_ALEN);
+
+	capability = 0x2421;
+
+	switch (action_code) {
+	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+		woal_tdls_get_ies(priv, peer, tdls_ies,
+				  TDLS_IE_FLAGS_EXTCAP |
+				  TDLS_IE_FLAGS_SUPP_CS_IE);
+		skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+		mgmt->u.action.u.tdls_discover_resp.action_code =
+			WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+		mgmt->u.action.u.tdls_discover_resp.dialog_token = dialog_token;
+		mgmt->u.action.u.tdls_discover_resp.capability =
+			cpu_to_le16(capability);
+		/* move back for addr4 */
+		memmove(pos + ETH_ALEN, &mgmt->u.action,
+			1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+		/** init address 4 */
+		moal_memcpy_ext(priv->phandle, pos, addr, ETH_ALEN, ETH_ALEN);
+
+		woal_add_supported_rates_ie(priv, skb, band);
+		woal_add_ext_supported_rates_ie(priv, skb, band);
+		woal_tdls_add_ext_capab(priv, skb, tdls_ies);
+		/* supported chanel ie */
+		if (tdls_ies->supp_chan[0] == SUPPORTED_CHANNELS) {
+			pSupp_chan =
+				(void *)skb_put(skb,
+						sizeof(IEEEtypes_Header_t) +
+						tdls_ies->supp_chan[1]);
+			memset(pSupp_chan, 0,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->supp_chan[1]);
+			moal_memcpy_ext(priv->phandle, pSupp_chan,
+					tdls_ies->supp_chan,
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->supp_chan[1],
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->supp_chan[1]);
+		}
+		/* supported regulatory class ie */
+		if (tdls_ies->regulatory_class[0] == REGULATORY_CLASS) {
+			pRegulatory_class =
+				(void *)skb_put(skb,
+						sizeof(IEEEtypes_Header_t) +
+						tdls_ies->regulatory_class[1]);
+			memset(pRegulatory_class, 0,
+			       sizeof(IEEEtypes_Header_t) +
+			       tdls_ies->regulatory_class[1]);
+			moal_memcpy_ext(priv->phandle, pRegulatory_class,
+					tdls_ies->regulatory_class,
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->regulatory_class[1],
+					sizeof(IEEEtypes_Header_t) +
+					tdls_ies->regulatory_class[1]);
+		}
+
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (tdls_ies)
+		kfree(tdls_ies);
+	return ret;
+}
+
+/**
+ * @brief woal add tdls link identifier ie
+ *
+ * @param skb                   skb buffer
+ * @param src_addr              source address
+ * @param peer                  peer address
+ * @param bssid                 AP's bssid
+ *
+ * @return                      NA
+ */
+static void
+woal_tdls_add_link_ie(moal_private *priv, struct sk_buff *skb,
+		      u8 *src_addr, u8 *peer, u8 *bssid)
+{
+	struct ieee80211_tdls_lnkie *lnkid;
+
+	lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+
+	lnkid->ie_type = WLAN_EID_LINK_ID;
+	lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
+
+	moal_memcpy_ext(priv->phandle, lnkid->bssid, bssid, ETH_ALEN,
+			sizeof(lnkid->bssid));
+	moal_memcpy_ext(priv->phandle, lnkid->init_sta, src_addr, ETH_ALEN,
+			sizeof(lnkid->init_sta));
+	moal_memcpy_ext(priv->phandle, lnkid->resp_sta, peer, ETH_ALEN,
+			sizeof(lnkid->resp_sta));
+}
+
+/**
+ * @brief woal send tdls action frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param extra_ies              A pointer to extra ie buffer
+ * @param extra_ies_len          etra ie len
+ * @param skb                   skb buffer
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+static int
+woal_send_tdls_action_frame(struct wiphy *wiphy,
+			    struct net_device *dev, t_u8 *peer,
+			    u8 action_code, t_u8 dialog_token,
+			    t_u16 status_code, const t_u8 *extra_ies,
+			    size_t extra_ies_len)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	pmlan_buffer pmbuf = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	t_u8 *pos;
+	t_u32 pkt_type;
+	t_u32 tx_control;
+	t_u16 pkt_len;
+	int ret = 0;
+
+	ENTER();
+
+#define HEADER_SIZE 8		/* pkt_type + tx_control */
+
+	pmbuf = woal_alloc_mlan_buffer(priv->phandle, MLAN_MIN_DATA_HEADER_LEN + HEADER_SIZE + sizeof(pkt_len) + max(sizeof(struct ieee80211_mgmt), sizeof(struct ieee80211_tdls_data)) + 50 +	/* supported rates */
+				       sizeof(IEEEtypes_ExtCap_t) +	/* ext capab */
+				       extra_ies_len +
+				       sizeof(IEEEtypes_tdls_linkie));
+	if (!pmbuf) {
+		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	skb = (struct sk_buff *)pmbuf->pdesc;
+
+	skb_put(skb, MLAN_MIN_DATA_HEADER_LEN);
+
+	pos = skb_put(skb, HEADER_SIZE + sizeof(pkt_len));
+	pkt_type = MRVL_PKT_TYPE_MGMT_FRAME;
+	tx_control = 0;
+	memset(pos, 0, HEADER_SIZE + sizeof(pkt_len));
+	moal_memcpy_ext(priv->phandle, pos, &pkt_type, sizeof(pkt_type),
+			sizeof(pkt_type));
+	moal_memcpy_ext(priv->phandle, pos + sizeof(pkt_type), &tx_control,
+			sizeof(tx_control), sizeof(tx_control));
+
+	woal_construct_tdls_action_frame(priv, peer, action_code, dialog_token,
+					 status_code, skb);
+
+	if (extra_ies_len)
+		moal_memcpy_ext(priv->phandle, skb_put(skb, extra_ies_len),
+				extra_ies, extra_ies_len, extra_ies_len);
+
+	/* the TDLS link IE is always added last */
+	/* we are the responder */
+	woal_tdls_add_link_ie(priv, skb, peer, priv->current_addr,
+			      priv->cfg_bssid);
+
+	/*
+	 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
+	 * we should default to AC_VI.
+	 */
+	skb_set_queue_mapping(skb, WMM_AC_VI);
+	skb->priority = 5;
+
+	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
+	pmbuf->data_len = skb->len - pmbuf->data_offset;
+	pmbuf->priority = skb->priority;
+	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
+	pmbuf->bss_index = priv->bss_index;
+
+	pkt_len = pmbuf->data_len - HEADER_SIZE - sizeof(pkt_len);
+	moal_memcpy_ext(priv->phandle,
+			pmbuf->pbuf + pmbuf->data_offset + HEADER_SIZE,
+			&pkt_len, sizeof(pkt_len), sizeof(pkt_len));
+
+	DBG_HEXDUMP(MDAT_D, "TDLS action:", pmbuf->pbuf + pmbuf->data_offset,
+		    pmbuf->data_len);
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		woal_free_mlan_buffer(priv->phandle, pmbuf);
+		ret = -EFAULT;
+		break;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief woal send tdls data frame
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param extra_ies              A pointer to extra ie buffer
+ * @param extra_ies_len          etra ie len
+ * @param skb                   skb buffer
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+static int
+woal_send_tdls_data_frame(struct wiphy *wiphy,
+			  struct net_device *dev, t_u8 *peer,
+			  u8 action_code, t_u8 dialog_token,
+			  t_u16 status_code, const t_u8 *extra_ies,
+			  size_t extra_ies_len)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	pmlan_buffer pmbuf = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	int ret = 0;
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	t_u32 index = 0;
+#endif
+
+	ENTER();
+
+	skb = dev_alloc_skb(priv->extra_tx_head_len + MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) + max(sizeof(struct ieee80211_mgmt), sizeof(struct ieee80211_tdls_data)) + 50 +	/* supported rates */
+			    sizeof(IEEEtypes_ExtCap_t) +	/* ext capab */
+			    3 +	/* Qos Info */
+			    sizeof(IEEEtypes_WmmParameter_t) +	/*wmm ie */
+			    sizeof(IEEEtypes_HTCap_t) +
+			    sizeof(IEEEtypes_2040BSSCo_t) +
+			    sizeof(IEEEtypes_HTInfo_t) +
+			    sizeof(IEEEtypes_VHTCap_t) +
+			    sizeof(IEEEtypes_VHTOprat_t) +
+			    sizeof(IEEEtypes_AID_t) + extra_ies_len +
+			    sizeof(IEEEtypes_tdls_linkie));
+	if (!skb)
+		return -ENOMEM;
+
+	skb_reserve(skb, MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
+		    priv->extra_tx_head_len);
+
+	woal_construct_tdls_data_frame(priv, peer, action_code, dialog_token,
+				       status_code, skb);
+
+	if (extra_ies_len)
+		moal_memcpy_ext(priv->phandle, skb_put(skb, extra_ies_len),
+				extra_ies, extra_ies_len, extra_ies_len);
+
+	/* the TDLS link IE is always added last */
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_CONFIRM:
+	case WLAN_TDLS_TEARDOWN:
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		/* we are the initiator */
+		woal_tdls_add_link_ie(priv, skb, priv->current_addr, peer,
+				      priv->cfg_bssid);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		/* we are the responder */
+		woal_tdls_add_link_ie(priv, skb, peer, priv->current_addr,
+				      priv->cfg_bssid);
+		break;
+	default:
+		ret = -ENOTSUPP;
+		goto fail;
+	}
+
+	/*
+	 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
+	 * we should default to AC_VI.
+	 */
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_RESPONSE:
+		skb_set_queue_mapping(skb, WMM_AC_BK);
+		skb->priority = 2;
+		break;
+	default:
+		skb_set_queue_mapping(skb, WMM_AC_VI);
+		skb->priority = 5;
+		break;
+	}
+
+	pmbuf = (mlan_buffer *)skb->head;
+	memset((t_u8 *)pmbuf, 0, sizeof(mlan_buffer));
+	pmbuf->bss_index = priv->bss_index;
+	pmbuf->pdesc = skb;
+	pmbuf->pbuf = skb->head + sizeof(mlan_buffer);
+
+	pmbuf->data_offset = skb->data - (skb->head + sizeof(mlan_buffer));
+	pmbuf->data_len = skb->len;
+	pmbuf->priority = skb->priority;
+	pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
+
+	DBG_HEXDUMP(MDAT_D, "TDLS data:", pmbuf->pbuf + pmbuf->data_offset,
+		    pmbuf->data_len);
+
+	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
+
+	switch (status) {
+	case MLAN_STATUS_PENDING:
+		atomic_inc(&priv->phandle->tx_pending);
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+		index = skb_get_queue_mapping(skb);
+		atomic_inc(&priv->wmm_tx_pending[index]);
+#endif
+		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
+		/*delay 10 ms to guarantee the teardown/confirm frame can be
+		 * sent out before disalbe/enable tdls link if we don't delay
+		 * and return immediately, wpa_supplicant will call
+		 * disalbe/enable tdls link this may cause tdls link
+		 * disabled/enabled before teardown/confirm frame sent out */
+		if (action_code == WLAN_TDLS_TEARDOWN ||
+		    action_code == WLAN_TDLS_SETUP_CONFIRM)
+			woal_sched_timeout(10);
+		break;
+	case MLAN_STATUS_SUCCESS:
+		dev_kfree_skb(skb);
+		break;
+	case MLAN_STATUS_FAILURE:
+	default:
+		dev_kfree_skb(skb);
+		ret = -ENOTSUPP;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+fail:
+	dev_kfree_skb(skb);
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+/**
+ * @brief Tx TDLS packet
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param peer_capability       peer capability
+ * @param initiator             initiator
+ * @param extra_ies              A pointer to extra ie buffer
+ * @param extra_ies_len          etra ie len
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+			const t_u8 *peer, u8 action_code, t_u8 dialog_token,
+			t_u16 status_code, t_u32 peer_capability,
+			bool initiator, const t_u8 *extra_ies,
+			size_t extra_ies_len)
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+/**
+ * @brief Tx TDLS packet
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param peer_capability       peer capability
+ * @param extra_ies              A pointer to extra ie buffer
+ * @param extra_ies_len          etra ie len
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			const t_u8 *peer,
+#else
+			t_u8 *peer,
+#endif
+			u8 action_code, t_u8 dialog_token,
+			t_u16 status_code, t_u32 peer_capability,
+			const t_u8 *extra_ies, size_t extra_ies_len)
+#else
+/**
+ * @brief Tx TDLS packet
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param peer                  A pointer to peer mac
+ * @param action_code           tdls action code
+ * @param dialog_token          dialog_token
+ * @param status_code           status_code
+ * @param extra_ies              A pointer to extra ie buffer
+ * @param extra_ies_len          etra ie len
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+			t_u8 *peer, u8 action_code, t_u8 dialog_token,
+			t_u16 status_code, const t_u8 *extra_ies,
+			size_t extra_ies_len)
+#endif
+#endif
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) {
+		LEAVE();
+		return -ENOTSUPP;
+	}
+	/* make sure we are not in uAP mode and Go mode */
+	if (priv->bss_type != MLAN_BSS_TYPE_STA) {
+		LEAVE();
+		return -ENOTSUPP;
+	}
+
+	/* check if AP prohited TDLS */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (IS_EXTCAP_TDLS_PROHIBITED(bss_info.ext_cap)) {
+		PRINTM(MMSG, "TDLS is prohibited by AP\n");
+		LEAVE();
+		return -ENOTSUPP;
+	}
+
+	switch (action_code) {
+	case TDLS_SETUP_REQUEST:
+		woal_add_tdls_peer(priv, (t_u8 *)peer);
+		PRINTM(MMSG,
+		       "wlan: Send TDLS Setup Request to " MACSTR
+		       " status_code=%d\n", MAC2STR(peer), status_code);
+		ret = woal_send_tdls_data_frame(wiphy, dev, (t_u8 *)peer,
+						action_code, dialog_token,
+						status_code, extra_ies,
+						extra_ies_len);
+		break;
+	case TDLS_SETUP_RESPONSE:
+		PRINTM(MMSG,
+		       "wlan: Send TDLS Setup Response to " MACSTR
+		       " status_code=%d\n", MAC2STR(peer), status_code);
+		ret = woal_send_tdls_data_frame(wiphy, dev, (t_u8 *)peer,
+						action_code, dialog_token,
+						status_code, extra_ies,
+						extra_ies_len);
+		break;
+	case TDLS_SETUP_CONFIRM:
+		PRINTM(MMSG,
+		       "wlan: Send TDLS Confirm to " MACSTR " status_code=%d\n",
+		       MAC2STR(peer), status_code);
+		ret = woal_send_tdls_data_frame(wiphy, dev, (t_u8 *)peer,
+						action_code, dialog_token,
+						status_code, extra_ies,
+						extra_ies_len);
+		break;
+	case TDLS_TEARDOWN:
+		PRINTM(MMSG, "wlan: Send TDLS Tear down to " MACSTR "\n",
+		       MAC2STR(peer));
+		ret = woal_send_tdls_data_frame(wiphy, dev, (t_u8 *)peer,
+						action_code, dialog_token,
+						status_code, extra_ies,
+						extra_ies_len);
+		break;
+	case TDLS_DISCOVERY_REQUEST:
+		PRINTM(MMSG,
+		       "wlan: Send TDLS Discovery Request to " MACSTR "\n",
+		       MAC2STR(peer));
+		ret = woal_send_tdls_data_frame(wiphy, dev, (t_u8 *)peer,
+						action_code, dialog_token,
+						status_code, extra_ies,
+						extra_ies_len);
+		break;
+	case TDLS_DISCOVERY_RESPONSE:
+		PRINTM(MMSG,
+		       "wlan: Send TDLS Discovery Response to " MACSTR "\n",
+		       MAC2STR(peer));
+		ret = woal_send_tdls_action_frame(wiphy, dev, (t_u8 *)peer,
+						  action_code, dialog_token,
+						  status_code, extra_ies,
+						  extra_ies_len);
+		break;
+	default:
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief cfg80211_tdls_oper handler
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param peer                  tdls peer mac
+ * @param oper                  tdls operation code
+ *
+ * @return                  	0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			const u8 *peer,
+#else
+			u8 *peer,
+#endif
+			enum nl80211_tdls_operation oper)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	t_u8 action;
+	int ret = 0;
+	t_u8 event_buf[32];
+	int custom_len = 0;
+
+	ENTER();
+
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+		return -ENOTSUPP;
+
+	if (!(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
+		return -ENOTSUPP;
+	/* make sure we are in managed mode, and associated */
+	if (priv->bss_type != MLAN_BSS_TYPE_STA)
+		return -ENOTSUPP;
+
+	PRINTM(MIOCTL, "wlan: TDLS peer=" MACSTR ", oper=%d\n", MAC2STR(peer),
+	       oper);
+	switch (oper) {
+	case NL80211_TDLS_ENABLE_LINK:
+		/*Configure TDLS link first */
+		woal_tdls_oper(priv, (u8 *)peer, WLAN_TDLS_CONFIG_LINK);
+		woal_updata_peer_status(priv, (t_u8 *)peer,
+					TDLS_SETUP_COMPLETE);
+		PRINTM(MMSG, "wlan: TDLS_ENABLE_LINK: peer=" MACSTR "\n",
+		       MAC2STR(peer));
+		action = WLAN_TDLS_ENABLE_LINK;
+		memset(event_buf, 0, sizeof(event_buf));
+		custom_len = strlen(CUS_EVT_TDLS_CONNECTED);
+		moal_memcpy_ext(priv->phandle, event_buf,
+				CUS_EVT_TDLS_CONNECTED, custom_len,
+				sizeof(event_buf));
+		moal_memcpy_ext(priv->phandle, event_buf + custom_len, peer,
+				ETH_ALEN, sizeof(event_buf) - custom_len);
+		woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN);
+		break;
+	case NL80211_TDLS_DISABLE_LINK:
+		woal_updata_peer_status(priv, (t_u8 *)peer, TDLS_NOT_SETUP);
+		PRINTM(MMSG, "wlan: TDLS_DISABLE_LINK: peer=" MACSTR "\n",
+		       MAC2STR(peer));
+		action = WLAN_TDLS_DISABLE_LINK;
+		memset(event_buf, 0, sizeof(event_buf));
+		custom_len = strlen(CUS_EVT_TDLS_TEARDOWN);
+		moal_memcpy_ext(priv->phandle, event_buf, CUS_EVT_TDLS_TEARDOWN,
+				custom_len, sizeof(event_buf));
+		moal_memcpy_ext(priv->phandle, event_buf + custom_len, peer,
+				ETH_ALEN, sizeof(event_buf) - custom_len);
+		woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN);
+		break;
+	case NL80211_TDLS_TEARDOWN:
+	case NL80211_TDLS_SETUP:
+	case NL80211_TDLS_DISCOVERY_REQ:
+		return 0;
+
+	default:
+		return -ENOTSUPP;
+	}
+	ret = woal_tdls_oper(priv, (u8 *)peer, action);
+
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+/**
+ * @brief tdls channel switch
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param addr                  A pointer to peer addr
+ * @param oper_class            The operating class
+ * @param chandef               A pointer to cfg80211_chan_def structure
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_tdls_channel_switch(struct wiphy *wiphy,
+				  struct net_device *dev,
+				  const u8 *addr, u8 oper_class,
+				  struct cfg80211_chan_def *chandef)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_tdls_config *tdls_data = NULL;
+	tdls_all_config *tdls_all_cfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	/* check if AP prohited TDLS channel switch */
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+	if (IS_EXTCAP_TDLS_CHLSWITCHPROHIB(bss_info.ext_cap)) {
+		PRINTM(MMSG, "TDLS Channel Switching is prohibited by AP\n");
+		LEAVE();
+		return -ENOTSUPP;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TDLS_OPER;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	tdls_data = &misc->param.tdls_config;
+	tdls_data->tdls_action = WLAN_TDLS_INIT_CHAN_SWITCH;
+
+	tdls_all_cfg = (tdls_all_config *)tdls_data->tdls_data;
+	moal_memcpy_ext(priv->phandle,
+			tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr, addr,
+			ETH_ALEN,
+			sizeof(tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr));
+	tdls_all_cfg->u.tdls_chan_switch.primary_channel =
+		chandef->chan->hw_value;
+	tdls_all_cfg->u.tdls_chan_switch.band = chandef->chan->band;
+	tdls_all_cfg->u.tdls_chan_switch.regulatory_class = oper_class;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "TDLS channel switch request failed.\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief tdls cancel channel switch
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param addr                  A pointer to peer addr
+ *
+ */
+void
+woal_cfg80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
+					 struct net_device *dev, const u8 *addr)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_tdls_config *tdls_data = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TDLS_CONFIG;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	tdls_data = &misc->param.tdls_config;
+	tdls_data->tdls_action = WLAN_TDLS_STOP_CHAN_SWITCH;
+	moal_memcpy_ext(priv->phandle, tdls_data->tdls_data, addr, ETH_ALEN,
+			sizeof(tdls_data->tdls_data));
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	PRINTM(MIOCTL, "Tdls channel switch stop!\n");
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+}
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+/**
+ * @brief change station info
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param mac                   A pointer to peer mac
+ * @param params                station parameters
+ *
+ * @return                      0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			     const u8 *mac,
+#else
+			     u8 *mac,
+#endif
+			     struct station_parameters *params)
+{
+	int ret = 0;
+
+	ENTER();
+	/**do nothing*/
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#ifdef UAP_SUPPORT
+/**
+ * @brief add station
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param mac                  A pointer to peer mac
+ * @param params           	station parameters
+ *
+ * @return                  	0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			  const u8 *mac,
+#else
+			  u8 *mac,
+#endif
+			  struct station_parameters *params)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+#ifdef UAP_SUPPORT
+	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME) &&
+	    (priv->bss_role == MLAN_BSS_ROLE_UAP)) {
+		ret = woal_cfg80211_uap_add_station(wiphy, dev, (u8 *)mac,
+						    params);
+		LEAVE();
+		return ret;
+	}
+#endif
+#endif
+	if (!(params->sta_flags_set & MBIT(NL80211_STA_FLAG_TDLS_PEER)))
+		goto done;
+	/* make sure we are in connected mode */
+	if ((priv->bss_type != MLAN_BSS_TYPE_STA) ||
+	    (priv->media_connected == MFALSE)) {
+		ret = -ENOTSUPP;
+		goto done;
+	}
+	PRINTM(MMSG, "wlan: TDLS add peer station, address =" MACSTR "\n",
+	       MAC2STR(mac));
+	ret = woal_tdls_oper(priv, (u8 *)mac, WLAN_TDLS_CREATE_LINK);
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+/**
+ * @brief Update ft ie for Fast BSS Transition
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param ftie           A pointer to cfg80211_update_ft_ies_params structure
+ *
+ * @return                0 success , other failure
+ */
+int
+woal_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
+			    struct cfg80211_update_ft_ies_params *ftie)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	IEEEtypes_MobilityDomain_t *md_ie = NULL;
+	int ret = 0;
+	mlan_ds_misc_assoc_rsp assoc_rsp;
+	IEEEtypes_AssocRsp_t *passoc_rsp = NULL;
+	mlan_bss_info bss_info;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	struct cfg80211_roam_info roam_info = { };
+#endif
+
+	ENTER();
+
+	if (!ftie) {
+		LEAVE();
+		return ret;
+	}
+#ifdef MLAN_64BIT
+	PRINTM(MINFO, "==>woal_cfg80211_update_ft_ies %lx \n", ftie->ie_len);
+#else
+	PRINTM(MINFO, "==>woal_cfg80211_update_ft_ies %x \n", ftie->ie_len);
+#endif
+	md_ie = (IEEEtypes_MobilityDomain_t *)woal_parse_ie_tlv(ftie->ie,
+								ftie->ie_len,
+								MOBILITY_DOMAIN);
+	if (!md_ie) {
+		PRINTM(MERROR, "No Mobility domain IE\n");
+		LEAVE();
+		return ret;
+	}
+	priv->ft_cap = md_ie->ft_cap;
+	if (priv->ft_ie_len) {
+		priv->pre_ft_ie_len = priv->ft_ie_len;
+		moal_memcpy_ext(priv->phandle, priv->pre_ft_ie, priv->ft_ie,
+				priv->ft_ie_len, MAX_IE_SIZE);
+	}
+	memset(priv->ft_ie, 0, MAX_IE_SIZE);
+	moal_memcpy_ext(priv->phandle, priv->ft_ie, ftie->ie,
+			MIN(ftie->ie_len, MAX_IE_SIZE), sizeof(priv->ft_ie));
+	priv->ft_ie_len = ftie->ie_len;
+	priv->ft_md = ftie->md;
+
+	if (!priv->ft_pre_connect) {
+		LEAVE();
+		return ret;
+	}
+	/* check if is different AP */
+	if (!memcmp(&priv->target_ap_bssid, priv->cfg_bssid,
+		    MLAN_MAC_ADDR_LENGTH)) {
+		PRINTM(MMSG, "This is the same AP, no Fast bss transition\n");
+		priv->ft_pre_connect = MFALSE;
+		priv->ft_ie_len = 0;
+		LEAVE();
+		return 0;
+	}
+
+	/* start fast BSS transition to target AP */
+	priv->assoc_status = 0;
+	priv->sme_current.bssid = priv->conn_bssid;
+	moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.bssid,
+			&priv->target_ap_bssid, MLAN_MAC_ADDR_LENGTH,
+			sizeof(priv->conn_bssid));
+	memset(&assoc_rsp, 0, sizeof(mlan_ds_misc_assoc_rsp));
+	ret = woal_cfg80211_assoc(priv, (void *)&priv->sme_current,
+				  MOAL_IOCTL_WAIT, &assoc_rsp);
+
+	if ((priv->ft_cap & MBIT(0)) || priv->ft_roaming_triggered_by_driver) {
+		if (!ret) {
+			woal_inform_bss_from_scan_result(priv, NULL,
+							 MOAL_IOCTL_WAIT);
+			passoc_rsp = (IEEEtypes_AssocRsp_t *)
+				assoc_rsp.assoc_resp_buf;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+			roam_info.bssid = priv->cfg_bssid;
+			roam_info.req_ie = priv->sme_current.ie;
+			roam_info.req_ie_len = priv->sme_current.ie_len;
+			roam_info.resp_ie = passoc_rsp->ie_buffer;
+			roam_info.resp_ie_len = assoc_rsp.assoc_resp_len -
+				ASSOC_RESP_FIXED_SIZE;
+			cfg80211_roamed(priv->netdev, &roam_info, GFP_KERNEL);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			cfg80211_roamed(priv->netdev, NULL, priv->cfg_bssid,
+					priv->sme_current.ie,
+					priv->sme_current.ie_len,
+					passoc_rsp->ie_buffer,
+					assoc_rsp.assoc_resp_len -
+					ASSOC_RESP_FIXED_SIZE, GFP_KERNEL);
+#else
+			cfg80211_roamed(priv->netdev, priv->cfg_bssid,
+					priv->sme_current.ie,
+					priv->sme_current.ie_len,
+					passoc_rsp->ie_buffer,
+					assoc_rsp.assoc_resp_len -
+					ASSOC_RESP_FIXED_SIZE, GFP_KERNEL);
+#endif
+#endif
+			PRINTM(MMSG,
+			       "Fast BSS transition to bssid " MACSTR
+			       " successfully\n", MAC2STR(priv->cfg_bssid));
+		} else {
+			PRINTM(MMSG,
+			       "Fast BSS transition failed, keep connect to "
+			       MACSTR " \n", MAC2STR(priv->cfg_bssid));
+			moal_memcpy_ext(priv->phandle,
+					(void *)priv->sme_current.bssid,
+					&priv->cfg_bssid, MLAN_MAC_ADDR_LENGTH,
+					sizeof(priv->conn_bssid));
+			priv->ft_ie_len = priv->pre_ft_ie_len;
+			moal_memcpy_ext(priv->phandle, priv->ft_ie,
+					priv->pre_ft_ie, priv->pre_ft_ie_len,
+					MAX_IE_SIZE);
+		}
+		priv->ft_roaming_triggered_by_driver = MFALSE;
+
+	} else {
+		if (!ret) {
+			memset(&assoc_rsp, 0, sizeof(mlan_ds_misc_assoc_rsp));
+			woal_get_assoc_rsp(priv, &assoc_rsp, MOAL_IOCTL_WAIT);
+			passoc_rsp = (IEEEtypes_AssocRsp_t *)
+				assoc_rsp.assoc_resp_buf;
+			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
+						NULL, 0, passoc_rsp->ie_buffer,
+						assoc_rsp.assoc_resp_len -
+						ASSOC_RESP_FIXED_SIZE,
+						WLAN_STATUS_SUCCESS,
+						GFP_KERNEL);
+			PRINTM(MMSG,
+			       "wlan: Fast Bss transition to bssid " MACSTR
+			       " successfully\n", MAC2STR(priv->cfg_bssid));
+
+			memset(&bss_info, 0, sizeof(bss_info));
+			woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+			priv->channel = bss_info.bss_chan;
+		} else {
+			PRINTM(MMSG,
+			       "wlan: Failed to connect to bssid " MACSTR "\n",
+			       MAC2STR(priv->target_ap_bssid));
+			cfg80211_connect_result(priv->netdev,
+						priv->target_ap_bssid, NULL, 0,
+						NULL, 0,
+						woal_get_assoc_status(priv),
+						GFP_KERNEL);
+			moal_memcpy_ext(priv->phandle,
+					(void *)priv->sme_current.bssid,
+					&priv->cfg_bssid, MLAN_MAC_ADDR_LENGTH,
+					sizeof(priv->conn_bssid));
+			memset(priv->target_ap_bssid, 0, ETH_ALEN);
+			priv->ft_ie_len = priv->pre_ft_ie_len;
+			moal_memcpy_ext(priv->phandle, priv->ft_ie,
+					priv->pre_ft_ie, priv->pre_ft_ie_len,
+					MAX_IE_SIZE);
+			// priv->ft_ie_len = 0;
+		}
+	}
+
+	priv->ft_pre_connect = MFALSE;
+	LEAVE();
+	return 0;
+}
+#endif
+
+/**
+ * @brief Save connect parameters for roaming
+ *
+ * @param priv            A pointer to moal_private
+ * @param sme             A pointer to cfg80211_connect_params structure
+ */
+void
+woal_save_conn_params(moal_private *priv, struct cfg80211_connect_params *sme)
+{
+	ENTER();
+	woal_clear_conn_params(priv);
+	moal_memcpy_ext(priv->phandle, &priv->sme_current, sme,
+			sizeof(struct cfg80211_connect_params),
+			sizeof(priv->sme_current));
+	if (sme->channel) {
+		priv->sme_current.channel = &priv->conn_chan;
+		moal_memcpy_ext(priv->phandle, priv->sme_current.channel,
+				sme->channel, sizeof(struct ieee80211_channel),
+				sizeof(priv->conn_chan));
+	}
+	if (sme->bssid) {
+		priv->sme_current.bssid = priv->conn_bssid;
+		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.bssid,
+				sme->bssid, MLAN_MAC_ADDR_LENGTH,
+				sizeof(priv->conn_bssid));
+	}
+	if (sme->ssid && sme->ssid_len) {
+		priv->sme_current.ssid = priv->conn_ssid;
+		memset(priv->conn_ssid, 0, MLAN_MAX_SSID_LENGTH);
+		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.ssid,
+				sme->ssid, sme->ssid_len,
+				sizeof(priv->conn_ssid));
+	}
+	if (sme->ie && sme->ie_len) {
+		priv->sme_current.ie = kzalloc(sme->ie_len, GFP_KERNEL);
+		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.ie,
+				sme->ie, sme->ie_len, sme->ie_len);
+	}
+	if (sme->key && sme->key_len && (sme->key_len <= MAX_WEP_KEY_SIZE)) {
+		priv->sme_current.key = priv->conn_wep_key;
+		moal_memcpy_ext(priv->phandle, (t_u8 *)priv->sme_current.key,
+				sme->key, sme->key_len,
+				sizeof(priv->conn_wep_key));
+	}
+	if (priv->sinfo)
+		memset(priv->sinfo, 0, sizeof(struct station_info));
+	else
+		priv->sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL);
+}
+
+/**
+ * @brief clear connect parameters for ing
+ *
+ * @param priv            A pointer to moal_private
+ */
+void
+woal_clear_conn_params(moal_private *priv)
+{
+	ENTER();
+	if (priv->sme_current.ie_len)
+		kfree(priv->sme_current.ie);
+	memset(&priv->sme_current, 0, sizeof(struct cfg80211_connect_params));
+	priv->roaming_required = MFALSE;
+	priv->assoc_bss = NULL;
+	if (priv->sinfo) {
+		kfree(priv->sinfo);
+		priv->sinfo = NULL;
+	}
+	LEAVE();
+}
+
+/**
+ * @brief Build new roaming connect ie for okc
+ *
+ * @param priv            A pointer to moal_private
+ * @param entry           A pointer to pmksa_entry
+ **/
+static int
+woal_update_okc_roaming_ie(moal_private *priv, struct pmksa_entry *entry)
+{
+	struct cfg80211_connect_params *sme = &priv->sme_current;
+	int ret = MLAN_STATUS_SUCCESS;
+	const t_u8 *sme_pos, *sme_ptr;
+	t_u8 *okc_ie_pos;
+	t_u8 id, ie_len;
+	int left_len;
+
+	ENTER();
+
+	if (!sme->ie || !sme->ie_len) {
+		PRINTM(MERROR, "No connect ie saved in driver\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (!entry) {
+		PRINTM(MERROR, "No roaming ap pmkid\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (!priv->okc_roaming_ie) {
+		int okc_ie_len = sme->ie_len + sizeof(t_u16) + PMKID_LEN;
+
+		/** Alloc new buffer for okc roaming ie */
+		priv->okc_roaming_ie = kzalloc(okc_ie_len, GFP_KERNEL);
+		if (!priv->okc_roaming_ie) {
+			PRINTM(MERROR, "Fail to allocate assoc req ie\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	/* Build OKC RSN IE with PMKID list
+	 * Format of RSN IE: length(bytes) and container
+	 * | 1| 1 |   2   |          4            |           2               |
+	 * |id|len|version|group data cipher suite|pairwise cipher suite count|
+	 * |          4 * m           |       2       |    4 * n     |   2    |
+	 * |pairwise cipher suite list|AKM suite count|AKM suite list|RSN Cap |
+	 * |    2     |  16 * s  |              4              |
+	 * |PMKIDCount|PMKID List|Group Management Cipher Suite|
+	 */
+#define PAIRWISE_CIPHER_COUNT_OFFSET 8
+#define AKM_SUITE_COUNT_OFFSET(n) (10 + (n)*4)
+#define PMKID_COUNT_OFFSET(n) (14 + (n)*4)
+
+	sme_pos = sme->ie;
+	left_len = sme->ie_len;
+	okc_ie_pos = priv->okc_roaming_ie;
+	priv->okc_ie_len = 0;
+
+	while (left_len >= 2) {
+		id = *sme_pos;
+		ie_len = *(sme_pos + 1);
+		if ((ie_len + 2) > left_len) {
+			PRINTM(MERROR, "Invalid ie len %d\n", ie_len);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		if (id == RSN_IE) {
+			t_u16 pairwise_count, akm_count;
+			t_u8 *rsn_ie_len;
+			int rsn_offset;
+
+			pairwise_count =
+				*(t_u16 *)(sme_pos +
+					   PAIRWISE_CIPHER_COUNT_OFFSET);
+			akm_count =
+				*(t_u16 *)(sme_pos +
+					   AKM_SUITE_COUNT_OFFSET
+					   (pairwise_count));
+			rsn_offset =
+				PMKID_COUNT_OFFSET(pairwise_count + akm_count);
+			sme_ptr = (t_u8 *)(sme_pos + rsn_offset);
+
+			moal_memcpy_ext(priv->phandle, okc_ie_pos, sme_pos,
+					rsn_offset, rsn_offset);
+			rsn_ie_len = okc_ie_pos + 1;
+			okc_ie_pos += rsn_offset;
+			*(t_u16 *)okc_ie_pos = 1;
+			okc_ie_pos += sizeof(t_u16);
+			moal_memcpy_ext(priv->phandle, okc_ie_pos, entry->pmkid,
+					PMKID_LEN, PMKID_LEN);
+			okc_ie_pos += PMKID_LEN;
+			priv->okc_ie_len +=
+				rsn_offset + sizeof(t_u16) + PMKID_LEN;
+			*rsn_ie_len =
+				rsn_offset - 2 + sizeof(t_u16) + PMKID_LEN;
+
+			if ((ie_len + 2) > rsn_offset) {
+				/** Previous conn ie include pmkid list */
+				u16 pmkid_count = *(t_u16 *)sme_ptr;
+				rsn_offset += (sizeof(t_u16) +
+					       PMKID_LEN * pmkid_count);
+				if ((ie_len + 2) > rsn_offset) {
+					sme_ptr += (sizeof(t_u16) +
+						    PMKID_LEN * pmkid_count);
+					moal_memcpy_ext(priv->phandle,
+							okc_ie_pos, sme_ptr,
+							(ie_len + 2 -
+							 rsn_offset),
+							(ie_len + 2 -
+							 rsn_offset));
+					okc_ie_pos += (ie_len + 2 - rsn_offset);
+					priv->okc_ie_len +=
+						(ie_len + 2 - rsn_offset);
+					*rsn_ie_len +=
+						(ie_len + 2 - rsn_offset);
+				}
+			}
+		} else {
+			moal_memcpy_ext(priv->phandle, okc_ie_pos, sme_pos,
+					ie_len + 2, ie_len + 2);
+			okc_ie_pos += ie_len + 2;
+			priv->okc_ie_len += ie_len + 2;
+		}
+
+		sme_pos += (ie_len + 2);
+		left_len -= (ie_len + 2);
+	}
+
+done:
+	if (ret != MLAN_STATUS_SUCCESS) {
+		if (priv->okc_roaming_ie) {
+			kfree(priv->okc_roaming_ie);
+			priv->okc_roaming_ie = NULL;
+			priv->okc_ie_len = 0;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Start roaming: driver handle roaming
+ *
+ * @param priv      A pointer to moal_private structure
+ *
+ * @return          N/A
+ */
+void
+woal_start_roaming(moal_private *priv)
+{
+	mlan_ds_get_signal signal;
+	mlan_ssid_bssid ssid_bssid;
+	char rssi_low[10];
+	int ret = 0;
+	mlan_ds_misc_assoc_rsp *assoc_rsp;
+	IEEEtypes_AssocRsp_t *passoc_rsp = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	struct cfg80211_roam_info roam_info = { };
+#endif
+
+	ENTER();
+	if (priv->ft_roaming_triggered_by_driver) {
+		PRINTM(MIOCTL, "FT roaming is in processing ...... \n");
+		LEAVE();
+		return;
+	}
+
+	if (priv->last_event & EVENT_BG_SCAN_REPORT) {
+		woal_inform_bss_from_scan_result(priv, NULL, MOAL_IOCTL_WAIT);
+		PRINTM(MIOCTL, "Report bgscan result\n");
+	}
+	if (priv->media_connected == MFALSE || !priv->sme_current.ssid_len) {
+		PRINTM(MIOCTL, "Not connected, ignore roaming\n");
+		LEAVE();
+		return;
+	}
+
+	/* Get signal information from the firmware */
+	memset(&signal, 0, sizeof(mlan_ds_get_signal));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_signal_info(priv, MOAL_IOCTL_WAIT, &signal)) {
+		PRINTM(MERROR, "Error getting signal information\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+	ssid_bssid.ssid.ssid_len = priv->sme_current.ssid_len;
+	moal_memcpy_ext(priv->phandle, ssid_bssid.ssid.ssid,
+			priv->sme_current.ssid, priv->sme_current.ssid_len,
+			sizeof(ssid_bssid.ssid.ssid));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		PRINTM(MIOCTL, "Can not find better network\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	/* check if we found different AP */
+	if (!memcmp(&ssid_bssid.bssid, priv->cfg_bssid, MLAN_MAC_ADDR_LENGTH)) {
+		PRINTM(MIOCTL, "This is the same AP, no roaming\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MIOCTL, "Find AP: bssid=" MACSTR ", signal=%d\n",
+	       MAC2STR(ssid_bssid.bssid), ssid_bssid.rssi);
+	/* check signal */
+	if (!(priv->last_event & EVENT_PRE_BCN_LOST)) {
+		if ((abs(signal.bcn_rssi_avg) - abs(ssid_bssid.rssi)) <
+		    DELTA_RSSI) {
+			PRINTM(MERROR, "New AP's signal is not good too.\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	/**check if need start FT Roaming*/
+	if (priv->ft_ie_len && (priv->ft_md == ssid_bssid.ft_md) &&
+	    (priv->ft_cap == ssid_bssid.ft_cap)) {
+		priv->ft_roaming_triggered_by_driver = MTRUE;
+		woal_start_ft_roaming(priv, &ssid_bssid);
+		goto done;
+	}
+	/* start roaming to new AP */
+	priv->sme_current.bssid = priv->conn_bssid;
+	moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.bssid,
+			&ssid_bssid.bssid, MLAN_MAC_ADDR_LENGTH,
+			sizeof(priv->conn_bssid));
+
+#ifdef STA_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext)) {
+		/** Check if current roaming support OKC offload roaming */
+		if (priv->sme_current.crypto.n_akm_suites &&
+		    priv->sme_current.crypto.akm_suites[0] ==
+		    WLAN_AKM_SUITE_8021X) {
+			struct pmksa_entry *entry = NULL;
+
+			/** Get OKC PMK Cache entry
+			 *  Firstly try to get pmksa from cfg80211
+			 */
+			priv->wait_target_ap_pmkid = MTRUE;
+			cfg80211_pmksa_candidate_notify(priv->netdev, 0,
+							priv->sme_current.bssid,
+							MTRUE, GFP_ATOMIC);
+			if (wait_event_interruptible_timeout(priv->okc_wait_q,
+							     !priv->
+							     wait_target_ap_pmkid,
+							     OKC_WAIT_TARGET_PMKSA_TIMEOUT))
+			{
+				PRINTM(MIOCTL, "OKC Roaming is ready\n");
+				entry = priv->target_ap_pmksa;
+			} else {
+				/** Try to get pmksa from pmksa list */
+				priv->wait_target_ap_pmkid = MFALSE;
+				entry = woal_get_pmksa_entry(priv,
+							     priv->sme_current.
+							     bssid);
+			}
+			/** Build okc roaming ie */
+			woal_update_okc_roaming_ie(priv, entry);
+			priv->target_ap_pmksa = NULL;
+		}
+	}
+#endif
+#endif
+	assoc_rsp = kzalloc(sizeof(mlan_ds_misc_assoc_rsp), GFP_ATOMIC);
+	if (!assoc_rsp) {
+		PRINTM(MERROR, "Failed to allocate memory for assoc_rsp\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	ret = woal_cfg80211_assoc(priv, (void *)&priv->sme_current,
+				  MOAL_IOCTL_WAIT, assoc_rsp);
+	if (!ret) {
+		const t_u8 *ie;
+		int ie_len;
+
+		woal_inform_bss_from_scan_result(priv, NULL, MOAL_IOCTL_WAIT);
+		passoc_rsp = (IEEEtypes_AssocRsp_t *)assoc_rsp->assoc_resp_buf;
+
+		/** Update connect ie in roam event */
+		ie = priv->sme_current.ie;
+		ie_len = priv->sme_current.ie_len;
+#ifdef STA_CFG80211
+		if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext)) {
+			/** Check if current roaming support OKC offload roaming
+			 */
+			if (priv->sme_current.crypto.n_akm_suites &&
+			    priv->sme_current.crypto.akm_suites[0] ==
+			    WLAN_AKM_SUITE_8021X) {
+				if (priv->okc_roaming_ie && priv->okc_ie_len) {
+					ie = priv->okc_roaming_ie;
+					ie_len = priv->okc_ie_len;
+				}
+			}
+		}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+		roam_info.bssid = priv->cfg_bssid;
+		roam_info.req_ie = ie;
+		roam_info.req_ie_len = ie_len;
+		roam_info.resp_ie = passoc_rsp->ie_buffer;
+		roam_info.resp_ie_len =
+			assoc_rsp->assoc_resp_len - ASSOC_RESP_FIXED_SIZE;
+		cfg80211_roamed(priv->netdev, &roam_info, GFP_KERNEL);
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+		cfg80211_roamed(priv->netdev, NULL, priv->cfg_bssid, ie, ie_len,
+				passoc_rsp->ie_buffer,
+				assoc_rsp->assoc_resp_len -
+				ASSOC_RESP_FIXED_SIZE, GFP_KERNEL);
+#else
+		cfg80211_roamed(priv->netdev, priv->cfg_bssid, ie, ie_len,
+				passoc_rsp->ie_buffer,
+				assoc_rsp->assoc_resp_len -
+				ASSOC_RESP_FIXED_SIZE, GFP_KERNEL);
+#endif
+#endif
+		PRINTM(MMSG, "Roamed to bssid " MACSTR " successfully\n",
+		       MAC2STR(priv->cfg_bssid));
+	} else {
+		PRINTM(MIOCTL, "Roaming to bssid " MACSTR " failed\n",
+		       MAC2STR(ssid_bssid.bssid));
+	}
+	kfree(assoc_rsp);
+done:
+	/* config rssi low threshold again */
+	priv->last_event = 0;
+	priv->rssi_low = DEFAULT_RSSI_LOW_THRESHOLD;
+	sprintf(rssi_low, "%d", priv->rssi_low);
+	woal_set_rssi_low_threshold(priv, rssi_low, MOAL_IOCTL_WAIT);
+	LEAVE();
+	return;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+#ifdef UAP_SUPPORT
+/**
+ * @brief add uap station
+ *
+ * @param wiphy                 A pointer to wiphy structure
+ * @param dev                   A pointer to net_device structure
+ * @param mac                  A pointer to peer mac
+ * @param params           	station parameters
+ *
+ * @return                  	0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev,
+			      u8 *mac, struct station_parameters *params)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ioctl_req *req = NULL;
+	t_u32 req_len = 0;
+	mlan_ds_bss *bss = NULL;
+	t_u8 *pos;
+	t_u8 qosinfo;
+	MrvlIEtypes_Data_t *tlv;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+	MrvlExtIEtypes_Data_t *ext_tlv;
+#endif
+	mlan_status status;
+	int ret = 0;
+
+	ENTER();
+
+	req_len = sizeof(mlan_ds_bss);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	if (params->ext_capab_len)
+		req_len += sizeof(MrvlIEtypesHeader_t) + params->ext_capab_len;
+#endif
+	if (params->supported_rates_len)
+		req_len += sizeof(MrvlIEtypesHeader_t) +
+			params->supported_rates_len;
+	if (params->uapsd_queues || params->max_sp)
+		req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(qosinfo);
+	if (params->ht_capa)
+		req_len += sizeof(MrvlIEtypesHeader_t) +
+			sizeof(struct ieee80211_ht_cap);
+	if (params->vht_capa)
+		req_len += sizeof(MrvlIEtypesHeader_t) +
+			sizeof(struct ieee80211_vht_cap);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (params->opmode_notif_used)
+		req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(u8);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+	if (params->he_capa_len)
+		req_len += sizeof(MrvlExtIEtypesHeader_t) + params->he_capa_len;
+#endif
+	req = woal_alloc_mlan_ioctl_req(req_len);
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_ADD_STATION;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+	bss->param.sta_info.listen_interval = params->listen_interval;
+	bss->param.sta_info.aid = params->aid;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	bss->param.sta_info.cap_info = params->capability;
+#else
+	bss->param.sta_info.cap_info = 0;
+#endif
+	bss->param.sta_info.tlv_len = 0;
+	bss->param.sta_info.sta_flags = params->sta_flags_set;
+	moal_memcpy_ext(priv->phandle, bss->param.sta_info.peer_mac, mac,
+			MLAN_MAC_ADDR_LENGTH,
+			sizeof(bss->param.sta_info.peer_mac));
+	PRINTM(MMSG, "wlan: UAP/GO add peer station, address =" MACSTR "\n",
+	       MAC2STR(mac));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	PRINTM(MCMND,
+	       "sta_flags=0x%x listen_interval=%d aid=%d cap_info=0x%x\n",
+	       params->sta_flags_set, params->listen_interval, params->aid,
+	       params->capability);
+#else
+	PRINTM(MCMND, "sta_flags=0x%x listen_interval=%d aid=%d\n",
+	       params->sta_flags_set, params->listen_interval, params->aid);
+#endif
+	pos = &bss->param.sta_info.tlv[0];
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	if (params->ext_capab_len) {
+		tlv = (MrvlIEtypes_Data_t *)pos;
+		tlv->header.type = EXT_CAPABILITY;
+		tlv->header.len = params->ext_capab_len;
+		moal_memcpy_ext(priv->phandle, tlv->data, params->ext_capab,
+				tlv->header.len, tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+#endif
+	if (params->supported_rates_len) {
+		tlv = (MrvlIEtypes_Data_t *)pos;
+		tlv->header.type = SUPPORTED_RATES;
+		tlv->header.len = params->supported_rates_len;
+		moal_memcpy_ext(priv->phandle, tlv->data,
+				params->supported_rates, tlv->header.len,
+				tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+	if (params->uapsd_queues || params->max_sp) {
+		tlv = (MrvlIEtypes_Data_t *)pos;
+		tlv->header.type = QOS_INFO;
+		tlv->header.len = sizeof(qosinfo);
+		qosinfo = params->uapsd_queues | (params->max_sp << 5);
+		moal_memcpy_ext(priv->phandle, tlv->data, &qosinfo,
+				tlv->header.len, tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+	if (params->ht_capa) {
+		tlv = (MrvlIEtypes_Data_t *)pos;
+		tlv->header.type = HT_CAPABILITY;
+		tlv->header.len = sizeof(struct ieee80211_ht_cap);
+		moal_memcpy_ext(priv->phandle, tlv->data, params->ht_capa,
+				tlv->header.len, tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+	if (params->vht_capa) {
+		tlv = (MrvlIEtypes_Data_t *)pos;
+		tlv->header.type = VHT_CAPABILITY;
+		tlv->header.len = sizeof(struct ieee80211_vht_cap);
+		moal_memcpy_ext(priv->phandle, tlv->data, params->vht_capa,
+				tlv->header.len, tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (params->opmode_notif_used) {
+		tlv = (MrvlIEtypes_Data_t *)pos;
+		tlv->header.type = OPER_MODE_NTF;
+		tlv->header.len = sizeof(u8);
+		moal_memcpy_ext(priv->phandle, tlv->data, &params->opmode_notif,
+				tlv->header.len, tlv->header.len);
+		pos += sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlIEtypesHeader_t) + tlv->header.len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+	if (params->he_capa_len) {
+		ext_tlv = (MrvlExtIEtypes_Data_t *) pos;
+		ext_tlv->header.type = EXTENSION;
+		ext_tlv->header.len = params->he_capa_len + sizeof(u8);
+		ext_tlv->header.ext_id = HE_CAPABILITY;
+		moal_memcpy_ext(priv->phandle, ext_tlv->data,
+				(u8 *)params->he_capa, params->he_capa_len,
+				params->he_capa_len);
+		pos += sizeof(MrvlExtIEtypesHeader_t) + params->he_capa_len;
+		bss->param.sta_info.tlv_len +=
+			sizeof(MrvlExtIEtypesHeader_t) + params->he_capa_len;
+		tlv = (MrvlIEtypes_Data_t *)pos;
+	}
+#endif
+	DBG_HEXDUMP(MCMD_D, "sta tlv", &bss->param.sta_info.tlv[0],
+		    bss->param.sta_info.tlv_len);
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function is probe client handle.
+ *
+ *  @param wiphy       A pointer to wiphy.
+ *
+ *  @param dev         A pointer to net_device
+ *
+ *  @param peer        A pointer to peer
+ *
+ *  @param cookie      A pointer to cookie
+ *
+ *  @return            0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_probe_client(struct wiphy *wiphy,
+			   struct net_device *dev, const u8 *peer, u64 * cookie)
+{
+	return -1;
+}
+#endif
+
+/**
+ *  @brief Sends deauth packet to kernel
+ *
+ *  @param priv A pointer to moal_private struct
+ *  @param sa   A pointer to source address
+ *  @param reason_code  disconnect reason code
+ *  @return     N/A
+ */
+void
+woal_host_mlme_disconnect(moal_private *priv, u16 reason_code, u8 *sa)
+{
+	t_u8 broadcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	t_u8 frame_buf[26];
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)frame_buf;
+	ENTER();
+
+	mgmt->frame_control = (__force __le16) IEEE80211_STYPE_DEAUTH;
+	mgmt->duration = 0;
+	mgmt->seq_ctrl = 0;
+	mgmt->u.deauth.reason_code = (__force __le16) reason_code;
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		moal_memcpy_ext(priv->phandle, mgmt->da, broadcast_addr,
+				ETH_ALEN, sizeof(mgmt->da));
+		moal_memcpy_ext(priv->phandle, mgmt->sa,
+				priv->sme_current.bssid, ETH_ALEN,
+				sizeof(mgmt->sa));
+		moal_memcpy_ext(priv->phandle, mgmt->bssid, priv->cfg_bssid,
+				ETH_ALEN, sizeof(mgmt->bssid));
+		priv->host_mlme = MFALSE;
+		priv->auth_flag = 0;
+	} else {
+		moal_memcpy_ext(priv->phandle, mgmt->da, priv->current_addr,
+				ETH_ALEN, sizeof(mgmt->da));
+		moal_memcpy_ext(priv->phandle, mgmt->sa, sa, ETH_ALEN,
+				sizeof(mgmt->sa));
+		moal_memcpy_ext(priv->phandle, mgmt->bssid, priv->current_addr,
+				ETH_ALEN, sizeof(mgmt->bssid));
+		PRINTM(MMSG,
+		       "wlan: hostmlme notify deauth station " MACSTR "\n",
+		       MAC2STR(sa));
+	}
+
+	if (GET_BSS_ROLE(priv) != MLAN_BSS_ROLE_UAP) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+		mutex_lock(&priv->wdev->mtx);
+		cfg80211_rx_mlme_mgmt(priv->netdev, frame_buf, 26);
+		mutex_unlock(&priv->wdev->mtx);
+#else
+		cfg80211_send_deauth(priv->netdev, frame_buf, 26);
+#endif
+
+	} else {
+		int freq = ieee80211_channel_to_frequency(priv->channel
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+							  ,
+							  (priv->channel <=
+							   14 ?
+							   IEEE80211_BAND_2GHZ :
+							   IEEE80211_BAND_5GHZ)
+#endif
+			);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		cfg80211_rx_mgmt(
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+					priv->wdev,
+#else
+					priv->netdev,
+#endif
+					freq, 0, frame_buf, 26
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+					, 0
+#endif
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
+					, GFP_ATOMIC
+#endif
+			);
+#else
+		cfg80211_rx_mgmt(priv->netdev, freq, frame_buf, 26, GFP_ATOMIC);
+#endif
+	}
+
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ * @brief Register the device with cfg80211
+ *
+ * @param dev       A pointer to net_device structure
+ * @param bss_type  BSS type
+ *
+ * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_register_sta_cfg80211(struct net_device *dev, t_u8 bss_type)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct wireless_dev *wdev = NULL;
+	int psmode = 0;
+	enum ieee80211_band band;
+
+	ENTER();
+
+	wdev = (struct wireless_dev *)&priv->w_dev;
+	memset(wdev, 0, sizeof(struct wireless_dev));
+	wdev->wiphy = priv->phandle->wiphy;
+	if (!wdev->wiphy) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (bss_type == MLAN_BSS_TYPE_STA) {
+		wdev->iftype = NL80211_IFTYPE_STATION;
+		priv->roaming_enabled = MFALSE;
+		priv->roaming_required = MFALSE;
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+		wdev->iftype = NL80211_IFTYPE_STATION;
+#endif
+#endif
+	dev_net_set(dev, wiphy_net(wdev->wiphy));
+	dev->ieee80211_ptr = wdev;
+	SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
+	priv->wdev = wdev;
+	/* Get IEEE power save mode */
+	if (MLAN_STATUS_SUCCESS == woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
+							   &psmode, 0,
+							   MOAL_IOCTL_WAIT)) {
+		/* Save the IEEE power save mode to wiphy, because after
+		 * warmreset wiphy power save should be updated instead
+		 * of using the last saved configuration */
+		if (psmode)
+			priv->wdev->ps = MTRUE;
+		else
+			priv->wdev->ps = MFALSE;
+	}
+	if (priv->phandle->country_code[0] && priv->phandle->country_code[1]) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+		if (priv->phandle->params.cntry_txpwr == CNTRY_RGPOWER_MODE
+		    && !priv->phandle->params.txpwrlimit_cfg)
+			queue_work(priv->phandle->evt_workqueue,
+				   &priv->phandle->regulatory_work);
+#endif
+		band = priv->phandle->band;
+		priv->phandle->band = IEEE80211_BAND_2GHZ;
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+		woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
+		priv->phandle->band = band;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Initialize the wiphy
+ *
+ * @param priv            A pointer to moal_private structure
+ * @param wiphy 		  A pointer to structure wiphy
+ * @param wait_option     Wait option
+ * @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_cfg80211_init_wiphy(moal_private *priv, struct wiphy *wiphy,
+			 t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int retry_count, rts_thr, frag_thr;
+	mlan_ioctl_req *req = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	mlan_ds_radio_cfg *radio = NULL;
+#endif
+	pmlan_ds_11n_cfg cfg_11n = NULL;
+	t_u32 hw_dev_cap;
+#ifdef UAP_SUPPORT
+	pmlan_uap_bss_param sys_cfg = NULL;
+#endif
+	int mcs_supp = 0;
+
+	ENTER();
+	/* Get 11n tx parameters from MLAN */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	req->action = MLAN_ACT_GET;
+	cfg_11n->param.htcap_cfg.hw_cap_req = MTRUE;
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	hw_dev_cap = cfg_11n->param.htcap_cfg.htcap;
+
+	/* Get supported MCS sets */
+	memset(req->pbuf, 0, sizeof(mlan_ds_11n_cfg));
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_SUPPORTED_MCS_SET;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+	req->action = MLAN_ACT_GET;
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	/* Initialize parameters for 2GHz and 5GHz bands */
+	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+		if (IS_CARD9098(priv->phandle->card_type) ||
+		    IS_CARD9097(priv->phandle->card_type)) {
+			mcs_supp = priv->phandle->params.antcfg & 0xf;
+			if (mcs_supp != 3 && mcs_supp != 0)
+				cfg_11n->param.supported_mcs_set[1] = 0;
+			cfg_11n->param.supported_mcs_set[4] = 0;
+		}
+		woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->
+					   ht_cap, hw_dev_cap,
+					   cfg_11n->param.supported_mcs_set);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+		woal_cfg80211_setup_vht_cap(priv,
+					    &wiphy->bands[IEEE80211_BAND_2GHZ]->
+					    vht_cap);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+		woal_cfg80211_setup_he_cap(priv,
+					   wiphy->bands[IEEE80211_BAND_2GHZ]);
+#endif
+	}
+	/* For 2.4G band only card, this shouldn't be set */
+	if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+		if (IS_CARD9098(priv->phandle->card_type) ||
+		    IS_CARD9097(priv->phandle->card_type)) {
+			mcs_supp = (priv->phandle->params.antcfg & 0xf00) >> 8;
+			if (mcs_supp != 3 && mcs_supp != 0)
+				cfg_11n->param.supported_mcs_set[1] = 0;
+		}
+		woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_5GHZ]->
+					   ht_cap, hw_dev_cap,
+					   cfg_11n->param.supported_mcs_set);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+		woal_cfg80211_setup_vht_cap(priv,
+					    &wiphy->bands[IEEE80211_BAND_5GHZ]->
+					    vht_cap);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+		woal_cfg80211_setup_he_cap(priv,
+					   wiphy->bands[IEEE80211_BAND_5GHZ]);
+#endif
+	}
+	kfree(req);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	/* Get antenna modes */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	radio = (mlan_ds_radio_cfg *)req->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	req->req_id = MLAN_IOCTL_RADIO_CFG;
+	req->action = MLAN_ACT_GET;
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	/* Set available antennas to wiphy */
+	if (IS_CARD9098(priv->phandle->card_type) ||
+	    IS_CARD9097(priv->phandle->card_type)) {
+		woal_cfg80211_notify_antcfg(priv, wiphy, radio);
+	}
+	wiphy->available_antennas_tx = radio->param.ant_cfg.tx_antenna;
+	wiphy->available_antennas_rx = radio->param.ant_cfg.rx_antenna;
+#endif /* CFG80211_VERSION_CODE */
+
+	/* Set retry limit count to wiphy */
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_retry(priv, MLAN_ACT_GET, wait_option,
+				       &retry_count)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+#ifdef UAP_SUPPORT
+	else {
+		sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+		if (!sys_cfg) {
+			PRINTM(MERROR,
+			       "Fail to alloc memory for mlan_uap_bss_param\n");
+			ret = MLAN_STATUS_FAILURE;
+			kfree(sys_cfg);
+			goto done;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_sys_config(priv, MLAN_ACT_GET, wait_option,
+					    sys_cfg)) {
+			ret = MLAN_STATUS_FAILURE;
+			kfree(sys_cfg);
+			goto done;
+		}
+		retry_count = sys_cfg->retry_limit;
+		kfree(sys_cfg);
+	}
+#endif
+	wiphy->retry_long = (t_u8)retry_count;
+	wiphy->retry_short = (t_u8)retry_count;
+	wiphy->max_scan_ie_len = MAX_IE_SIZE;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+	wiphy->mgmt_stypes = ieee80211_mgmt_stypes;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
+#endif /* KERNEL_VERSION */
+
+	/* Set RTS threshold to wiphy */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_rts(priv, MLAN_ACT_GET, wait_option, &rts_thr)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (rts_thr < MLAN_RTS_MIN_VALUE || rts_thr > MLAN_RTS_MAX_VALUE)
+		rts_thr = MLAN_FRAG_RTS_DISABLED;
+	wiphy->rts_threshold = (t_u32)rts_thr;
+
+	/* Set fragment threshold to wiphy */
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_frag(priv, MLAN_ACT_GET, wait_option, &frag_thr)) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (frag_thr < MLAN_RTS_MIN_VALUE || frag_thr > MLAN_RTS_MAX_VALUE)
+		frag_thr = MLAN_FRAG_RTS_DISABLED;
+	wiphy->frag_threshold = (t_u32)frag_thr;
+
+done:
+	LEAVE();
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+/**
+ * @brief Update channel flag
+ *
+ * @param wiphy          A pointer to wiphy structure
+ *
+ * @return                N/A
+ */
+static void
+woal_update_channel_flag(struct wiphy *wiphy, mlan_fw_info *fw_info)
+{
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	int i;
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		sband = wiphy->bands[band];
+		if (!sband)
+			continue;
+		if (sband->band == IEEE80211_BAND_5GHZ &&
+		    fw_info->prohibit_80mhz) {
+			for (i = 0; i < sband->n_channels; i++) {
+				sband->channels[i].flags |=
+					IEEE80211_CHAN_NO_80MHZ;
+				PRINTM(MCMND, "hw_value=%d channel flag %x\n",
+				       sband->channels[i].hw_value,
+				       sband->channels[i].flags);
+			}
+		}
+	}
+}
+#endif
+
+/*
+ * This function registers the device with CFG802.11 subsystem.
+ *
+ * @param priv       A pointer to moal_private
+ *
+ */
+mlan_status
+woal_register_cfg80211(moal_private *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct wiphy *wiphy;
+	void *wdev_priv = NULL;
+	mlan_fw_info fw_info;
+	char *country = NULL, *reg_alpha2 = NULL;
+	int index = 0;
+
+	ENTER();
+
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	reg_alpha2 = priv->phandle->params.reg_alpha2;
+	wiphy = wiphy_new(&woal_cfg80211_ops, sizeof(moal_handle *));
+	if (!wiphy) {
+		PRINTM(MERROR, "Could not allocate wiphy device\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_wiphy;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) {
+		woal_cfg80211_ops.auth = woal_cfg80211_authenticate;
+		woal_cfg80211_ops.assoc = woal_cfg80211_associate;
+		woal_cfg80211_ops.disconnect = NULL;
+		woal_cfg80211_ops.connect = NULL;
+#ifdef UAP_SUPPORT
+		woal_cfg80211_ops.probe_client = woal_cfg80211_probe_client;
+#endif
+	}
+#endif
+#ifdef CONFIG_PM
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+	if (fw_info.fw_supplicant_support)
+		wiphy->wowlan = &wowlan_support_with_gtk;
+	else
+		wiphy->wowlan = &wowlan_support;
+#else
+	wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_MAGIC_PKT;
+	if (fw_info.fw_supplicant_support) {
+		wiphy->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+			WIPHY_WOWLAN_GTK_REKEY_FAILURE;
+	}
+	wiphy->wowlan.n_patterns = MAX_NUM_FILTERS;
+	wiphy->wowlan.pattern_min_len = 1;
+	wiphy->wowlan.pattern_max_len = WOWLAN_MAX_PATTERN_LEN;
+	wiphy->wowlan.max_pkt_offset = WOWLAN_MAX_OFFSET_LEN;
+#endif
+#endif
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	wiphy->coalesce = &coalesce_support;
+#endif
+	wiphy->max_scan_ssids = MRVDRV_MAX_SSID_LIST_LENGTH;
+	wiphy->max_scan_ie_len = MAX_IE_SIZE;
+	wiphy->interface_modes = 0;
+	wiphy->interface_modes = MBIT(NL80211_IFTYPE_STATION) |
+		MBIT(NL80211_IFTYPE_AP);
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	wiphy->interface_modes |=
+		MBIT(NL80211_IFTYPE_P2P_GO) | MBIT(NL80211_IFTYPE_P2P_CLIENT);
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	woal_register_cfg80211_vendor_command(wiphy);
+#endif
+	/* Make this wiphy known to this driver only */
+	wiphy->privid = mrvl_wiphy_privid;
+
+	if (!fw_info.fw_bands)
+		fw_info.fw_bands = BAND_B | BAND_G;
+	if (fw_info.fw_bands & BAND_A) {
+		if (priv->phandle->second_mac)
+			wiphy->bands[IEEE80211_BAND_5GHZ] =
+				&mac1_cfg80211_band_5ghz;
+		else
+
+			wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+		woal_update_channel_flag(wiphy, &fw_info);
+#endif
+		priv->phandle->band = IEEE80211_BAND_5GHZ;
+	}
+	/* Supported bands */
+	if (fw_info.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
+		if (priv->phandle->second_mac)
+			wiphy->bands[IEEE80211_BAND_2GHZ] =
+				&mac1_cfg80211_band_2ghz;
+		else
+			wiphy->bands[IEEE80211_BAND_2GHZ] = &cfg80211_band_2ghz;
+		/* If 2.4G enable, it will overwrite default to 2.4G */
+		priv->phandle->band = IEEE80211_BAND_2GHZ;
+	}
+
+	if (fw_info.fw_bands & BAND_A) {
+		/** reduce scan time from 110ms to 80ms */
+		woal_set_scan_time(priv, INIT_ACTIVE_SCAN_CHAN_TIME,
+				   INIT_PASSIVE_SCAN_CHAN_TIME,
+				   INIT_SPECIFIC_SCAN_CHAN_TIME);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+		cfg80211_iface_comb_ap_sta.radar_detect_widths |=
+			MBIT(NL80211_CHAN_WIDTH_40);
+		if (fw_info.fw_bands & BAND_AAC)
+			cfg80211_iface_comb_ap_sta.radar_detect_widths |=
+				MBIT(NL80211_CHAN_WIDTH_80);
+#endif
+	} else
+		woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME,
+				   PASSIVE_SCAN_CHAN_TIME,
+				   SPECIFIC_SCAN_CHAN_TIME);
+
+	/* Initialize cipher suits */
+	wiphy->cipher_suites = cfg80211_cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(cfg80211_cipher_suites);
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (!moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+#endif
+		wiphy->max_acl_mac_addrs = MAX_MAC_FILTER_NUM;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+	if (fw_info.max_ap_assoc_sta) {
+		wiphy->max_ap_assoc_sta = fw_info.max_ap_assoc_sta;
+		PRINTM(MCMND, "Set wiphy max_ap_assoc_sta=%d\n",
+		       wiphy->max_ap_assoc_sta);
+	}
+#endif
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+	/* Initialize interface combinations */
+	wiphy->iface_combinations = &cfg80211_iface_comb_ap_sta;
+	wiphy->n_iface_combinations = 1;
+#endif
+
+	moal_memcpy_ext(priv->phandle, wiphy->perm_addr, priv->current_addr,
+			ETH_ALEN, sizeof(wiphy->perm_addr));
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+	wiphy->flags = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+	wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+	wiphy->flags |= WIPHY_FLAG_NETNS_OK;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+	wiphy->flags |=
+		WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_OFFCHAN_TX;
+	wiphy->flags |= WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+		wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS;
+	else
+#endif
+		wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+#endif
+#ifdef ANDROID_KERNEL
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (!moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+#endif
+		wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (priv->phandle->params.sched_scan) {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+		wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+#else
+		wiphy->max_sched_scan_reqs = 1;
+#endif
+		wiphy->max_sched_scan_ssids = MRVDRV_MAX_SSID_LIST_LENGTH;
+		wiphy->max_sched_scan_ie_len = MAX_IE_SIZE;
+		wiphy->max_match_sets = MRVDRV_MAX_SSID_LIST_LENGTH;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
+		wiphy->max_sched_scan_plans = 3;
+		wiphy->max_sched_scan_plan_iterations = 100;
+#endif
+	}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
+        wiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	wiphy->flags |=
+		WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+		wiphy->features |= NL80211_FEATURE_SAE;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN;
+#endif
+
+	wiphy->reg_notifier = woal_cfg80211_reg_notifier;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+	/* Indicate to cfg80211 that the driver can support
+	 * CSA and ESCA,i.e., both types of channel switch
+	 * Applications like hostapd 2.6 will append CSA IE
+	 * and ECSA IE and expect the driver to advertise 2
+	 * in max_num_csa_counters to successfully issue a
+	 * channel switch
+	 */
+	wiphy->max_num_csa_counters = MAX_CSA_COUNTERS_NUM;
+#endif
+	wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
+	wiphy_ext_feature_set(wiphy,
+			      NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+		wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+	if (fw_info.fw_beacon_prot) {
+		wiphy_ext_feature_set(wiphy,
+				      NL80211_EXT_FEATURE_BEACON_PROTECTION);
+		wiphy_ext_feature_set(wiphy,
+				      NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT);
+	}
+#endif
+
+	/* Set struct moal_handle pointer in wiphy_priv */
+	wdev_priv = wiphy_priv(wiphy);
+	*(unsigned long *)wdev_priv = (unsigned long)priv->phandle;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	set_wiphy_dev(wiphy, (struct device *)priv->phandle->hotplug_device);
+#endif
+	/* Set phy name */
+	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
+		if (m_handle[index] == priv->phandle) {
+			dev_set_name(&wiphy->dev, mwiphy_name, index);
+			break;
+		}
+	}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_BEACON_HINTS)) {
+		/* REGULATORY_DISABLE_BEACON_HINTS: NO-IR flag won't be removed
+		 * on chn where an AP is visible! */
+		wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
+	}
+	if (moal_extflg_isset(priv->phandle, EXT_COUNTRY_IE_IGNORE)) {
+		PRINTM(MIOCTL, "Don't follow countryIE provided by AP.\n");
+		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
+	} else {
+		PRINTM(MIOCTL, "Follow countryIE provided by AP.\n");
+	}
+#endif
+
+	memset(&priv->phandle->country_code, 0,
+	       sizeof(priv->phandle->country_code));
+
+	if (reg_alpha2 && !strncmp(reg_alpha2, "99", strlen("99"))) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+			REGULATORY_DISABLE_BEACON_HINTS |
+			REGULATORY_COUNTRY_IE_IGNORE;
+#else
+		wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+#endif
+		wiphy_apply_custom_regulatory(wiphy, &mrvl_regdom);
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+	if (woal_request_extcap(priv, (t_u8 *)&priv->extended_capabilities,
+				sizeof(priv->extended_capabilities)) < 0)
+		PRINTM(MERROR,
+		       "Failed to get driver extended capability, use default\n");
+	DBG_HEXDUMP(MCMD_D, "wiphy ext cap",
+		    (t_u8 *)&priv->extended_capabilities,
+		    sizeof(priv->extended_capabilities));
+	wiphy->extended_capabilities = (t_u8 *)&priv->extended_capabilities;
+	wiphy->extended_capabilities_mask =
+		(t_u8 *)&priv->extended_capabilities;
+	wiphy->extended_capabilities_len = sizeof(priv->extended_capabilities);
+#endif
+	woal_cfg80211_init_wiphy(priv, wiphy, MOAL_IOCTL_WAIT);
+	if (wiphy_register(wiphy) < 0) {
+		PRINTM(MERROR, "Wiphy device registration failed!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto err_wiphy;
+	}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	if (fw_info.force_reg || (priv->phandle->params.txpwrlimit_cfg &&
+				  priv->phandle->params.cntry_txpwr ==
+				  CNTRY_RGPOWER_MODE)) {
+		PRINTM(MCMND, "FW region_code=%d force_reg=%d\n",
+		       fw_info.region_code, fw_info.force_reg);
+		country = region_code_2_string(fw_info.region_code);
+		if (country) {
+			moal_memcpy_ext(priv->phandle,
+					priv->phandle->country_code, country, 2,
+					2);
+			queue_work(priv->phandle->evt_workqueue,
+				   &priv->phandle->regulatory_work);
+		}
+	}
+#endif
+	if ((!reg_alpha2 || strncmp(reg_alpha2, "99", strlen("99")))
+
+		) {
+		/** we will try driver parameter first */
+		if (reg_alpha2 && woal_is_valid_alpha2(reg_alpha2)) {
+			PRINTM(MIOCTL, "Notify reg_alpha2 %c%c\n",
+			       reg_alpha2[0], reg_alpha2[1]);
+			if (!moal_extflg_isset(priv->phandle,
+					       EXT_DISABLE_REGD_BY_DRIVER))
+				regulatory_hint(wiphy, reg_alpha2);
+		} else {
+			country = region_code_2_string(fw_info.region_code);
+			if (country) {
+				if (fw_info.region_code != 0) {
+					PRINTM(MIOCTL,
+					       "Notify hw region code=%d %c%c\n",
+					       fw_info.region_code, country[0],
+					       country[1]);
+					if (!moal_extflg_isset(priv->phandle,
+							       EXT_DISABLE_REGD_BY_DRIVER))
+						regulatory_hint(wiphy, country);
+				}
+			} else
+				PRINTM(MCMND,
+				       "hw region code=%d not supported\n",
+				       fw_info.region_code);
+		}
+	}
+	priv->phandle->wiphy = wiphy;
+	return ret;
+err_wiphy:
+	if (wiphy)
+		wiphy_free(wiphy);
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlinux/moal_sta_cfg80211.h b/wlan_sd8987/mlinux/moal_sta_cfg80211.h
new file mode 100755
index 0000000..193c64e
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_sta_cfg80211.h
@@ -0,0 +1,31 @@
+/** @file moal_sta_cfg80211.h
+ *
+ * @brief This file contains the STA CFG80211 specific defines.
+ *
+ *
+ * Copyright 2011-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#ifndef _MOAL_STA_CFG80211_H_
+#define _MOAL_STA_CFG80211_H_
+
+/** Convert RSSI signal strength from dBm to mBm (100*dBm) */
+#define RSSI_DBM_TO_MDM(x) ((x)*100)
+
+mlan_status woal_register_sta_cfg80211(struct net_device *dev, t_u8 bss_type);
+
+#endif /* _MOAL_STA_CFG80211_H_ */
diff --git a/wlan_sd8987/mlinux/moal_uap.c b/wlan_sd8987/mlinux/moal_uap.c
new file mode 100755
index 0000000..8155260
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap.c
@@ -0,0 +1,4601 @@
+/** @file moal_uap.c
+ *
+ * @brief This file contains the major functions in UAP
+ * driver.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#include "moal_uap.h"
+#ifdef SDIO
+#include "moal_sdio.h"
+#endif /* SDIO */
+#include "moal_eth_ioctl.h"
+#if defined(STA_CFG80211) && defined(UAP_CFG80211)
+#include "moal_cfg80211.h"
+#endif
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+/********************************************************
+		Global Variables
+********************************************************/
+/********************************************************
+		Local Functions
+********************************************************/
+/**
+ *  @brief uap addba parameter handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_addba_param(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	uap_addba_param param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_addba_param() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MIOCTL,
+	       "addba param: action=%d, timeout=%d, txwinsize=%d, rxwinsize=%d txamsdu=%d rxamsdu=%d\n",
+	       (int)param.action, (int)param.timeout, (int)param.txwinsize,
+	       (int)param.rxwinsize, (int)param.txamsdu, (int)param.rxamsdu);
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
+	ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (!param.action)
+		/* Get addba param from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	else {
+		/* Set addba param in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		cfg_11n->param.addba_param.timeout = param.timeout;
+		cfg_11n->param.addba_param.txwinsize = param.txwinsize;
+		cfg_11n->param.addba_param.rxwinsize = param.rxwinsize;
+		cfg_11n->param.addba_param.txamsdu = param.txamsdu;
+		cfg_11n->param.addba_param.rxamsdu = param.rxamsdu;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	param.timeout = cfg_11n->param.addba_param.timeout;
+	param.txwinsize = cfg_11n->param.addba_param.txwinsize;
+	param.rxwinsize = cfg_11n->param.addba_param.rxwinsize;
+	param.txamsdu = cfg_11n->param.addba_param.txamsdu;
+	param.rxamsdu = cfg_11n->param.addba_param.rxamsdu;
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap aggr priority tbl
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_aggr_priotbl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	uap_aggr_prio_tbl param;
+	int ret = 0;
+	int i = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_aggr_priotbl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "aggr_prio_tbl", (t_u8 *)&param, sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
+	ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (!param.action) {
+		/* Get aggr_prio_tbl from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set aggr_prio_tbl in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			cfg_11n->param.aggr_prio_tbl.ampdu[i] = param.ampdu[i];
+			cfg_11n->param.aggr_prio_tbl.amsdu[i] = param.amsdu[i];
+		}
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	for (i = 0; i < MAX_NUM_TID; i++) {
+		param.ampdu[i] = cfg_11n->param.aggr_prio_tbl.ampdu[i];
+		param.amsdu[i] = cfg_11n->param.aggr_prio_tbl.amsdu[i];
+	}
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap addba reject tbl
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_addba_reject(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	addba_reject_para param;
+	int ret = 0;
+	int i = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_addba_reject() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "addba_reject tbl", (t_u8 *)&param, sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
+	ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (!param.action) {
+		/* Get addba_reject tbl from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set addba_reject tbl in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		for (i = 0; i < MAX_NUM_TID; i++)
+			cfg_11n->param.addba_reject[i] = param.addba_reject[i];
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	for (i = 0; i < MAX_NUM_TID; i++)
+		param.addba_reject[i] = cfg_11n->param.addba_reject[i];
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap get_fw_info handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_get_fw_info(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	uap_fw_info fw;
+	mlan_fw_info fw_info;
+	int ret = 0;
+
+	ENTER();
+	memset(&fw, 0, sizeof(fw));
+	memset(&fw_info, 0, sizeof(fw_info));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_get_fw_info() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&fw, req->ifr_data, sizeof(fw))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	fw.fw_release_number = fw_info.fw_ver;
+	fw.hw_dev_mcs_support = fw_info.hw_dev_mcs_support;
+	fw.fw_bands = fw_info.fw_bands;
+	fw.region_code = fw_info.region_code;
+	fw.hw_dot_11n_dev_cap = fw_info.hw_dot_11n_dev_cap;
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &fw, sizeof(fw))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief configure deep sleep
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_deep_sleep(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_pm_cfg *pm = NULL;
+	deep_sleep_para param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_deep_sleep() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "deep_sleep_para", (t_u8 *)&param, sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	pm = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
+	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
+	ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
+
+	if (!param.action) {
+		/* Get deep_sleep status from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set deep_sleep in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		if (param.deep_sleep == MTRUE) {
+			pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
+			pm->param.auto_deep_sleep.idletime = param.idle_time;
+		} else {
+			pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
+		}
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON)
+		param.deep_sleep = MTRUE;
+	else
+		param.deep_sleep = MFALSE;
+	param.idle_time = pm->param.auto_deep_sleep.idletime;
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief configure band steering
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_band_steer(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *pm = NULL;
+	band_steer_para param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_band_steer() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "band_steer_para", (t_u8 *)&param, sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_band_steer_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	pm = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	pm->sub_command = MLAN_OID_MISC_BAND_STEERING;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	pm->param.band_steer_cfg.action = param.action;
+	pm->param.band_steer_cfg.block_2g_prb_req = param.block_2g_prb_req;
+	pm->param.band_steer_cfg.state = param.state;
+	pm->param.band_steer_cfg.max_btm_req_allowed =
+		param.max_btm_req_allowed;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	param.action = pm->param.band_steer_cfg.action;
+	param.block_2g_prb_req = pm->param.band_steer_cfg.block_2g_prb_req;
+	param.state = pm->param.band_steer_cfg.state;
+	param.max_btm_req_allowed =
+		pm->param.band_steer_cfg.max_btm_req_allowed;
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief configure beacon stuck detect mechanism
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_beacon_stuck(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *pm = NULL;
+	beacon_stuck_detect_para param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_beacon_stuck() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	DBG_HEXDUMP(MCMD_D, "beacon_stuck_detect_para", (t_u8 *)&param,
+		    sizeof(param));
+
+	ioctl_req =
+		woal_alloc_mlan_ioctl_req(sizeof
+					  (mlan_ds_beacon_stuck_param_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	pm = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	pm->sub_command = MLAN_OID_MISC_BEACON_STUCK;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	pm->param.beacon_stuck_cfg.action = param.action;
+	pm->param.beacon_stuck_cfg.beacon_stuck_detect_count =
+		param.beacon_stuck_detect_count;
+	pm->param.beacon_stuck_cfg.recovery_confirm_count =
+		param.recovery_confirm_count;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	param.action = pm->param.beacon_stuck_cfg.action;
+	param.beacon_stuck_detect_count =
+		pm->param.beacon_stuck_cfg.beacon_stuck_detect_count;
+	param.recovery_confirm_count =
+		pm->param.beacon_stuck_cfg.recovery_confirm_count;
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+
+	return ret;
+}
+
+/**
+ *  @brief configure tx_pause settings
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_txdatapause(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	tx_data_pause_para param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_txdatapause corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "tx_data_pause_para", (t_u8 *)&param,
+		    sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_TX_DATAPAUSE;
+	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (!param.action) {
+		/* Get Tx data pause status from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set Tx data pause in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		misc->param.tx_datapause.tx_pause = param.txpause;
+		misc->param.tx_datapause.tx_buf_cnt = param.txbufcnt;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	param.txpause = misc->param.tx_datapause.tx_pause;
+	param.txbufcnt = misc->param.tx_datapause.tx_buf_cnt;
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef SDIO
+/**
+ *  @brief uap sdcmd52rw ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_sdcmd52_rw(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	sdcmd52_para param;
+	t_u8 func, data = 0;
+	int ret = 0, reg;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_sdcmd52_rw() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	func = (t_u8)param.cmd52_params[0];
+	reg = (t_u32)param.cmd52_params[1];
+
+	if (!param.action) {
+		PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
+#ifdef SDIO_MMC
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (func)
+			data = sdio_readb(((struct sdio_mmc_card *)priv->
+					   phandle->card)
+					  ->func, reg, &ret);
+		else
+			data = sdio_f0_readb(((struct sdio_mmc_card *)priv->
+					      phandle->card)
+					     ->func, reg, &ret);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		if (ret) {
+			PRINTM(MERROR,
+			       "sdio_readb: reading register 0x%X failed\n",
+			       reg);
+			goto done;
+		}
+#else
+		if (sdio_read_ioreg(priv->phandle->card, func, reg, &data) < 0) {
+			PRINTM(MERROR,
+			       "sdio_read_ioreg: reading register 0x%X failed\n",
+			       reg);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#endif
+		param.cmd52_params[2] = data;
+	} else {
+		data = (t_u8)param.cmd52_params[2];
+		PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
+		       func, reg, data);
+#ifdef SDIO_MMC
+		sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
+				func);
+		if (func)
+			sdio_writeb(((struct sdio_mmc_card *)priv->phandle->
+				     card)
+				    ->func, data, reg, &ret);
+		else
+			sdio_f0_writeb(((struct sdio_mmc_card *)priv->phandle->
+					card)
+				       ->func, data, reg, &ret);
+		sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
+				   card)->func);
+		if (ret) {
+			PRINTM(MERROR,
+			       "sdio_writeb: writing register 0x%X failed\n",
+			       reg);
+			goto done;
+		}
+#else
+		if (sdio_write_ioreg(priv->phandle->card, func, reg, data) < 0) {
+			PRINTM(MERROR,
+			       "sdio_write_ioreg: writing register 0x%X failed\n",
+			       reg);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+#endif
+	}
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief configure snmp mib
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_snmp_mib(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_snmp_mib *snmp = NULL;
+	snmp_mib_para param;
+	t_u8 value[MAX_SNMP_VALUE_SIZE];
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+	memset(value, 0, MAX_SNMP_VALUE_SIZE);
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_snmp_mib() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy from user */
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "snmp_mib_para", (t_u8 *)&param, sizeof(param));
+	if (param.action) {
+		if (copy_from_user(value, req->ifr_data + sizeof(param),
+				   MIN(param.oid_val_len,
+				       MAX_SNMP_VALUE_SIZE))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		DBG_HEXDUMP(MCMD_D, "snmp_mib_para value", value,
+			    MIN(param.oid_val_len, sizeof(t_u32)));
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	snmp = (mlan_ds_snmp_mib *)ioctl_req->pbuf;
+	ioctl_req->req_id = MLAN_IOCTL_SNMP_MIB;
+	switch (param.oid) {
+	case OID_80211D_ENABLE:
+		snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
+		break;
+	case OID_80211H_ENABLE:
+		snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11H;
+		break;
+	default:
+		PRINTM(MERROR, "%s: Unsupported SNMP_MIB OID (%d).\n", __func__,
+		       param.oid);
+		goto done;
+	}
+
+	if (!param.action) {
+		/* Get mib value from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set mib value to MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		snmp->param.oid_value = *(t_u32 *)value;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!param.action) {	/* GET */
+		if (copy_to_user(req->ifr_data + sizeof(param),
+				 &snmp->param.oid_value,
+				 MIN(param.oid_val_len, sizeof(t_u32)))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief configure domain info
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_domain_info(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11d_cfg *cfg11d = NULL;
+	domain_info_para param;
+	t_u8 tlv[MAX_DOMAIN_TLV_LEN];
+	t_u16 tlv_data_len = 0;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+	memset(tlv, 0, MAX_DOMAIN_TLV_LEN);
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_domain_info() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy from user */
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "domain_info_para", (t_u8 *)&param, sizeof(param));
+	if (param.action) {
+		/* get tlv header */
+		if (copy_from_user(tlv, req->ifr_data + sizeof(param),
+				   TLV_HEADER_LEN)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		tlv_data_len = ((t_u16 *)(tlv))[1];
+		if ((TLV_HEADER_LEN + tlv_data_len) > (int)sizeof(tlv)) {
+			PRINTM(MERROR, "TLV buffer is overflowed");
+			ret = -EINVAL;
+			goto done;
+		}
+		/* get full tlv */
+		if (copy_from_user(tlv, req->ifr_data + sizeof(param),
+				   TLV_HEADER_LEN + tlv_data_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		DBG_HEXDUMP(MCMD_D, "domain_info_para tlv", tlv,
+			    TLV_HEADER_LEN + tlv_data_len);
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg11d = (mlan_ds_11d_cfg *)ioctl_req->pbuf;
+	ioctl_req->req_id = MLAN_IOCTL_11D_CFG;
+	cfg11d->sub_command = MLAN_OID_11D_DOMAIN_INFO;
+
+	if (!param.action) {
+		/* Get mib value from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set mib value to MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		moal_memcpy_ext(priv->phandle, cfg11d->param.domain_tlv, tlv,
+				TLV_HEADER_LEN + tlv_data_len,
+				sizeof(cfg11d->param.domain_tlv));
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!param.action) {	/* GET */
+		tlv_data_len = ((t_u16 *)(cfg11d->param.domain_tlv))[1];
+		if (copy_to_user(req->ifr_data + sizeof(param),
+				 &cfg11d->param.domain_tlv,
+				 TLV_HEADER_LEN + tlv_data_len)) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief configure dfs testing settings
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_dfs_testing(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11h_cfg *cfg11h = NULL;
+	dfs_testing_para param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_dfs_testing() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy from user */
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "dfs_testing_para", (t_u8 *)&param, sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
+	ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
+	cfg11h->sub_command = MLAN_OID_11H_DFS_TESTING;
+
+	if (!param.action) {
+		/* Get mib value from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set mib value to MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		cfg11h->param.dfs_testing.usr_cac_period_msec =
+			param.usr_cac_period * 1000;
+		cfg11h->param.dfs_testing.usr_nop_period_sec =
+			param.usr_nop_period;
+		cfg11h->param.dfs_testing.usr_no_chan_change =
+			param.no_chan_change;
+		cfg11h->param.dfs_testing.usr_fixed_new_chan =
+			param.fixed_new_chan;
+		cfg11h->param.dfs_testing.usr_cac_restart = param.cac_restart;
+		priv->phandle->cac_restart = param.cac_restart;
+		priv->phandle->cac_period_jiffies = param.usr_cac_period * HZ;
+		priv->user_cac_period_msec =
+			cfg11h->param.dfs_testing.usr_cac_period_msec;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!param.action) {	/* GET */
+		param.usr_cac_period =
+			cfg11h->param.dfs_testing.usr_cac_period_msec / 1000;
+		param.usr_nop_period =
+			cfg11h->param.dfs_testing.usr_nop_period_sec;
+		param.no_chan_change =
+			cfg11h->param.dfs_testing.usr_no_chan_change;
+		param.fixed_new_chan =
+			cfg11h->param.dfs_testing.usr_fixed_new_chan;
+		param.cac_restart = cfg11h->param.dfs_testing.usr_cac_restart;
+	}
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+/**
+ *  @brief uap channel NOP status check ioctl handler
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param data             BSS control type
+ *  @return                 0 --success, otherwise fail
+ */
+int
+woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
+			      mlan_ds_11h_chan_nop_info * ch_info)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_cfg *ds_11hcfg = NULL;
+
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!ch_info) {
+		PRINTM(MERROR, "Invalid chan_info\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	req->req_id = MLAN_IOCTL_11H_CFG;
+	req->action = MLAN_ACT_GET;
+
+	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
+	ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_NOP_INFO;
+	moal_memcpy_ext(priv->phandle, &ds_11hcfg->param.ch_nop_info, ch_info,
+			sizeof(mlan_ds_11h_chan_nop_info),
+			sizeof(ds_11hcfg->param.ch_nop_info));
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, ch_info, &ds_11hcfg->param.ch_nop_info,
+			sizeof(mlan_ds_11h_chan_nop_info),
+			sizeof(mlan_ds_11h_chan_nop_info));
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+#endif
+
+/**
+ *  @brief configure channel switch count
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_chan_switch_count_cfg(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11h_cfg *cfg11h = NULL;
+	cscount_cfg_t param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	memset(&param, 0, sizeof(param));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "%s corrupt data\n", __func__);
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy from user */
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "cscount_cfg_t", (t_u8 *)&param, sizeof(param));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+	cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
+	ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
+	cfg11h->sub_command = MLAN_OID_11H_CHAN_SWITCH_COUNT;
+
+	if (!param.action) {
+		/* Get mib value from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set mib value to MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		cfg11h->param.cs_count = param.cs_count;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!param.action) {	/* GET */
+		param.cs_count = cfg11h->param.cs_count;
+	}
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Configure TX beamforming support
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_tx_bf_cfg(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ds_11n_tx_bf_cfg bf_cfg;
+	tx_bf_cfg_para_hdr param;
+	t_u16 action = 0;
+
+	ENTER();
+
+	memset(&param, 0, sizeof(param));
+	memset(&bf_cfg, 0, sizeof(bf_cfg));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_tx_bf_cfg corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!param.action)
+		/* Get BF configurations */
+		action = MLAN_ACT_GET;
+	else
+		/* Set BF configurations */
+		action = MLAN_ACT_SET;
+	if (copy_from_user(&bf_cfg, req->ifr_data + sizeof(tx_bf_cfg_para_hdr),
+			   sizeof(bf_cfg))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	DBG_HEXDUMP(MCMD_D, "bf_cfg", (t_u8 *)&bf_cfg, sizeof(bf_cfg));
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data + sizeof(tx_bf_cfg_para_hdr), &bf_cfg,
+			 sizeof(bf_cfg))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get 11n configurations
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_ht_tx_cfg(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_ds_11n_tx_cfg httx_cfg;
+	mlan_ioctl_req *ioctl_req = NULL;
+	ht_tx_cfg_para_hdr param;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&param, 0, sizeof(ht_tx_cfg_para_hdr));
+	memset(&httx_cfg, 0, sizeof(mlan_ds_11n_tx_cfg));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(ht_tx_cfg_para_hdr))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
+	ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
+	if (copy_from_user(&httx_cfg,
+			   req->ifr_data + sizeof(ht_tx_cfg_para_hdr),
+			   sizeof(mlan_ds_11n_tx_cfg))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!param.action) {
+		/* Get 11n tx parameters from MLAN */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set HT Tx configurations */
+		cfg_11n->param.tx_cfg.httxcap = httx_cfg.httxcap;
+		PRINTM(MINFO, "SET: httxcap:0x%x\n", httx_cfg.httxcap);
+		/* Update 11n tx parameters in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		httx_cfg.httxcap = cfg_11n->param.tx_cfg.httxcap;
+		PRINTM(MINFO, "GET: httxcap:0x%x\n", httx_cfg.httxcap);
+	}
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data + sizeof(ht_tx_cfg_para_hdr), &httx_cfg,
+			 sizeof(mlan_ds_11n_tx_cfg))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get Set/Get 11AC configurations
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_vht_cfg(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0, resbuf_len = 0;
+	mlan_ds_11ac_cfg *cfg_11ac = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_11ac_vht_cfg *vhtcfg = NULL, vht_cfg;
+	t_u8 *respbuf = NULL;
+	vht_cfg_para_hdr param;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+#define CMD_RESPBUF_LEN 2048
+	gfp_t flag;
+
+	ENTER();
+
+	memset(&param, 0, sizeof(vht_cfg_para_hdr));
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	respbuf = kzalloc(CMD_RESPBUF_LEN, flag);
+	if (!respbuf) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(vht_cfg_para_hdr))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11ac = (mlan_ds_11ac_cfg *)ioctl_req->pbuf;
+	cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
+	ioctl_req->req_id = MLAN_IOCTL_11AC_CFG;
+	if (copy_from_user(&vht_cfg, req->ifr_data + sizeof(vht_cfg_para_hdr),
+			   sizeof(mlan_ds_11ac_vht_cfg))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (vht_cfg.band == BAND_SELECT_BOTH) {
+		cfg_11ac->param.vht_cfg.band = (BAND_SELECT_BG | BAND_SELECT_A);
+	} else {
+		cfg_11ac->param.vht_cfg.band = vht_cfg.band;
+	}
+	if (!param.action) {
+		/* GET operation */
+		if (vht_cfg.band == BAND_SELECT_BOTH) {
+			/* if get both bands, get BG first */
+			cfg_11ac->param.vht_cfg.band = BAND_SELECT_BG;
+		}
+		PRINTM(MINFO, "GET: vhtcfg band: 0x%x\n",
+		       cfg_11ac->param.vht_cfg.band);
+		if (priv->bss_role == MLAN_BSS_ROLE_UAP)
+			cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_RX;
+		else
+			cfg_11ac->param.vht_cfg.txrx = vht_cfg.txrx;
+		PRINTM(MINFO, "GET: vhtcfg txrx: 0x%x\n",
+		       cfg_11ac->param.vht_cfg.txrx);
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Band */
+		if (vht_cfg.band == BAND_SELECT_BOTH)
+			cfg_11ac->param.vht_cfg.band =
+				(BAND_SELECT_BG | BAND_SELECT_A);
+		else
+			cfg_11ac->param.vht_cfg.band = vht_cfg.band;
+		PRINTM(MINFO, "SET: vhtcfg band: 0x%x\n",
+		       cfg_11ac->param.vht_cfg.band);
+		/* Tx/Rx */
+		cfg_11ac->param.vht_cfg.txrx = vht_cfg.txrx;
+		PRINTM(MINFO, "SET: vhtcfg txrx: 0x%x\n",
+		       cfg_11ac->param.vht_cfg.txrx);
+		/* BW cfg */
+		cfg_11ac->param.vht_cfg.bwcfg = vht_cfg.bwcfg;
+		PRINTM(MINFO, "SET: vhtcfg bw cfg:0x%x\n",
+		       cfg_11ac->param.vht_cfg.bwcfg);
+
+		cfg_11ac->param.vht_cfg.vht_cap_info = vht_cfg.vht_cap_info;
+		PRINTM(MINFO, "SET: vhtcfg vht_cap_info:0x%x\n",
+		       cfg_11ac->param.vht_cfg.vht_cap_info);
+		cfg_11ac->param.vht_cfg.vht_tx_mcs = vht_cfg.vht_tx_mcs;
+		cfg_11ac->param.vht_cfg.vht_rx_mcs = vht_cfg.vht_rx_mcs;
+		/* Update 11AC parameters in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* number of vhtcfg entries */
+	*respbuf = 1;
+	vhtcfg = (mlan_ds_11ac_vht_cfg *)(respbuf + 1);
+	moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
+			sizeof(mlan_ds_11ac_vht_cfg),
+			sizeof(mlan_ds_11ac_vht_cfg));
+	resbuf_len = 1 + sizeof(mlan_ds_11ac_vht_cfg);
+
+	if ((ioctl_req->action == MLAN_ACT_GET) &&
+	    (vht_cfg.band == BAND_SELECT_BOTH)) {
+		cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
+		status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* number of vhtcfg entries */
+		*respbuf = 2;
+		vhtcfg++;
+		moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
+				sizeof(mlan_ds_11ac_vht_cfg),
+				sizeof(mlan_ds_11ac_vht_cfg));
+		resbuf_len += sizeof(mlan_ds_11ac_vht_cfg);
+	}
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		if (copy_to_user(req->ifr_data, respbuf, resbuf_len)) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	if (respbuf)
+		kfree(respbuf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap hs_cfg ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_hs_cfg(struct net_device *dev, struct ifreq *req,
+		BOOLEAN invoke_hostcmd)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ds_hs_cfg hscfg;
+	ds_hs_cfg hs_cfg;
+	mlan_bss_info bss_info;
+	t_u16 action;
+	int ret = 0;
+
+	ENTER();
+
+	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
+	memset(&hs_cfg, 0, sizeof(ds_hs_cfg));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_hs_cfg() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&hs_cfg, req->ifr_data, sizeof(ds_hs_cfg))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MIOCTL,
+	       "ioctl hscfg: flags=0x%x condition=0x%x gpio=%d gap=0x%x\n",
+	       hs_cfg.flags, hs_cfg.conditions, (int)hs_cfg.gpio, hs_cfg.gap);
+
+	/* HS config is blocked if HS is already activated */
+	if ((hs_cfg.flags & HS_CFG_FLAG_CONDITION) &&
+	    (hs_cfg.conditions != HOST_SLEEP_CFG_CANCEL ||
+	     invoke_hostcmd == MFALSE)) {
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+		if (bss_info.is_hs_configured) {
+			PRINTM(MERROR, "HS already configured\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (hs_cfg.flags & HS_CFG_FLAG_SET) {
+		action = MLAN_ACT_SET;
+		if (hs_cfg.flags != HS_CFG_FLAG_ALL) {
+			woal_set_get_hs_params(priv, MLAN_ACT_GET,
+					       MOAL_IOCTL_WAIT, &hscfg);
+		}
+		if (hs_cfg.flags & HS_CFG_FLAG_CONDITION)
+			hscfg.conditions = hs_cfg.conditions;
+		if (hs_cfg.flags & HS_CFG_FLAG_GPIO)
+			hscfg.gpio = hs_cfg.gpio;
+		if (hs_cfg.flags & HS_CFG_FLAG_GAP)
+			hscfg.gap = hs_cfg.gap;
+
+		if (invoke_hostcmd == MTRUE) {
+			/* Issue IOCTL to set up parameters */
+			hscfg.is_invoke_hostcmd = MFALSE;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_get_hs_params(priv, action,
+						   MOAL_IOCTL_WAIT, &hscfg)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	} else {
+		action = MLAN_ACT_GET;
+	}
+
+	/* Issue IOCTL to invoke hostcmd */
+	hscfg.is_invoke_hostcmd = invoke_hostcmd;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!(hs_cfg.flags & HS_CFG_FLAG_SET)) {
+		hs_cfg.flags = HS_CFG_FLAG_CONDITION | HS_CFG_FLAG_GPIO |
+			HS_CFG_FLAG_GAP;
+		hs_cfg.conditions = hscfg.conditions;
+		hs_cfg.gpio = hscfg.gpio;
+		hs_cfg.gap = hscfg.gap;
+		/* Copy to user */
+		if (copy_to_user(req->ifr_data, &hs_cfg, sizeof(ds_hs_cfg))) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Host Sleep parameters
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_uap_hs_set_para(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+
+	ENTER();
+
+	if (req->ifr_data != NULL) {
+		ret = woal_uap_hs_cfg(dev, req, MFALSE);
+		goto done;
+	} else {
+		PRINTM(MERROR, "Invalid data\n");
+		ret = -EINVAL;
+		goto done;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap mgmt_frame_control ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_mgmt_frame_control(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	t_u16 action = 0;
+	mgmt_frame_ctrl param;
+	mlan_uap_bss_param *sys_config = NULL;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_mgmt_frame_ctrl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Get user data */
+	if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_config) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (param.action)
+		action = MLAN_ACT_SET;
+	else
+		action = MLAN_ACT_GET;
+	if (action == MLAN_ACT_SET) {
+		/* Initialize the invalid values so that the correct
+		   values below are downloaded to firmware */
+		woal_set_sys_config_invalid_data(sys_config);
+		sys_config->mgmt_ie_passthru_mask = param.mask;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, action,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (action == MLAN_ACT_GET) {
+		param.mask = sys_config->mgmt_ie_passthru_mask;
+		if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	kfree(sys_config);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get tx rate
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_tx_rate_cfg(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0, i = 0;
+	mlan_ds_rate *rate = NULL;
+	mlan_ioctl_req *mreq = NULL;
+	tx_rate_cfg_t tx_rate_config;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_tx_rate_cfg() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t));
+	/* Get user data */
+	if (copy_from_user(&tx_rate_config, req->ifr_data,
+			   sizeof(tx_rate_cfg_t))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
+	if (mreq == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	rate = (mlan_ds_rate *)mreq->pbuf;
+	rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
+	rate->sub_command = MLAN_OID_RATE_CFG;
+	mreq->req_id = MLAN_IOCTL_RATE;
+	if (!(tx_rate_config.action))
+		mreq->action = MLAN_ACT_GET;
+	else {
+		if ((tx_rate_config.user_data_cnt <= 0) ||
+		    (tx_rate_config.user_data_cnt > 4)) {
+			PRINTM(MERROR, "Invalid user_data_cnt\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		mreq->action = MLAN_ACT_SET;
+		if (tx_rate_config.rate_format == AUTO_RATE)
+			rate->param.rate_cfg.is_rate_auto = 1;
+		else {
+			if ((tx_rate_config.rate_format < 0) ||
+			    (tx_rate_config.rate < 0)) {
+				PRINTM(MERROR,
+				       "Invalid format or rate selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			/* rate_format sanity check */
+			if ((tx_rate_config.rate_format > MLAN_RATE_FORMAT_HE)
+				) {
+				PRINTM(MERROR, "Invalid format selection\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			rate->param.rate_cfg.rate_format =
+				tx_rate_config.rate_format;
+
+			/* rate sanity check */
+			if (tx_rate_config.user_data_cnt >= 2) {
+				if (((tx_rate_config.rate_format ==
+				      MLAN_RATE_FORMAT_LG) &&
+				     (tx_rate_config.rate >
+				      MLAN_RATE_INDEX_OFDM7)) ||
+				    ((tx_rate_config.rate_format ==
+				      MLAN_RATE_FORMAT_HT) &&
+				     (tx_rate_config.rate != 32) &&
+				     (tx_rate_config.rate > 15)
+				    )
+				    || ((tx_rate_config.rate_format ==
+					 MLAN_RATE_FORMAT_VHT) &&
+					(tx_rate_config.rate >
+					 MLAN_RATE_INDEX_MCS9))
+				    || ((tx_rate_config.rate_format ==
+					 MLAN_RATE_FORMAT_HE) &&
+					(tx_rate_config.rate >
+					 MLAN_RATE_INDEX_MCS11))
+					) {
+					PRINTM(MERROR,
+					       "Invalid rate selection\n");
+					ret = -EINVAL;
+					goto done;
+				}
+				rate->param.rate_cfg.rate = tx_rate_config.rate;
+			}
+
+			/* nss sanity check */
+			if ((tx_rate_config.rate_format == 2) ||
+			    (tx_rate_config.rate_format == 3)) {
+				if ((tx_rate_config.nss < 1) ||
+				    (tx_rate_config.nss > 2)) {
+					PRINTM(MERROR,
+					       "Invalid nss selection %d\n",
+					       tx_rate_config.nss);
+					ret = -EINVAL;
+					goto done;
+				}
+				rate->param.rate_cfg.nss = tx_rate_config.nss;
+			}
+			if (tx_rate_config.user_data_cnt <= 3)
+				rate->param.rate_cfg.rate_setting = 0xffff;
+			else
+				rate->param.rate_cfg.rate_setting =
+					tx_rate_config.rate_setting;
+		}
+	}
+
+	status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (tx_rate_config.action) {
+		priv->rate_index = tx_rate_config.action;
+	} else {
+		if (rate->param.rate_cfg.is_rate_auto)
+			tx_rate_config.rate_format = AUTO_RATE;
+		else {
+			/* fixed rate */
+			tx_rate_config.rate_format =
+				rate->param.rate_cfg.rate_format;
+			tx_rate_config.rate = rate->param.rate_cfg.rate;
+			if (rate->param.rate_cfg.rate_format ==
+			    MLAN_RATE_FORMAT_VHT
+			    || rate->param.rate_cfg.rate_format ==
+			    MLAN_RATE_FORMAT_HE)
+				tx_rate_config.nss = rate->param.rate_cfg.nss;
+			tx_rate_config.rate_setting =
+				rate->param.rate_cfg.rate_setting;
+		}
+		for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
+			tx_rate_config.bitmap_rates[i] =
+				rate->param.rate_cfg.bitmap_rates[i];
+		}
+
+		if (copy_to_user(req->ifr_data, &tx_rate_config,
+				 sizeof(tx_rate_cfg_t))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(mreq);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get RF antenna mode
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_antenna_cfg(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *mreq = NULL;
+	ant_cfg_t antenna_config;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&antenna_config, 0, sizeof(ant_cfg_t));
+	/* Get user data */
+	if (copy_from_user(&antenna_config, req->ifr_data, sizeof(ant_cfg_t))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+	if (mreq == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	radio = (mlan_ds_radio_cfg *)mreq->pbuf;
+	radio->sub_command = MLAN_OID_ANT_CFG;
+	mreq->req_id = MLAN_IOCTL_RADIO_CFG;
+	if (!(antenna_config.action))
+		mreq->action = MLAN_ACT_GET;
+	else {
+		mreq->action = MLAN_ACT_SET;
+		radio->param.ant_cfg.tx_antenna = antenna_config.tx_mode;
+		radio->param.ant_cfg.rx_antenna = antenna_config.rx_mode;
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_CARD9098(priv->phandle->card_type) ||
+		    IS_CARD9097(priv->phandle->card_type)) {
+			if (IS_STA_CFG80211
+			    (priv->phandle->params.cfg80211_wext))
+				woal_cfg80211_notify_antcfg(priv,
+							    priv->phandle->
+							    wiphy, radio);
+		}
+#endif
+	}
+
+	status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (mreq->action == MLAN_ACT_GET) {
+		antenna_config.tx_mode = radio->param.ant_cfg.tx_antenna;
+		antenna_config.rx_mode = radio->param.ant_cfg.rx_antenna;
+		if (copy_to_user(req->ifr_data, &antenna_config,
+				 sizeof(ant_cfg_t))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(mreq);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get HT stream configurations
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_htstream_cfg(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	mlan_ds_11n_cfg *cfg = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	htstream_cfg_t htstream_cfg;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&htstream_cfg, 0, sizeof(htstream_cfg_t));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_htstream_cfg corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&htstream_cfg, req->ifr_data,
+			   sizeof(htstream_cfg_t))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
+	cfg->sub_command = MLAN_OID_11N_CFG_STREAM_CFG;
+	ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
+
+	if (!htstream_cfg.action) {
+		/* Get operation */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Update HT stream parameter in MLAN */
+		ioctl_req->action = MLAN_ACT_SET;
+		/* Set HT Stream configuration */
+		cfg->param.stream_cfg = htstream_cfg.stream_cfg;
+		PRINTM(MINFO, "SET: htstream_cfg:0x%x\n",
+		       cfg->param.stream_cfg);
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	/* Copy to user */
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		PRINTM(MINFO, "GET: htstream_cfg:0x%x\n",
+		       htstream_cfg.stream_cfg);
+		htstream_cfg.stream_cfg = cfg->param.stream_cfg;
+		if (copy_to_user(req->ifr_data, &htstream_cfg,
+				 sizeof(htstream_cfg_t))) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Get DFS_REPEATER mode
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_dfs_repeater(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	dfs_repeater_mode param;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *mreq = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&param, 0, sizeof(dfs_repeater_mode));
+	/* Get user data */
+	if (copy_from_user(&param, req->ifr_data, sizeof(dfs_repeater_mode))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (mreq == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)mreq->pbuf;
+	misc->sub_command = MLAN_OID_MISC_DFS_REAPTER_MODE;
+	mreq->req_id = MLAN_IOCTL_MISC_CFG;
+	mreq->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	param.mode = misc->param.dfs_repeater.mode;
+
+	if (copy_to_user(req->ifr_data, &param, sizeof(dfs_repeater_mode))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(mreq);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get skip CAC mode
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_skip_cac(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	skip_cac_para param;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "skip_cac() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&param, 0, sizeof(skip_cac_para));
+
+	/* Get user data */
+	if (copy_from_user(&param, req->ifr_data, sizeof(skip_cac_para))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Currently default action is get */
+	if (param.action == 0) {
+		param.skip_cac = (t_u16)priv->skip_cac;
+	} else {
+		priv->skip_cac = param.skip_cac;
+	}
+
+	if (copy_to_user(req->ifr_data, &param, sizeof(skip_cac_para))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+	}
+done:
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Get DFS_REPEATER mode
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_cac_timer_status(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	cac_timer_status param;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&param, 0, sizeof(cac_timer_status));
+
+	/* Get user data */
+	if (copy_from_user(&param, req->ifr_data, sizeof(cac_timer_status))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Currently default action is get */
+	param.mode = 0;
+
+	if (priv->phandle->cac_period == MTRUE) {
+		long cac_left_jiffies;
+
+		cac_left_jiffies =
+			MEAS_REPORT_TIME -
+			(jiffies - priv->phandle->meas_start_jiffies);
+
+		/* cac_left_jiffies would be negative if timer has already
+		 * elapsed. positive if timer is still yet to lapsed
+		 */
+		if (cac_left_jiffies > 0)
+			param.mode = (t_u32)cac_left_jiffies / HZ;
+	}
+
+	if (copy_to_user(req->ifr_data, &param, sizeof(cac_timer_status))) {
+		PRINTM(MERROR, "Copy to user failed\n");
+		ret = -EFAULT;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		LEAVE();
+	return ret;
+}
+
+/**
+ * @brief set/get uap operation control
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_operation_ctrl(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_uap_oper_ctrl uap_oper;
+	uap_oper_para_hdr param;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&param, 0, sizeof(uap_oper_para_hdr));
+	memset(&uap_oper, 0, sizeof(mlan_uap_oper_ctrl));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "woal_uap_operation_ctrl corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&param, req->ifr_data, sizeof(uap_oper_para_hdr))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (ioctl_req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)ioctl_req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_OPER_CTRL;
+	ioctl_req->req_id = MLAN_IOCTL_BSS;
+	if (copy_from_user(&uap_oper, req->ifr_data + sizeof(uap_oper_para_hdr),
+			   sizeof(mlan_uap_oper_ctrl))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (!param.action) {
+		/* Get uap operation control parameters from FW */
+		ioctl_req->action = MLAN_ACT_GET;
+	} else {
+		/* Set uap operation control configurations */
+		ioctl_req->action = MLAN_ACT_SET;
+		bss->param.ap_oper_ctrl.ctrl_value = uap_oper.ctrl_value;
+		if (uap_oper.ctrl_value == 2)
+			bss->param.ap_oper_ctrl.chan_opt = uap_oper.chan_opt;
+		if (uap_oper.chan_opt == 3) {
+			bss->param.ap_oper_ctrl.band_cfg = uap_oper.band_cfg;
+			bss->param.ap_oper_ctrl.channel = uap_oper.channel;
+		}
+	}
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Copy to user */
+	if (copy_to_user(req->ifr_data + sizeof(uap_oper_para_hdr),
+			 &bss->param.ap_oper_ctrl,
+			 sizeof(mlan_uap_oper_ctrl))) {
+		PRINTM(MERROR, "Copy to user failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	int ret = 0;
+	t_u32 subcmd = 0;
+	ENTER();
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&subcmd, req->ifr_data, sizeof(subcmd))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MIOCTL, "ioctl subcmd=%d\n", (int)subcmd);
+	switch (subcmd) {
+	case UAP_ADDBA_PARA:
+		ret = woal_uap_addba_param(dev, req);
+		break;
+	case UAP_AGGR_PRIOTBL:
+		ret = woal_uap_aggr_priotbl(dev, req);
+		break;
+	case UAP_ADDBA_REJECT:
+		ret = woal_uap_addba_reject(dev, req);
+		break;
+	case UAP_FW_INFO:
+		ret = woal_uap_get_fw_info(dev, req);
+		break;
+	case UAP_DEEP_SLEEP:
+		ret = woal_uap_deep_sleep(dev, req);
+		break;
+	case UAP_TX_DATA_PAUSE:
+		ret = woal_uap_txdatapause(dev, req);
+		break;
+#ifdef SDIO
+	case UAP_SDCMD52_RW:
+		ret = woal_uap_sdcmd52_rw(dev, req);
+		break;
+#endif
+	case UAP_SNMP_MIB:
+		ret = woal_uap_snmp_mib(dev, req);
+		break;
+	case UAP_DFS_TESTING:
+		ret = woal_uap_dfs_testing(dev, req);
+		break;
+	case UAP_CHAN_SWITCH_COUNT_CFG:
+		ret = woal_uap_chan_switch_count_cfg(dev, req);
+		break;
+	case UAP_DOMAIN_INFO:
+		ret = woal_uap_domain_info(dev, req);
+		break;
+	case UAP_TX_BF_CFG:
+		ret = woal_uap_tx_bf_cfg(dev, req);
+		break;
+	case UAP_HT_TX_CFG:
+		ret = woal_uap_ht_tx_cfg(dev, req);
+		break;
+	case UAP_VHT_CFG:
+		ret = woal_uap_vht_cfg(dev, req);
+		break;
+	case UAP_HS_CFG:
+		ret = woal_uap_hs_cfg(dev, req, MTRUE);
+		break;
+	case UAP_HS_SET_PARA:
+		ret = woal_uap_hs_set_para(dev, req);
+		break;
+	case UAP_MGMT_FRAME_CONTROL:
+		ret = woal_uap_mgmt_frame_control(dev, req);
+		break;
+	case UAP_TX_RATE_CFG:
+		ret = woal_uap_tx_rate_cfg(dev, req);
+		break;
+	case UAP_ANTENNA_CFG:
+		ret = woal_uap_antenna_cfg(dev, req);
+		break;
+	case UAP_HT_STREAM_CFG:
+		ret = woal_uap_htstream_cfg(dev, req);
+		break;
+	case UAP_DFS_REPEATER_MODE:
+		ret = woal_uap_dfs_repeater(dev, req);
+		break;
+	case UAP_CAC_TIMER_STATUS:
+		ret = woal_uap_cac_timer_status(dev, req);
+		break;
+	case UAP_SKIP_CAC:
+		ret = woal_uap_skip_cac(dev, req);
+		break;
+	case UAP_OPERATION_CTRL:
+		ret = woal_uap_operation_ctrl(dev, req);
+		break;
+	case UAP_BAND_STEER:
+		ret = woal_uap_band_steer(dev, req);
+		break;
+	case UAP_BEACON_STUCK_DETECT:
+		ret = woal_uap_beacon_stuck(dev, req);
+		break;
+	default:
+		break;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap station deauth ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_deauth_param deauth_param;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&deauth_param, 0, sizeof(mlan_deauth_param));
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_sta_deauth_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&deauth_param, req->ifr_data,
+			   sizeof(mlan_deauth_param))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n",
+	       MAC2STR(deauth_param.mac_addr), deauth_param.reason_code);
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)ioctl_req->pbuf;
+
+	bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
+	ioctl_req->req_id = MLAN_IOCTL_BSS;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.deauth_param, &deauth_param,
+			sizeof(mlan_deauth_param),
+			sizeof(bss->param.deauth_param));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
+				 sizeof(t_u32)))
+			PRINTM(MERROR, "Copy to user failed!\n");
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Set/Get radio
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *
+ * @return           0 --success, otherwise fail
+ */
+static int
+woal_uap_radio_ctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	mlan_ds_radio_cfg *radio = NULL;
+	mlan_ioctl_req *mreq = NULL;
+	int data[2] = { 0, 0 };
+	mlan_bss_info bss_info;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_radio_ctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Get user data */
+	if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (data[0]) {
+		mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
+		if (mreq == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		radio = (mlan_ds_radio_cfg *)mreq->pbuf;
+		radio->sub_command = MLAN_OID_RADIO_CTRL;
+		mreq->req_id = MLAN_IOCTL_RADIO_CFG;
+		mreq->action = MLAN_ACT_SET;
+		radio->param.radio_on_off = (t_u32)data[1];
+		status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS)
+			ret = -EFAULT;
+		if (status != MLAN_STATUS_PENDING)
+			kfree(mreq);
+	} else {
+		/* Get radio status */
+		memset(&bss_info, 0, sizeof(bss_info));
+		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+		data[1] = bss_info.radio_on;
+		if (copy_to_user(req->ifr_data, data, sizeof(data))) {
+			PRINTM(MERROR, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap bss control ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_bss_ctrl_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0, data = 0;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_bss_ctrl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, data);
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap report mic error ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_report_mic_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(mac_addr, 0, MLAN_MAC_ADDR_LENGTH);
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_report_mic_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(mac_addr, req->ifr_data, MLAN_MAC_ADDR_LENGTH)) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MINFO, "ioctl report mic err station: " MACSTR "\n",
+	       MAC2STR(mac_addr));
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	sec = (mlan_ds_sec_cfg *)ioctl_req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_REPORT_MIC_ERR;
+	ioctl_req->req_id = MLAN_IOCTL_SEC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+	moal_memcpy_ext(priv->phandle, sec->param.sta_mac, mac_addr,
+			MLAN_MAC_ADDR_LENGTH, sizeof(sec->param.sta_mac));
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap set key ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_set_key_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	encrypt_key key;
+	int ret = 0;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&key, 0, sizeof(encrypt_key));
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_set_key_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&key, req->ifr_data, sizeof(encrypt_key))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MIOCTL,
+	       "ioctl report set key: " MACSTR " key_index=%d, key_len=%d \n",
+	       MAC2STR(key.mac_addr), (int)key.key_index, (int)key.key_len);
+
+	if ((key.key_len > MLAN_MAX_KEY_LENGTH) || (key.key_index > 3)) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	sec = (mlan_ds_sec_cfg *)ioctl_req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY,
+		ioctl_req->req_id = MLAN_IOCTL_SEC_CFG;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
+			key.mac_addr, MLAN_MAC_ADDR_LENGTH,
+			sizeof(sec->param.encrypt_key.mac_addr));
+	sec->param.encrypt_key.key_index = key.key_index;
+	sec->param.encrypt_key.key_len = key.key_len;
+	moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.key_material,
+			key.key_material, key.key_len,
+			sizeof(sec->param.encrypt_key.key_material));
+	if (0 == memcmp(sec->param.encrypt_key.mac_addr, bcast_addr, ETH_ALEN))
+		 sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
+	else
+		sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get uap power mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param action               Action set or get
+ *  @param ps_mgmt              A pointer to mlan_ds_ps_mgmt structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+int
+woal_set_get_uap_power_mode(moal_private *priv, t_u32 action,
+			    mlan_ds_ps_mgmt *ps_mgmt)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (!ps_mgmt) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
+	ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
+	ioctl_req->action = action;
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_mgmt, ps_mgmt,
+				sizeof(mlan_ds_ps_mgmt),
+				sizeof(pm_cfg->param.ps_mgmt));
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (action == MLAN_ACT_GET)
+			moal_memcpy_ext(priv->phandle, ps_mgmt,
+					&pm_cfg->param.ps_mgmt,
+					sizeof(mlan_ds_ps_mgmt),
+					sizeof(mlan_ds_ps_mgmt));
+	}
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief uap power mode ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ds_ps_mgmt ps_mgmt;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&ps_mgmt, 0, sizeof(mlan_ds_ps_mgmt));
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (copy_from_user(&ps_mgmt, req->ifr_data, sizeof(mlan_ds_ps_mgmt))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (priv->bss_type != MLAN_BSS_TYPE_UAP) {
+		PRINTM(MERROR, "Invlaid BSS_TYPE for UAP power mode command\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MIOCTL,
+	       "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
+	       "inact_to=%d min_awake=%d max_awake=%d\n",
+	       ps_mgmt.flags, (int)ps_mgmt.ps_mode,
+	       (int)ps_mgmt.sleep_param.ctrl_bitmap,
+	       (int)ps_mgmt.sleep_param.min_sleep,
+	       (int)ps_mgmt.sleep_param.max_sleep,
+	       (int)ps_mgmt.inact_param.inactivity_to,
+	       (int)ps_mgmt.inact_param.min_awake,
+	       (int)ps_mgmt.inact_param.max_awake);
+
+	if (ps_mgmt.flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
+			      PS_FLAG_INACT_SLEEP_PARAM)) {
+		PRINTM(MERROR, "Invalid parameter: flags = 0x%x\n",
+		       ps_mgmt.flags);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (ps_mgmt.ps_mode > PS_MODE_INACTIVITY) {
+		PRINTM(MERROR, "Invalid parameter: ps_mode = %d\n",
+		       (int)ps_mgmt.flags);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
+	ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
+	if (ps_mgmt.flags) {
+		ioctl_req->action = MLAN_ACT_SET;
+		moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_mgmt, &ps_mgmt,
+				sizeof(mlan_ds_ps_mgmt),
+				sizeof(pm_cfg->param.ps_mgmt));
+	} else {
+		ioctl_req->action = MLAN_ACT_GET;
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
+				 sizeof(t_u32)))
+			PRINTM(MERROR, "Copy to user failed!\n");
+		goto done;
+	}
+	if (!ps_mgmt.flags) {
+		/* Copy to user */
+		if (copy_to_user(req->ifr_data, &pm_cfg->param.ps_mgmt,
+				 sizeof(mlan_ds_ps_mgmt))) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap BSS config ioctl handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_bss_cfg_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	int offset = 0;
+	t_u32 action = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_bss_cfg_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Get action */
+	if (copy_from_user(&action, req->ifr_data + offset, sizeof(action))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	offset += sizeof(action);
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)ioctl_req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
+	ioctl_req->req_id = MLAN_IOCTL_BSS;
+	if (action == 1)
+		ioctl_req->action = MLAN_ACT_SET;
+	else
+		ioctl_req->action = MLAN_ACT_GET;
+
+	if (ioctl_req->action == MLAN_ACT_SET) {
+		/* Get the BSS config from user */
+		if (copy_from_user(&bss->param.bss_config,
+				   req->ifr_data + offset,
+				   sizeof(mlan_uap_bss_param))) {
+			PRINTM(MERROR, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		offset = sizeof(action);
+
+		/* Copy to user : BSS config */
+		if (copy_to_user(req->ifr_data + offset, &bss->param.bss_config,
+				 sizeof(mlan_uap_bss_param))) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap get station list handler
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_get_sta_list_ioctl(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_get_sta_list_ioctl() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	info = (mlan_ds_get_info *)ioctl_req->pbuf;
+	info->sub_command = MLAN_OID_UAP_STA_LIST;
+	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (ioctl_req->action == MLAN_ACT_GET) {
+		/* Copy to user : sta_list */
+		if (copy_to_user(req->ifr_data, &info->param.sta_list,
+				 ioctl_req->data_read_written)) {
+			PRINTM(MERROR, "Copy to user failed!\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uAP set WAPI key ioctl
+ *
+ *  @param priv      A pointer to moal_private structure
+ *  @param msg       A pointer to wapi_msg structure
+ *
+ *  @return          0 --success, otherwise fail
+ */
+static int
+woal_uap_set_wapi_key_ioctl(moal_private *priv, wapi_msg *msg)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	int ret = 0;
+	wapi_key_msg *key_msg = NULL;
+	t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (msg->msg_len != sizeof(wapi_key_msg)) {
+		ret = -EINVAL;
+		goto done;
+	}
+	key_msg = (wapi_key_msg *)msg->msg;
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	sec->param.encrypt_key.is_wapi_key = MTRUE;
+	sec->param.encrypt_key.key_len = MLAN_MAX_KEY_LENGTH;
+	moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
+			key_msg->mac_addr, ETH_ALEN,
+			sizeof(sec->param.encrypt_key.mac_addr));
+	sec->param.encrypt_key.key_index = key_msg->key_id;
+	if (0 == memcmp(key_msg->mac_addr, bcast_addr, ETH_ALEN))
+		sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
+	else
+		sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
+	moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.key_material,
+			key_msg->key, sec->param.encrypt_key.key_len,
+			sizeof(sec->param.encrypt_key.key_material));
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		ret = -EFAULT;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Enable/Disable wapi in firmware
+ *
+ *  @param priv          A pointer to moal_private structure
+ *  @param enable        MTRUE/MFALSE
+ *
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_enable_wapi(moal_private *priv, t_u8 enable)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Get AP setting  failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+	}
+
+	/* Change AP default setting */
+	req->action = MLAN_ACT_SET;
+	if (enable == MFALSE) {
+		bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
+		bss->param.bss_config.protocol = PROTOCOL_NO_SECURITY;
+	} else {
+		bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
+		bss->param.bss_config.protocol = PROTOCOL_WAPI;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Set AP setting failed! status=%d, error_code=0x%x\n",
+		       status, req->status_code);
+	}
+	if (enable)
+		woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief uAP set WAPI flag ioctl
+ *
+ *  @param priv      A pointer to moal_private structure
+ *  @param msg       A pointer to wapi_msg structure
+ *
+ *  @return          0 --success, otherwise fail
+ */
+static int
+woal_uap_set_wapi_flag_ioctl(moal_private *priv, wapi_msg *msg)
+{
+	t_u8 wapi_psk_ie[] = { 0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
+		0x72, 0x02, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
+		0x00, 0x14, 0x72, 0x01, 0x00, 0x00
+	};
+	t_u8 wapi_cert_ie[] = { 0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
+		0x72, 0x01, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
+		0x00, 0x14, 0x72, 0x01, 0x00, 0x00
+	};
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GEN_IE;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
+	misc->param.gen_ie.len = sizeof(wapi_psk_ie);
+	if (msg->msg[0] & WAPI_MODE_PSK) {
+		moal_memcpy_ext(priv->phandle, misc->param.gen_ie.ie_data,
+				wapi_psk_ie, misc->param.gen_ie.len,
+				sizeof(misc->param.gen_ie.ie_data));
+	} else if (msg->msg[0] & WAPI_MODE_CERT) {
+		moal_memcpy_ext(priv->phandle, misc->param.gen_ie.ie_data,
+				wapi_cert_ie, misc->param.gen_ie.len,
+				sizeof(misc->param.gen_ie.ie_data));
+	} else if (msg->msg[0] == 0) {
+		/* disable WAPI in driver */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, 0))
+			ret = -EFAULT;
+		woal_enable_wapi(priv, MFALSE);
+		goto done;
+	} else {
+		ret = -EINVAL;
+		goto done;
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	woal_enable_wapi(priv, MTRUE);
+done:
+	if ((status != MLAN_STATUS_PENDING) && req)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief set wapi ioctl function
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_set_wapi(struct net_device *dev, struct ifreq *req)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	wapi_msg msg;
+	int ret = 0;
+
+	ENTER();
+
+	/* Sanity check */
+	if (req->ifr_data == NULL) {
+		PRINTM(MERROR, "uap_set_wapi() corrupt data\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+
+	if (copy_from_user(&msg, req->ifr_data, sizeof(msg))) {
+		PRINTM(MERROR, "Copy from user failed\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	PRINTM(MIOCTL, "set wapi msg_type = %d, msg_len=%d\n", msg.msg_type,
+	       msg.msg_len);
+	DBG_HEXDUMP(MCMD_D, "wapi msg", msg.msg,
+		    MIN(msg.msg_len, sizeof(msg.msg)));
+
+	switch (msg.msg_type) {
+	case P80211_PACKET_WAPIFLAG:
+		ret = woal_uap_set_wapi_flag_ioctl(priv, &msg);
+		break;
+	case P80211_PACKET_SETKEY:
+		ret = woal_uap_set_wapi_key_ioctl(priv, &msg);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+done:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/**
+ *  @brief Initialize the members of mlan_uap_bss_param
+ *  which are uploaded from firmware
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param sys_cfg  A pointer to mlan_uap_bss_param structure
+ *  @param wait_option      Wait option
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_uap_get_bss_param(moal_private *priv,
+		       mlan_uap_bss_param *sys_cfg, t_u8 wait_option)
+{
+	mlan_ds_bss *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	info = (mlan_ds_bss *)req->pbuf;
+	info->sub_command = MLAN_OID_UAP_BSS_CONFIG;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Get bss info failed!\n");
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, sys_cfg, &info->param.bss_config,
+			sizeof(mlan_uap_bss_param), sizeof(mlan_uap_bss_param));
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief  Set uap httxcfg
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param band_cfg Band cfg
+ *  @param en       Enabled/Disabled
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg,
+		       t_u16 ht_cap, t_u8 en)
+{
+	int ret = 0;
+	mlan_ds_11n_cfg *cfg_11n = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
+	cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
+	ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
+
+	/* Set HT Tx configurations */
+	if (bandcfg.chanBand == BAND_2GHZ) {
+		if (en)
+			cfg_11n->param.tx_cfg.httxcap = ht_cap;
+		else
+			cfg_11n->param.tx_cfg.httxcap = 0;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
+	} else if (bandcfg.chanBand == BAND_5GHZ) {
+		if (en)
+			cfg_11n->param.tx_cfg.httxcap = ht_cap;
+		else
+			cfg_11n->param.tx_cfg.httxcap = 0;
+		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
+	}
+	PRINTM(MCMND, "SET: httxcap=0x%x band:0x%x\n",
+	       cfg_11n->param.tx_cfg.httxcap, cfg_11n->param.tx_cfg.misc_cfg);
+	/* Update 11n tx parameters in MLAN */
+	ioctl_req->action = MLAN_ACT_SET;
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set 11n status based on the configured security mode
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param sys_cfg  A pointer to mlan_uap_bss_param structure
+ *  @param action   MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
+ *
+ *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_uap_set_11n_status(moal_private *priv,
+			mlan_uap_bss_param *sys_cfg, t_u8 action)
+{
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_fw_info fw_info;
+
+	ENTER();
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	if (action == MLAN_ACT_DISABLE) {
+		if ((sys_cfg->supported_mcs_set[0] == 0) &&
+		    (sys_cfg->supported_mcs_set[4] == 0)
+		    && (sys_cfg->supported_mcs_set[1] == 0)
+			) {
+			goto done;
+		} else {
+			sys_cfg->supported_mcs_set[0] = 0;
+			sys_cfg->supported_mcs_set[4] = 0;
+			sys_cfg->supported_mcs_set[1] = 0;
+		}
+	}
+
+	if (action == MLAN_ACT_ENABLE) {
+		woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+		sys_cfg->supported_mcs_set[0] = 0xFF;
+		if (sys_cfg->bandcfg.chan2Offset)
+			sys_cfg->supported_mcs_set[4] = 0x01;
+		else
+			sys_cfg->supported_mcs_set[4] = 0x0;
+		if (fw_info.usr_dev_mcs_support == HT_STREAM_MODE_2X2)
+			sys_cfg->supported_mcs_set[1] = 0xFF;
+		else
+			sys_cfg->supported_mcs_set[1] = 0;
+	}
+
+done:
+	LEAVE();
+	return status;
+}
+
+#define VHT_CAP_11AC_MASK 0x007fffff
+
+/**
+ *  @brief enable/disable 11AC
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param action   MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
+ *  @param vht20_40 Enable VHT 20 MHz or 40 MHz band
+ *  @param vhtcap_ie A pointer to vht capability IE
+ *
+ *  @return         0--success, otherwise failure
+ */
+int
+woal_uap_set_11ac_status(moal_private *priv, t_u8 action, t_u8 vht20_40,
+			 IEEEtypes_VHTCap_t *vhtcap_ie)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ac_cfg *cfg_11ac = NULL;
+	mlan_fw_info fw_info;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
+	cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
+	req->req_id = MLAN_IOCTL_11AC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
+	cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_TXRX;
+
+	/*
+	 * p2p GO (negotiation or auto GO) cases, wpa_supplicant will download
+	 * invalid vht capability with value 0 in beacon parameters, so for p2p
+	 * GO case (vht_cap_info = 0), driver will use hardware 11ac vht
+	 * capability value instead of up layer value.
+	 */
+	if (vhtcap_ie && vhtcap_ie->vht_cap.vht_cap_info != 0) {
+		cfg_11ac->param.vht_cfg.vht_cap_info =
+			woal_le32_to_cpu(vhtcap_ie->vht_cap.vht_cap_info);
+		/** todo mcs configuration */
+	} else {
+		cfg_11ac->param.vht_cfg.vht_cap_info =
+			fw_info.usr_dot_11ac_dev_cap_a;
+	}
+	if (action == MLAN_ACT_DISABLE) {
+		cfg_11ac->param.vht_cfg.bwcfg = MFALSE;
+		cfg_11ac->param.vht_cfg.vht_cap_info &= ~VHT_CAP_11AC_MASK;
+		cfg_11ac->param.vht_cfg.vht_rx_mcs =
+			cfg_11ac->param.vht_cfg.vht_tx_mcs = 0xffff;
+		cfg_11ac->param.vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
+	} else {
+		if (vht20_40)
+			cfg_11ac->param.vht_cfg.bwcfg = MFALSE;
+		else
+			cfg_11ac->param.vht_cfg.bwcfg = MTRUE;
+		cfg_11ac->param.vht_cfg.vht_cap_info &=
+			~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
+		cfg_11ac->param.vht_cfg.vht_tx_mcs =
+			fw_info.usr_dot_11ac_mcs_support >> 16;
+		cfg_11ac->param.vht_cfg.vht_rx_mcs =
+			fw_info.usr_dot_11ac_mcs_support & 0xffff;
+		cfg_11ac->param.vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
+	}
+	PRINTM(MCMND,
+	       "Uap:11ac=%d vht_cap_info=0x%x, vht_tx_mcs=0x%x, vht_rx_mcs=0x%x\n",
+	       action, cfg_11ac->param.vht_cfg.vht_cap_info,
+	       cfg_11ac->param.vht_cfg.vht_tx_mcs,
+	       cfg_11ac->param.vht_cfg.vht_rx_mcs);
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set 11ax cfg
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param action   MLAN_ACT_SET or MLAN_ACT_GET
+ *  @param he_cfg   a pointer to mlan_ds_11ax_he_cfg
+ *
+ *  @return         0--success, otherwise failure
+ */
+int
+woal_11ax_cfg(moal_private *priv, t_u8 action, mlan_ds_11ax_he_cfg * he_cfg)
+{
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11ax_cfg *cfg_11ax = NULL;
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ax_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	cfg_11ax = (mlan_ds_11ax_cfg *) req->pbuf;
+	cfg_11ax->sub_command = MLAN_OID_11AX_HE_CFG;
+	req->req_id = MLAN_IOCTL_11AX_CFG;
+	req->action = action;
+	moal_memcpy_ext(priv->phandle, &cfg_11ax->param.he_cfg, he_cfg,
+			sizeof(mlan_ds_11ax_he_cfg),
+			sizeof(mlan_ds_11ax_he_cfg));
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, he_cfg, &cfg_11ax->param.he_cfg,
+			sizeof(mlan_ds_11ax_he_cfg),
+			sizeof(mlan_ds_11ax_he_cfg));
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief enable/disable 11AX
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param action   MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
+ *  @param band     band config
+ *  @param hecap_ie
+ *
+ *  @return         0--success, otherwise failure
+ */
+int
+woal_uap_set_11ax_status(moal_private *priv, t_u8 action, t_u8 band,
+			 IEEEtypes_HECap_t * hecap_ie)
+{
+	mlan_fw_info fw_info;
+	int ret = 0;
+	mlan_ds_11ax_he_cfg he_cfg;
+	ENTER();
+
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if ((band == BAND_5GHZ && !(fw_info.fw_bands & BAND_AAX)) ||
+	    (band == BAND_2GHZ && !(fw_info.fw_bands & BAND_GAX))) {
+		PRINTM(MERROR, "fw doesn't support 11ax\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(&he_cfg, 0, sizeof(he_cfg));
+	if (band == BAND_5GHZ)
+		he_cfg.band = MBIT(1);
+	else if (band == BAND_2GHZ)
+		he_cfg.band = MBIT(0);
+	else {
+		PRINTM(MERROR, "Invalid band!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (woal_11ax_cfg(priv, MLAN_ACT_GET, &he_cfg)) {
+		PRINTM(MERROR, "Fail to get 11ax cfg!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (hecap_ie) {
+		DBG_HEXDUMP(MCMD_D, "hecap_ie", (t_u8 *)hecap_ie,
+			    hecap_ie->ieee_hdr.len +
+			    sizeof(IEEEtypes_Header_t));
+		he_cfg.he_cap.id = hecap_ie->ieee_hdr.element_id;
+		he_cfg.he_cap.len = hecap_ie->ieee_hdr.len;
+		moal_memcpy_ext(priv->phandle, &he_cfg.he_cap.ext_id,
+				&hecap_ie->ext_id, he_cfg.he_cap.len,
+				he_cfg.he_cap.len);
+	}
+	if (action == MLAN_ACT_DISABLE) {
+		if (he_cfg.he_cap.len &&
+		    (he_cfg.he_cap.ext_id == HE_CAPABILITY)) {
+			memset(he_cfg.he_cap.he_txrx_mcs_support, 0xff,
+			       sizeof(he_cfg.he_cap.he_txrx_mcs_support));
+		} else {
+			PRINTM(MCMND, "11ax already disabled\n");
+			goto done;
+		}
+	}
+	DBG_HEXDUMP(MCMD_D, "HE_CFG ", (t_u8 *)&he_cfg, sizeof(he_cfg));
+	ret = woal_11ax_cfg(priv, MLAN_ACT_SET, &he_cfg);
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Parse AP configuration from ASCII string
+ *
+ *  @param priv       A pointer to moal_private structure
+ *  @param ap_cfg   A pointer to mlan_uap_bss_param structure
+ *  @param buf      A pointer to user data
+ *
+ *  @return         0 --success, otherwise fail
+ */
+static int
+woal_uap_ap_cfg_parse_data(moal_private *priv, mlan_uap_bss_param *ap_cfg,
+			   char *buf)
+{
+	int ret = 0, atoi_ret;
+	int set_sec = 0, set_key = 0, set_chan = 0;
+	int set_preamble = 0, set_scb = 0, set_ssid = 0;
+	char *begin = buf, *value = NULL, *opt = NULL;
+
+	ENTER();
+
+	while (begin) {
+		value = woal_strsep(&begin, ',', '/');
+		opt = woal_strsep(&value, '=', '/');
+		if (opt && !strncmp(opt, "END", strlen("END"))) {
+			if (!ap_cfg->ssid.ssid_len) {
+				PRINTM(MERROR,
+				       "Minimum option required is SSID\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			PRINTM(MINFO, "Parsing terminated by string END\n");
+			break;
+		}
+		if (!opt || !value || !value[0]) {
+			PRINTM(MERROR, "Invalid option\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (!strncmp(opt, "ASCII_CMD", strlen("ASCII_CMD"))) {
+			if (strncmp(value, "AP_CFG", strlen("AP_CFG"))) {
+				PRINTM(MERROR,
+				       "ASCII_CMD: %s not matched with AP_CFG\n",
+				       value);
+				ret = -EFAULT;
+				goto done;
+			}
+			value = woal_strsep(&begin, ',', '/');
+			opt = woal_strsep(&value, '=', '/');
+			if (!opt || !value || !value[0]) {
+				PRINTM(MERROR,
+				       "Minimum option required is SSID\n");
+				ret = -EINVAL;
+				goto done;
+			} else if (!strncmp(opt, "SSID", strlen("SSID"))) {
+				if (set_ssid) {
+					PRINTM(MWARN,
+					       "Skipping SSID, found again!\n");
+					continue;
+				}
+				if (strlen(value) >= MLAN_MAX_SSID_LENGTH) {
+					PRINTM(MERROR,
+					       "SSID length exceeds max length\n");
+					ret = -EFAULT;
+					goto done;
+				}
+				ap_cfg->ssid.ssid_len = strlen(value);
+				strncpy((char *)ap_cfg->ssid.ssid, value,
+					MIN(MLAN_MAX_SSID_LENGTH - 1,
+					    strlen(value)));
+				PRINTM(MINFO, "ssid=%s, len=%d\n",
+				       ap_cfg->ssid.ssid,
+				       (int)ap_cfg->ssid.ssid_len);
+				set_ssid = 1;
+			} else {
+				PRINTM(MERROR,
+				       "AP_CFG: Invalid option %s, expect SSID\n",
+				       opt);
+				ret = -EINVAL;
+				goto done;
+			}
+		} else if (!strncmp(opt, "SEC", strlen("SEC"))) {
+			if (set_sec) {
+				PRINTM(MWARN, "Skipping SEC, found again!\n");
+				continue;
+			}
+			if (!strnicmp(value, "open", strlen("open"))) {
+				ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
+				if (set_key)
+					ap_cfg->wpa_cfg.length = 0;
+				ap_cfg->key_mgmt = KEY_MGMT_NONE;
+				ap_cfg->protocol = PROTOCOL_NO_SECURITY;
+			} else if (!strnicmp(value, "wpa2-psk",
+					     strlen("wpa2-psk"))) {
+				ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
+				ap_cfg->protocol = PROTOCOL_WPA2;
+				ap_cfg->key_mgmt = KEY_MGMT_PSK;
+				ap_cfg->wpa_cfg.pairwise_cipher_wpa =
+					CIPHER_AES_CCMP;
+				ap_cfg->wpa_cfg.pairwise_cipher_wpa2 =
+					CIPHER_AES_CCMP;
+				ap_cfg->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+			} else if (!strnicmp(value, "wpa-psk",
+					     strlen("wpa-psk"))) {
+				ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
+				ap_cfg->protocol = PROTOCOL_WPA;
+				ap_cfg->key_mgmt = KEY_MGMT_PSK;
+				ap_cfg->wpa_cfg.pairwise_cipher_wpa =
+					CIPHER_TKIP;
+				ap_cfg->wpa_cfg.group_cipher = CIPHER_TKIP;
+			} else if (!strnicmp(value, "wep128", strlen("wep128"))) {
+				ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
+				if (set_key)
+					ap_cfg->wpa_cfg.length = 0;
+				ap_cfg->key_mgmt = KEY_MGMT_NONE;
+				ap_cfg->protocol = PROTOCOL_STATIC_WEP;
+			} else {
+				PRINTM(MERROR,
+				       "AP_CFG: Invalid value=%s for %s\n",
+				       value, opt);
+				ret = -EFAULT;
+				goto done;
+			}
+			set_sec = 1;
+		} else if (!strncmp(opt, "KEY", strlen("KEY"))) {
+			if (set_key) {
+				PRINTM(MWARN, "Skipping KEY, found again!\n");
+				continue;
+			}
+			if (set_sec && ap_cfg->protocol == PROTOCOL_STATIC_WEP) {
+				if (strlen(value) != MAX_WEP_KEY_SIZE) {
+					PRINTM(MERROR,
+					       "Invalid WEP KEY length\n");
+					ret = -EFAULT;
+					goto done;
+				}
+				ap_cfg->wep_cfg.key0.key_index = 0;
+				ap_cfg->wep_cfg.key0.is_default = 1;
+				ap_cfg->wep_cfg.key0.length = strlen(value);
+				moal_memcpy_ext(priv->phandle,
+						ap_cfg->wep_cfg.key0.key, value,
+						strlen(value),
+						sizeof(ap_cfg->wep_cfg.key0.
+						       key));
+				set_key = 1;
+				continue;
+			}
+			if (set_sec && ap_cfg->protocol != PROTOCOL_WPA2 &&
+			    ap_cfg->protocol != PROTOCOL_WPA) {
+				PRINTM(MWARN,
+				       "Warning! No KEY for open mode\n");
+				set_key = 1;
+				continue;
+			}
+			if (strlen(value) < MLAN_MIN_PASSPHRASE_LENGTH ||
+			    strlen(value) > MLAN_PMK_HEXSTR_LENGTH) {
+				PRINTM(MERROR, "Invalid PSK/PMK length\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			ap_cfg->wpa_cfg.length = strlen(value);
+			moal_memcpy_ext(priv->phandle,
+					ap_cfg->wpa_cfg.passphrase, value,
+					strlen(value),
+					sizeof(ap_cfg->wpa_cfg.passphrase));
+			set_key = 1;
+		} else if (!strncmp(opt, "CHANNEL", strlen("CHANNEL"))) {
+			if (set_chan) {
+				PRINTM(MWARN,
+				       "Skipping CHANNEL, found again!\n");
+				continue;
+			}
+			if (woal_atoi(&atoi_ret, value)) {
+				ret = -EINVAL;
+				goto done;
+			}
+			if (atoi_ret < 1 || atoi_ret > MLAN_MAX_CHANNEL) {
+				PRINTM(MERROR,
+				       "AP_CFG: Channel must be between 1 and %d"
+				       "(both included)\n", MLAN_MAX_CHANNEL);
+				ret = -EINVAL;
+				goto done;
+			}
+			ap_cfg->channel = atoi_ret;
+			set_chan = 1;
+		} else if (!strncmp(opt, "PREAMBLE", strlen("PREAMBLE"))) {
+			if (set_preamble) {
+				PRINTM(MWARN,
+				       "Skipping PREAMBLE, found again!\n");
+				continue;
+			}
+			if (woal_atoi(&atoi_ret, value)) {
+				ret = -EINVAL;
+				goto done;
+			}
+			/* This is a READ only value from FW, so we
+			 * can not set this and pass it successfully */
+			set_preamble = 1;
+		} else if (!strncmp(opt, "MAX_SCB", strlen("MAX_SCB"))) {
+			if (set_scb) {
+				PRINTM(MWARN,
+				       "Skipping MAX_SCB, found again!\n");
+				continue;
+			}
+			if (woal_atoi(&atoi_ret, value)) {
+				ret = -EINVAL;
+				goto done;
+			}
+			if (atoi_ret < 1 || atoi_ret > MAX_STA_COUNT) {
+				PRINTM(MERROR,
+				       "AP_CFG: MAX_SCB must be between 1 to %d "
+				       "(both included)\n", MAX_STA_COUNT);
+				ret = -EINVAL;
+				goto done;
+			}
+			ap_cfg->max_sta_count = (t_u16)atoi_ret;
+			set_scb = 1;
+		} else {
+			PRINTM(MERROR, "Invalid option %s\n", opt);
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set AP configuration
+ *
+ *  @param priv     A pointer to moal_private structure
+ *  @param data     A pointer to user data
+ *  @param len      Length of buf
+ *
+ *  @return         0 --success, otherwise fail
+ */
+int
+woal_uap_set_ap_cfg(moal_private *priv, t_u8 *data, int len)
+{
+	int ret = 0;
+	static char buf[MAX_BUF_LEN];
+	mlan_uap_bss_param *sys_config = NULL;
+	int restart = 0;
+
+	ENTER();
+
+#define MIN_AP_CFG_CMD_LEN 16	/* strlen("ASCII_CMD=AP_CFG") */
+	if ((len - 1) <= MIN_AP_CFG_CMD_LEN) {
+		PRINTM(MERROR, "Invalid length of command\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_config) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(buf, 0, MAX_BUF_LEN);
+	moal_memcpy_ext(priv->phandle, buf, data, len, sizeof(buf) - 1);
+
+	/* Initialize the uap bss values which are uploaded from firmware */
+	woal_uap_get_bss_param(priv, sys_config, MOAL_IOCTL_WAIT);
+
+	/* Setting the default values */
+	sys_config->channel = 6;
+	sys_config->preamble_type = 0;
+
+	ret = woal_uap_ap_cfg_parse_data(priv, sys_config, buf);
+	if (ret)
+		goto done;
+
+	/* If BSS already started stop it first and restart
+	 * after changing the setting */
+	if (priv->bss_started == MTRUE) {
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+		if (ret)
+			goto done;
+		restart = 1;
+	}
+
+	/* If the security mode is configured as WEP or WPA-PSK,
+	 * it will disable 11n automatically, and if configured as
+	 * open(off) or wpa2-psk, it will automatically enable 11n */
+	if ((sys_config->protocol == PROTOCOL_STATIC_WEP) ||
+	    (sys_config->protocol == PROTOCOL_WPA)) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_set_11n_status(priv, sys_config,
+					    MLAN_ACT_DISABLE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_set_11n_status(priv, sys_config,
+					    MLAN_ACT_ENABLE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Start the BSS after successful configuration */
+	if (restart)
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
+
+done:
+	kfree(sys_config);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get ap scan channel list
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *  @param scan_channels    A pointer to mlan_uap_scan_channels structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_set_get_ap_scan_channels(moal_private *priv, t_u16 action,
+			      mlan_uap_scan_channels * scan_channels)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_SCAN_CHANNELS;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = action;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.ap_scan_channels,
+			scan_channels, sizeof(mlan_uap_scan_channels),
+			sizeof(bss->param.ap_scan_channels));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, scan_channels,
+				&bss->param.ap_scan_channels,
+				sizeof(mlan_uap_scan_channels),
+				sizeof(mlan_uap_scan_channels));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get uap channel
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *  @param wait_option      wait option
+ *  @param uap_channel      A pointer to mlan_uap_channel structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_set_get_ap_channel(moal_private *priv, t_u16 action,
+			t_u8 wait_option, chan_band_info * uap_channel)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_CHANNEL;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = action;
+
+	moal_memcpy_ext(priv->phandle, &bss->param.ap_channel, uap_channel,
+			sizeof(chan_band_info), sizeof(bss->param.ap_channel));
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, uap_channel,
+				&bss->param.ap_channel, sizeof(chan_band_info),
+				sizeof(chan_band_info));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief start ACS scan
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_start_acs_scan(moal_private *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_ACS_SCAN;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	PRINTM(MIOCTL,
+	       "ACS scan done: bandcfg:[chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x scanMode=0x%x], channel=%d\n",
+	       bss->param.ap_acs_scan.bandcfg.chanBand,
+	       bss->param.ap_acs_scan.bandcfg.chanWidth,
+	       bss->param.ap_acs_scan.bandcfg.chan2Offset,
+	       bss->param.ap_acs_scan.bandcfg.scanMode,
+	       bss->param.ap_acs_scan.chan);
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brie check if we need do ACS scan
+ *
+ *  @param priv             A pointer to moal_private structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_do_acs_check(moal_private *priv)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_uap_bss_param *sys_config = NULL;
+	mlan_uap_scan_channels *scan_channels = NULL;
+	chan_band_info uap_channel;
+	ENTER();
+
+	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_config) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		PRINTM(MERROR, "Fail to get sys config data\n");
+		kfree(sys_config);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	if (!(sys_config->bandcfg.scanMode == SCAN_MODE_ACS)) {
+		kfree(sys_config);
+		LEAVE();
+		return ret;
+	}
+	scan_channels = kzalloc(sizeof(mlan_uap_scan_channels), GFP_ATOMIC);
+	if (scan_channels == NULL) {
+		PRINTM(MERROR, "Fail to alloc scan channels buffer\n");
+		kfree(sys_config);
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	scan_channels->remove_nop_channel = MTRUE;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_ap_scan_channels(priv, MLAN_ACT_GET, scan_channels)) {
+		PRINTM(MERROR, "Fail to get scan channels\n");
+		goto done;
+	}
+
+	if (scan_channels->num_remvoed_channel && scan_channels->num_of_chan) {
+		scan_channels->remove_nop_channel = 0;
+		/** set back new channel list after remove nop channels */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_ap_scan_channels(priv, MLAN_ACT_SET,
+						  scan_channels)) {
+			PRINTM(MERROR, "Fail to get scan channels\n");
+			goto done;
+		}
+	}
+	if (scan_channels->num_of_chan)
+		ret = woal_start_acs_scan(priv);
+	else
+		ret = MLAN_STATUS_FAILURE;
+	/** set to default channel 6 when 5G ACS is configured */
+	if ((ret != MLAN_STATUS_SUCCESS) &&
+	    (sys_config->bandcfg.chanBand == BAND_5GHZ)) {
+		memset(&uap_channel, 0, sizeof(uap_channel));
+		uap_channel.bandcfg.chanBand = DEFAULT_UAP_BAND;
+		uap_channel.channel = DEFAULT_UAP_CHANNEL;
+		ret = woal_set_get_ap_channel(priv, MLAN_ACT_SET,
+					      MOAL_IOCTL_WAIT, &uap_channel);
+	}
+done:
+	kfree(scan_channels);
+	kfree(sys_config);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief uap BSS control ioctl handler
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param wait_option      Wait option
+ *  @param data             BSS control type
+ *  @return                 0 --success, otherwise fail
+ */
+int
+woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	PRINTM(MIOCTL, "ioctl bss ctrl=%d\n", data);
+	if ((data != UAP_BSS_START) && (data != UAP_BSS_STOP) &&
+	    (data != UAP_BSS_RESET)) {
+		PRINTM(MERROR, "Invalid parameter: %d\n", data);
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	switch (data) {
+	case UAP_BSS_START:
+		if (priv->bss_started == MTRUE) {
+			PRINTM(MWARN, "Warning: BSS already started!\n");
+			/* goto done; */
+		} else if (!priv->uap_host_based
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			   || moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD)
+#endif
+			) {
+			woal_do_acs_check(priv);
+			/* about to start bss: issue channel check */
+			status = woal_11h_channel_check_ioctl(priv,
+							      MOAL_IOCTL_WAIT);
+			if (status) {
+				PRINTM(MMSG, "11h channel check fails\n");
+				status = MLAN_STATUS_FAILURE;
+				ret = -1;
+				goto done;
+			}
+		}
+		bss->sub_command = MLAN_OID_BSS_START;
+		if (priv->uap_host_based) {
+			bss->param.host_based |= UAP_FLAG_HOST_BASED;
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+			if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
+				bss->param.host_based |= UAP_FLAG_HOST_MLME;
+#endif
+#endif
+		}
+		break;
+	case UAP_BSS_STOP:
+		if (priv->bss_started == MFALSE) {
+			PRINTM(MWARN, "Warning: BSS already stopped!\n");
+			/* This is a situation where CAC it started and BSS
+			 * start is dealyed and before CAC timer expires BSS
+			 * stop is triggered.
+			 *
+			 * Do not skip sending the BSS_STOP command since there
+			 * are many routines triggered on BSS_STOP command
+			 * response.
+			 */
+			woal_cancel_cac_block(priv);
+		}
+		bss->sub_command = MLAN_OID_BSS_STOP;
+		break;
+	case UAP_BSS_RESET:
+		bss->sub_command = MLAN_OID_UAP_BSS_RESET;
+		woal_cancel_cac_block(priv);
+		break;
+	}
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_FAILURE) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) {
+		priv->bss_started = MFALSE;
+		woal_stop_queue(priv->netdev);
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		if (data == UAP_BSS_RESET)
+			woal_request_set_mac_address(priv, wait_option);
+		woal_flush_tcp_sess_queue(priv);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function sets multicast addresses to firmware
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return        N/A
+ */
+void
+woal_uap_set_multicast_list(struct net_device *dev)
+{
+	ENTER();
+
+	LEAVE();
+}
+
+/**
+ *  @brief ioctl function - entry point
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @param cmd      Command
+ *
+ *  @return         0 --success, otherwise fail
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+int
+woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, void __user * data,
+		  int cmd)
+#else
+int
+woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+#endif
+{
+	int ret = 0;
+	ENTER();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+	if (in_compat_syscall())	/* not implemented yet */
+		return -EOPNOTSUPP;
+#endif
+
+	switch (cmd) {
+	case WOAL_ANDROID_DEF_CMD:
+		/** android default ioctl ID is SIOCDEVPRIVATE + 1 */
+		ret = woal_android_priv_cmd(dev, req);
+		break;
+	case UAP_IOCTL_CMD:
+		ret = woal_uap_ioctl(dev, req);
+		break;
+	case UAP_POWER_MODE:
+		ret = woal_uap_power_mode_ioctl(dev, req);
+		break;
+	case UAP_BSS_CTRL:
+		ret = woal_uap_bss_ctrl_ioctl(dev, req);
+		break;
+	case UAP_WAPI_MSG:
+		ret = woal_uap_set_wapi(dev, req);
+		break;
+	case UAP_BSS_CONFIG:
+		ret = woal_uap_bss_cfg_ioctl(dev, req);
+		break;
+	case UAP_STA_DEAUTH:
+		ret = woal_uap_sta_deauth_ioctl(dev, req);
+		break;
+	case UAP_RADIO_CTL:
+		ret = woal_uap_radio_ctl(dev, req);
+		break;
+	case UAP_REPORT_MIC_ERR:
+		ret = woal_uap_report_mic_ioctl(dev, req);
+		break;
+	case UAP_SET_KEY:
+		ret = woal_uap_set_key_ioctl(dev, req);
+		break;
+	case UAPHOSTPKTINJECT:
+		ret = woal_send_host_packet(dev, req);
+		break;
+	case UAP_GET_STA_LIST:
+		ret = woal_uap_get_sta_list_ioctl(dev, req);
+		break;
+	case UAP_CUSTOM_IE:
+		ret = woal_custom_ie_ioctl(dev, req);
+		break;
+	case UAP_GET_BSS_TYPE:
+		ret = woal_get_bss_type(dev, req);
+		break;
+	case WOAL_ANDROID_PRIV_CMD:
+		ret = woal_android_priv_cmd(dev, req);
+		break;
+	default:
+#ifdef UAP_WEXT
+		ret = woal_uap_do_priv_ioctl(dev, req, cmd);
+#else
+		ret = -EOPNOTSUPP;
+#endif
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+#ifdef CONFIG_PROC_FS
+/**
+ *  @brief Get version
+ *
+ *  @param priv         A pointer to moal_private structure
+ *  @param version      A pointer to version buffer
+ *  @param max_len      max length of version buffer
+ *
+ *  @return             N/A
+ */
+void
+woal_uap_get_version(moal_private *priv, char *version, int max_len)
+{
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		LEAVE();
+		return;
+	}
+
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_VER_EXT;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MINFO, "MOAL UAP VERSION: %s\n",
+		       info->param.ver_ext.version_str);
+		snprintf(version, max_len, priv->phandle->driver_version,
+			 info->param.ver_ext.version_str);
+	}
+
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ *  @brief Get uap statistics
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param ustats               A pointer to mlan_ds_uap_stats structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
+ * success, otherwise fail
+ */
+mlan_status
+woal_uap_get_stats(moal_private *priv, t_u8 wait_option,
+		   mlan_ds_uap_stats *ustats)
+{
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (req == NULL) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	info = (mlan_ds_get_info *)req->pbuf;
+	info->sub_command = MLAN_OID_GET_STATS;
+	req->req_id = MLAN_IOCTL_GET_INFO;
+	req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, req, wait_option);
+	if (status == MLAN_STATUS_SUCCESS) {
+		if (ustats)
+			moal_memcpy_ext(priv->phandle, ustats,
+					&info->param.ustats,
+					sizeof(mlan_ds_uap_stats),
+					sizeof(mlan_ds_uap_stats));
+#ifdef UAP_WEXT
+		priv->w_stats.discard.fragment =
+			info->param.ustats.fcs_error_count;
+		priv->w_stats.discard.retries = info->param.ustats.retry_count;
+		priv->w_stats.discard.misc =
+			info->param.ustats.ack_failure_count;
+#endif
+	}
+
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief Set/Get system configuration parameters
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *  @param ap_wmm_para      A pointer to wmm_parameter_t structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_set_get_ap_wmm_para(moal_private *priv, t_u16 action,
+			 wmm_parameter_t *ap_wmm_para)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_CFG_WMM_PARAM;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &bss->param.ap_wmm_para,
+				ap_wmm_para, sizeof(wmm_parameter_t),
+				sizeof(bss->param.ap_wmm_para));
+
+	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (bss->param.ap_wmm_para.reserved != MLAN_STATUS_COMPLETE) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, ap_wmm_para,
+				&bss->param.ap_wmm_para,
+				sizeof(wmm_parameter_t),
+				sizeof(wmm_parameter_t));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set/Get system configuration parameters
+ *
+ *  @param priv             A pointer to moal_private structure
+ *  @param action           MLAN_ACT_SET or MLAN_ACT_GET
+ *  @param wait_option      Wait option
+ *  @param sys_cfg          A pointer to mlan_uap_bss_param structure
+ *
+ *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_set_get_sys_config(moal_private *priv, t_u16 action,
+			t_u8 wait_option, mlan_uap_bss_param *sys_cfg)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = action;
+
+	if (action == MLAN_ACT_SET)
+		moal_memcpy_ext(priv->phandle, &bss->param.bss_config, sys_cfg,
+				sizeof(mlan_uap_bss_param),
+				sizeof(bss->param.bss_config));
+
+	ret = woal_request_ioctl(priv, req, wait_option);
+	if (ret != MLAN_STATUS_SUCCESS)
+		goto done;
+
+	if (action == MLAN_ACT_GET)
+		moal_memcpy_ext(priv->phandle, sys_cfg, &bss->param.bss_config,
+				sizeof(mlan_uap_bss_param),
+				sizeof(mlan_uap_bss_param));
+
+done:
+	if (ret != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set invalid data for each member of mlan_uap_bss_param
+ *  structure
+ *
+ *  @param config   A pointer to mlan_uap_bss_param structure
+ *
+ *  @return         N/A
+ */
+void
+woal_set_sys_config_invalid_data(mlan_uap_bss_param *config)
+{
+	ENTER();
+
+	memset(config, 0, sizeof(mlan_uap_bss_param));
+	config->bcast_ssid_ctl = 0x7F;
+	config->radio_ctl = 0x7F;
+	config->dtim_period = 0x7F;
+	config->beacon_period = 0x7FFF;
+	config->tx_data_rate = 0x7FFF;
+	config->mcbc_data_rate = 0x7FFF;
+	config->tx_power_level = 0x7F;
+	config->tx_antenna = 0x7F;
+	config->rx_antenna = 0x7F;
+	config->pkt_forward_ctl = 0x7F;
+	config->max_sta_count = 0x7FFF;
+	config->auth_mode = 0x7F;
+	config->sta_ageout_timer = 0x7FFFFFFF;
+	config->pairwise_update_timeout = 0x7FFFFFFF;
+	config->pwk_retries = 0x7FFFFFFF;
+	config->groupwise_update_timeout = 0x7FFFFFFF;
+	config->gwk_retries = 0x7FFFFFFF;
+	config->mgmt_ie_passthru_mask = 0x7FFFFFFF;
+	config->ps_sta_ageout_timer = 0x7FFFFFFF;
+	config->rts_threshold = 0x7FFF;
+	config->frag_threshold = 0x7FFF;
+	config->retry_limit = 0x7FFF;
+	config->filter.filter_mode = 0x7FFF;
+	config->filter.mac_count = 0x7FFF;
+	config->wpa_cfg.rsn_protection = 0x7F;
+	config->wpa_cfg.gk_rekey_time = 0x7FFFFFFF;
+	config->enable_2040coex = 0x7F;
+	config->wmm_para.qos_info = 0x7F;
+
+	LEAVE();
+}
diff --git a/wlan_sd8987/mlinux/moal_uap.h b/wlan_sd8987/mlinux/moal_uap.h
new file mode 100755
index 0000000..f687710
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap.h
@@ -0,0 +1,588 @@
+/** @file moal_uap.h
+ *
+ * @brief This file contains uap driver specific defines etc.
+ *
+ *
+ * Copyright 2008-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    02/02/2009: initial version
+********************************************************/
+
+#ifndef _MOAL_UAP_H
+#define _MOAL_UAP_H
+
+/** Maximum buffer length for WOAL_UAP_SET_GET_256_CHAR */
+#define MAX_BUF_LEN 256
+
+/** Private command ID to send ioctl */
+#define UAP_IOCTL_CMD (SIOCDEVPRIVATE + 2)
+/** Updating ADDBA variables */
+#define UAP_ADDBA_PARA 0
+/** Updating priority table for AMPDU/AMSDU */
+#define UAP_AGGR_PRIOTBL 1
+/** Updating addbareject table */
+
+#define UAP_ADDBA_REJECT 2
+/** Get FW INFO */
+#define UAP_FW_INFO 4
+/** Updating Deep sleep variables */
+#define UAP_DEEP_SLEEP 3
+/** Tx data pause subcommand */
+#define UAP_TX_DATA_PAUSE 5
+#ifdef SDIO
+/** sdcmd52 read write subcommand */
+#define UAP_SDCMD52_RW 6
+#endif
+/** snmp mib subcommand */
+#define UAP_SNMP_MIB 7
+/** domain info subcommand */
+#define UAP_DOMAIN_INFO 8
+/** TX beamforming configuration */
+#define UAP_TX_BF_CFG 9
+/** dfs testing subcommand */
+#define UAP_DFS_TESTING 10
+/** sub command ID to set/get Host Sleep configuration */
+#define UAP_HS_CFG 11
+/** sub command ID to set/get Host Sleep Parameters */
+#define UAP_HS_SET_PARA 12
+
+/** Management Frame Control Mask */
+#define UAP_MGMT_FRAME_CONTROL 13
+
+#define UAP_TX_RATE_CFG 14
+
+/** Subcommand ID to set/get antenna configuration */
+#define UAP_ANTENNA_CFG 15
+
+#define UAP_DFS_REPEATER_MODE 16
+
+#define UAP_CAC_TIMER_STATUS 17
+
+/** Skip CAC */
+#define UAP_SKIP_CAC 18
+
+#define UAP_HT_TX_CFG 19
+
+#define UAP_VHT_CFG 20
+
+#define UAP_HT_STREAM_CFG 21
+
+#define UAP_OPERATION_CTRL 22
+
+#define UAP_CHAN_SWITCH_COUNT_CFG 23
+#define UAP_BAND_STEER 24
+
+#define UAP_BEACON_STUCK_DETECT      25
+
+/** Private command ID to Power Mode */
+#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3)
+
+/** Private command id to start/stop/reset bss */
+#define UAP_BSS_CTRL (SIOCDEVPRIVATE + 4)
+/** BSS START */
+#define UAP_BSS_START 0
+/** BSS STOP */
+#define UAP_BSS_STOP 1
+/** BSS RESET */
+#define UAP_BSS_RESET 2
+
+/** wapi_msg */
+typedef struct _wapi_msg {
+	/** message type */
+	t_u16 msg_type;
+	/** message len */
+	t_u16 msg_len;
+	/** message */
+	t_u8 msg[96];
+} wapi_msg;
+
+/* wapi key msg */
+typedef struct _wapi_key_msg {
+	/** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+	/** pad */
+	t_u8 pad;
+	/** key id */
+	t_u8 key_id;
+	/** key */
+	t_u8 key[32];
+} wapi_key_msg;
+
+/** Private command ID to set wapi info */
+#define UAP_WAPI_MSG (SIOCDEVPRIVATE + 10)
+/** set wapi flag */
+#define P80211_PACKET_WAPIFLAG 0x0001
+/** set wapi key */
+#define P80211_PACKET_SETKEY 0x0003
+/** wapi mode psk */
+#define WAPI_MODE_PSK 0x04
+/** wapi mode certificate */
+#define WAPI_MODE_CERT 0x08
+
+typedef struct _tx_rate_cfg_t {
+	/** sub command */
+	int subcmd;
+	/** Action */
+	int action;
+	/** Rate format */
+	int rate_format;
+	/** Rate configured */
+	int rate;
+	/** nss */
+	int nss;
+	/** user_data_cnt */
+	int user_data_cnt;
+	/** Rate bitmap */
+	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
+	/** Rate Setting */
+	t_u16 rate_setting;
+} tx_rate_cfg_t;
+
+/** ant_cfg structure */
+typedef struct _ant_cfg_t {
+	/** Subcommand */
+	int subcmd;
+	/** Action */
+	int action;
+	/** TX mode configured */
+	int tx_mode;
+	/** RX mode configured */
+	int rx_mode;
+} ant_cfg_t;
+
+/** htstream_cfg structure */
+typedef struct _htstream_cfg_t {
+	/** Subcommand */
+	int subcmd;
+	/** Action */
+	int action;
+	/** HT stream configuration */
+	t_u32 stream_cfg;
+} htstream_cfg_t;
+
+/* dfs repeater mode */
+typedef struct _dfs_repeater_mode {
+	/** subcmd */
+	t_u32 subcmd;
+	/** set/get */
+	t_u32 action;
+	/** mode */
+	t_u32 mode;
+} dfs_repeater_mode;
+
+/* */
+typedef struct _cac_timer_status {
+	/** subcmd */
+	t_u32 subcmd;
+	/** set/get */
+	t_u32 action;
+	/** mode */
+	t_u32 mode;
+} cac_timer_status;
+
+/** skip_cac parameters */
+typedef struct _skip_cac_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** enable/disable deepsleep*/
+	t_u16 skip_cac;
+} skip_cac_para;
+
+/** radio control command */
+#define UAP_RADIO_CTL (SIOCDEVPRIVATE + 5)
+
+/** Private command ID to BSS config */
+#define UAP_BSS_CONFIG (SIOCDEVPRIVATE + 6)
+
+/** deauth station */
+#define UAP_STA_DEAUTH (SIOCDEVPRIVATE + 7)
+
+/** enable UAP report mic error */
+#define UAP_REPORT_MIC_ERR (SIOCDEVPRIVATE + 8)
+/** uap set key */
+#define UAP_SET_KEY (SIOCDEVPRIVATE + 9)
+/** encrypt key */
+typedef struct _encrypt_key {
+	/** Key index */
+	t_u32 key_index;
+	/** Key length */
+	t_u32 key_len;
+	/** Key */
+	t_u8 key_material[MLAN_MAX_KEY_LENGTH];
+	/** mac address */
+	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
+} encrypt_key;
+
+/** pkt_header */
+typedef struct _pkt_header {
+	/** pkt_len */
+	u32 pkt_len;
+	/** pkt_type */
+	u32 TxPktType;
+	/** tx control */
+	u32 TxControl;
+} pkt_header;
+/** uap get station list */
+#define UAP_GET_STA_LIST (SIOCDEVPRIVATE + 11)
+/** Packet inject command ioctl number */
+#define UAPHOSTPKTINJECT WOAL_MGMT_FRAME_TX_IOCTL
+
+/** Private command ID to set/get custom IE buffer */
+#define UAP_CUSTOM_IE (SIOCDEVPRIVATE + 13)
+
+/** HS WAKE UP event id */
+#define UAP_EVENT_ID_HS_WAKEUP 0x80000001
+/** HS_ACTIVATED event id */
+#define UAP_EVENT_ID_DRV_HS_ACTIVATED 0x80000002
+/** HS DEACTIVATED event id */
+#define UAP_EVENT_ID_DRV_HS_DEACTIVATED 0x80000003
+
+/** Host sleep flag set */
+#define HS_CFG_FLAG_GET 0
+/** Host sleep flag get */
+#define HS_CFG_FLAG_SET 1
+/** Host sleep flag for condition */
+#define HS_CFG_FLAG_CONDITION 2
+/** Host sleep flag for GPIO */
+#define HS_CFG_FLAG_GPIO 4
+/** Host sleep flag for Gap */
+#define HS_CFG_FLAG_GAP 8
+/** Host sleep flag for all */
+#define HS_CFG_FLAG_ALL 0x0f
+/** Host sleep mask to get condition */
+#define HS_CFG_CONDITION_MASK 0x0f
+
+/** ds_hs_cfg */
+typedef struct _ds_hs_cfg {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Bit0: 0 - Get, 1 Set
+	 *  Bit1: 1 - conditions is valid
+	 *  Bit2: 2 - gpio is valid
+	 *  Bit3: 3 - gap is valid
+	 */
+	t_u32 flags;
+	/** Host sleep config condition */
+	/** Bit0: non-unicast data
+	 *  Bit1: unicast data
+	 *  Bit2: mac events
+	 *  Bit3: magic packet
+	 */
+	t_u32 conditions;
+	/** GPIO */
+	t_u32 gpio;
+	/** Gap in milliseconds */
+	t_u32 gap;
+} ds_hs_cfg;
+
+/** Private command ID to get BSS type */
+#define UAP_GET_BSS_TYPE (SIOCDEVPRIVATE + 15)
+
+/** addba_param */
+typedef struct _uap_addba_param {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** block ack timeout for ADDBA request */
+	t_u32 timeout;
+	/** Buffer size for ADDBA request */
+	t_u32 txwinsize;
+	/** Buffer size for ADDBA response */
+	t_u32 rxwinsize;
+	/** amsdu for ADDBA request */
+	t_u8 txamsdu;
+	/** amsdu for ADDBA response */
+	t_u8 rxamsdu;
+} uap_addba_param;
+
+/** aggr_prio_tbl */
+typedef struct _uap_aggr_prio_tbl {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** ampdu priority table */
+	t_u8 ampdu[MAX_NUM_TID];
+	/** amsdu priority table */
+	t_u8 amsdu[MAX_NUM_TID];
+} uap_aggr_prio_tbl;
+
+/** addba_reject parameters */
+typedef struct _addba_reject_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** BA Reject paramters */
+	t_u8 addba_reject[MAX_NUM_TID];
+} addba_reject_para;
+
+/** fw_info */
+typedef struct _uap_fw_info {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Get */
+	t_u32 action;
+	/** Firmware release number */
+	t_u32 fw_release_number;
+	/** Device support for MIMO abstraction of MCSs */
+	t_u8 hw_dev_mcs_support;
+	/** fw_bands*/
+	t_u8 fw_bands;
+	/** Region Code */
+	t_u16 region_code;
+	/** 802.11n device capabilities */
+	t_u32 hw_dot_11n_dev_cap;
+} uap_fw_info;
+
+typedef struct _ht_tx_cfg_para_hdr {
+	/** Sub command */
+	t_u32 subcmd;
+	/** Action: Set/Get */
+	t_u32 action;
+} ht_tx_cfg_para_hdr;
+
+typedef struct _tx_bf_cfg_para_hdr {
+	/** Sub command */
+	t_u32 subcmd;
+	/** Action: Set/Get */
+	t_u32 action;
+} tx_bf_cfg_para_hdr;
+
+typedef struct _vht_cfg_para_hdr {
+	/** Sub command */
+	t_u32 subcmd;
+	/** Action: Set/Get */
+	t_u32 action;
+} vht_cfg_para_hdr;
+
+typedef struct _uap_oper_para_hdr {
+	/** Sub command */
+	t_u32 subcmd;
+	/** Action: Set/Get */
+	t_u32 action;
+} uap_oper_para_hdr;
+
+#ifdef SDIO
+/** sdcmd52rw parameters */
+typedef struct _sdcmd52_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Write /Read */
+	t_u32 action;
+	/** Command 52 paramters */
+	t_u8 cmd52_params[3];
+} sdcmd52_para;
+#endif
+
+/** deep_sleep parameters */
+typedef struct _deep_sleep_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** enable/disable deepsleep*/
+	t_u16 deep_sleep;
+	/** idle_time */
+	t_u16 idle_time;
+} deep_sleep_para;
+
+/** band_steering parameters */
+typedef struct _band_steer_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u8 action;
+	/** enable/disable band steering*/
+	t_u8 state;
+	/** Probe Response will be blocked to 2G channel for first
+	 * block_2g_prb_req probe requests*/
+	t_u8 block_2g_prb_req;
+	/** When band steering is enabled, limit the btm request sent to STA at
+	 * <max_btm_req_allowed>*/
+	t_u8 max_btm_req_allowed;
+
+} band_steer_para;
+
+/** beacon stuck detect mechanism parameters */
+typedef struct _beacon_stuck_detect_para {
+    /** subcmd */
+	t_u32 subcmd;
+    /** Set/Get */
+	t_u8 action;
+    /** No of beacon interval after which firmware will check if beacon Tx is going fine */
+	t_u8 beacon_stuck_detect_count;
+    /** Upon performing MAC reset, no of beacon interval after which firmware will check if recovery was successful */
+	t_u8 recovery_confirm_count;
+} beacon_stuck_detect_para;
+
+/** tx_data_pause parameters */
+typedef struct _tx_data_pause_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** enable/disable Tx data pause*/
+	t_u16 txpause;
+	/** Max number of TX buffer allowed for all PS client*/
+	t_u16 txbufcnt;
+} tx_data_pause_para;
+
+/** mgmt_frame_ctrl */
+typedef struct _mgmt_frame_ctrl {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** mask */
+	t_u32 mask;
+} mgmt_frame_ctrl;
+
+typedef struct _snmp_mib_para {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** oid to set/get */
+	t_u16 oid;
+	/** length of oid value */
+	t_u16 oid_val_len;
+	/** oid value to set/get */
+	t_u8 oid_value[];
+} snmp_mib_para;
+
+/** Max length for oid_value field */
+#define MAX_SNMP_VALUE_SIZE 128
+
+/** Oid for 802.11D enable/disable */
+#define OID_80211D_ENABLE 0x0009
+/** Oid for 802.11H enable/disable */
+#define OID_80211H_ENABLE 0x000a
+
+/** dfs_testing parameters */
+typedef struct _dfs_testing_param {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** user CAC period (msec) */
+	t_u32 usr_cac_period;
+	/** user NOP period (sec) */
+	t_u16 usr_nop_period;
+	/** don't change channel on radar */
+	t_u8 no_chan_change;
+	/** fixed channel to change to on radar */
+	t_u8 fixed_new_chan;
+	/** CAC restart */
+	t_u8 cac_restart;
+} dfs_testing_para;
+
+/** Channel switch count config */
+typedef struct _cscount_cfg_t {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** user channel switch count */
+	t_u8 cs_count;
+} cscount_cfg_t;
+
+/** domain_info parameters */
+typedef struct _domain_info_param {
+	/** subcmd */
+	t_u32 subcmd;
+	/** Set/Get */
+	t_u32 action;
+	/** domain_param TLV (incl. header) */
+	t_u8 tlv[];
+} domain_info_para;
+
+/** DOMAIN_INFO param sizes */
+#define TLV_HEADER_LEN (2 + 2)
+#define SUB_BAND_LEN 3
+#define MAX_SUB_BANDS 40
+
+/** MAX domain TLV length */
+#define MAX_DOMAIN_TLV_LEN                                                     \
+	(TLV_HEADER_LEN + COUNTRY_CODE_LEN + (SUB_BAND_LEN * MAX_SUB_BANDS))
+
+int woal_set_get_uap_power_mode(moal_private *priv, t_u32 action,
+				mlan_ds_ps_mgmt *ps_mgmt);
+void woal_uap_set_multicast_list(struct net_device *dev);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req,
+		      void __user * data, int cmd);
+#else
+int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+#endif
+
+int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data);
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+int woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
+				  pmlan_ds_11h_chan_nop_info ch_info);
+#endif
+#endif
+mlan_status woal_set_get_ap_channel(moal_private *priv, t_u16 action,
+				    t_u8 wait_option,
+				    chan_band_info * uap_channel);
+#ifdef CONFIG_PROC_FS
+void woal_uap_get_version(moal_private *priv, char *version, int max_len);
+#endif
+mlan_status woal_uap_get_stats(moal_private *priv, t_u8 wait_option,
+			       pmlan_ds_uap_stats ustats);
+#if defined(UAP_WEXT) || defined(UAP_CFG80211)
+extern struct iw_handler_def woal_uap_handler_def;
+struct iw_statistics *woal_get_uap_wireless_stats(struct net_device *dev);
+/** IOCTL function for wireless private IOCTLs */
+int woal_uap_do_priv_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
+#endif
+/** Set invalid data for each member of mlan_uap_bss_param */
+void woal_set_sys_config_invalid_data(pmlan_uap_bss_param config);
+/** Set/Get system configuration parameters */
+mlan_status woal_set_get_sys_config(moal_private *priv, t_u16 action,
+				    t_u8 wait_option,
+				    mlan_uap_bss_param *sys_cfg);
+/** Set get AP wmm parameter */
+mlan_status woal_set_get_ap_wmm_para(moal_private *priv, t_u16 action,
+				     wmm_parameter_t *ap_wmm_para);
+int woal_uap_set_ap_cfg(moal_private *priv, t_u8 *data, int len);
+
+int woal_uap_set_11ac_status(moal_private *priv, t_u8 action, t_u8 vht20_40,
+			     IEEEtypes_VHTCap_t *vhtcap_ie);
+int woal_11ax_cfg(moal_private *priv, t_u8 action,
+		  mlan_ds_11ax_he_cfg * he_cfg);
+int woal_uap_set_11ax_status(moal_private *priv, t_u8 action, t_u8 band,
+			     IEEEtypes_HECap_t * hecap_ie);
+int woal_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg,
+			   t_u16 ht_cap, t_u8 en);
+mlan_status woal_uap_set_11n_status(moal_private *priv,
+				    mlan_uap_bss_param *sys_cfg, t_u8 action);
+#ifdef UAP_WEXT
+void woal_ioctl_get_uap_info_resp(moal_private *priv, pmlan_ds_get_info info);
+int woal_set_get_custom_ie(moal_private *priv, t_u16 mask, t_u8 *ie,
+			   int ie_len);
+#endif /* UAP_WEXT */
+
+#endif /* _MOAL_UAP_H */
diff --git a/wlan_sd8987/mlinux/moal_uap_cfg80211.c b/wlan_sd8987/mlinux/moal_uap_cfg80211.c
new file mode 100755
index 0000000..eae934f
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_cfg80211.c
@@ -0,0 +1,3504 @@
+/** @file moal_uap_cfg80211.c
+ *
+ * @brief This file contains the functions for uAP CFG80211.
+ *
+ *
+ * Copyright 2011-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#include "moal_cfg80211.h"
+#include "moal_uap_cfg80211.h"
+/** deauth reason code */
+#define REASON_CODE_DEAUTH_LEAVING 3
+/********************************************************
+				Local Variables
+********************************************************/
+
+/********************************************************
+				Global Variables
+********************************************************/
+/********************************************************
+				Local Functions
+********************************************************/
+
+/********************************************************
+				Global Functions
+********************************************************/
+/**
+ * @brief send deauth to station
+ *
+ * @param                 A pointer to moal_private
+ * @param mac			  A pointer to station mac address
+ * @param reason_code     ieee deauth reason code
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_deauth_station(moal_private *priv, u8 *mac_addr, u16 reason_code)
+{
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_ds_bss *bss = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)ioctl_req->pbuf;
+	bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
+	ioctl_req->req_id = MLAN_IOCTL_BSS;
+	ioctl_req->action = MLAN_ACT_SET;
+
+	moal_memcpy_ext(priv->phandle, bss->param.deauth_param.mac_addr,
+			mac_addr, MLAN_MAC_ADDR_LENGTH,
+			sizeof(bss->param.deauth_param.mac_addr));
+	bss->param.deauth_param.reason_code = reason_code;
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send deauth to station, that has been added and associated
+ *
+ * @param                 A pointer to moal_private
+ * @param mac			        A pointer to station mac address
+ * @param reason_code     ieee deauth reason code
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_deauth_assoc_station(moal_private *priv, u8 *mac_addr, u16 reason_code)
+{
+	int ret = -EFAULT;
+	int i = 0;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!mac_addr) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (ioctl_req == NULL) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	info = (mlan_ds_get_info *)ioctl_req->pbuf;
+	info->sub_command = MLAN_OID_UAP_STA_LIST;
+	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (!info->param.sta_list.sta_count) {
+		PRINTM(MCMND, "wlan: skip deauth to station " MACSTR "\n",
+		       MAC2STR(mac_addr));
+		goto done;
+	}
+
+	for (i = 0; i < info->param.sta_list.sta_count; i++) {
+		if (!memcmp(info->param.sta_list.info[i].mac_address,
+			    mac_addr, ETH_ALEN))
+			ret = woal_deauth_station(priv, mac_addr, reason_code);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief send deauth to all station
+ *
+ * @param                 A pointer to moal_private
+ * @param mac			  A pointer to station mac address
+ *
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_deauth_all_station(moal_private *priv)
+{
+	int ret = -EFAULT;
+	int i = 0;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MINFO, "cfg80211: Media not connected!\n");
+		LEAVE();
+		return 0;
+	}
+	PRINTM(MIOCTL, "del all station\n");
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	info = (mlan_ds_get_info *)ioctl_req->pbuf;
+	info->sub_command = MLAN_OID_UAP_STA_LIST;
+	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (!info->param.sta_list.sta_count)
+		goto done;
+	for (i = 0; i < info->param.sta_list.sta_count; i++) {
+		PRINTM(MIOCTL, "deauth station " MACSTR "\n",
+		       MAC2STR(info->param.sta_list.info[i].mac_address));
+		ret = woal_deauth_station(priv,
+					  info->param.sta_list.info[i].
+					  mac_address,
+					  REASON_CODE_DEAUTH_LEAVING);
+	}
+	woal_sched_timeout(200);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	return ret;
+}
+
+/**
+ * @brief Verify RSN IE
+ *
+ * @param rsn_ie          Pointer RSN IE
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                MTRUE/MFALSE
+ */
+static t_u8
+woal_check_rsn_ie(IEEEtypes_Rsn_t *rsn_ie, mlan_uap_bss_param *sys_config)
+{
+	int left = 0;
+	int count = 0;
+	int i = 0;
+	wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
+	left = rsn_ie->len + 2;
+	if (left < (int)sizeof(IEEEtypes_Rsn_t))
+		return MFALSE;
+	sys_config->wpa_cfg.group_cipher = 0;
+	sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
+	sys_config->key_mgmt = 0;
+	/* check the group cipher */
+	switch (rsn_ie->group_cipher.type) {
+	case WPA_CIPHER_TKIP:
+		sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
+		break;
+	case WPA_CIPHER_AES_CCM:
+		sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+		break;
+	default:
+		break;
+	}
+	count = woal_le16_to_cpu(rsn_ie->pairwise_cipher.count);
+	for (i = 0; i < count; i++) {
+		switch (rsn_ie->pairwise_cipher.list[i].type) {
+		case WPA_CIPHER_TKIP:
+			sys_config->wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_TKIP;
+			break;
+		case WPA_CIPHER_AES_CCM:
+			sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
+				CIPHER_AES_CCMP;
+			break;
+		default:
+			break;
+		}
+	}
+	left -= sizeof(IEEEtypes_Rsn_t) + (count - 1) * sizeof(wpa_suite);
+	if (left < (int)sizeof(wpa_suite_auth_key_mgmt_t))
+		return MFALSE;
+	key_mgmt =
+		(wpa_suite_auth_key_mgmt_t *)((u8 *)rsn_ie +
+					      sizeof(IEEEtypes_Rsn_t) +
+					      (count - 1) * sizeof(wpa_suite));
+	count = woal_le16_to_cpu(key_mgmt->count);
+	if (left < (int)(sizeof(wpa_suite_auth_key_mgmt_t) +
+			 (count - 1) * sizeof(wpa_suite)))
+		return MFALSE;
+	for (i = 0; i < count; i++) {
+		switch (key_mgmt->list[i].type) {
+		case RSN_AKM_8021X:
+			sys_config->key_mgmt |= KEY_MGMT_EAP;
+			break;
+		case RSN_AKM_PSK:
+			sys_config->key_mgmt |= KEY_MGMT_PSK;
+			break;
+		case RSN_AKM_PSK_SHA256:
+			sys_config->key_mgmt |= KEY_MGMT_PSK_SHA256;
+			break;
+		case RSN_AKM_SAE:
+			sys_config->key_mgmt |= KEY_MGMT_SAE;
+			break;
+		case RSN_AKM_OWE:
+			sys_config->key_mgmt |= KEY_MGMT_OWE;
+			break;
+		}
+	}
+	return MTRUE;
+}
+
+/**
+ * @brief Verify WPA IE
+ *
+ * @param wpa_ie          Pointer WPA IE
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                MTRUE/MFALSE
+ */
+static t_u8
+woal_check_wpa_ie(IEEEtypes_Wpa_t *wpa_ie, mlan_uap_bss_param *sys_config)
+{
+	int left = 0;
+	int count = 0;
+	int i = 0;
+	wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
+	left = wpa_ie->len + 2;
+	if (left < (int)sizeof(IEEEtypes_Wpa_t))
+		return MFALSE;
+	sys_config->wpa_cfg.group_cipher = 0;
+	sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
+	switch (wpa_ie->group_cipher.type) {
+	case WPA_CIPHER_TKIP:
+		sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
+		break;
+	case WPA_CIPHER_AES_CCM:
+		sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+		break;
+	default:
+		break;
+	}
+	count = woal_le16_to_cpu(wpa_ie->pairwise_cipher.count);
+	for (i = 0; i < count; i++) {
+		switch (wpa_ie->pairwise_cipher.list[i].type) {
+		case WPA_CIPHER_TKIP:
+			sys_config->wpa_cfg.pairwise_cipher_wpa |= CIPHER_TKIP;
+			break;
+		case WPA_CIPHER_AES_CCM:
+			sys_config->wpa_cfg.pairwise_cipher_wpa |=
+				CIPHER_AES_CCMP;
+			break;
+		default:
+			break;
+		}
+	}
+	left -= sizeof(IEEEtypes_Wpa_t) + (count - 1) * sizeof(wpa_suite);
+	if (left < (int)sizeof(wpa_suite_auth_key_mgmt_t))
+		return MFALSE;
+	key_mgmt =
+		(wpa_suite_auth_key_mgmt_t *)((u8 *)wpa_ie +
+					      sizeof(IEEEtypes_Wpa_t) +
+					      (count - 1) * sizeof(wpa_suite));
+	count = woal_le16_to_cpu(key_mgmt->count);
+	if (left < (int)(sizeof(wpa_suite_auth_key_mgmt_t) +
+			 (count - 1) * sizeof(wpa_suite)))
+		return MFALSE;
+	for (i = 0; i < count; i++) {
+		switch (key_mgmt->list[i].type) {
+		case RSN_AKM_8021X:
+			sys_config->key_mgmt = KEY_MGMT_EAP;
+			break;
+		case RSN_AKM_PSK:
+			sys_config->key_mgmt = KEY_MGMT_PSK;
+			break;
+		}
+	}
+	return MTRUE;
+}
+
+/**
+ * @brief Find RSN/WPA IES
+ *
+ * @param ie              Pointer IE buffer
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                MTRUE/MFALSE
+ */
+static t_u8
+woal_find_wpa_ies(const t_u8 *ie, int len, mlan_uap_bss_param *sys_config)
+{
+	int bytes_left = len;
+	const t_u8 *pcurrent_ptr = ie;
+	t_u16 total_ie_len;
+	t_u8 element_len;
+	t_u8 wpa2 = 0;
+	t_u8 wpa = 0;
+	t_u8 ret = MFALSE;
+	IEEEtypes_ElementId_e element_id;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
+
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR,
+			       "InterpretIE: Error in processing IE, bytes left < IE length\n");
+			bytes_left = 0;
+			continue;
+		}
+		switch (element_id) {
+		case RSN_IE:
+			wpa2 = woal_check_rsn_ie((IEEEtypes_Rsn_t *)
+						 pcurrent_ptr, sys_config);
+			break;
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wpa_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    (pvendor_ie->vend_hdr.oui_type == wpa_oui[3])) {
+				wpa = woal_check_wpa_ie((IEEEtypes_Wpa_t *)
+							pcurrent_ptr,
+							sys_config);
+			}
+			break;
+		default:
+			break;
+		}
+		pcurrent_ptr += element_len + 2;
+		/* Need to account for IE ID and IE Len */
+		bytes_left -= (element_len + 2);
+	}
+	if (wpa && wpa2) {
+		sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
+		ret = MTRUE;
+	} else if (wpa2) {
+		sys_config->protocol = PROTOCOL_WPA2;
+		ret = MTRUE;
+	} else if (wpa) {
+		sys_config->protocol = PROTOCOL_WPA;
+		ret = MTRUE;
+	}
+	return ret;
+}
+
+/**
+ * @brief Find and set WMM IES
+ *
+ * @param priv            Pointer to moal_private
+ * @param ie              Pointer IE buffer
+ * @param sys_config      Pointer to mlan_uap_bss_param structure
+ *
+ * @return                N/A
+ */
+static t_void
+woal_set_wmm_ies(moal_private *priv, const t_u8 *ie, int len,
+		 mlan_uap_bss_param *sys_config)
+{
+	int bytes_left = len;
+	const t_u8 *pcurrent_ptr = ie;
+	t_u16 total_ie_len;
+	t_u8 element_len;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	IEEEtypes_ElementId_e element_id;
+	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
+
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR,
+			       "InterpretIE: Error in processing IE, bytes left < IE length\n");
+			bytes_left = 0;
+			continue;
+		}
+		switch (element_id) {
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+			if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui,
+				    sizeof(pvendor_ie->vend_hdr.oui)) &&
+			    pvendor_ie->vend_hdr.oui_type == wmm_oui[3]) {
+				if (total_ie_len ==
+				    sizeof(IEEEtypes_WmmParameter_t)) {
+					/*
+					 * Only accept and copy the WMM IE if
+					 * it matches the size expected for the
+					 * WMM Parameter IE.
+					 */
+					moal_memcpy_ext(priv->phandle,
+							&sys_config->wmm_para,
+							pcurrent_ptr +
+							sizeof
+							(IEEEtypes_Header_t),
+							element_len,
+							sizeof(sys_config->
+							       wmm_para));
+					/** set uap_host_based_config to true */
+					sys_config->uap_host_based_config =
+						MTRUE;
+				}
+			}
+
+			break;
+		default:
+			break;
+		}
+		pcurrent_ptr += element_len + 2;
+		/* Need to account for IE ID and IE Len */
+		bytes_left -= (element_len + 2);
+	}
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @brief initialize AP or GO bss config
+ * @param priv            A pointer to moal private structure
+ * @param band		  BAND_2GHZ/BAND_5GHZ
+ * @param params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+static t_u8
+woal_check_11ac_capability(moal_private *priv, t_u8 band,
+			   struct cfg80211_ap_settings *params)
+#else
+/**
+ * @brief initialize AP or GO bss config
+ * @param band		  BAND_2GHZ/BAND_5GHZ
+ * @param priv            A pointer to moal private structure
+ * @return                0 -- success, otherwise fail
+ */
+static t_u8
+woal_check_11ac_capability(moal_private *priv, t_u8 band)
+#endif
+{
+	mlan_fw_info fw_info;
+	t_u8 enable_11ac = MFALSE;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	const u8 *vht_ie = NULL;
+#endif
+	ENTER();
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if ((band == BAND_5GHZ) && !(fw_info.fw_bands & BAND_AAC)) {
+		PRINTM(MCMND, "FW don't support 5G AC");
+		LEAVE();
+		return enable_11ac;
+	}
+	if ((band == BAND_2GHZ) && !(fw_info.fw_bands & BAND_GAC)) {
+		PRINTM(MCMND, "FW don't support 2G AC");
+		LEAVE();
+		return enable_11ac;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
+				  params->beacon.tail_len);
+	if (vht_ie)
+		enable_11ac = MTRUE;
+	else
+		enable_11ac = MFALSE;
+#else
+	enable_11ac = MTRUE;
+#endif
+	LEAVE();
+	return enable_11ac;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @brief initialize AP or GO bss config
+ * @param priv            A pointer to moal private structure
+ * @param band            BAND_5G/BAND_2GHZ
+ * @param params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+static t_u8
+woal_check_11ax_capability(moal_private *priv, t_u8 band,
+			   struct cfg80211_ap_settings *params)
+{
+	mlan_fw_info fw_info;
+	t_u8 enable_11ax = MFALSE;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
+	mlan_ds_11ax_he_cfg he_cfg;
+	t_u8 he_txrx_mcs_support[4] = { 0xff, 0xff, 0xff, 0xff };
+#endif
+	ENTER();
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if ((band == BAND_5GHZ) && !(fw_info.fw_bands & BAND_AAX)) {
+		PRINTM(MCMND, "FW don't support 5G AX\n");
+		LEAVE();
+		return enable_11ax;
+	}
+	if ((band == BAND_2GHZ) && !(fw_info.fw_bands & BAND_GAX)) {
+		PRINTM(MCMND, "FW don't support 2G AX");
+		LEAVE();
+		return enable_11ax;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+	if (params->he_cap)
+		enable_11ax = MTRUE;
+	else
+		enable_11ax = MFALSE;
+#else
+	memset(&he_cfg, 0, sizeof(he_cfg));
+	if (band == BAND_5GHZ)
+		he_cfg.band = MBIT(1);
+	else if (band == BAND_2GHZ)
+		he_cfg.band = MBIT(0);
+	if (0 == woal_11ax_cfg(priv, MLAN_ACT_GET, &he_cfg)) {
+		if (he_cfg.he_cap.len &&
+		    (he_cfg.he_cap.ext_id == HE_CAPABILITY)) {
+			if (memcmp(he_cfg.he_cap.he_txrx_mcs_support,
+				   he_txrx_mcs_support,
+				   sizeof(he_txrx_mcs_support)))
+				enable_11ax = MTRUE;
+		}
+	}
+#endif
+	PRINTM(MCMND, "enable_11ax=%d\n", enable_11ax);
+	LEAVE();
+	return enable_11ax;
+}
+#endif
+
+/**
+ * @brief get ht_cap from beacon ie
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ *
+ * @return                ht_cap
+ */
+static t_u16
+woal_get_htcap_info(const t_u8 *ie, int len)
+{
+	t_u16 ht_cap_info = 0;
+	IEEEtypes_HTCap_t *htcap_ie = NULL;
+	htcap_ie =
+		(IEEEtypes_HTCap_t *)woal_parse_ie_tlv(ie, len, HT_CAPABILITY);
+	if (htcap_ie) {
+		/* hostap has converted ht_cap_info to little endian, here
+		 * conver to host endian */
+		ht_cap_info = woal_le16_to_cpu(htcap_ie->ht_cap.ht_cap_info);
+		PRINTM(MMSG, "Get ht_cap from beacon ies: 0x%x\n", ht_cap_info);
+	}
+	return ht_cap_info;
+}
+
+/**
+ * @brief get vht_cap from beacon ie
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ *
+ * @return                Pointer to vht_cap ie
+ */
+static IEEEtypes_VHTCap_t *
+woal_get_vhtcap_info(const t_u8 *ie, int len)
+{
+	IEEEtypes_VHTCap_t *vhtcap_ie = NULL;
+	vhtcap_ie = (IEEEtypes_VHTCap_t *)woal_parse_ie_tlv(ie, len,
+							    VHT_CAPABILITY);
+	if (vhtcap_ie)
+		PRINTM(MMSG, "Get vht_cap from beacon ies: 0x%x\n",
+		       vhtcap_ie->vht_cap.vht_cap_info);
+	return vhtcap_ie;
+}
+
+/**
+ * @brief get vht_oper from beacon ie
+ *
+ * @param ie              Pointer to IEs
+ * @param len             Total length of ie
+ *
+ * @return                Pointer to vht_opr ie
+ */
+static IEEEtypes_VHTOprat_t *
+woal_get_vht_oprat_ie(const t_u8 *ie, int len)
+{
+	IEEEtypes_VHTOprat_t *vht_oprat_ie = NULL;
+	vht_oprat_ie = (IEEEtypes_VHTOprat_t *)woal_parse_ie_tlv(ie, len,
+								 VHT_OPERATION);
+	if (vht_oprat_ie)
+		PRINTM(MMSG,
+		       "Get vht_oprat_ie from beacon ies: chan_width=%d\n",
+		       vht_oprat_ie->chan_width);
+	return vht_oprat_ie;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+/** Starting Frequency for 11A band */
+#define START_FREQ_11A_BAND 5000	/* in MHz */
+/**
+ * @brief convert cfg80211_chan_def to Band_Config
+ *
+ * @param priv            A pointer to moal private structure
+ * @param bandcfg         A pointer to (Band_Config_t structure
+ * @param chandef         A pointer to cfg80211_chan_def structure
+ *
+ * @return                N/A
+ */
+static void
+woal_convert_chan_to_bandconfig(moal_private *priv,
+				Band_Config_t *bandcfg,
+				struct cfg80211_chan_def *chandef)
+{
+	ENTER();
+
+	if (chandef->chan->hw_value <= MAX_BG_CHANNEL)
+		bandcfg->chanBand = BAND_2GHZ;
+	else
+		bandcfg->chanBand = BAND_5GHZ;
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_20_NOHT:
+	case NL80211_CHAN_WIDTH_20:
+		bandcfg->chanWidth = CHAN_BW_20MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		bandcfg->chanWidth = CHAN_BW_40MHZ;
+		if (chandef->center_freq1 > chandef->chan->center_freq)
+			bandcfg->chan2Offset = SEC_CHAN_ABOVE;
+		else
+			bandcfg->chan2Offset = SEC_CHAN_BELOW;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+		bandcfg->chan2Offset =
+			woal_get_second_channel_offset(priv,
+						       chandef->chan->hw_value);
+		bandcfg->chanWidth = CHAN_BW_80MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+	default:
+		break;
+	}
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief Enable radar detect for DFS channel
+ *
+ * @param priv            A pointer to moal private structure
+ * @param chandef         A pointer to cfg80211_chan_def structure
+ * @return                N/A
+ */
+static void
+woal_enable_dfs_support(moal_private *priv, struct cfg80211_chan_def *chandef)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_chan_rep_req *pchan_rpt_req = NULL;
+	mlan_ds_11h_cfg *p11h_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	ENTER();
+	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
+		PRINTM(MIOCTL, "No radar channel\n");
+		LEAVE();
+		return;
+	}
+	PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d \n",
+	       chandef->chan->hw_value, chandef->width);
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (NULL == req) {
+		PRINTM(MIOCTL, "No Memory to allocate ioctl buffer\n");
+		LEAVE();
+		return;
+	}
+	p11h_cfg = (mlan_ds_11h_cfg *)req->pbuf;
+	pchan_rpt_req = &p11h_cfg->param.chan_rpt_req;
+	pchan_rpt_req->startFreq = 5000;
+	pchan_rpt_req->chanNum = (t_u8)chandef->chan->hw_value;
+	woal_convert_chan_to_bandconfig(priv, &pchan_rpt_req->bandcfg, chandef);
+	pchan_rpt_req->host_based = MTRUE;
+	pchan_rpt_req->millisec_dwell_time = 0;
+
+	p11h_cfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+	req->action = MLAN_ACT_SET;
+	/* Send Channel Check command and wait until the report is ready */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return;
+}
+#endif
+
+/**
+ * @brief Prase supported rates from beacon data, set bss cfg accordingly
+ *
+ * @param priv                  A pointer to moal_private
+ * @param bss_cfg            A pointer to bss configuration structure
+ * @param head_ie            A pointer to beacon head IE buffer
+ * @param head_len           head IE buffer length
+ * @param tail_ie            A pointer to beacon tail IE buffer
+ * @param tail_len           tail IE buffer length *
+ * @return                   N/A
+ */
+static void
+woal_set_uap_rates(moal_private *priv, mlan_uap_bss_param *bss_cfg,
+		   const t_u8 *head_ie, int head_len,
+		   const t_u8 *tail_ie, int tail_len)
+{
+	pIEEEtypes_Header_t rate_ie;
+	pIEEEtypes_Header_t ext_rate_ie;
+	int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+	const u8 *var_pos = head_ie + var_offset;
+	int len = head_len - var_offset;
+	int rate_len = 0;
+
+	rate_ie = (void *)woal_parse_ie_tlv(var_pos, len, WLAN_EID_SUPP_RATES);
+	if (rate_ie) {
+		memset(bss_cfg->rates, 0, sizeof(bss_cfg->rates));
+		moal_memcpy_ext(priv->phandle, bss_cfg->rates, rate_ie + 1,
+				rate_ie->len, sizeof(bss_cfg->rates));
+		rate_len = MIN(rate_ie->len, sizeof(bss_cfg->rates));
+	}
+	ext_rate_ie = (void *)woal_parse_ie_tlv(tail_ie, tail_len,
+						WLAN_EID_EXT_SUPP_RATES);
+	if (ext_rate_ie) {
+		moal_memcpy_ext(priv->phandle, &bss_cfg->rates[rate_len],
+				ext_rate_ie + 1, ext_rate_ie->len,
+				sizeof(bss_cfg->rates) - rate_len);
+		rate_len += MIN(ext_rate_ie->len,
+				(sizeof(bss_cfg->rates) - rate_len));
+	}
+	DBG_HEXDUMP(MCMD_D, "rates", bss_cfg->rates, sizeof(bss_cfg->rates));
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+/**
+ * @brief initialize AP or GO bss config
+ *
+ * @param priv            A pointer to moal private structure
+ * @param params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_beacon_config(moal_private *priv,
+			    struct cfg80211_ap_settings *params)
+#else
+/**
+ * @brief initialize AP or GO bss config
+ *
+ * @param priv            A pointer to moal private structure
+ * @param params          A pointer to beacon_parameters structure
+ * @return                0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_beacon_config(moal_private *priv,
+			    struct beacon_parameters *params)
+#endif
+{
+	struct wiphy *wiphy = NULL;
+	const t_u8 *ie = NULL;
+	int ret = 0, ie_len;
+	mlan_uap_bss_param *sys_config = NULL;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	int i = 0;
+#else
+	t_u8 wpa_ies;
+	const t_u8 *ssid_ie = NULL;
+	struct ieee80211_mgmt *head = NULL;
+	t_u16 capab_info = 0;
+#endif
+	t_u8 rates_bg[13] = { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18,
+		0x24, 0x30, 0x48, 0x60, 0x6c, 0x00
+	};
+	t_u8 rates_a[9] = { 0x8c, 0x12, 0x98, 0x24, 0xb0,
+		0x48, 0x60, 0x6c, 0x00
+	};
+#ifdef WIFI_DIRECT_SUPPORT
+	t_u8 rates_wfd[9] = { 0x8c, 0x12, 0x18, 0x24, 0x30,
+		0x48, 0x60, 0x6c, 0x00
+	};
+#endif
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+	t_u8 enable_11n = MTRUE;
+	t_u16 ht_cap = 0;
+	t_u8 enable_11ac = MFALSE;
+	t_u8 vht20_40 = MFALSE;
+	IEEEtypes_VHTCap_t *vhtcap_ie = NULL;
+	IEEEtypes_VHTOprat_t *vhtopr_ie = NULL;
+	IEEEtypes_HECap_t *hecap_ie = NULL;
+	t_u8 enable_11ax = MFALSE;
+	t_u8 *wapi_ie = NULL;
+	int wapi_ie_len = 0;
+#ifdef WIFI_DIRECT_SUPPORT
+	int GoAgeoutTime = priv->phandle->params.GoAgeoutTime;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	mlan_ds_11h_chan_nop_info chan_nop_info;
+	Band_Config_t bandcfg;
+#endif
+	ENTER();
+
+	if (!params) {
+		ret = -EFAULT;
+		goto done;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	ie = ((struct cfg80211_ap_settings *)params)->beacon.tail;
+	ie_len = ((struct cfg80211_ap_settings *)params)->beacon.tail_len;
+#else
+	ie = ((struct beacon_parameters *)params)->tail;
+	ie_len = ((struct beacon_parameters *)params)->tail_len;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	wapi_ie = (t_u8 *)woal_parse_ie_tlv(params->beacon.tail,
+					    params->beacon.tail_len, WAPI_IE);
+#else
+	wapi_ie = (t_u8 *)woal_parse_ie_tlv(params->tail, params->tail_len,
+					    WAPI_IE);
+#endif
+	if (wapi_ie) {
+		wapi_ie_len = *(wapi_ie + 1) + 2;
+		if (MLAN_STATUS_FAILURE ==
+		    woal_set_get_gen_ie(priv, MLAN_ACT_SET, wapi_ie,
+					&wapi_ie_len, MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Failed to set wapi ie\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	wiphy = priv->phandle->wiphy;
+	if (priv->bss_type != MLAN_BSS_TYPE_UAP
+#ifdef WIFI_DIRECT_SUPPORT
+	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
+#endif
+		) {
+		ret = -EFAULT;
+		goto done;
+	}
+	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_config) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Initialize the uap bss values which are uploaded from firmware */
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (priv->phandle->params.uap_max_sta)
+		sys_config->max_sta_count = priv->phandle->params.uap_max_sta;
+
+	/* Setting the default values */
+	sys_config->channel = 6;
+	sys_config->preamble_type = 0;
+	sys_config->mgmt_ie_passthru_mask = priv->mgmt_subtype_mask;
+	moal_memcpy_ext(priv->phandle, sys_config->mac_addr, priv->current_addr,
+			ETH_ALEN, sizeof(sys_config->mac_addr));
+
+#ifdef WIFI_DIRECT_SUPPORT
+	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && GoAgeoutTime) {
+		sys_config->sta_ageout_timer = GoAgeoutTime;
+		sys_config->ps_sta_ageout_timer = GoAgeoutTime;
+	}
+#endif
+	/* Set frag_threshold, rts_threshold, and retry limit */
+	sys_config->frag_threshold = wiphy->frag_threshold;
+	sys_config->rts_threshold = wiphy->rts_threshold;
+	sys_config->retry_limit = wiphy->retry_long;
+	if (sys_config->frag_threshold == (t_u16)MLAN_FRAG_RTS_DISABLED) {
+		sys_config->frag_threshold = MLAN_FRAG_MAX_VALUE;
+	}
+	if (sys_config->rts_threshold == (t_u16)MLAN_FRAG_RTS_DISABLED) {
+		sys_config->rts_threshold = MLAN_RTS_MAX_VALUE;
+	}
+
+	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		if (params->beacon_interval)
+			sys_config->beacon_period = params->beacon_interval;
+#else
+		if (params->interval)
+			sys_config->beacon_period = params->interval;
+#endif
+		if (params->dtim_period)
+			sys_config->dtim_period = params->dtim_period;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	/** back up ap's channel */
+	moal_memcpy_ext(priv->phandle, &priv->chan, &params->chandef,
+			sizeof(struct cfg80211_chan_def), sizeof(priv->chan));
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	if (priv->phandle->usr_nop_period_sec) {
+		PRINTM(MCMND, "Checking if AP's channel %d is under NOP\n",
+		       priv->channel);
+		woal_convert_chan_to_bandconfig(priv, &bandcfg,
+						&params->chandef);
+		memset(&chan_nop_info, 0, sizeof(chan_nop_info));
+		chan_nop_info.curr_chan = priv->channel;
+		chan_nop_info.chan_width = bandcfg.chanWidth;
+		if (params->chandef.width >= NL80211_CHAN_WIDTH_20)
+			chan_nop_info.new_chan.is_11n_enabled = MTRUE;
+		chan_nop_info.new_chan.bandcfg = bandcfg;
+		woal_uap_get_channel_nop_info(priv, MOAL_IOCTL_WAIT,
+					      &chan_nop_info);
+		if (chan_nop_info.chan_under_nop) {
+			PRINTM(MCMND,
+			       "cfg80211: Channel %d is under NOP, New channel=%d\n",
+			       priv->channel, chan_nop_info.new_chan.channel);
+			priv->chan_under_nop = chan_nop_info.chan_under_nop;
+			priv->channel = chan_nop_info.new_chan.channel;
+			woal_chandef_create(priv, &priv->chan,
+					    &chan_nop_info.new_chan);
+		}
+	}
+#endif
+
+	if (priv->channel) {
+		memset(sys_config->rates, 0, sizeof(sys_config->rates));
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		switch (priv->chan.width) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+		case NL80211_CHAN_WIDTH_5:
+		case NL80211_CHAN_WIDTH_10:
+#endif
+		case NL80211_CHAN_WIDTH_20_NOHT:
+			enable_11n = MFALSE;
+			break;
+		case NL80211_CHAN_WIDTH_20:
+			break;
+		case NL80211_CHAN_WIDTH_40:
+			if (priv->chan.center_freq1 <
+			    priv->chan.chan->center_freq)
+				chan2Offset = SEC_CHAN_BELOW;
+			else
+				chan2Offset = SEC_CHAN_ABOVE;
+			break;
+		case NL80211_CHAN_WIDTH_80:
+		case NL80211_CHAN_WIDTH_80P80:
+		case NL80211_CHAN_WIDTH_160:
+			chan2Offset =
+				woal_get_second_channel_offset(priv,
+							       priv->channel);
+			break;
+		default:
+			PRINTM(MWARN, "Unknown channel width: %d\n",
+			       priv->chan.width);
+			break;
+		}
+#else
+		switch (params->channel_type) {
+		case NL80211_CHAN_NO_HT:
+			enable_11n = MFALSE;
+			break;
+		case NL80211_CHAN_HT20:
+			break;
+		case NL80211_CHAN_HT40PLUS:
+			chan2Offset = SEC_CHAN_ABOVE;
+			break;
+		case NL80211_CHAN_HT40MINUS:
+			chan2Offset = SEC_CHAN_BELOW;
+			break;
+		default:
+			PRINTM(MWARN, "Unknown channel type: %d\n",
+			       params->channel_type);
+			break;
+		}
+#endif
+#endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
+
+		sys_config->channel = priv->channel;
+		if (priv->channel <= MAX_BG_CHANNEL) {
+			sys_config->bandcfg.chanBand = BAND_2GHZ;
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				moal_memcpy_ext(priv->phandle,
+						sys_config->rates, rates_wfd,
+						sizeof(rates_wfd),
+						sizeof(sys_config->rates));
+			else
+#endif
+				moal_memcpy_ext(priv->phandle,
+						sys_config->rates, rates_bg,
+						sizeof(rates_bg),
+						sizeof(sys_config->rates));
+		} else {
+			sys_config->bandcfg.chanBand = BAND_5GHZ;
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+			chan2Offset =
+				woal_get_second_channel_offset(priv,
+							       priv->channel);
+#endif
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+			/* Force enable 40MHZ on WFD interface */
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				chan2Offset =
+					woal_get_second_channel_offset(priv,
+								       priv->
+								       channel);
+#endif
+#endif
+#ifdef WIFI_DIRECT_SUPPORT
+			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
+				moal_memcpy_ext(priv->phandle,
+						sys_config->rates, rates_wfd,
+						sizeof(rates_wfd),
+						sizeof(sys_config->rates));
+			else
+#endif
+				moal_memcpy_ext(priv->phandle,
+						sys_config->rates, rates_a,
+						sizeof(rates_a),
+						sizeof(sys_config->rates));
+		}
+
+		/* Replaced with rate from userspace, if exist */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+		woal_set_uap_rates(priv, sys_config, params->beacon.head,
+				   params->beacon.head_len, params->beacon.tail,
+				   params->beacon.tail_len);
+#else
+		woal_set_uap_rates(priv, sys_config, params->head,
+				   params->head_len, params->tail,
+				   params->tail_len);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		enable_11ac = woal_check_11ac_capability(priv,
+							 sys_config->bandcfg.
+							 chanBand, params);
+		if (enable_11ac && ((priv->chan.width == NL80211_CHAN_WIDTH_20)
+				    || (priv->chan.width ==
+					NL80211_CHAN_WIDTH_40)))
+			vht20_40 = MTRUE;
+#else
+		enable_11ac = woal_check_11ac_capability(priv,
+							 sys_config->bandcfg.
+							 chanBand);
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+		enable_11ax =
+			woal_check_11ax_capability(priv,
+						   sys_config->bandcfg.chanBand,
+						   params);
+#endif
+
+		/* Disable GreenField by default */
+		sys_config->ht_cap_info = 0x10c;
+		if (enable_11n)
+			sys_config->ht_cap_info |= 0x20;
+		if (chan2Offset) {
+			sys_config->bandcfg.chan2Offset = chan2Offset;
+			sys_config->ht_cap_info |= 0x1042;
+			sys_config->ampdu_param = 3;
+		} else {
+			sys_config->bandcfg.chan2Offset = 0;
+		}
+		ht_cap = woal_get_htcap_info(ie, ie_len);
+		if (ht_cap) {
+			if (sys_config->bandcfg.chanBand == BAND_2GHZ)
+				sys_config->ht_cap_info =
+					(ht_cap &
+					 (wiphy->bands[IEEE80211_BAND_2GHZ]
+					  ->ht_cap.cap & 0x13ff)) | 0x0c;
+			else
+				sys_config->ht_cap_info =
+					(ht_cap &
+					 (wiphy->bands[IEEE80211_BAND_5GHZ]
+					  ->ht_cap.cap & 0x13ff)) | 0x0c;
+		}
+		PRINTM(MCMND,
+		       "11n=%d, ht_cap=0x%x, channel=%d, bandcfg:chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x scanMode=0x%x\n",
+		       enable_11n, sys_config->ht_cap_info,
+		       priv->channel, sys_config->bandcfg.chanBand,
+		       sys_config->bandcfg.chanWidth,
+		       sys_config->bandcfg.chan2Offset,
+		       sys_config->bandcfg.scanMode);
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+	if (!params->ssid || !params->ssid_len) {
+		ret = -EINVAL;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, sys_config->ssid.ssid, params->ssid,
+			MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len),
+			sizeof(sys_config->ssid.ssid));
+	sys_config->ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len);
+	/**
+	 * hidden_ssid=0: broadcast SSID in beacons.
+	 * hidden_ssid=1: send empty SSID (length=0) in beacon.
+	 * hidden_ssid=2: clear SSID (ACSII 0), but keep the original length
+	 */
+	if (!params->hidden_ssid)
+		sys_config->bcast_ssid_ctl = 1;
+	else if (params->hidden_ssid == 1)
+		sys_config->bcast_ssid_ctl = 0;
+	else if (params->hidden_ssid == 2)
+		sys_config->bcast_ssid_ctl = 2;
+	switch (params->auth_type) {
+	case NL80211_AUTHTYPE_SHARED_KEY:
+		sys_config->auth_mode = MLAN_AUTH_MODE_SHARED;
+		break;
+	case NL80211_AUTHTYPE_AUTOMATIC:
+		sys_config->auth_mode = MLAN_AUTH_MODE_AUTO;
+		break;
+	case NL80211_AUTHTYPE_OPEN_SYSTEM:
+	default:
+		sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
+		break;
+	}
+
+	sys_config->protocol = PROTOCOL_NO_SECURITY;
+	if ((params->crypto.wpa_versions & NL80211_WPA_VERSION_1) &&
+	    (params->crypto.wpa_versions & NL80211_WPA_VERSION_2))
+		sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
+	else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+		sys_config->protocol = PROTOCOL_WPA2;
+	else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+		sys_config->protocol = PROTOCOL_WPA;
+	if (params->crypto.n_akm_suites ||
+	    (params->privacy && params->crypto.wpa_versions))
+		woal_find_wpa_ies(ie, ie_len, sys_config);
+	for (i = 0; i < params->crypto.n_akm_suites; i++) {
+		switch (params->crypto.akm_suites[i]) {
+		case WLAN_AKM_SUITE_8021X:
+			sys_config->key_mgmt |= KEY_MGMT_EAP;
+			break;
+		case WLAN_AKM_SUITE_PSK:
+			sys_config->key_mgmt |= KEY_MGMT_PSK;
+			break;
+		}
+	}
+	sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
+	sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
+	for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
+		switch (params->crypto.ciphers_pairwise[i]) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+				sys_config->wpa_cfg.pairwise_cipher_wpa |=
+					CIPHER_TKIP;
+			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+				sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
+					CIPHER_TKIP;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+				sys_config->wpa_cfg.pairwise_cipher_wpa |=
+					CIPHER_AES_CCMP;
+			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+				sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
+					CIPHER_AES_CCMP;
+			break;
+		case WLAN_CIPHER_SUITE_SMS4:
+			sys_config->protocol = PROTOCOL_WAPI;
+			break;
+		}
+	}
+	switch (params->crypto.cipher_group) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) ||
+		    (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) {
+			sys_config->protocol = PROTOCOL_STATIC_WEP;
+			sys_config->key_mgmt = KEY_MGMT_NONE;
+			sys_config->wpa_cfg.length = 0;
+			moal_memcpy_ext(priv->phandle,
+					&sys_config->wep_cfg.key0,
+					&priv->uap_wep_key[0], sizeof(wep_key),
+					sizeof(sys_config->wep_cfg.key0));
+			moal_memcpy_ext(priv->phandle,
+					&sys_config->wep_cfg.key1,
+					&priv->uap_wep_key[1], sizeof(wep_key),
+					sizeof(sys_config->wep_cfg.key1));
+			moal_memcpy_ext(priv->phandle,
+					&sys_config->wep_cfg.key2,
+					&priv->uap_wep_key[2], sizeof(wep_key),
+					sizeof(sys_config->wep_cfg.key2));
+			moal_memcpy_ext(priv->phandle,
+					&sys_config->wep_cfg.key3,
+					&priv->uap_wep_key[3], sizeof(wep_key),
+					sizeof(sys_config->wep_cfg.key3));
+		}
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+		break;
+	case WLAN_CIPHER_SUITE_SMS4:
+		sys_config->protocol = PROTOCOL_WAPI;
+		break;
+	}
+#else
+/* Since in Android ICS 4.0.1's wpa_supplicant, there is no way to set ssid
+ * when GO (AP) starts up, so get it from beacon head parameter
+ * TODO: right now use hard code
+ * 24 -- ieee80211 header lenth, 12 -- fixed element length for beacon
+ */
+#define BEACON_IE_OFFSET 36
+	/* Find SSID in head
+	 * SSID IE id: 0, right now use hard code
+	 */
+	ssid_ie = woal_parse_ie_tlv(params->head + BEACON_IE_OFFSET,
+				    params->head_len - BEACON_IE_OFFSET, 0);
+
+	if (!ssid_ie) {
+		PRINTM(MERROR, "No ssid IE found.\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (*(ssid_ie + 1) > 32) {
+		PRINTM(MERROR, "ssid len error: %d\n", *(ssid_ie + 1));
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, sys_config->ssid.ssid, ssid_ie + 2,
+			*(ssid_ie + 1), sizeof(sys_config->ssid.ssid));
+	sys_config->ssid.ssid_len = *(ssid_ie + 1);
+	head = (struct ieee80211_mgmt *)params->head;
+
+	capab_info = le16_to_cpu(head->u.beacon.capab_info);
+	PRINTM(MIOCTL, "capab_info=0x%x\n", head->u.beacon.capab_info);
+	sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
+	/** For ICS, we don't support OPEN mode */
+	if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) ||
+	    (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) {
+		sys_config->protocol = PROTOCOL_STATIC_WEP;
+		sys_config->key_mgmt = KEY_MGMT_NONE;
+		sys_config->.wpa_cfg.length = 0;
+		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key0,
+				&priv->uap_wep_key[0], sizeof(wep_key),
+				sizeof(sys_config->wep_cfg.key0));
+		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key1,
+				&priv->uap_wep_key[1], sizeof(wep_key),
+				sizeof(sys_config->wep_cfg.key1));
+		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key2,
+				&priv->uap_wep_key[2], sizeof(wep_key),
+				sizeof(sys_config->wep_cfg.key2));
+		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key3,
+				&priv->uap_wep_key[3], sizeof(wep_key),
+				sizeof(sys_config->wep_cfg.key3));
+	} else {
+		/** Get cipher and key_mgmt from RSN/WPA IE */
+		if (capab_info & WLAN_CAPABILITY_PRIVACY) {
+			wpa_ies =
+				woal_find_wpa_ies(params->tail,
+						  params->tail_len, sys_config);
+			if (wpa_ies == MFALSE) {
+				/* hard code setting to wpa2-psk */
+				sys_config->protocol = PROTOCOL_WPA2;
+				sys_config->key_mgmt = KEY_MGMT_PSK;
+				sys_config->wpa_cfg.pairwise_cipher_wpa2 =
+					CIPHER_AES_CCMP;
+				sys_config->wpa_cfg.group_cipher =
+					CIPHER_AES_CCMP;
+			}
+		}
+	}
+#endif
+
+	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
+		/*find and set wmm ie */
+		woal_set_wmm_ies(priv, ie, ie_len, sys_config);
+	}
+	/* If the security mode is configured as WEP or WPA-PSK,
+	 * it will disable 11n automatically, and if configured as
+	 * open(off) or wpa2-psk, it will automatically enable 11n */
+	if ((sys_config->protocol == PROTOCOL_STATIC_WEP) ||
+	    (sys_config->protocol == PROTOCOL_WPA))
+		enable_11n = MFALSE;
+	if (!enable_11n) {
+		woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, ht_cap,
+				       MFALSE);
+		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_DISABLE);
+	} else {
+		woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, ht_cap,
+				       MTRUE);
+		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_ENABLE);
+		woal_set_get_tx_bf_cap(priv, MLAN_ACT_GET,
+				       &sys_config->tx_bf_cap);
+	}
+	if (enable_11ac && enable_11n) {
+		vhtcap_ie = woal_get_vhtcap_info(ie, ie_len);
+		vhtopr_ie = woal_get_vht_oprat_ie(ie, ie_len);
+		//Enable VHT80
+		if (vhtopr_ie && vhtopr_ie->chan_width)
+			vht20_40 = 0;
+		woal_uap_set_11ac_status(priv, MLAN_ACT_ENABLE,
+					 vht20_40, vhtcap_ie);
+	} else {
+		woal_uap_set_11ac_status(priv, MLAN_ACT_DISABLE,
+					 vht20_40, NULL);
+	}
+	if (enable_11ax && enable_11n) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+		hecap_ie =
+			(IEEEtypes_HECap_t *) woal_parse_ext_ie_tlv(ie, ie_len,
+								    HE_CAPABILITY);
+#endif
+		woal_uap_set_11ax_status(priv, MLAN_ACT_ENABLE,
+					 sys_config->bandcfg.chanBand,
+					 hecap_ie);
+	} else
+		woal_uap_set_11ax_status(priv, MLAN_ACT_DISABLE,
+					 sys_config->bandcfg.chanBand, NULL);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	if (params->inactivity_timeout) {
+		sys_config->sta_ageout_timer = params->inactivity_timeout * 10;
+		sys_config->ps_sta_ageout_timer =
+			params->inactivity_timeout * 10;
+	}
+	PRINTM(MIOCTL, "inactivity_timeout=%d\n", params->inactivity_timeout);
+	PRINTM(MIOCTL, "sta_ageout_timer=%d ps_sta_ageout_timer=%d\n",
+	       sys_config->sta_ageout_timer, sys_config->ps_sta_ageout_timer);
+#endif
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+    /** Set wacp_mode for uAP/P2P-GO */
+	if (priv->phandle->params.wacp_mode) {
+		PRINTM(MIOCTL, "wacp_mode: %d\n",
+		       priv->phandle->params.wacp_mode);
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wacp_mode(priv, MOAL_IOCTL_WAIT)) {
+			PRINTM(MERROR, "Set wacp_mode failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	woal_enable_dfs_support(priv, &priv->chan);
+#endif
+done:
+	kfree(sys_config);
+	LEAVE();
+	return ret;
+}
+
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+/**
+ * @brief Callback function for virtual interface
+ *      setup
+ *
+ *  @param dev    A pointer to structure net_device
+ *
+ *  @return       N/A
+ */
+static void
+woal_virt_if_setup(struct net_device *dev)
+{
+	ENTER();
+	ether_setup(dev);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)
+	dev->needs_free_netdev = true;
+#else
+	dev->destructor = free_netdev;
+#endif
+	LEAVE();
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+/**
+ * @brief This function adds a new interface. It will
+ *        allocate, initialize and register the device.
+ *
+ *  @param handle           A pointer to moal_handle structure
+ *  @param bss_index        BSS index number
+ *  @param name_assign_type Interface name assignment type
+ *  @param bss_type         BSS type
+ *
+ *  @return                 A pointer to the new priv structure
+ */
+static moal_private *
+woal_alloc_virt_interface(moal_handle *handle, t_u8 bss_index,
+			  unsigned char name_assign_type,
+			  t_u8 bss_type, const char *name)
+#else
+/**
+ * @brief This function adds a new interface. It will
+ *        allocate, initialize and register the device.
+ *
+ *  @param handle    A pointer to moal_handle structure
+ *  @param bss_index BSS index number
+ *  @param bss_type  BSS type
+ *
+ *  @return          A pointer to the new priv structure
+ */
+moal_private *
+woal_alloc_virt_interface(moal_handle *handle, t_u8 bss_index, t_u8 bss_type,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+			  const
+#endif
+			  char *name)
+#endif
+{
+	struct net_device *dev = NULL;
+	moal_private *priv = NULL;
+	ENTER();
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+#ifndef MAX_WMM_QUEUE
+#define MAX_WMM_QUEUE 4
+#endif
+	/* Allocate an Ethernet device */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	dev = alloc_netdev_mq(sizeof(moal_private), name, name_assign_type,
+			      woal_virt_if_setup, MAX_WMM_QUEUE);
+#else
+	dev = alloc_netdev_mq(sizeof(moal_private), name, NET_NAME_UNKNOWN,
+			      woal_virt_if_setup, MAX_WMM_QUEUE);
+#endif
+#else
+	dev = alloc_netdev_mq(sizeof(moal_private), name, woal_virt_if_setup,
+			      MAX_WMM_QUEUE);
+#endif
+#else
+	dev = alloc_netdev(sizeof(moal_private), name, woal_virt_if_setup);
+#endif
+	if (!dev) {
+		PRINTM(MFATAL, "Init virtual ethernet device failed\n");
+		goto error;
+	}
+	/* Allocate device name */
+	if ((dev_alloc_name(dev, name) < 0)) {
+		PRINTM(MERROR, "Could not allocate device name\n");
+		goto error;
+	}
+
+	priv = (moal_private *)netdev_priv(dev);
+	/* Save the priv to handle */
+	handle->priv[bss_index] = priv;
+
+	/* Use the same handle structure */
+	priv->phandle = handle;
+	priv->netdev = dev;
+	priv->bss_index = bss_index;
+	priv->bss_type = bss_type;
+	priv->bss_role = MLAN_BSS_ROLE_STA;
+
+	INIT_LIST_HEAD(&priv->tcp_sess_queue);
+	spin_lock_init(&priv->tcp_sess_lock);
+
+	INIT_LIST_HEAD(&priv->tx_stat_queue);
+	spin_lock_init(&priv->tx_stat_lock);
+	spin_lock_init(&priv->connect_lock);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	SET_MODULE_OWNER(dev);
+#endif
+
+	PRINTM(MCMND, "Alloc virtual interface%s\n", dev->name);
+
+	LEAVE();
+	return priv;
+error:
+	if (dev)
+		free_netdev(dev);
+	LEAVE();
+	return NULL;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+/**
+ * @brief Request the driver to add a virtual interface
+ *
+ * @param wiphy             A pointer to wiphy structure
+ * @param name              Virtual interface name
+ * @param name_assign_type  Interface name assignment type
+ * @param type              Virtual interface type
+ * @param flags             Flags for the virtual interface
+ * @param params            A pointer to vif_params structure
+ * @param new_dev		    new net_device to return
+ *
+ * @return                  0 -- success, otherwise fail
+ */
+static int
+woal_cfg80211_add_virt_if(struct wiphy *wiphy, const char *name,
+			  unsigned char name_assign_type,
+			  enum nl80211_iftype type, u32 *flags,
+			  struct vif_params *params,
+			  struct net_device **new_dev)
+#else
+/**
+ * @brief Request the driver to add a virtual interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ * @param type            Virtual interface type
+ * @param flags           Flags for the virtual interface
+ * @param params          A pointer to vif_params structure
+ * @param new_dev		  new net_device to return
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_add_virt_if(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+			  const
+#endif
+			  char *name,
+			  enum nl80211_iftype type, u32 *flags,
+			  struct vif_params *params,
+			  struct net_device **new_dev)
+#endif
+{
+	int ret = 0;
+	struct net_device *ndev = NULL;
+	moal_private *priv = NULL, *new_priv = NULL;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	struct wireless_dev *wdev = NULL;
+	moal_private *vir_priv;
+	int i = 0;
+
+	ENTER();
+	ASSERT_RTNL();
+	priv = woal_get_vir_priv_bss_type(handle, MLAN_BSS_TYPE_WIFIDIRECT);
+	if (priv && priv->bss_role == MLAN_BSS_ROLE_UAP &&
+	    priv->bss_started == MTRUE) {
+		if (handle->pref_mac)
+			handle = (moal_handle *)handle->pref_mac;
+	}
+	priv = (moal_private *)woal_get_priv_bss_type(handle,
+						      MLAN_BSS_TYPE_WIFIDIRECT);
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) {
+		PRINTM(MERROR, "max virtual interface limit reached\n");
+		for (i = 0; i < priv->phandle->priv_num; i++) {
+			vir_priv = priv->phandle->priv[i];
+			if (vir_priv->bss_virtual) {
+				woal_cfg80211_del_virt_if(wiphy,
+							  vir_priv->netdev);
+				break;
+			}
+		}
+		if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) {
+			LEAVE();
+			return -ENOMEM;
+		}
+	}
+	PRINTM(MMSG, "Add virtual interface %s\n", name);
+	if ((type != NL80211_IFTYPE_P2P_CLIENT) &&
+	    (type != NL80211_IFTYPE_P2P_GO)) {
+		PRINTM(MERROR, "Invalid iftype: %d\n", type);
+		LEAVE();
+		return -EINVAL;
+	}
+
+	handle = priv->phandle;
+	/* Cancel previous scan req */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+	new_priv = woal_alloc_virt_interface(handle, handle->priv_num,
+					     name_assign_type,
+					     MLAN_BSS_TYPE_WIFIDIRECT, name);
+#else
+	new_priv = woal_alloc_virt_interface(handle, handle->priv_num,
+					     MLAN_BSS_TYPE_WIFIDIRECT, name);
+#endif
+	if (!new_priv) {
+		PRINTM(MERROR, "Add virtual interface fail.");
+		LEAVE();
+		return -EFAULT;
+	}
+	handle->priv_num++;
+
+	wdev = (struct wireless_dev *)&new_priv->w_dev;
+	memset(wdev, 0, sizeof(struct wireless_dev));
+	ndev = new_priv->netdev;
+	SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
+	ndev->ieee80211_ptr = wdev;
+	wdev->iftype = type;
+	wdev->wiphy = wiphy;
+	new_priv->wdev = wdev;
+	new_priv->bss_virtual = MTRUE;
+	new_priv->pa_netdev = priv->netdev;
+
+	/* Create workqueue for main process */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+	new_priv->mclist_workqueue =
+		alloc_workqueue("MCLIST_WORK_QUEUE",
+				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+#else
+	new_priv->mclist_workqueue = create_workqueue("MCLIST_WORK_QUEUE");
+#endif
+	if (!new_priv->mclist_workqueue) {
+		PRINTM(MERROR, "cannot alloc mclist workqueue \n");
+		return -EFAULT;
+	}
+	MLAN_INIT_WORK(&new_priv->mclist_work, woal_mclist_work_queue);
+
+	woal_init_sta_dev(ndev, new_priv);
+
+	/* Initialize priv structure */
+	woal_init_priv(new_priv, MOAL_IOCTL_WAIT);
+	/** Init to GO/CLIENT mode */
+	if (type == NL80211_IFTYPE_P2P_CLIENT)
+		woal_cfg80211_init_p2p_client(new_priv);
+	else if (type == NL80211_IFTYPE_P2P_GO)
+		woal_cfg80211_init_p2p_go(new_priv);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
+	ret = cfg80211_register_netdevice(ndev);
+#else
+	ret = register_netdevice(ndev);
+#endif
+	if (ret) {
+		handle->priv[new_priv->bss_index] = NULL;
+		handle->priv_num--;
+		if (ndev->reg_state == NETREG_REGISTERED) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
+			cfg80211_unregister_netdevice(ndev);
+#else
+			unregister_netdevice(ndev);
+#endif
+			free_netdev(ndev);
+			ndev = NULL;
+		}
+		PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
+		goto done;
+	}
+	netif_carrier_off(ndev);
+	woal_stop_queue(ndev);
+	if (new_dev)
+		*new_dev = ndev;
+#ifdef CONFIG_PROC_FS
+	woal_create_proc_entry(new_priv);
+	woal_debug_entry(new_priv);
+#endif /* CONFIG_PROC_FS */
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Notify mlan BSS will be removed.
+ *
+ *  @param priv          A pointer to moal_private structure
+ *
+ *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
+ * otherwise fail
+ */
+static mlan_status
+woal_bss_remove(moal_private *priv)
+{
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_bss *bss = NULL;
+	mlan_status status;
+
+	ENTER();
+
+	/* Allocate an IOCTL request buffer */
+	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		status = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_REMOVE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return status;
+}
+
+/**
+ *  @brief This function removes an virtual interface.
+ *
+ *  @param wiphy    A pointer to the wiphy structure
+ *  @param dev      A pointer to the net_device structure
+ *
+ *  @return         0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev)
+{
+	int ret = 0;
+	int i = 0;
+	moal_private *priv = NULL;
+	moal_private *vir_priv = NULL;
+	moal_private *remain_priv = NULL;
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	t_u8 find_bss = MFALSE;
+
+	for (i = 0; i < handle->priv_num; i++) {
+		vir_priv = handle->priv[i];
+		if (vir_priv) {
+			if (vir_priv->netdev == dev) {
+				find_bss = MTRUE;
+				PRINTM(MMSG,
+				       "Del virtual interface %s, index=%d\n",
+				       dev->name, i);
+				break;
+			}
+		}
+	}
+	if (!find_bss) {
+		/* Switch to the other MAC */
+		if (handle->pref_mac)
+			handle = (moal_handle *)handle->pref_mac;
+		for (i = 0; i < handle->priv_num; i++) {
+			vir_priv = handle->priv[i];
+			if (vir_priv) {
+				if (vir_priv->netdev == dev) {
+					find_bss = MTRUE;
+					PRINTM(MMSG,
+					       "Del virtual interface %s, index=%d\n",
+					       dev->name, i);
+					break;
+				}
+			}
+		}
+	}
+
+	priv = (moal_private *)woal_get_priv_bss_type(handle,
+						      MLAN_BSS_TYPE_WIFIDIRECT);
+	if (!priv)
+		return ret;
+	if (vir_priv && vir_priv->netdev == dev) {
+		woal_stop_queue(dev);
+		netif_carrier_off(dev);
+		netif_device_detach(dev);
+		if (handle->is_remain_timer_set) {
+			woal_cancel_timer(&handle->remain_timer);
+			woal_remain_timer_func(handle);
+		}
+
+		/*** cancel pending scan */
+		woal_cancel_scan(vir_priv, MOAL_IOCTL_WAIT);
+
+		woal_flush_tx_stat_queue(vir_priv);
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+		/* cancel previous remain on channel to avoid firmware hang */
+		if (priv->phandle->remain_on_channel) {
+			t_u8 channel_status;
+			remain_priv =
+				priv->phandle->priv[priv->phandle->
+						    remain_bss_index];
+			if (remain_priv) {
+				if (woal_cfg80211_remain_on_channel_cfg
+				    (remain_priv, MOAL_IOCTL_WAIT, MTRUE,
+				     &channel_status, NULL, 0, 0))
+					PRINTM(MERROR,
+					       "del_virt_if: Fail to cancel remain on channel\n");
+
+				if (priv->phandle->cookie) {
+					cfg80211_remain_on_channel_expired(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+										  remain_priv->
+										  netdev,
+#else
+										  remain_priv->
+										  wdev,
+#endif
+										  priv->
+										  phandle->
+										  cookie,
+										  &priv->
+										  phandle->
+										  chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+										  priv->
+										  phandle->
+										  channel_type,
+#endif
+										  GFP_ATOMIC);
+					priv->phandle->cookie = 0;
+				}
+				priv->phandle->remain_on_channel = MFALSE;
+			}
+		}
+#endif
+		if (vir_priv->mclist_workqueue) {
+			flush_workqueue(vir_priv->mclist_workqueue);
+			destroy_workqueue(vir_priv->mclist_workqueue);
+			vir_priv->mclist_workqueue = NULL;
+		}
+		woal_clear_all_mgmt_ies(vir_priv, MOAL_IOCTL_WAIT);
+		woal_cfg80211_deinit_p2p(vir_priv);
+		woal_bss_remove(vir_priv);
+#ifdef CONFIG_PROC_FS
+		/* Remove proc debug */
+		woal_debug_remove(vir_priv);
+		woal_proc_remove(vir_priv);
+#endif /* CONFIG_PROC_FS */
+		/* Last reference is our one */
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+		PRINTM(MINFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
+#else
+		PRINTM(MINFO, "refcnt = %d\n", netdev_refcnt_read(dev));
+#endif
+		PRINTM(MINFO, "netdev_finish_unregister: %s\n", dev->name);
+		/* Clear the priv in handle */
+		vir_priv->phandle->priv[vir_priv->bss_index] = NULL;
+		priv->phandle->priv_num--;
+		if (dev->reg_state == NETREG_REGISTERED)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
+			cfg80211_unregister_netdevice(dev);
+#else
+			unregister_netdevice(dev);
+#endif
+	}
+	return ret;
+}
+#endif
+#endif
+
+#if defined(WIFI_DIRECT_SUPPORT)
+/**
+ *  @brief This function removes an virtual interface.
+ *
+ *  @param handle    A pointer to the moal_handle structure
+ *
+ *  @return        N/A
+ */
+void
+woal_remove_virtual_interface(moal_handle *handle)
+{
+#ifdef WIFI_DIRECT_SUPPORT
+	moal_private *priv = NULL;
+	int vir_intf = 0;
+	int i = 0;
+#endif
+	ENTER();
+	rtnl_lock();
+#ifdef WIFI_DIRECT_SUPPORT
+	for (i = 0; i < handle->priv_num; i++) {
+		priv = handle->priv[i];
+		if (priv) {
+			if (priv->bss_virtual) {
+				PRINTM(MCMND, "Remove virtual interface %s\n",
+				       priv->netdev->name);
+#ifdef CONFIG_PROC_FS
+				/* Remove proc debug */
+				woal_debug_remove(priv);
+				woal_proc_remove(priv);
+#endif /* CONFIG_PROC_FS */
+				netif_device_detach(priv->netdev);
+				if (priv->netdev->reg_state ==
+				    NETREG_REGISTERED)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
+					cfg80211_unregister_netdevice(priv->
+								      netdev);
+#else
+					unregister_netdevice(priv->netdev);
+#endif
+				handle->priv[i] = NULL;
+				vir_intf++;
+			}
+		}
+	}
+#endif
+	rtnl_unlock();
+#ifdef WIFI_DIRECT_SUPPORT
+	handle->priv_num -= vir_intf;
+#endif
+	LEAVE();
+}
+#endif
+
+/**
+ *  @brief This function check if uap interface is ready
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ *
+ *  @return        MTRUE/MFALSE;
+ */
+static t_u8
+woal_uap_interface_ready(struct wiphy *wiphy, char *name,
+			 struct net_device **new_dev)
+{
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	moal_private *priv = NULL;
+	int i;
+
+	for (i = 0; i < handle->priv_num; i++) {
+		priv = handle->priv[i];
+		if (priv && (priv->bss_type == MLAN_BSS_TYPE_UAP) &&
+		    !strcmp(priv->netdev->name, name)) {
+			priv->wdev->iftype = NL80211_IFTYPE_AP;
+			*new_dev = priv->netdev;
+			break;
+		}
+	}
+	if (priv && *new_dev)
+		return MTRUE;
+	else
+		return MFALSE;
+}
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+/**
+ * @brief Request the driver to add a virtual interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ * @param type            Virtual interface type
+ * @param flags           Flags for the virtual interface
+ * @param params          A pointer to vif_params structure
+ *
+ * @return                A pointer to net_device -- success, otherwise null
+ */
+struct net_device *
+woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
+			       char *name,
+			       enum nl80211_iftype type,
+			       u32 *flags, struct vif_params *params)
+#else
+/**
+ * @brief Request the driver to add a virtual interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ * @param type            Virtual interface type
+ * @param flags           Flags for the virtual interface
+ * @param params          A pointer to vif_params structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
+			       enum nl80211_iftype type, u32 *flags,
+			       struct vif_params *params)
+#endif
+#else
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
+/**
+ * @brief Request the driver to add a virtual interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param name            Virtual interface name
+ * @param type            Virtual interface type
+ * @param flags           Flags for the virtual interface
+ * @param params          A pointer to vif_params structure
+ *
+ * @return                A pointer to wireless_dev -- success, otherwise null
+ */
+struct wireless_dev *
+woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+			       const
+#endif
+			       char *name,
+			       enum nl80211_iftype type,
+			       u32 *flags, struct vif_params *params)
+#else
+/**
+ * @brief Request the driver to add a virtual interface
+ *
+ * @param wiphy             A pointer to wiphy structure
+ * @param name              Virtual interface name
+ * @param name_assign_type  Interface name assignment type
+ * @param type              Virtual interface type
+ * @param flags             Flags for the virtual interface
+ * @param params            A pointer to vif_params structure
+ *
+ * @return                  A pointer to wireless_dev -- success, otherwise null
+ */
+struct wireless_dev *
+woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, const char *name,
+			       unsigned char name_assign_type,
+			       enum nl80211_iftype type,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
+			       u32 *flags,
+#endif
+			       struct vif_params *params)
+#endif
+#endif
+{
+	struct net_device *ndev = NULL;
+	int ret = 0;
+#if defined(WIFI_DIRECT_SUPPORT)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	u32 *flags = &params->flags;
+#endif
+#endif
+
+	ENTER();
+	PRINTM(MIOCTL, "add virtual intf: %d name: %s\n", type, name);
+	switch (type) {
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_P2P_GO:
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+		ret = woal_cfg80211_add_virt_if(wiphy, name, name_assign_type,
+						type, flags, params, &ndev);
+#else
+		ret = woal_cfg80211_add_virt_if(wiphy, name, type, flags,
+						params, &ndev);
+#endif
+		break;
+#endif
+#endif
+	case NL80211_IFTYPE_AP:
+		if (!woal_uap_interface_ready(wiphy, (char *)name, &ndev)) {
+			PRINTM(MMSG,
+			       "Not support dynamically create %s UAP interface\n",
+			       name);
+			ret = -EFAULT;
+		}
+		break;
+	default:
+		PRINTM(MWARN, "Not supported if type: %d\n", type);
+		ret = -EFAULT;
+		break;
+	}
+	LEAVE();
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
+	if (ret)
+		return ERR_PTR(ret);
+	else
+		return ndev;
+#else
+	return ret;
+#endif
+#else
+	if (ret)
+		return ERR_PTR(ret);
+	else
+		return ndev->ieee80211_ptr;
+#endif
+}
+
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+/**
+ * @brief Request the driver to del a virtual interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             The pointer to net_device
+ *
+ * @return               0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
+#else
+/**
+ * @brief Request the driver to del a virtual interface
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param wdev            The pointer to wireless_dev
+ *
+ * @return               0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
+#endif
+{
+	int ret = 0;
+
+	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
+	int i;
+	moal_private *vir_priv = NULL;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	struct net_device *dev = wdev->netdev;
+#endif
+
+	ENTER();
+
+	PRINTM(MIOCTL, "del virtual intf %s\n", dev->name);
+	ASSERT_RTNL();
+
+	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
+		for (i = 0; i < handle->priv_num; i++) {
+			vir_priv = handle->priv[i];
+			if (vir_priv) {
+				if (vir_priv->netdev == dev) {
+					PRINTM(MMSG,
+					       "Del virtual interface %s, index=%d\n",
+					       dev->name, i);
+					break;
+				}
+			}
+		}
+		if (vir_priv && vir_priv->bss_type == MLAN_BSS_TYPE_UAP) {
+			woal_cfg80211_del_beacon(wiphy, dev);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
+			vir_priv->wdev->beacon_interval = 0;
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+			memset(&vir_priv->wdev->chandef, 0,
+			       sizeof(vir_priv->wdev->chandef));
+#endif
+#endif
+			vir_priv->wdev->ssid_len = 0;
+			PRINTM(MMSG, "Skip del UAP virtual interface %s",
+			       dev->name);
+		}
+		LEAVE();
+		return ret;
+	}
+#ifdef WIFI_DIRECT_SUPPORT
+#if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
+	ret = woal_cfg80211_del_virt_if(wiphy, dev);
+#endif
+#endif
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+/**
+ * @brief initialize AP or GO parameters
+
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to cfg80211_ap_settings structure
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
+			 struct cfg80211_ap_settings *params)
+#else
+/**
+ * @brief initialize AP or GO parameters
+
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to beacon_parameters structure
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
+			 struct beacon_parameters *params)
+#endif
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+
+	t_u8 wait_option = MOAL_IOCTL_WAIT_TIMEOUT;
+
+	ENTER();
+
+	PRINTM(MMSG, "wlan: Starting AP\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+	/* cancel previous remain on channel to avoid firmware hang */
+	if (priv->phandle->remain_on_channel) {
+		t_u8 channel_status;
+		moal_private *remain_priv;
+		remain_priv =
+			priv->phandle->priv[priv->phandle->remain_bss_index];
+		if (remain_priv) {
+			PRINTM(MCMND,
+			       "Cancel Remain on Channel before Starting AP\n");
+			if (woal_cfg80211_remain_on_channel_cfg
+			    (remain_priv, MOAL_IOCTL_WAIT, MTRUE,
+			     &channel_status, NULL, 0, 0))
+				PRINTM(MERROR,
+				       "add beacon: Fail to cancel remain on channel\n");
+			if (priv->phandle->cookie) {
+				cfg80211_remain_on_channel_expired(
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+									  remain_priv->
+									  netdev,
+#else
+									  remain_priv->
+									  wdev,
+#endif
+									  priv->
+									  phandle->
+									  cookie,
+									  &priv->
+									  phandle->
+									  chan,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
+									  priv->
+									  phandle->
+									  channel_type,
+#endif
+									  GFP_ATOMIC);
+				priv->phandle->cookie = 0;
+			}
+			priv->phandle->remain_on_channel = MFALSE;
+		}
+	}
+#endif
+
+#ifdef STA_CFG80211
+	/*** cancel pending scan */
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+
+	if (!params) {
+		LEAVE();
+		return -EFAULT;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+	priv->channel =
+		ieee80211_frequency_to_channel(params->chandef.chan->
+					       center_freq);
+#else
+	priv->channel =
+		ieee80211_frequency_to_channel(params->channel->center_freq);
+#endif
+#endif
+	/* bss config */
+	if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* set mgmt frame ies */
+	ret = woal_cfg80211_mgmt_frame_ie(priv,
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+					  params->tail, params->tail_len, NULL,
+					  0, NULL, 0, NULL, 0, MGMT_MASK_BEACON
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+					  params->beacon.tail,
+					  params->beacon.tail_len,
+					  params->beacon.proberesp_ies,
+					  params->beacon.proberesp_ies_len,
+					  params->beacon.assocresp_ies,
+					  params->beacon.assocresp_ies_len,
+#else
+					  params->tail, params->tail_len,
+					  params->proberesp_ies,
+					  params->proberesp_ies_len,
+					  params->assocresp_ies,
+					  params->assocresp_ies_len,
+#endif
+					  NULL, 0,
+					  MGMT_MASK_BEACON |
+					  MGMT_MASK_PROBE_RESP |
+					  MGMT_MASK_ASSOC_RESP
+#endif
+					  , MOAL_IOCTL_WAIT);
+	if (ret)
+		goto done;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+	if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
+		ret = woal_cfg80211_mgmt_frame_ie(priv,
+						  params->beacon.beacon_ies,
+						  params->beacon.beacon_ies_len,
+						  NULL, 0, NULL, 0, NULL, 0,
+						  MGMT_MASK_BEACON_WPS_P2P,
+						  MOAL_IOCTL_WAIT);
+		if (ret) {
+			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
+			goto done;
+		}
+	}
+#else
+	if (params->beacon_ies && params->beacon_ies_len) {
+		ret = woal_cfg80211_mgmt_frame_ie(priv, params->beacon_ies,
+						  params->beacon_ies_len, NULL,
+						  0, NULL, 0, NULL, 0,
+						  MGMT_MASK_BEACON_WPS_P2P,
+						  MOAL_IOCTL_WAIT);
+		if (ret) {
+			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
+			goto done;
+		}
+	}
+#endif
+#endif
+	priv->uap_host_based = MTRUE;
+
+	/* if the bss is stopped, then start it */
+	if (priv->bss_started == MFALSE) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+			wait_option = MOAL_NO_WAIT;
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_uap_bss_ctrl(priv, wait_option, UAP_BSS_START)) {
+			priv->uap_host_based = MFALSE;
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	PRINTM(MMSG, "wlan: AP started\n");
+done:
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+/**
+ * @brief set AP or GO parameter
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to cfg80211_beacon_data structure
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+			 struct cfg80211_beacon_data *params)
+#else
+/**
+ * @brief set AP or GO parameter
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to beacon_parameters structure
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+			 struct beacon_parameters *params)
+#endif
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+
+	PRINTM(MIOCTL, "set beacon\n");
+	if (params != NULL) {
+#if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+		if (params->tail && params->tail_len) {
+			ret = woal_cfg80211_mgmt_frame_ie(priv, params->tail,
+							  params->tail_len,
+							  NULL, 0, NULL, 0,
+							  NULL, 0,
+							  MGMT_MASK_BEACON,
+							  MOAL_IOCTL_WAIT);
+			if (ret)
+				goto done;
+		}
+#else
+		t_u16 mask = 0;
+		if (params->tail && params->tail_len)
+			mask |= MGMT_MASK_BEACON;
+		if (params->proberesp_ies && params->proberesp_ies_len)
+			mask |= MGMT_MASK_PROBE_RESP;
+		if (params->assocresp_ies && params->assocresp_ies_len)
+			mask |= MGMT_MASK_ASSOC_RESP;
+		PRINTM(MIOCTL, "Set beacon: mask=0x%x\n", mask);
+		if (mask) {
+			ret = woal_cfg80211_mgmt_frame_ie(priv, params->tail,
+							  params->tail_len,
+							  params->proberesp_ies,
+							  params->
+							  proberesp_ies_len,
+							  params->assocresp_ies,
+							  params->
+							  assocresp_ies_len,
+							  NULL, 0, mask,
+							  MOAL_IOCTL_WAIT);
+			if (ret)
+				goto done;
+		}
+		if (params->beacon_ies && params->beacon_ies_len) {
+			ret = woal_cfg80211_mgmt_frame_ie(priv,
+							  params->beacon_ies,
+							  params->
+							  beacon_ies_len, NULL,
+							  0, NULL, 0, NULL, 0,
+							  MGMT_MASK_BEACON_WPS_P2P,
+							  MOAL_IOCTL_WAIT);
+			if (ret) {
+				PRINTM(MERROR,
+				       "Failed to set beacon wps/p2p ie\n");
+				goto done;
+			}
+		}
+#endif
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief reset AP or GO parameters
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = 0;
+#ifdef STA_SUPPORT
+	moal_private *pmpriv = NULL;
+#endif
+
+	ENTER();
+
+	if (priv->phandle->driver_status) {
+		PRINTM(MERROR,
+		       "Block  woal_cfg80211_del_beacon in abnormal driver state\n");
+		LEAVE();
+		return ret;
+	}
+	priv->uap_host_based = MFALSE;
+	PRINTM(MMSG, "wlan: Stoping AP\n");
+#ifdef STA_SUPPORT
+	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
+#endif
+	memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
+	woal_deauth_all_station(priv);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+		woal_cancel_cac_block(priv);
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	memset(&priv->chan, 0, sizeof(struct cfg80211_chan_def));
+	if (priv->phandle->is_cac_timer_set &&
+	    priv->bss_index == priv->phandle->cac_bss_index) {
+		woal_cancel_timer(&priv->phandle->cac_timer);
+		priv->phandle->is_cac_timer_set = MFALSE;
+		/* Make sure Chan Report is cancelled */
+		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+#else
+		cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
+				   GFP_KERNEL);
+#endif
+		memset(&priv->phandle->dfs_channel, 0,
+		       sizeof(struct cfg80211_chan_def));
+		priv->phandle->cac_bss_index = 0xff;
+	}
+	if (priv->csa_workqueue)
+		flush_workqueue(priv->csa_workqueue);
+#endif
+	/* if the bss is still running, then stop it */
+	if (priv->bss_started == MTRUE) {
+		if ((int)MLAN_STATUS_FAILURE ==
+		    woal_uap_bss_ctrl(priv, MOAL_NO_WAIT, UAP_BSS_STOP)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if ((int)MLAN_STATUS_FAILURE ==
+		    woal_uap_bss_ctrl(priv, MOAL_NO_WAIT, UAP_BSS_RESET)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		/* Set WLAN MAC addresses */
+		if (MLAN_STATUS_FAILURE ==
+		    woal_request_set_mac_address(priv, MOAL_NO_WAIT)) {
+			PRINTM(MERROR, "Set MAC address failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+	woal_clear_all_mgmt_ies(priv, MOAL_NO_WAIT);
+#ifdef STA_SUPPORT
+	if (!woal_is_any_interface_active(priv->phandle)) {
+		pmpriv = woal_get_priv((moal_handle *)priv->phandle,
+				       MLAN_BSS_ROLE_STA);
+		if (pmpriv)
+			woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
+					   PASSIVE_SCAN_CHAN_TIME,
+					   SPECIFIC_SCAN_CHAN_TIME);
+	}
+#endif
+
+	priv->cipher = 0;
+	memset(priv->uap_wep_key, 0, sizeof(priv->uap_wep_key));
+	priv->channel = 0;
+	PRINTM(MMSG, "wlan: AP stopped\n");
+done:
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+/**
+ * @brief change BSS
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params          A pointer to bss_parameters structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
+			 struct bss_parameters *params)
+{
+	int ret = 0;
+	t_u8 change = MFALSE;
+	mlan_uap_bss_param *sys_config = NULL;
+	u8 bss_started = MFALSE;
+	t_u8 pkt_forward_ctl;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+	PRINTM(MIOCTL, "isolate=%d\n", params->ap_isolate);
+
+	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_config) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	pkt_forward_ctl = sys_config->pkt_forward_ctl;
+	if (params->ap_isolate) {
+		/** disable packet forwarding */
+		sys_config->pkt_forward_ctl |= PKT_FWD_INTRA_BCAST;
+		sys_config->pkt_forward_ctl |= PKT_FWD_INTRA_UCAST;
+	} else {
+		sys_config->pkt_forward_ctl &= ~PKT_FWD_INTRA_BCAST;
+		sys_config->pkt_forward_ctl &= ~PKT_FWD_INTRA_UCAST;
+	}
+	if (pkt_forward_ctl != sys_config->pkt_forward_ctl) {
+		change = MTRUE;
+		PRINTM(MIOCTL, "ap_isolate=%xd\n", params->ap_isolate);
+	}
+	if (change) {
+		if (priv->bss_started == MTRUE) {
+			bss_started = MTRUE;
+			woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+		}
+		if (params->use_short_preamble == 1)
+			sys_config->preamble_type = 1;
+		else if (params->use_short_preamble == 0)
+			sys_config->preamble_type = 2;
+		else
+			sys_config->preamble_type = 0;
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					    sys_config))
+			ret = 0;
+		if (bss_started)
+			woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT,
+					  UAP_BSS_START);
+	}
+done:
+	kfree(sys_config);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+/**
+ * @brief del station
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param param           A pointer tostation_del_parameters structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#else
+/**
+ * @brief del station
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param mac_addr		  A pointer to station mac address
+ *
+ * @return                0 -- success, otherwise fail
+ */
+#endif
+int
+woal_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+			  struct station_del_parameters *param)
+#else
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			  const u8 *mac_addr)
+#else
+			  u8 *mac_addr)
+#endif
+#endif
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	const u8 *mac_addr = NULL;
+#endif
+	u16 reason_code = REASON_CODE_DEAUTH_LEAVING;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	ENTER();
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	if (priv->phandle->is_cac_timer_set &&
+	    priv->bss_index == priv->phandle->cac_bss_index) {
+		woal_cancel_timer(&priv->phandle->cac_timer);
+		priv->phandle->is_cac_timer_set = MFALSE;
+		/* Make sure Chan Report is cancelled */
+		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+#else
+		cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
+				   GFP_KERNEL);
+#endif
+		memset(&priv->phandle->dfs_channel, 0,
+		       sizeof(struct cfg80211_chan_def));
+		priv->phandle->cac_bss_index = 0xff;
+	}
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
+		woal_cancel_cac_block(priv);
+#endif
+
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MINFO, "cfg80211: Media not connected!\n");
+		LEAVE();
+		return 0;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+	if (param) {
+		mac_addr = param->mac;
+		reason_code = param->reason_code;
+	}
+#endif
+	/** we will not send deauth to p2p interface, it might cause WPS failure
+	 */
+	if (mac_addr) {
+		PRINTM(MMSG, "wlan: deauth station " MACSTR "\n",
+		       MAC2STR(mac_addr));
+#ifdef WIFI_DIRECT_SUPPORT
+		if (!priv->phandle->is_go_timer_set)
+#endif
+			woal_deauth_assoc_station(priv, (u8 *)mac_addr,
+						  reason_code);
+	} else {
+		PRINTM(MIOCTL, "del all station\n");
+	}
+	LEAVE();
+	return 0;
+}
+
+/**
+ * @brief Get station info
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param mac			  A pointer to station mac address
+ * @param stainfo		  A pointer to station_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+			      const u8 *mac,
+#else
+			      u8 *mac,
+#endif
+			      struct station_info *stainfo)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = -EFAULT;
+	int i = 0;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	mlan_ds_get_stats stats;
+
+	ENTER();
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MINFO, "cfg80211: Media not connected!\n");
+		LEAVE();
+		return -ENOENT;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	info = (mlan_ds_get_info *)ioctl_req->pbuf;
+	info->sub_command = MLAN_OID_UAP_STA_LIST;
+	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	for (i = 0; i < info->param.sta_list.sta_count; i++) {
+		if (!memcmp(info->param.sta_list.info[i].mac_address, mac,
+			    ETH_ALEN)) {
+			PRINTM(MIOCTL, "Get station: " MACSTR " RSSI=%d\n",
+			       MAC2STR(mac),
+			       (int)info->param.sta_list.info[i].rssi);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+			stainfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME) |
+				BIT(NL80211_STA_INFO_RX_BYTES) |
+				BIT(NL80211_STA_INFO_TX_BYTES) |
+				BIT(NL80211_STA_INFO_RX_PACKETS) |
+				BIT(NL80211_STA_INFO_TX_PACKETS) |
+				BIT(NL80211_STA_INFO_SIGNAL);
+
+			stainfo->rx_bytes = priv->stats.rx_bytes;
+			stainfo->tx_bytes = priv->stats.tx_bytes;
+			stainfo->rx_packets = priv->stats.rx_packets;
+			stainfo->tx_packets = priv->stats.tx_packets;
+#else
+			stainfo->filled = STATION_INFO_INACTIVE_TIME |
+				STATION_INFO_SIGNAL;
+#endif
+			stainfo->inactive_time = 0;
+			stainfo->signal = info->param.sta_list.info[i].rssi;
+			ret = 0;
+			break;
+		}
+	}
+	memset(&stats, 0, sizeof(mlan_ds_get_stats));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, &stats)) {
+		PRINTM(MERROR, "Error getting stats information\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	stainfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES) |
+		BIT(NL80211_STA_INFO_TX_FAILED) |
+		BIT(NL80211_STA_INFO_RX_DROP_MISC);
+	stainfo->tx_failed = stats.failed;
+	stainfo->tx_retries = stats.retry;
+	stainfo->rx_dropped_misc = stats.fcs_error;
+#endif
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief Request the driver to dump the station information
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param idx             Station index
+ * @param mac             MAC address of the station
+ * @param sinfo           A pointer to station_info structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_uap_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
+			       int idx, t_u8 *mac, struct station_info *sinfo)
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	int ret = -EFAULT;
+	mlan_ds_get_info *info = NULL;
+	mlan_ioctl_req *ioctl_req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	t_u32 sec = 0, usec = 0;
+	t_u64 cur_msec = 0;
+
+	ENTER();
+	if (priv->media_connected == MFALSE) {
+		PRINTM(MINFO, "cfg80211: Media not connected!\n");
+		LEAVE();
+		return -ENOENT;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	ioctl_req =
+		(mlan_ioctl_req *)
+		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
+	if (ioctl_req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	info = (mlan_ds_get_info *)ioctl_req->pbuf;
+	info->sub_command = MLAN_OID_UAP_STA_LIST;
+	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
+	ioctl_req->action = MLAN_ACT_GET;
+
+	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		goto done;
+	if (idx >= info->param.sta_list.sta_count) {
+		ret = -EFAULT;
+		goto done;
+	}
+	ret = 0;
+	moal_memcpy_ext(priv->phandle, mac,
+			info->param.sta_list.info[idx].mac_address, ETH_ALEN,
+			ETH_ALEN);
+	PRINTM(MIOCTL, "Dump station: " MACSTR " RSSI=%d\n", MAC2STR(mac),
+	       (int)info->param.sta_list.info[idx].rssi);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME) |
+		BIT(NL80211_STA_INFO_SIGNAL);
+#else
+	sinfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_SIGNAL;
+#endif
+	if (info->param.sta_list.info[idx].stats.last_rx_in_msec) {
+		moal_get_system_time(priv->phandle, &sec, &usec);
+		cur_msec = (t_u64)sec *1000 + (t_u64)usec / 1000;
+		sinfo->inactive_time = (t_u32)(cur_msec -
+					       info->param.sta_list.info[idx].
+					       stats.last_rx_in_msec);
+		PRINTM(MIOCTL,
+		       "cur:%llu - [%d].last_rx:%llu = inactive_time:%d\n",
+		       cur_msec, idx,
+		       info->param.sta_list.info[idx].stats.last_rx_in_msec,
+		       sinfo->inactive_time);
+	} else
+		sinfo->inactive_time = 0;
+	sinfo->signal = info->param.sta_list.info[idx].rssi;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(ioctl_req);
+	LEAVE();
+	return ret;
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+/**
+ * @brief set mac filter
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params		  A pointer to cfg80211_acl_data structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
+			  const struct cfg80211_acl_data *params)
+{
+	int ret = -EFAULT;
+	mlan_uap_bss_param *sys_config = NULL;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	u8 bss_started = MFALSE;
+	ENTER();
+
+	PRINTM(MIOCTL, "Set mac acl, entries=%d, policy=%d\n",
+	       params->n_acl_entries, params->acl_policy);
+	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_config) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	/* Initialize the uap bss values which are uploaded from firmware */
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(&sys_config->filter, 0, sizeof(mac_filter));
+	if (params->n_acl_entries <= MAX_MAC_FILTER_NUM)
+		sys_config->filter.mac_count = params->n_acl_entries;
+	else
+		sys_config->filter.mac_count = MAX_MAC_FILTER_NUM;
+
+	if (params->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
+		sys_config->filter.filter_mode = MAC_FILTER_MODE_ALLOW_MAC;
+	else if (params->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED)
+		sys_config->filter.filter_mode = MAC_FILTER_MODE_BLOCK_MAC;
+	moal_memcpy_ext(priv->phandle, sys_config->filter.mac_list,
+			params->mac_addrs,
+			sys_config->filter.mac_count *
+			sizeof(mlan_802_11_mac_addr),
+			sizeof(sys_config->filter.mac_list));
+	if (priv->bss_started == MTRUE) {
+		bss_started = MTRUE;
+		woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+	}
+	if (MLAN_STATUS_SUCCESS == woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_config))
+		ret = 0;
+done:
+	kfree(sys_config);
+	if (bss_started)
+		woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT, UAP_BSS_START);
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+/**
+ * @brief Set txq parameters
+
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params		  A pointer to ieee80211_txq_params structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
+			     struct ieee80211_txq_params *params)
+{
+	int ret = 0;
+	u8 ac = 0;
+	wmm_parameter_t ap_wmm_para;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+
+	ENTER();
+
+	/* AC_BE: 0, AC_BK:1, AC_VI: 2, AC_VO:3 */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+	switch (params->ac) {
+	case NL80211_AC_VO:
+		ac = 3;
+		break;
+	case NL80211_AC_VI:
+		ac = 2;
+		break;
+	case NL80211_AC_BK:
+		ac = 1;
+		break;
+	case NL80211_AC_BE:
+		ac = 0;
+		break;
+	default:
+		break;
+	}
+#else
+	switch (params->queue) {
+	case NL80211_TXQ_Q_VO:
+		ac = 3;
+		break;
+	case NL80211_TXQ_Q_VI:
+		ac = 2;
+		break;
+	case NL80211_TXQ_Q_BK:
+		ac = 1;
+		break;
+	case NL80211_TXQ_Q_BE:
+		ac = 0;
+		break;
+	default:
+		break;
+	}
+#endif
+
+	PRINTM(MMSG, "Set AC=%d, txop=%d cwmin=%d, cwmax=%d aifs=%d\n", ac,
+	       params->txop, params->cwmin, params->cwmax, params->aifs);
+
+	memset(&ap_wmm_para, 0, sizeof(wmm_parameter_t));
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_ap_wmm_para(priv, MLAN_ACT_GET, &ap_wmm_para)) {
+		PRINTM(MERROR, "wlan: We don't support AP WMM parameter\n");
+		LEAVE();
+		return ret;
+	}
+	ap_wmm_para.ac_params[ac].aci_aifsn.aifsn = params->aifs;
+	ap_wmm_para.ac_params[ac].ecw.ecw_max = ilog2(params->cwmax + 1);
+	ap_wmm_para.ac_params[ac].ecw.ecw_min = ilog2(params->cwmin + 1);
+	ap_wmm_para.ac_params[ac].tx_op_limit = params->txop;
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_ap_wmm_para(priv, MLAN_ACT_SET, &ap_wmm_para)) {
+		PRINTM(MERROR, "wlan: Fail to set AP WMM parameter\n");
+		ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+}
+#endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+/**
+ * @brief cac timer call back function.
+ *
+ * @param context   a pointer to moal_handle
+ *
+ * @return           N/A
+ */
+void
+woal_cac_timer_func(void *context)
+{
+	moal_handle *handle = (moal_handle *)context;
+	moal_private *priv = handle->priv[handle->cac_bss_index];
+
+	PRINTM(MEVENT, "cac_timer fired.\n");
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+	cfg80211_cac_event(priv->netdev, &handle->dfs_channel,
+			   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+#else
+	cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+#endif
+	handle->is_cac_timer_set = MFALSE;
+	memset(&handle->dfs_channel, 0, sizeof(struct cfg80211_chan_def));
+	handle->cac_bss_index = 0xff;
+}
+
+/**
+ * @brief This function switch AP's channel
+ *        1. clear mgmt IEs  		2. stop uAP
+ *   	  3. set beacon after		4. set new channel
+ *   	  5. start uAP    		    6. notify cfg80211
+ *
+ * @param priv          a pointer to moal_private
+ * @param wait_option   wait option
+ *
+ * @return           N/A
+ */
+static void
+woal_switch_uap_channel(moal_private *priv, t_u8 wait_option)
+{
+	chan_band_info uap_channel;
+	t_u8 chan2Offset = SEC_CHAN_NONE;
+	ENTER();
+	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_uap_bss_ctrl(priv, wait_option, UAP_BSS_STOP)) {
+		PRINTM(MERROR, "%s: stop uap failed \n", __func__);
+		goto done;
+	}
+	if (woal_cfg80211_set_beacon(priv->wdev->wiphy, priv->netdev,
+				     &priv->beacon_after)) {
+		PRINTM(MERROR, "%s: set mgmt ies failed \n", __func__);
+		goto done;
+	}
+
+	uap_channel.channel =
+		ieee80211_frequency_to_channel(priv->csa_chan.chan->
+					       center_freq);
+	switch (priv->csa_chan.width) {
+	case NL80211_CHAN_WIDTH_5:
+	case NL80211_CHAN_WIDTH_10:
+	case NL80211_CHAN_WIDTH_20_NOHT:
+		uap_channel.bandcfg.chanWidth = CHAN_BW_20MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_20:
+		uap_channel.bandcfg.chanWidth = CHAN_BW_20MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		if (priv->csa_chan.center_freq1 <
+		    priv->csa_chan.chan->center_freq)
+			chan2Offset = SEC_CHAN_BELOW;
+		else
+			chan2Offset = SEC_CHAN_ABOVE;
+		uap_channel.bandcfg.chanWidth = CHAN_BW_40MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+		uap_channel.bandcfg.chanWidth = CHAN_BW_80MHZ;
+		chan2Offset =
+			woal_get_second_channel_offset(priv,
+						       uap_channel.channel);
+		break;
+	default:
+		PRINTM(MWARN, "Unknown channel width: %d\n",
+		       priv->csa_chan.width);
+		break;
+	}
+	if (priv->csa_chan.chan->band == IEEE80211_BAND_2GHZ)
+		uap_channel.bandcfg.chanBand = BAND_2GHZ;
+	else if (priv->csa_chan.chan->band == IEEE80211_BAND_5GHZ)
+		uap_channel.bandcfg.chanBand = BAND_5GHZ;
+	uap_channel.bandcfg.chan2Offset = chan2Offset;
+	if (MLAN_STATUS_SUCCESS != woal_set_get_ap_channel(priv, MLAN_ACT_SET,
+							   wait_option,
+							   &uap_channel)) {
+		PRINTM(MERROR, "Fail to set ap channel \n");
+		goto done;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT, UAP_BSS_START)) {
+		PRINTM(MERROR, "%s: start uap failed \n", __func__);
+		goto done;
+	}
+	PRINTM(MMSG, "CSA: old chan %d => new chan %d \n", priv->channel,
+	       uap_channel.channel);
+	priv->channel = uap_channel.channel;
+	moal_memcpy_ext(priv->phandle, &priv->chan, &priv->csa_chan,
+			sizeof(struct cfg80211_chan_def), sizeof(priv->chan));
+	cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
+	if (priv->uap_tx_blocked) {
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		woal_start_queue(priv->netdev);
+		priv->uap_tx_blocked = MFALSE;
+	}
+done:
+	LEAVE();
+	return;
+}
+
+/**
+ * @brief csa work handler
+ *
+ * @param work            a pointer to work_struct
+ *
+ * @return                0 -- success, otherwise fail
+ */
+void
+woal_csa_work_queue(struct work_struct *work)
+{
+	struct delayed_work *delayed_work =
+		container_of(work, struct delayed_work, work);
+	moal_private *priv = container_of(delayed_work, moal_private, csa_work);
+	ENTER();
+	if (priv->bss_started == MTRUE)
+		woal_switch_uap_channel(priv, MOAL_IOCTL_WAIT);
+	LEAVE();
+}
+
+/*
+ * @brief  handle WOAL_EVENT_CANCEL_CHANRPT
+ *
+ * @param priv           A pointer moal_private structure
+ *
+ * @return          N/A
+ */
+void
+woal_process_cancel_chanrpt_event(moal_private *priv)
+{
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	if (priv->phandle->is_cac_timer_set &&
+	    priv->bss_index == priv->phandle->cac_bss_index) {
+		woal_cancel_timer(&priv->phandle->cac_timer);
+		priv->phandle->is_cac_timer_set = MFALSE;
+		/* Make sure Chan Report is cancelled */
+		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+#else
+		cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
+				   GFP_KERNEL);
+#endif
+		memset(&priv->phandle->dfs_channel, 0,
+		       sizeof(struct cfg80211_chan_def));
+		priv->phandle->cac_bss_index = 0xff;
+	}
+#endif
+}
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+/**
+ * @brief start radar detection
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param chandef         A pointer to cfg80211_chan_def structure
+ * @param cac_time_ms     A cac dwell time
+ * @return                0 -- success, otherwise fail
+ */
+
+int
+woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
+				    struct net_device *dev,
+				    struct cfg80211_chan_def *chandef,
+				    u32 cac_time_ms)
+#else
+/**
+ * @brief start radar detection
+ *
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param chandef         A pointer to cfg80211_chan_def structure
+ * @return                0 -- success, otherwise fail
+ */
+
+int
+woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
+				    struct net_device *dev,
+				    struct cfg80211_chan_def *chandef)
+#endif
+{
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	moal_handle *handle = priv->phandle;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_11h_chan_rep_req *pchan_rpt_req = NULL;
+	mlan_ds_11h_cfg *p11h_cfg = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+	PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d , Time %d \n",
+	       chandef->chan->hw_value, chandef->width, cac_time_ms);
+#else
+	PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d \n",
+	       chandef->chan->hw_value, chandef->width);
+#endif
+
+	if (priv->bss_started == MTRUE) {
+		PRINTM(MERROR, "recv CAC request when bss already started \n");
+		ret = -EFAULT;
+		goto done;
+	}
+	if (priv->phandle->cac_period || handle->is_cac_timer_set) {
+		PRINTM(MERROR,
+		       "Maybe other interface is doing CAC, please defer your oper\n");
+		ret = -EBUSY;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
+	if (NULL == req) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	p11h_cfg = (mlan_ds_11h_cfg *)req->pbuf;
+	pchan_rpt_req = &p11h_cfg->param.chan_rpt_req;
+	pchan_rpt_req->startFreq = START_FREQ_11A_BAND;
+	pchan_rpt_req->chanNum = (t_u8)chandef->chan->hw_value;
+	woal_convert_chan_to_bandconfig(priv, &pchan_rpt_req->bandcfg, chandef);
+	pchan_rpt_req->host_based = MTRUE;
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+	pchan_rpt_req->millisec_dwell_time = cac_time_ms;
+#else
+	pchan_rpt_req->millisec_dwell_time = IEEE80211_DFS_MIN_CAC_TIME_MS;
+
+	if ((woal_is_etsi_country(priv->phandle->country_code) == MTRUE)) {
+		if (chandef->chan->hw_value == 120 ||
+		    chandef->chan->hw_value == 124 ||
+		    chandef->chan->hw_value == 128) {
+			pchan_rpt_req->millisec_dwell_time =
+				IEEE80211_DFS_MIN_CAC_TIME_MS * 10;
+		}
+		if (chandef->chan->hw_value == 116 &&
+		    ((chandef->width == NL80211_CHAN_WIDTH_40) ||
+		     (chandef->width == NL80211_CHAN_WIDTH_80))) {
+			pchan_rpt_req->millisec_dwell_time =
+				IEEE80211_DFS_MIN_CAC_TIME_MS * 10;
+		}
+	}
+#endif
+	if (priv->user_cac_period_msec) {
+		pchan_rpt_req->millisec_dwell_time = priv->user_cac_period_msec;
+		PRINTM(MCMD_D,
+		       "cfg80211 dfstesting: User CAC Period=%d (msec) \n",
+		       pchan_rpt_req->millisec_dwell_time);
+	}
+
+	p11h_cfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
+	req->req_id = MLAN_IOCTL_11H_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Send Channel Check command and wait until the report is ready */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Fail to start radar detection\n");
+		ret = -EFAULT;
+	} else {
+		moal_memcpy_ext(priv->phandle, &handle->dfs_channel, chandef,
+				sizeof(struct cfg80211_chan_def),
+				sizeof(handle->dfs_channel));
+		handle->cac_bss_index = priv->bss_index;
+		handle->is_cac_timer_set = MTRUE;
+		/* avoid EVENT_CHANNEL_RAPORT_READY missing, add 1s gap */
+		woal_mod_timer(&handle->cac_timer,
+			       pchan_rpt_req->millisec_dwell_time + 1000);
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief channel switch
+
+ * @param wiphy           A pointer to wiphy structure
+ * @param dev             A pointer to net_device structure
+ * @param params		  A pointer to cfg80211_csa_settings structure
+ *
+ * @return                0 -- success, otherwise fail
+ */
+int
+woal_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+			     struct cfg80211_csa_settings *params)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	t_u32 chsw_msec;
+	mlan_uap_bss_param *bss_cfg = NULL;
+
+	ENTER();
+
+	if (!params) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* TODO: support this case in next version */
+	if (params->radar_required) {
+		PRINTM(MMSG,
+		       " hostapd handle this case by disable and re-enable interface\n");
+		ret = -ENOTSUPP;
+		goto done;
+	}
+
+	/* actually hostapd would always choose one diff channel */
+	if (cfg80211_chandef_identical(&params->chandef, &priv->chan)) {
+		PRINTM(MMSG,
+		       "csa channel is same with current channel, invaild\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	bss_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!bss_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (params->block_tx) {
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
+		woal_stop_queue(dev);
+		priv->uap_tx_blocked = MTRUE;
+	}
+
+	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
+	if (woal_cfg80211_set_beacon(wiphy, dev, &params->beacon_csa)) {
+		PRINTM(MERROR, "%s: setting csa mgmt ies failed\n", __func__);
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, &priv->csa_chan, &params->chandef,
+			sizeof(struct cfg80211_chan_def),
+			sizeof(priv->csa_chan));
+	moal_memcpy_ext(priv->phandle, &priv->beacon_after,
+			&params->beacon_after,
+			sizeof(struct cfg80211_beacon_data),
+			sizeof(priv->beacon_after));
+
+	if (!priv->phandle->fw_ecsa_enable) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
+					    bss_cfg)) {
+			PRINTM(MERROR, "%s: get uap config failed\n", __func__);
+			ret = -EFAULT;
+			goto done;
+		}
+		chsw_msec = params->count * bss_cfg->beacon_period;
+		queue_delayed_work(priv->csa_workqueue, &priv->csa_work,
+				   msecs_to_jiffies(chsw_msec));
+	}
+done:
+	kfree(bss_cfg);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ * @brief Register the device with cfg80211
+ *
+ * @param dev       A pointer to net_device structure
+ * @param bss_type  BSS type
+ *
+ * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_register_uap_cfg80211(struct net_device *dev, t_u8 bss_type)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct wireless_dev *wdev = NULL;
+
+	ENTER();
+
+	wdev = (struct wireless_dev *)&priv->w_dev;
+	memset(wdev, 0, sizeof(struct wireless_dev));
+
+	wdev->wiphy = priv->phandle->wiphy;
+	if (!wdev->wiphy) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	if (bss_type == MLAN_BSS_TYPE_UAP)
+		wdev->iftype = NL80211_IFTYPE_AP;
+
+	dev_net_set(dev, wiphy_net(wdev->wiphy));
+	dev->ieee80211_ptr = wdev;
+	SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
+	priv->wdev = wdev;
+
+	LEAVE();
+	return ret;
+}
diff --git a/wlan_sd8987/mlinux/moal_uap_cfg80211.h b/wlan_sd8987/mlinux/moal_uap_cfg80211.h
new file mode 100755
index 0000000..4f607e9
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_cfg80211.h
@@ -0,0 +1,30 @@
+/** @file moal_uap_cfg80211.h
+ *
+ * @brief This file contains the uAP CFG80211 specific defines.
+ *
+ *
+ * Copyright 2011-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+#ifndef _MOAL_UAP_CFG80211_H_
+#define _MOAL_UAP_CFG80211_H_
+
+#include "moal_uap.h"
+
+mlan_status woal_register_uap_cfg80211(struct net_device *dev, t_u8 bss_type);
+
+#endif /* _MOAL_UAP_CFG80211_H_ */
diff --git a/wlan_sd8987/mlinux/moal_uap_priv.c b/wlan_sd8987/mlinux/moal_uap_priv.c
new file mode 100755
index 0000000..4c16900
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_priv.c
@@ -0,0 +1,183 @@
+/** @file  moal_uap_priv.c
+ *
+ * @brief This file contains standard ioctl functions
+ *
+ *
+ * Copyright 2010-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/************************************************************************
+Change log:
+    08/06/2010: initial version
+************************************************************************/
+
+#include "moal_main.h"
+#include "moal_uap.h"
+#include "moal_uap_priv.h"
+
+/********************************************************
+			Local Variables
+********************************************************/
+
+/********************************************************
+			Global Variables
+********************************************************/
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+/**
+ *  @brief ioctl function for wireless IOCTLs
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param req      A pointer to ifreq structure
+ *  @param cmd      Command
+ *
+ *  @return          0 --success, otherwise fail
+ */
+int
+woal_uap_do_priv_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iwreq *wrq = (struct iwreq *)req;
+	int ret = 0;
+
+	ENTER();
+
+	switch (cmd) {
+	case WOAL_UAP_SETNONE_GETNONE:
+		switch (wrq->u.data.flags) {
+		case WOAL_UAP_START:
+			break;
+		case WOAL_UAP_STOP:
+			ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT,
+						UAP_BSS_STOP);
+			break;
+		case WOAL_AP_BSS_START:
+			ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT,
+						UAP_BSS_START);
+			break;
+		case WOAL_AP_BSS_STOP:
+			ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT,
+						UAP_BSS_STOP);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	case WOAL_UAP_SETONEINT_GETWORDCHAR:
+		switch (wrq->u.data.flags) {
+		case WOAL_UAP_VERSION:
+			ret = woal_get_driver_version(priv, req);
+			break;
+		case WOAL_UAP_VEREXT:
+			ret = woal_get_driver_verext(priv, req);
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		break;
+	case WOAL_UAP_SET_GET_256_CHAR:
+		switch (wrq->u.data.flags) {
+		case WOAL_WL_FW_RELOAD:
+			break;
+		case WOAL_AP_SET_CFG:
+			ret = woal_uap_set_ap_cfg(priv,
+						  (t_u8 __force *)wrq->u.data.
+						  pointer, wrq->u.data.length);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	case WOAL_UAP_SETONEINT_GETONEINT:
+		switch (wrq->u.data.flags) {
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+		case WOAL_UAP_SET_GET_BSS_ROLE:
+			ret = woal_set_get_bss_role(priv, wrq);
+			break;
+#endif
+#endif
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	case WOAL_UAP_HOST_CMD:
+		ret = woal_host_command(priv, wrq);
+		break;
+	case WOAL_UAP_FROYO_START:
+		break;
+	case WOAL_UAP_FROYO_STOP:
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+		break;
+	case WOAL_UAP_FROYO_AP_BSS_START:
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
+		break;
+	case WOAL_UAP_FROYO_AP_BSS_STOP:
+		ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
+		break;
+	case WOAL_UAP_FROYO_WL_FW_RELOAD:
+		break;
+	case WOAL_UAP_FROYO_AP_SET_CFG:
+		ret = woal_uap_set_ap_cfg(priv,
+					  (t_u8 __force *)wrq->u.data.pointer,
+					  wrq->u.data.length);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle get info resp
+ *
+ *  @param priv     Pointer to moal_private structure
+ *  @param info     Pointer to mlan_ds_get_info structure
+ *
+ *  @return         N/A
+ */
+void
+woal_ioctl_get_uap_info_resp(moal_private *priv, mlan_ds_get_info *info)
+{
+	ENTER();
+	switch (info->sub_command) {
+	case MLAN_OID_GET_STATS:
+		priv->w_stats.discard.fragment =
+			info->param.ustats.fcs_error_count;
+		priv->w_stats.discard.retries = info->param.ustats.retry_count;
+		priv->w_stats.discard.misc =
+			info->param.ustats.ack_failure_count;
+		break;
+	default:
+		break;
+	}
+	LEAVE();
+}
diff --git a/wlan_sd8987/mlinux/moal_uap_priv.h b/wlan_sd8987/mlinux/moal_uap_priv.h
new file mode 100755
index 0000000..dcb391a
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_priv.h
@@ -0,0 +1,85 @@
+/** @file  moal_uap_priv.h
+ *
+ * @brief This file contains definition for extended private IOCTL call.
+ *
+ *
+ * Copyright 2010-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/************************************************************************
+Change log:
+    08/06/2010: initial version
+************************************************************************/
+
+#ifndef _MOAL_UAP_PRIV_H_
+#define _MOAL_UAP_PRIV_H_
+
+/** Private command ID */
+#define WOAL_UAP_IOCTL 0x8BE0
+
+/** Private command to get/set 256 chars */
+#define WOAL_UAP_SET_GET_256_CHAR (WOAL_UAP_IOCTL + 1)
+/** Private command ID to FW reload */
+#define WOAL_WL_FW_RELOAD 1
+/** Private command ID to set AP configuration */
+#define WOAL_AP_SET_CFG 2
+
+/** Private command ID to set/get none */
+#define WOAL_UAP_SETNONE_GETNONE (WOAL_UAP_IOCTL + 2)
+/** Private command ID to start UAP */
+#define WOAL_UAP_START 1
+/** Private command ID to stop UAP */
+#define WOAL_UAP_STOP 2
+/** Private command ID to start AP BSS */
+#define WOAL_AP_BSS_START 3
+/** Private command ID to stop AP BSS */
+#define WOAL_AP_BSS_STOP 4
+
+/** Private command ID to set one int/get word char */
+#define WOAL_UAP_SETONEINT_GETWORDCHAR (WOAL_UAP_IOCTL + 3)
+/** Private command ID to get version */
+#define WOAL_UAP_VERSION 1
+/** Private command ID to get extended version */
+#define WOAL_UAP_VEREXT 2
+
+/** Private command ID to set one int/get one int */
+#define WOAL_UAP_SETONEINT_GETONEINT (WOAL_UAP_IOCTL + 5)
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+/** Private command ID for set/get BSS role */
+#define WOAL_UAP_SET_GET_BSS_ROLE 1
+#endif
+#endif
+
+/** Private command ID for hostcmd */
+#define WOAL_UAP_HOST_CMD (WOAL_UAP_IOCTL + 17)
+
+/** The following command IDs are for Froyo app */
+/** Private command ID to start AP BSS */
+#define WOAL_UAP_FROYO_AP_BSS_START (WOAL_UAP_IOCTL + 24)
+/** Private command ID to stop AP BSS */
+#define WOAL_UAP_FROYO_AP_BSS_STOP (WOAL_UAP_IOCTL + 26)
+/** Private command ID to set AP config */
+#define WOAL_UAP_FROYO_AP_SET_CFG (WOAL_UAP_IOCTL + 27)
+/** Private command ID to start driver */
+#define WOAL_UAP_FROYO_START (WOAL_UAP_IOCTL + 28)
+/** Private command ID to reload FW */
+#define WOAL_UAP_FROYO_WL_FW_RELOAD (WOAL_UAP_IOCTL + 29)
+/** Private command ID to stop driver */
+#define WOAL_UAP_FROYO_STOP (WOAL_UAP_IOCTL + 30)
+
+#endif /* _MOAL_UAP_PRIV_H_ */
diff --git a/wlan_sd8987/mlinux/moal_uap_wext.c b/wlan_sd8987/mlinux/moal_uap_wext.c
new file mode 100755
index 0000000..9010f8d
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_uap_wext.c
@@ -0,0 +1,1932 @@
+/** @file  moal_uap_wext.c
+ *
+ * @brief This file contains wireless extension standard ioctl functions
+ *
+ *
+ * Copyright 2010-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/************************************************************************
+Change log:
+    08/06/2010: initial version
+************************************************************************/
+
+#include "moal_main.h"
+#include "moal_uap.h"
+#include "moal_wext.h"
+#include "moal_uap_priv.h"
+
+/********************************************************
+			Global Variables
+********************************************************/
+typedef struct _chan_to_freq_t {
+	/** Channel */
+	t_u16 channel;
+	/** Frequency */
+	t_u32 freq;
+	/** Band */
+	t_u8 band;
+} chan_to_freq_t;
+
+static const chan_to_freq_t chan_to_freq[] = {
+	{1, 2412, 0}, {2, 2417, 0}, {3, 2422, 0}, {4, 2427, 0},
+	{5, 2432, 0}, {6, 2437, 0}, {7, 2442, 0}, {8, 2447, 0},
+	{9, 2452, 0}, {10, 2457, 0}, {11, 2462, 0}, {12, 2467, 0},
+	{13, 2472, 0}, {14, 2484, 0}, {183, 4915, 1}, {184, 4920, 1},
+	{185, 4925, 1}, {187, 4935, 1}, {188, 4940, 1}, {189, 4945, 1},
+	{192, 4960, 1}, {196, 4980, 1}, {7, 5035, 1}, {8, 5040, 1},
+	{9, 5045, 1}, {11, 5055, 1}, {12, 5060, 1}, {16, 5080, 1},
+	{34, 5170, 1}, {36, 5180, 1}, {38, 5190, 1}, {40, 5200, 1},
+	{42, 5210, 1}, {44, 5220, 1}, {46, 5230, 1}, {48, 5240, 1},
+	{52, 5260, 1}, {56, 5280, 1}, {60, 5300, 1}, {64, 5320, 1},
+	{100, 5500, 1}, {104, 5520, 1}, {108, 5540, 1}, {112, 5560, 1},
+	{116, 5580, 1}, {120, 5600, 1}, {124, 5620, 1}, {128, 5640, 1},
+	{132, 5660, 1}, {136, 5680, 1}, {140, 5700, 1}, {144, 5720, 1},
+	{149, 5745, 1}, {153, 5765, 1}, {157, 5785, 1}, {161, 5805, 1},
+	{165, 5825, 1},
+};
+
+/**
+ * iwpriv ioctl handlers
+ */
+static const struct iw_priv_args woal_uap_priv_args[] = {
+	{WOAL_UAP_SETNONE_GETNONE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, ""},
+	{WOAL_UAP_START, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "start"},
+	{WOAL_UAP_STOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "stop"},
+	{WOAL_AP_BSS_START, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "bssstart"},
+	{WOAL_AP_BSS_STOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "bssstop"},
+	{WOAL_UAP_SETONEINT_GETWORDCHAR, IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_CHAR | 128, ""},
+	{WOAL_UAP_VERSION, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128,
+	 "version"},
+	{WOAL_UAP_VEREXT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128,
+	 "verext"},
+	{WOAL_UAP_SETONEINT_GETONEINT, IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1, ""},
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	{WOAL_UAP_SET_GET_BSS_ROLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "bssrole"},
+#endif
+#endif
+
+	{WOAL_UAP_SET_GET_256_CHAR, IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256, ""},
+	{WOAL_WL_FW_RELOAD, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "fwreload"},
+	{WOAL_AP_SET_CFG, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "apcfg"},
+	{WOAL_UAP_HOST_CMD, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047,
+	 "hostcmd"},
+	{WOAL_UAP_FROYO_START, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "START"},
+	{WOAL_UAP_FROYO_STOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "STOP"},
+	{WOAL_UAP_FROYO_AP_BSS_START, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE,
+	 "AP_BSS_START"},
+	{WOAL_UAP_FROYO_AP_BSS_STOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE,
+	 "AP_BSS_STOP"},
+	{WOAL_UAP_FROYO_WL_FW_RELOAD, IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256, "WL_FW_RELOAD"},
+	{WOAL_UAP_FROYO_AP_SET_CFG, IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256, "AP_SET_CFG"},
+};
+
+/** Convertion from frequency to channel */
+#define freq_to_chan(x) ((((x)-2412) / 5) + 1)
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Sort Channels
+ *
+ *  @param freq                 A pointer to iw_freq structure
+ *  @param num                  Number of Channels
+ *
+ *  @return                     N/A
+ */
+static inline void
+woal_sort_channels(struct iw_freq *freq, int num)
+{
+	int i, j;
+	struct iw_freq temp;
+
+	for (i = 0; i < num; i++)
+		for (j = i + 1; j < num; j++)
+			if (freq[i].i > freq[j].i) {
+				temp.i = freq[i].i;
+				temp.m = freq[i].m;
+
+				freq[i].i = freq[j].i;
+				freq[i].m = freq[j].m;
+
+				freq[j].i = temp.i;
+				freq[j].m = temp.m;
+			}
+}
+
+/**
+ *  @brief Get frequency for channel in given band
+ *
+ *  @param channel      channel
+ *  @param band         band
+ *
+ *  @return             freq
+ */
+static int
+channel_to_frequency(t_u16 channel, t_u8 band)
+{
+	int i = 0;
+
+	ENTER();
+	for (i = 0; i < (int)ARRAY_SIZE(chan_to_freq); i++) {
+		if (channel == chan_to_freq[i].channel &&
+		    band == chan_to_freq[i].band) {
+			LEAVE();
+			return chan_to_freq[i].freq;
+		}
+	}
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Commit handler: called after a bunch of SET operations
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param cwrq         A pointer to char buffer
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success
+ */
+static int
+woal_config_commit(struct net_device *dev,
+		   struct iw_request_info *info, union iwreq_data *cwrq,
+		   char *extra)
+{
+	ENTER();
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get name
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param cwrq         A pointer to char buffer
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success
+ */
+static int
+woal_get_name(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	char *cwrq = wrqu->name;
+	ENTER();
+	strcpy(cwrq, "IEEE 802.11-DS");
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get current BSSID
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param awrq         A pointer to sockaddr structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success
+ */
+static int
+woal_get_wap(struct net_device *dev, struct iw_request_info *info,
+	     union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct sockaddr *awrq = &wrqu->addr;
+	int ret = 0;
+
+	ENTER();
+
+	if (priv->bss_started)
+		moal_memcpy_ext(priv->phandle, awrq->sa_data,
+				priv->current_addr, MLAN_MAC_ADDR_LENGTH,
+				sizeof(awrq->sa_data));
+	else
+		memset(awrq->sa_data, 0, MLAN_MAC_ADDR_LENGTH);
+	awrq->sa_family = ARPHRD_ETHER;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Change the AP BSSID
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param awrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_set_wap(struct net_device *dev, struct iw_request_info *info,
+	     union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct sockaddr *awrq = &wrqu->addr;
+	const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 };
+
+	ENTER();
+
+	if (awrq->sa_family != ARPHRD_ETHER) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	PRINTM(MINFO, "ASSOC: WAP: uAP bss : " MACSTR "\n",
+	       MAC2STR((t_u8 *)awrq->sa_data));
+
+	/*
+	 * Using this ioctl to start/stop the BSS, return if bss
+	 * is already started/stopped.
+	 */
+	if (memcmp(zero_mac, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
+		if (priv->bss_started == MFALSE)
+			ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT,
+						UAP_BSS_START);
+		else
+			PRINTM(MINFO, "BSS is already started.\n");
+	} else {
+		/* zero_mac means bss_stop */
+		if (priv->bss_started == MTRUE)
+			ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT,
+						UAP_BSS_STOP);
+		else
+			PRINTM(MINFO, "BSS is already stopped.\n");
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set frequency/channel
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param fwrq                 A pointer to iw_freq structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_freq(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_freq *fwrq = &wrqu->freq;
+	mlan_uap_bss_param *sys_cfg = NULL, *ap_cfg = NULL;
+	int ret = 0, chan = 0, i = 0;
+
+	ENTER();
+
+	ap_cfg = kmalloc(sizeof(mlan_uap_bss_param), GFP_KERNEL);
+	if (ap_cfg == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	sys_cfg = kmalloc(sizeof(mlan_uap_bss_param), GFP_KERNEL);
+	if (sys_cfg == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	i = ap_cfg->num_of_chan;
+
+	/* Initialize the invalid values so that the correct values
+	 * below are downloaded to firmware */
+	woal_set_sys_config_invalid_data(sys_cfg);
+
+	/* If setting by frequency, convert to a channel */
+	if (fwrq->e == 1)
+		chan = freq_to_chan(fwrq->m / 100000);
+	else
+		chan = fwrq->m;
+	if (chan > 0 && chan < MLAN_MAX_CHANNEL)
+		sys_cfg->channel = chan;
+	else {
+		ret = -EINVAL;
+		goto done;
+	}
+	for (i = 0; i < (int)ap_cfg->num_of_chan; i++)
+		if (ap_cfg->chan_list[i].chan_number == chan)
+			break;
+	if (i == (int)ap_cfg->num_of_chan) {
+		PRINTM(MERROR, "Channel %d is not supported\n", chan);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_cfg)) {
+		PRINTM(MERROR, "Error setting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	kfree(sys_cfg);
+	kfree(ap_cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get frequency and channel
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param fwrq                 A pointer to iw_freq structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_freq(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_freq *fwrq = &wrqu->freq;
+	mlan_uap_bss_param *ap_cfg = NULL;
+	t_u8 band = 0;
+	int ret = 0;
+
+	ENTER();
+
+	ap_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!ap_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		kfree(ap_cfg);
+		LEAVE();
+		return -EFAULT;
+	}
+
+	band = (ap_cfg->bandcfg.chanBand == BAND_5GHZ);
+	fwrq->m = (long)channel_to_frequency(ap_cfg->channel, band);
+	fwrq->i = (long)ap_cfg->channel;
+	fwrq->e = 6;
+
+	kfree(ap_cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set wlan mode
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param uwrq                 A pointer to t_u32 string
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_bss_mode(struct net_device *dev,
+		  struct iw_request_info *info, union iwreq_data *wrqu,
+		  char *extra)
+{
+	int ret = 0;
+	t_u32 *uwrq = &wrqu->mode;
+	ENTER();
+
+	switch (*uwrq) {
+	case IW_MODE_AUTO:
+	case IW_MODE_MASTER:
+		PRINTM(MINFO, "This is correct mode in AP mode\n");
+		break;
+	default:
+		PRINTM(MERROR, "Invalid mode for AP\n");
+		ret = -EINVAL;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get wlan mode
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param uwrq                 A pointer to t_u32 string
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success
+ */
+static int
+woal_get_bss_mode(struct net_device *dev,
+		  struct iw_request_info *info, union iwreq_data *wrqu,
+		  char *extra)
+{
+	t_u32 *uwrq = &wrqu->mode;
+	ENTER();
+
+	*uwrq = IW_MODE_MASTER;
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Set encryption key
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_encode(struct net_device *dev, struct iw_request_info *info,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_uap_bss_param *sys_cfg = NULL, *ap_cfg = NULL;
+	wep_key *pkey = NULL;
+	int key_index = 0;
+
+	ENTER();
+
+	/* Check index */
+	key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+	if (key_index > 3) {
+		PRINTM(MERROR, "Key index #%d out of range\n", key_index);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ap_cfg = kmalloc(sizeof(mlan_uap_bss_param), GFP_KERNEL);
+	if (ap_cfg == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	sys_cfg = kmalloc(sizeof(mlan_uap_bss_param), GFP_KERNEL);
+	if (sys_cfg == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Initialize the invalid values so that the correct values
+	 * below are downloaded to firmware */
+	woal_set_sys_config_invalid_data(sys_cfg);
+	sys_cfg->wep_cfg.key0.key_index = 0;
+	sys_cfg->wep_cfg.key1.key_index = 1;
+	sys_cfg->wep_cfg.key2.key_index = 2;
+	sys_cfg->wep_cfg.key3.key_index = 3;
+
+	if (key_index >= 0 && key_index <= 3) {
+		if (key_index == 0)
+			pkey = &sys_cfg->wep_cfg.key0;
+		else if (key_index == 1)
+			pkey = &sys_cfg->wep_cfg.key1;
+		else if (key_index == 2)
+			pkey = &sys_cfg->wep_cfg.key2;
+		else if (key_index == 3)
+			pkey = &sys_cfg->wep_cfg.key3;
+	}
+
+	if (!(dwrq->flags & IW_ENCODE_NOKEY) && dwrq->length) {
+		if (dwrq->length > MAX_WEP_KEY_SIZE) {
+			PRINTM(MERROR, "Key length (%d) out of range\n",
+			       dwrq->length);
+			ret = -E2BIG;
+			goto done;
+		}
+		if (key_index < 0) {
+			/* Get current default key index */
+			if (ap_cfg->wep_cfg.key0.is_default)
+				pkey = &sys_cfg->wep_cfg.key0;
+			if (ap_cfg->wep_cfg.key1.is_default)
+				pkey = &sys_cfg->wep_cfg.key1;
+			if (ap_cfg->wep_cfg.key2.is_default)
+				pkey = &sys_cfg->wep_cfg.key2;
+			if (ap_cfg->wep_cfg.key3.is_default)
+				pkey = &sys_cfg->wep_cfg.key3;
+			else {	/* Something wrong, select first key as default
+				 */
+				PRINTM(MERROR,
+				       "No default key set! Selecting first key.\n");
+				pkey = &sys_cfg->wep_cfg.key0;
+			}
+		}
+
+		sys_cfg->protocol = PROTOCOL_STATIC_WEP;
+		if (extra)
+			moal_memcpy_ext(priv->phandle, pkey->key, extra,
+					dwrq->length, sizeof(pkey->key));
+		/* Set the length */
+		if (dwrq->length > MIN_WEP_KEY_SIZE)
+			pkey->length = MAX_WEP_KEY_SIZE;
+		else
+			pkey->length = MIN_WEP_KEY_SIZE;
+		/* Set current key index as default */
+		pkey->is_default = MTRUE;
+	} else {
+		/*
+		 * No key provided so it is either enable key,
+		 * on or off
+		 */
+		if (dwrq->flags & IW_ENCODE_DISABLED) {
+			PRINTM(MINFO, "*** iwconfig mlanX key off ***\n");
+			sys_cfg->protocol = PROTOCOL_NO_SECURITY;
+		} else {
+			/*
+			 * iwconfig mlanX key [n]
+			 * iwconfig mlanX key on
+			 * Do we want to just set the transmit key index ?
+			 */
+			if (key_index < 0) {
+				PRINTM(MINFO,
+				       "*** iwconfig mlanX key on ***\n");
+			} else {
+				/* Get current key configuration at key_index */
+				if (key_index == 0)
+					moal_memcpy_ext(priv->phandle, pkey,
+							&ap_cfg->wep_cfg.key0,
+							sizeof(wep_key),
+							sizeof(wep_key));
+				if (key_index == 1)
+					moal_memcpy_ext(priv->phandle, pkey,
+							&ap_cfg->wep_cfg.key1,
+							sizeof(wep_key),
+							sizeof(wep_key));
+				if (key_index == 2)
+					moal_memcpy_ext(priv->phandle, pkey,
+							&ap_cfg->wep_cfg.key2,
+							sizeof(wep_key),
+							sizeof(wep_key));
+				if (key_index == 3)
+					moal_memcpy_ext(priv->phandle, pkey,
+							&ap_cfg->wep_cfg.key3,
+							sizeof(wep_key),
+							sizeof(wep_key));
+				/* Set current key index as default */
+				pkey->is_default = MTRUE;
+			}
+		}
+	}
+	if (dwrq->flags & (IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)) {
+		switch (dwrq->flags & 0xf000) {
+		case IW_ENCODE_RESTRICTED:
+			/* iwconfig mlanX restricted key [1] */
+			sys_cfg->auth_mode = MLAN_AUTH_MODE_SHARED;
+			PRINTM(MINFO, "Auth mode restricted!\n");
+			break;
+		case IW_ENCODE_OPEN:
+			/* iwconfig mlanX key [2] open */
+			sys_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
+			PRINTM(MINFO, "Auth mode open!\n");
+			break;
+		case IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN:
+		default:
+			/* iwconfig mlanX key [2] open restricted */
+			PRINTM(MINFO, "Auth mode auto!\n");
+			break;
+		}
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_cfg)) {
+		PRINTM(MERROR, "Error setting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	kfree(sys_cfg);
+	kfree(ap_cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get encryption key
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_encode(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	int index = (dwrq->flags & IW_ENCODE_INDEX);
+	wep_key *pkey = NULL;
+	mlan_uap_bss_param *ap_cfg = NULL;
+	int ret = 0;
+
+	ENTER();
+	if (index < 0 || index > 4) {
+		PRINTM(MERROR, "Key index #%d out of range\n", index);
+		ret = -EINVAL;
+		goto done;
+	}
+	ap_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!ap_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	dwrq->flags = 0;
+	/*
+	 * Check encryption mode
+	 */
+	switch (ap_cfg->auth_mode) {
+	case MLAN_AUTH_MODE_OPEN:
+		dwrq->flags = IW_ENCODE_OPEN;
+		break;
+	case MLAN_AUTH_MODE_SHARED:
+	case MLAN_AUTH_MODE_NETWORKEAP:
+		dwrq->flags = IW_ENCODE_RESTRICTED;
+		break;
+	default:
+		dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
+		break;
+	}
+
+	switch (ap_cfg->protocol) {
+	case PROTOCOL_NO_SECURITY:
+		dwrq->flags |= IW_ENCODE_DISABLED;
+		break;
+	case PROTOCOL_STATIC_WEP:
+		if (ap_cfg->wep_cfg.key0.is_default)
+			pkey = &ap_cfg->wep_cfg.key0;
+		else if (ap_cfg->wep_cfg.key1.is_default)
+			pkey = &ap_cfg->wep_cfg.key1;
+		else if (ap_cfg->wep_cfg.key2.is_default)
+			pkey = &ap_cfg->wep_cfg.key2;
+		else if (ap_cfg->wep_cfg.key3.is_default)
+			pkey = &ap_cfg->wep_cfg.key3;
+		if (pkey) {
+			dwrq->flags |= (pkey->key_index + 1);
+			dwrq->length = pkey->length;
+			moal_memcpy_ext(priv->phandle, extra, pkey->key,
+					pkey->length, pkey->length);
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else {
+			ret = -EFAULT;
+		}
+		break;
+	case PROTOCOL_WPA:
+	case PROTOCOL_WPA2:
+	case PROTOCOL_WPA2_MIXED:
+		moal_memcpy_ext(priv->phandle, extra,
+				ap_cfg->wpa_cfg.passphrase,
+				ap_cfg->wpa_cfg.length, ap_cfg->wpa_cfg.length);
+		dwrq->length = ap_cfg->wpa_cfg.length;
+		dwrq->flags |= 1;
+		dwrq->flags &= ~IW_ENCODE_DISABLED;
+		break;
+	default:
+		dwrq->flags &= ~IW_ENCODE_DISABLED;
+		break;
+	}
+	dwrq->flags |= IW_ENCODE_NOKEY;
+
+done:
+	kfree(ap_cfg);
+	LEAVE();
+	return ret;
+}
+
+#if (WIRELESS_EXT >= 18)
+/**
+ *  @brief Get IE
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     -EOPNOTSUPP
+ */
+static int
+woal_get_gen_ie(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	ENTER();
+	LEAVE();
+	return -EOPNOTSUPP;
+}
+
+/**
+ *  @brief Set IE
+ *
+ *  Pass an opaque block of data, expected to be IEEE IEs, to the driver
+ *    for eventual passthrough to the firmware in an associate/join
+ *    (and potentially start) command.
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_gen_ie(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	mlan_uap_bss_param *sys_cfg = NULL;
+	IEEEtypes_Header_t *tlv = NULL;
+	int tlv_hdr_len = sizeof(IEEEtypes_Header_t), tlv_buf_left = 0;
+	int ret = 0;
+
+	ENTER();
+
+	sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	/* Initialize the invalid values so that the correct values
+	 * below are downloaded to firmware */
+	woal_set_sys_config_invalid_data(sys_cfg);
+
+	tlv_buf_left = dwrq->length;
+	tlv = (IEEEtypes_Header_t *)extra;
+	while (tlv_buf_left >= tlv_hdr_len) {
+		if (tlv->element_id == WPA_IE) {
+			sys_cfg->protocol |= PROTOCOL_WPA;
+			if (priv->pairwise_cipher == CIPHER_TKIP) {
+				sys_cfg->wpa_cfg.pairwise_cipher_wpa =
+					CIPHER_TKIP;
+				PRINTM(MINFO, "Set IE Cipher TKIP\n");
+			}
+			if (priv->pairwise_cipher == CIPHER_AES_CCMP) {
+				sys_cfg->wpa_cfg.pairwise_cipher_wpa =
+					CIPHER_AES_CCMP;
+				PRINTM(MINFO, "Set IE Cipher CCMP\n");
+			}
+			if (priv->pairwise_cipher ==
+			    (CIPHER_TKIP | CIPHER_AES_CCMP)) {
+				sys_cfg->wpa_cfg.pairwise_cipher_wpa =
+					CIPHER_TKIP | CIPHER_AES_CCMP;
+				PRINTM(MINFO, "Set IE Cipher TKIP + CCMP\n");
+			}
+			moal_memcpy_ext(priv->phandle,
+					priv->bcn_ie_buf + priv->bcn_ie_len,
+					((t_u8 *)tlv),
+					sizeof(IEEEtypes_Header_t) + tlv->len,
+					sizeof(priv->bcn_ie_buf) -
+					priv->bcn_ie_len);
+			priv->bcn_ie_len +=
+				sizeof(IEEEtypes_Header_t) + tlv->len;
+		}
+		if (tlv->element_id == RSN_IE) {
+			sys_cfg->protocol |= PROTOCOL_WPA2;
+			if (priv->pairwise_cipher == CIPHER_TKIP) {
+				sys_cfg->wpa_cfg.pairwise_cipher_wpa2 =
+					CIPHER_TKIP;
+			}
+			if (priv->pairwise_cipher == CIPHER_AES_CCMP) {
+				sys_cfg->wpa_cfg.pairwise_cipher_wpa2 =
+					CIPHER_AES_CCMP;
+			}
+			if (priv->pairwise_cipher ==
+			    (CIPHER_TKIP | CIPHER_AES_CCMP)) {
+				sys_cfg->wpa_cfg.pairwise_cipher_wpa2 =
+					(CIPHER_TKIP | CIPHER_AES_CCMP);
+			}
+			moal_memcpy_ext(priv->phandle,
+					priv->bcn_ie_buf + priv->bcn_ie_len,
+					((t_u8 *)tlv),
+					sizeof(IEEEtypes_Header_t) + tlv->len,
+					sizeof(priv->bcn_ie_buf) -
+					priv->bcn_ie_len);
+			priv->bcn_ie_len +=
+				sizeof(IEEEtypes_Header_t) + tlv->len;
+		}
+		if (priv->group_cipher == CIPHER_TKIP)
+			sys_cfg->wpa_cfg.group_cipher = CIPHER_TKIP;
+		if (priv->group_cipher == CIPHER_AES_CCMP)
+			sys_cfg->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+		tlv_buf_left -= (tlv_hdr_len + tlv->len);
+		tlv = (IEEEtypes_Header_t *)((t_u8 *)tlv + tlv_hdr_len +
+					     tlv->len);
+	}
+	sys_cfg->key_mgmt = priv->uap_key_mgmt;
+	if (sys_cfg->key_mgmt & KEY_MGMT_PSK)
+		sys_cfg->key_mgmt_operation |= 0x01;
+	if (sys_cfg->key_mgmt & KEY_MGMT_EAP)
+		sys_cfg->key_mgmt_operation |= 0x03;
+
+	if (sys_cfg->protocol) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+					    sys_cfg)) {
+			PRINTM(MERROR, "Error setting AP configuration\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->pairwise_cipher = 0;
+		priv->group_cipher = 0;
+
+		/* custom IE command to set priv->bcn_ie_buf */
+		if (MLAN_STATUS_SUCCESS !=
+#define UAP_RSN_MASK (BIT(8) | BIT(5) | BIT(1) | BIT(3))
+		    woal_set_get_custom_ie(priv, UAP_RSN_MASK, priv->bcn_ie_buf,
+					   priv->bcn_ie_len)) {
+			PRINTM(MERROR, "Error setting wpa-rsn IE\n");
+			ret = -EFAULT;
+		}
+	} else if (dwrq->length == 0) {
+		/* custom IE command to re-set priv->bcn_ie_buf */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_custom_ie(priv, 0, priv->bcn_ie_buf,
+					   priv->bcn_ie_len)) {
+			PRINTM(MERROR, "Error resetting wpa-rsn IE\n");
+			ret = -EFAULT;
+		}
+		priv->bcn_ie_len = 0;
+	}
+
+done:
+	kfree(sys_cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Extended version of encoding configuration
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return              0 --success, otherwise fail
+ */
+static int
+woal_set_encode_ext(struct net_device *dev,
+		    struct iw_request_info *info,
+		    union iwreq_data *wrqu, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	int key_index;
+	t_u8 *pkey_material = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_uap_bss_param *sys_cfg = NULL;
+	wep_key *pwep_key = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+	if (key_index < 0 || key_index > 5) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) {
+		ret = -EINVAL;
+		goto done;
+	}
+	sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Initialize the invalid values so that the correct values
+	 * below are downloaded to firmware */
+	woal_set_sys_config_invalid_data(sys_cfg);
+
+	pkey_material = (t_u8 *)(ext + 1);
+	/* Disable Key */
+	if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) {
+		sys_cfg->protocol = PROTOCOL_NO_SECURITY;
+	} else if (ext->alg == IW_ENCODE_ALG_WEP) {
+		sys_cfg->protocol = PROTOCOL_STATIC_WEP;
+		/* Set WEP key */
+		switch (key_index) {
+		case 0:
+			pwep_key = &sys_cfg->wep_cfg.key0;
+			break;
+		case 1:
+			pwep_key = &sys_cfg->wep_cfg.key1;
+			break;
+		case 2:
+			pwep_key = &sys_cfg->wep_cfg.key2;
+			break;
+		case 3:
+			pwep_key = &sys_cfg->wep_cfg.key3;
+			break;
+		}
+		if (pwep_key) {
+			pwep_key->key_index = key_index;
+			pwep_key->is_default = MTRUE;
+			pwep_key->length = ext->key_len;
+			moal_memcpy_ext(priv->phandle, pwep_key->key,
+					pkey_material, ext->key_len,
+					sizeof(pwep_key->key));
+		}
+	} else {
+		/* Set GTK/PTK key */
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+		if (req == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		sec = (mlan_ds_sec_cfg *)req->pbuf;
+		sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+		req->req_id = MLAN_IOCTL_SEC_CFG;
+		req->action = MLAN_ACT_SET;
+		sec->param.encrypt_key.key_len = ext->key_len;
+		sec->param.encrypt_key.key_index = key_index;
+		moal_memcpy_ext(priv->phandle,
+				sec->param.encrypt_key.key_material,
+				pkey_material, ext->key_len,
+				sizeof(sec->param.encrypt_key.key_material));
+		moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
+				ext->addr.sa_data, ETH_ALEN,
+				sizeof(sec->param.encrypt_key.mac_addr));
+		sec->param.encrypt_key.key_flags = ext->ext_flags;
+		if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.pn,
+					(t_u8 *)ext->rx_seq, SEQ_MAX_SIZE,
+					sizeof(sec->param.encrypt_key.pn));
+			DBG_HEXDUMP(MCMD_D, "Uap Rx PN",
+				    sec->param.encrypt_key.pn, SEQ_MAX_SIZE);
+		}
+		if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.pn,
+					(t_u8 *)ext->tx_seq, SEQ_MAX_SIZE,
+					sizeof(sec->param.encrypt_key.pn));
+			DBG_HEXDUMP(MCMD_D, "Uap Tx PN",
+				    sec->param.encrypt_key.pn, SEQ_MAX_SIZE);
+		}
+		PRINTM(MIOCTL,
+		       "set uap wpa key key_index=%d, key_len=%d key_flags=0x%x "
+		       MACSTR "\n", key_index, ext->key_len,
+		       sec->param.encrypt_key.key_flags,
+		       MAC2STR(sec->param.encrypt_key.mac_addr));
+		DBG_HEXDUMP(MCMD_D, "uap wpa key", pkey_material, ext->key_len);
+#define IW_ENCODE_ALG_AES_CMAC 5
+
+		if (ext->alg == IW_ENCODE_ALG_AES_CMAC)
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_AES_MCAST_IGTK;
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS)
+			ret = -EFAULT;
+		/* Cipher set will be done in set generic IE */
+		priv->pairwise_cipher = ext->alg;
+		priv->group_cipher = ext->alg;
+		goto done;	/* No AP configuration */
+	}
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_cfg)) {
+		PRINTM(MERROR, "Error setting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	kfree(sys_cfg);
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Extended version of encoding configuration
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             -EOPNOTSUPP
+ */
+static int
+woal_get_encode_ext(struct net_device *dev,
+		    struct iw_request_info *info,
+		    union iwreq_data *wrqu, char *extra)
+{
+	ENTER();
+	LEAVE();
+	return -EOPNOTSUPP;
+}
+
+/**
+ *  @brief  Request MLME operation
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0--success, otherwise fail
+ */
+static int
+woal_set_mlme(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	struct iw_mlme *mlme = (struct iw_mlme *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ds_bss *bss = NULL;
+	mlan_ds_get_info *pinfo = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sta_list *sta_list = NULL;
+	const t_u8 bc_addr[] = { 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF };
+	t_u8 sta_addr[ETH_ALEN];
+	int ret = 0, i;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(sta_addr, 0, ETH_ALEN);
+	if ((mlme->cmd == IW_MLME_DEAUTH) || (mlme->cmd == IW_MLME_DISASSOC)) {
+		moal_memcpy_ext(priv->phandle, sta_addr,
+				(t_u8 *)mlme->addr.sa_data, ETH_ALEN,
+				sizeof(sta_addr));
+		PRINTM(MIOCTL, "Deauth station: " MACSTR ", reason=%d\n",
+		       MAC2STR(sta_addr), mlme->reason_code);
+
+		/* FIXME: For flushing all stations we need to use zero MAC,
+		 * but right now the FW does not support this. So, manually
+		 * delete each one individually.
+		 */
+		/* If deauth all station, get the connected STA list first */
+		if (!memcmp(bc_addr, sta_addr, ETH_ALEN)) {
+			PRINTM(MIOCTL, "Deauth all stations\n");
+			req = woal_alloc_mlan_ioctl_req(sizeof
+							(mlan_ds_get_info));
+			if (req == NULL) {
+				LEAVE();
+				return -ENOMEM;
+			}
+			pinfo = (mlan_ds_get_info *)req->pbuf;
+			pinfo->sub_command = MLAN_OID_UAP_STA_LIST;
+			req->req_id = MLAN_IOCTL_GET_INFO;
+			req->action = MLAN_ACT_GET;
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+			sta_list =
+				kmalloc(sizeof(mlan_ds_sta_list), GFP_KERNEL);
+			if (sta_list == NULL) {
+				PRINTM(MERROR, "Memory allocation failed!\n");
+				ret = -ENOMEM;
+				goto done;
+			}
+			moal_memcpy_ext(priv->phandle, sta_list,
+					&pinfo->param.sta_list,
+					sizeof(mlan_ds_sta_list),
+					sizeof(mlan_ds_sta_list));
+			kfree(req);
+			req = NULL;
+		}
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+		if (req == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		bss = (mlan_ds_bss *)req->pbuf;
+		bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
+		req->req_id = MLAN_IOCTL_BSS;
+		req->action = MLAN_ACT_SET;
+
+		if (sta_list && !memcmp(bc_addr, sta_addr, ETH_ALEN)) {
+			for (i = 0; i < sta_list->sta_count; i++) {
+				moal_memcpy_ext(priv->phandle,
+						bss->param.deauth_param.
+						mac_addr,
+						sta_list->info[i].mac_address,
+						ETH_ALEN,
+						sizeof(bss->param.deauth_param.
+						       mac_addr));
+				bss->param.deauth_param.reason_code =
+					mlme->reason_code;
+
+				status = woal_request_ioctl(priv, req,
+							    MOAL_IOCTL_WAIT);
+				if (status != MLAN_STATUS_SUCCESS) {
+					ret = -EFAULT;
+					goto done;
+				}
+			}
+		} else {
+			moal_memcpy_ext(priv->phandle,
+					bss->param.deauth_param.mac_addr,
+					sta_addr, ETH_ALEN,
+					sizeof(bss->param.deauth_param.
+					       mac_addr));
+			bss->param.deauth_param.reason_code = mlme->reason_code;
+
+			status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+			if (status != MLAN_STATUS_SUCCESS) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	kfree(sta_list);
+	LEAVE();
+	return ret;
+}
+
+/** @brief Set authentication mode parameters
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_auth(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_param *vwrq = &wrqu->param;
+	mlan_uap_bss_param *sys_cfg = NULL;
+
+	ENTER();
+
+	sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return -EFAULT;
+	}
+	/* Initialize the invalid values so that the correct values
+	 * below are downloaded to firmware */
+	woal_set_sys_config_invalid_data(sys_cfg);
+
+	switch (vwrq->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_CIPHER_PAIRWISE:
+		/* Rest are not supported now */
+		if (vwrq->value & IW_AUTH_CIPHER_NONE)
+			/* XXX Do not delete no-operation line */
+			;
+		else if (vwrq->value & IW_AUTH_CIPHER_WEP40)
+			/* XXX Do not delete no-operation line */
+			;
+		else if (vwrq->value & IW_AUTH_CIPHER_WEP104)
+			/* XXX Do not delete no-operation line */
+			;
+		else if (vwrq->value == IW_AUTH_CIPHER_TKIP) {
+			sys_cfg->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP;
+			sys_cfg->wpa_cfg.pairwise_cipher_wpa2 = CIPHER_TKIP;
+			priv->pairwise_cipher = CIPHER_TKIP;
+			if (!priv->uap_key_mgmt)
+				priv->uap_key_mgmt = KEY_MGMT_PSK;
+			PRINTM(MINFO, "Set Auth Cipher TKIP\n");
+		} else if (vwrq->value == IW_AUTH_CIPHER_CCMP) {
+			sys_cfg->wpa_cfg.pairwise_cipher_wpa = CIPHER_AES_CCMP;
+			sys_cfg->wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP;
+			priv->pairwise_cipher = CIPHER_AES_CCMP;
+			if (!priv->uap_key_mgmt)
+				priv->uap_key_mgmt = KEY_MGMT_PSK;
+			PRINTM(MINFO, "Set Auth Cipher CCMP\n");
+		} else if (vwrq->value ==
+			   (IW_AUTH_CIPHER_TKIP | IW_AUTH_CIPHER_CCMP)) {
+			sys_cfg->wpa_cfg.pairwise_cipher_wpa =
+				(CIPHER_TKIP | CIPHER_AES_CCMP);
+			sys_cfg->wpa_cfg.pairwise_cipher_wpa2 =
+				(CIPHER_TKIP | CIPHER_AES_CCMP);
+			priv->pairwise_cipher = (CIPHER_TKIP | CIPHER_AES_CCMP);
+			if (!priv->uap_key_mgmt)
+				priv->uap_key_mgmt = KEY_MGMT_PSK;
+			PRINTM(MINFO, "Set Auth Cipher TKIP + CCMP\n");
+		}
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+		/* Rest are not supported now */
+		if (vwrq->value & IW_AUTH_CIPHER_NONE)
+			/* XXX Do not delete no-operation line */
+			;
+		else if (vwrq->value & IW_AUTH_CIPHER_WEP40)
+			/* XXX Do not delete no-operation line */
+			;
+		else if (vwrq->value & IW_AUTH_CIPHER_WEP104)
+			/* XXX Do not delete no-operation line */
+			;
+		else if (vwrq->value & IW_AUTH_CIPHER_TKIP) {
+			sys_cfg->wpa_cfg.group_cipher = CIPHER_TKIP;
+			priv->group_cipher = CIPHER_TKIP;
+			if (!priv->uap_key_mgmt)
+				priv->uap_key_mgmt = KEY_MGMT_PSK;
+			PRINTM(MINFO, "Set Auth Cipher TKIP\n");
+		} else if (vwrq->value & IW_AUTH_CIPHER_CCMP) {
+			sys_cfg->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
+			priv->group_cipher = CIPHER_AES_CCMP;
+			if (!priv->uap_key_mgmt)
+				priv->uap_key_mgmt = KEY_MGMT_PSK;
+			PRINTM(MINFO, "Set Auth Cipher CCMP\n");
+		}
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		switch (vwrq->value) {
+		case IW_AUTH_ALG_SHARED_KEY:
+			PRINTM(MINFO, "Auth mode shared key!\n");
+			sys_cfg->auth_mode = MLAN_AUTH_MODE_SHARED;
+			break;
+		case IW_AUTH_ALG_LEAP:
+			break;
+		case IW_AUTH_ALG_OPEN_SYSTEM:
+			PRINTM(MINFO, "Auth mode open!\n");
+			sys_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
+			break;
+		default:
+			PRINTM(MINFO, "Auth mode auto!\n");
+			break;
+		}
+		break;
+	case IW_AUTH_WPA_VERSION:
+		switch (vwrq->value) {
+		case IW_AUTH_WPA_VERSION_DISABLED:
+			sys_cfg->protocol = PROTOCOL_NO_SECURITY;
+			break;
+		case IW_AUTH_WPA_VERSION_WPA:
+			sys_cfg->protocol = PROTOCOL_WPA;
+			break;
+		case IW_AUTH_WPA_VERSION_WPA2:
+			sys_cfg->protocol = PROTOCOL_WPA2;
+			break;
+		case IW_AUTH_WPA_VERSION_WPA | IW_AUTH_WPA_VERSION_WPA2:
+			sys_cfg->protocol = PROTOCOL_WPA2_MIXED;
+			break;
+		default:
+			break;
+		}
+		priv->uap_protocol = sys_cfg->protocol;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		switch (vwrq->value) {
+		case IW_AUTH_KEY_MGMT_802_1X:
+			sys_cfg->key_mgmt |= KEY_MGMT_EAP;
+			priv->uap_key_mgmt |= KEY_MGMT_EAP;
+			break;
+		case IW_AUTH_KEY_MGMT_PSK:
+			sys_cfg->key_mgmt |= KEY_MGMT_PSK;
+			priv->uap_key_mgmt |= KEY_MGMT_PSK;
+			break;
+		default:
+			break;
+		}
+		break;
+	case IW_AUTH_WPA_ENABLED:
+	case IW_AUTH_TKIP_COUNTERMEASURES:
+	case IW_AUTH_DROP_UNENCRYPTED:
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+	case IW_AUTH_ROAMING_CONTROL:
+	case IW_AUTH_PRIVACY_INVOKED:
+	default:
+		kfree(sys_cfg);
+		LEAVE();
+		return -EOPNOTSUPP;	/* No AP configuration */
+	}
+	if (!sys_cfg->key_mgmt)
+		sys_cfg->key_mgmt = priv->uap_key_mgmt;
+	if (sys_cfg->key_mgmt & KEY_MGMT_PSK)
+		sys_cfg->key_mgmt_operation |= 0x01;
+	if (sys_cfg->key_mgmt & KEY_MGMT_EAP)
+		sys_cfg->key_mgmt_operation |= 0x03;
+	if (!sys_cfg->protocol)
+		sys_cfg->protocol = priv->uap_protocol;
+
+	/* Set AP configuration */
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_cfg)) {
+		PRINTM(MERROR, "Error setting AP confiruration\n");
+		goto done;
+	}
+
+done:
+	kfree(sys_cfg);
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get authentication mode parameters
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_auth(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_param *vwrq = &wrqu->param;
+	mlan_uap_bss_param *ap_cfg = NULL;
+
+	ENTER();
+
+	ap_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!ap_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		kfree(ap_cfg);
+		LEAVE();
+		return -EFAULT;
+	}
+	switch (vwrq->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_CIPHER_PAIRWISE:
+		if (ap_cfg->wpa_cfg.pairwise_cipher_wpa == CIPHER_TKIP ||
+		    ap_cfg->wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP)
+			vwrq->value = IW_AUTH_CIPHER_TKIP;
+		else if (ap_cfg->wpa_cfg.pairwise_cipher_wpa ==
+			 CIPHER_AES_CCMP ||
+			 ap_cfg->wpa_cfg.pairwise_cipher_wpa2 ==
+			 CIPHER_AES_CCMP)
+			vwrq->value = IW_AUTH_CIPHER_CCMP;
+		else
+			vwrq->value = IW_AUTH_CIPHER_NONE;
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+		if (ap_cfg->wpa_cfg.group_cipher == CIPHER_TKIP)
+			vwrq->value = IW_AUTH_CIPHER_TKIP;
+		else if (ap_cfg->wpa_cfg.group_cipher == CIPHER_AES_CCMP)
+			vwrq->value = IW_AUTH_CIPHER_CCMP;
+		else
+			vwrq->value = IW_AUTH_CIPHER_NONE;
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		if (ap_cfg->auth_mode == MLAN_AUTH_MODE_SHARED)
+			vwrq->value = IW_AUTH_ALG_SHARED_KEY;
+		else if (ap_cfg->auth_mode == MLAN_AUTH_MODE_NETWORKEAP)
+			vwrq->value = IW_AUTH_ALG_LEAP;
+		else
+			vwrq->value = IW_AUTH_ALG_OPEN_SYSTEM;
+		break;
+	case IW_AUTH_WPA_ENABLED:
+		if (ap_cfg->protocol == PROTOCOL_WPA ||
+		    ap_cfg->protocol == PROTOCOL_WPA2 ||
+		    ap_cfg->protocol == PROTOCOL_WPA2_MIXED)
+			vwrq->value = 1;
+		else
+			vwrq->value = 0;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		if (ap_cfg->key_mgmt & KEY_MGMT_EAP)
+			vwrq->value |= IW_AUTH_KEY_MGMT_802_1X;
+		if (ap_cfg->key_mgmt & KEY_MGMT_PSK)
+			vwrq->value |= IW_AUTH_KEY_MGMT_PSK;
+		break;
+	case IW_AUTH_WPA_VERSION:
+	case IW_AUTH_TKIP_COUNTERMEASURES:
+	case IW_AUTH_DROP_UNENCRYPTED:
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+	case IW_AUTH_ROAMING_CONTROL:
+	case IW_AUTH_PRIVACY_INVOKED:
+	default:
+		kfree(ap_cfg);
+		LEAVE();
+		return -EOPNOTSUPP;
+	}
+	kfree(ap_cfg);
+	LEAVE();
+	return 0;
+}
+#endif /* WE >= 18 */
+
+/* Data rate listing
+ *      MULTI_BANDS:
+ *              abg             a       b       b/g
+ *  Infra       G(12)           A(8)    B(4)    G(12)
+ *  Adhoc       A+B(12)         A(8)    B(4)    B(4)
+ *      non-MULTI_BANDS:
+										b       b/g
+ *  Infra                               B(4)    G(12)
+ *  Adhoc                               B(4)    B(4)
+ */
+/**
+ *  @brief Get Range Info
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_range(struct net_device *dev, struct iw_request_info *info,
+	       union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	mlan_uap_bss_param *ap_cfg = NULL;
+	struct iw_range *range = (struct iw_range *)extra;
+	t_u8 band = 0;
+	int i;
+
+	ENTER();
+
+	ap_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!ap_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		kfree(ap_cfg);
+		LEAVE();
+		return -EFAULT;
+	}
+	dwrq->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+
+	range->min_nwid = 0;
+	range->max_nwid = 0;
+
+	range->num_bitrates = MAX_DATA_RATES;
+	for (i = 0;
+	     i < MIN(MAX_DATA_RATES, IW_MAX_BITRATES) && ap_cfg->rates[i];
+	     i++) {
+		range->bitrate[i] = (ap_cfg->rates[i] & 0x7f) * 500000;
+	}
+	range->num_bitrates = i;
+	PRINTM(MINFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
+	       range->num_bitrates);
+
+	range->num_frequency = MIN(ap_cfg->num_of_chan, IW_MAX_FREQUENCIES);
+
+	for (i = 0; i < range->num_frequency; i++) {
+		range->freq[i].i = (long)ap_cfg->chan_list[i].chan_number;
+		band = (ap_cfg->chan_list[i].bandcfg.chanBand == BAND_5GHZ);
+		range->freq[i].m =
+			(long)channel_to_frequency(ap_cfg->chan_list[i].
+						   chan_number, band) * 100000;
+		range->freq[i].e = 1;
+	}
+
+	PRINTM(MINFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
+	       IW_MAX_FREQUENCIES, range->num_frequency);
+
+	range->num_channels = range->num_frequency;
+
+	woal_sort_channels(&range->freq[0], range->num_frequency);
+
+	/*
+	 * Set an indication of the max TCP throughput in bit/s that we can
+	 * expect using this interface
+	 */
+	if (i > 2)
+		range->throughput = 5000 * 1000;
+	else
+		range->throughput = 1500 * 1000;
+
+	range->min_rts = MLAN_RTS_MIN_VALUE;
+	range->max_rts = MLAN_RTS_MAX_VALUE;
+	range->min_frag = MLAN_FRAG_MIN_VALUE;
+	range->max_frag = MLAN_FRAG_MAX_VALUE;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = 4;
+
+/** Minimum power period */
+#define IW_POWER_PERIOD_MIN 1000000	/* 1 sec */
+/** Maximum power period */
+#define IW_POWER_PERIOD_MAX 120000000	/* 2 min */
+/** Minimum power timeout value */
+#define IW_POWER_TIMEOUT_MIN 1000	/* 1 ms  */
+/** Maximim power timeout value */
+#define IW_POWER_TIMEOUT_MAX 1000000	/* 1 sec */
+
+	/* Power Management duration & timeout */
+	range->min_pmp = IW_POWER_PERIOD_MIN;
+	range->max_pmp = IW_POWER_PERIOD_MAX;
+	range->min_pmt = IW_POWER_TIMEOUT_MIN;
+	range->max_pmt = IW_POWER_TIMEOUT_MAX;
+	range->pmp_flags = IW_POWER_PERIOD;
+	range->pmt_flags = IW_POWER_TIMEOUT;
+	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
+
+	/*
+	 * Minimum version we recommend
+	 */
+	range->we_version_source = 15;
+
+	/*
+	 * Version we are compiled with
+	 */
+	range->we_version_compiled = WIRELESS_EXT;
+
+	range->retry_capa = IW_RETRY_LIMIT;
+	range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+
+	range->min_retry = MLAN_TX_RETRY_MIN;
+	range->max_retry = MLAN_TX_RETRY_MAX;
+
+#if (WIRELESS_EXT >= 18)
+	if (ap_cfg->protocol & PROTOCOL_WPA)
+		range->enc_capa |= IW_ENC_CAPA_WPA;
+	if (ap_cfg->protocol & PROTOCOL_WPA2)
+		range->enc_capa |= IW_ENC_CAPA_WPA2;
+	if (ap_cfg->wpa_cfg.pairwise_cipher_wpa == CIPHER_TKIP ||
+	    ap_cfg->wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP ||
+	    ap_cfg->wpa_cfg.group_cipher == CIPHER_TKIP)
+		range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
+	if (ap_cfg->wpa_cfg.pairwise_cipher_wpa == CIPHER_AES_CCMP ||
+	    ap_cfg->wpa_cfg.pairwise_cipher_wpa2 == CIPHER_AES_CCMP ||
+	    ap_cfg->wpa_cfg.group_cipher == CIPHER_AES_CCMP)
+		range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+	kfree(ap_cfg);
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Set priv command
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_priv(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	ENTER();
+	LEAVE();
+	return -EOPNOTSUPP;
+}
+
+/**
+ *  @brief Set essid
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0--success, otherwise fail
+ */
+static int
+woal_set_essid(struct net_device *dev, struct iw_request_info *info,
+	       union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	mlan_uap_bss_param *sys_cfg = NULL;
+	int ret = 0;
+
+	ENTER();
+
+	/* Check the size of the string */
+	if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+		ret = -E2BIG;
+		goto done;
+	}
+	sys_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!sys_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Initialize the invalid values so that the correct values
+	 * below are downloaded to firmware */
+	woal_set_sys_config_invalid_data(sys_cfg);
+
+	/* Set the SSID */
+#if WIRELESS_EXT > 20
+	sys_cfg->ssid.ssid_len = dwrq->length;
+#else
+	sys_cfg->ssid.ssid_len = dwrq->length - 1;
+#endif
+
+	moal_memcpy_ext(priv->phandle, sys_cfg->ssid.ssid, extra,
+			sys_cfg->ssid.ssid_len, sizeof(sys_cfg->ssid.ssid));
+	if (!sys_cfg->ssid.ssid_len || sys_cfg->ssid.ssid[0] < 0x20) {
+		PRINTM(MERROR, "Invalid SSID - aborting set_essid\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	PRINTM(MINFO, "Requested new SSID = %s\n",
+	       (sys_cfg->ssid.ssid_len > 0) ? (char *)sys_cfg->ssid.ssid :
+	       "NULL");
+
+	/* Set AP configuration */
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
+							   MOAL_IOCTL_WAIT,
+							   sys_cfg)) {
+		PRINTM(MERROR, "Error setting AP confiruration\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	kfree(sys_cfg);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get current essid
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param info     A pointer to iw_request_info structure
+ *  @param dwrq     A pointer to iw_point structure
+ *  @param extra    A pointer to extra data buf
+ *
+ *  @return         0--success, otherwise fail
+ */
+static int
+woal_get_essid(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_uap_bss_param *ap_cfg = NULL;
+
+	ENTER();
+
+	ap_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
+	if (!ap_cfg) {
+		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
+		return -EFAULT;
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
+							   MOAL_IOCTL_WAIT,
+							   ap_cfg)) {
+		PRINTM(MERROR, "Error getting AP confiruration\n");
+		kfree(ap_cfg);
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (priv->bss_started) {
+		dwrq->length = MIN(dwrq->length, ap_cfg->ssid.ssid_len);
+		moal_memcpy_ext(priv->phandle, extra, ap_cfg->ssid.ssid,
+				dwrq->length, dwrq->length);
+	} else
+		dwrq->length = 0;
+
+	dwrq->flags = 1;
+	kfree(ap_cfg);
+	LEAVE();
+	return 0;
+}
+
+/**
+ * iwconfig settable callbacks
+ */
+static const iw_handler woal_handler[] = {
+	(iw_handler) woal_config_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) woal_get_name,	/* SIOCGIWNAME */
+	(iw_handler) NULL,	/* SIOCSIWNWID */
+	(iw_handler) NULL,	/* SIOCGIWNWID */
+	(iw_handler) woal_set_freq,	/* SIOCSIWFREQ */
+	(iw_handler) woal_get_freq,	/* SIOCGIWFREQ */
+	(iw_handler) woal_set_bss_mode,	/* SIOCSIWMODE */
+	(iw_handler) woal_get_bss_mode,	/* SIOCGIWMODE */
+	(iw_handler) NULL,	/* SIOCSIWSENS */
+	(iw_handler) NULL,	/* SIOCGIWSENS */
+	(iw_handler) NULL,	/* SIOCSIWRANGE */
+	(iw_handler) woal_get_range,	/* SIOCGIWRANGE */
+	(iw_handler) woal_set_priv,	/* SIOCSIWPRIV */
+	(iw_handler) NULL,	/* SIOCGIWPRIV */
+	(iw_handler) NULL,	/* SIOCSIWSTATS */
+	(iw_handler) NULL,	/* SIOCGIWSTATS */
+#if WIRELESS_EXT > 15
+#ifdef CONFIG_WEXT_SPY
+	iw_handler_set_spy,	/* SIOCSIWSPY */
+	iw_handler_get_spy,	/* SIOCGIWSPY */
+	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
+#else
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+#endif
+#else /* WIRELESS_EXT > 15 */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+#endif /* WIRELESS_EXT > 15 */
+	(iw_handler) woal_set_wap,	/* SIOCSIWAP */
+	(iw_handler) woal_get_wap,	/* SIOCGIWAP */
+#if WIRELESS_EXT >= 18
+	(iw_handler) woal_set_mlme,	/* SIOCSIWMLME  */
+#else
+	(iw_handler) NULL,	/* -- hole -- */
+#endif
+	/* (iw_handler) wlan_get_aplist, *//* SIOCGIWAPLIST */
+	NULL,			/* SIOCGIWAPLIST */
+#if WIRELESS_EXT > 13
+	(iw_handler) NULL,	/* SIOCSIWSCAN */
+	(iw_handler) NULL,	/* SIOCGIWSCAN */
+#else /* WIRELESS_EXT > 13 */
+	(iw_handler) NULL,	/* SIOCSIWSCAN */
+	(iw_handler) NULL,	/* SIOCGIWSCAN */
+#endif /* WIRELESS_EXT > 13 */
+	(iw_handler) woal_set_essid,	/* SIOCSIWESSID */
+	(iw_handler) woal_get_essid,	/* SIOCGIWESSID */
+	(iw_handler) NULL,	/* SIOCSIWNICKN */
+	(iw_handler) NULL,	/* SIOCGIWNICKN */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* SIOCSIWRATE */
+	(iw_handler) NULL,	/* SIOCGIWRATE */
+	(iw_handler) NULL,	/* SIOCSIWRTS */
+	(iw_handler) NULL,	/* SIOCGIWRTS */
+	(iw_handler) NULL,	/* SIOCSIWFRAG */
+	(iw_handler) NULL,	/* SIOCGIWFRAG */
+	(iw_handler) NULL,	/* SIOCSIWTXPOW */
+	(iw_handler) NULL,	/* SIOCGIWTXPOW */
+	(iw_handler) NULL,	/* SIOCSIWRETRY */
+	(iw_handler) NULL,	/* SIOCGIWRETRY */
+	(iw_handler) woal_set_encode,	/* SIOCSIWENCODE */
+	(iw_handler) woal_get_encode,	/* SIOCGIWENCODE */
+	(iw_handler) NULL,	/* SIOCSIWPOWER */
+	(iw_handler) NULL,	/* SIOCGIWPOWER */
+#if (WIRELESS_EXT >= 18)
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) woal_set_gen_ie,	/* SIOCSIWGENIE */
+	(iw_handler) woal_get_gen_ie,	/* SIOCGIWGENIE */
+	(iw_handler) woal_set_auth,	/* SIOCSIWAUTH  */
+	(iw_handler) woal_get_auth,	/* SIOCGIWAUTH  */
+	(iw_handler) woal_set_encode_ext,	/* SIOCSIWENCODEEXT */
+	(iw_handler) woal_get_encode_ext,	/* SIOCGIWENCODEEXT */
+#endif /* WIRELESSS_EXT >= 18 */
+};
+
+/**
+ * iwpriv settable callbacks
+ */
+static const iw_handler woal_private_handler[] = {
+	NULL,			/* SIOCIWFIRSTPRIV */
+};
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+// clang-format off
+/** wlan_handler_def */
+struct iw_handler_def woal_uap_handler_def = {
+	.num_standard = ARRAY_SIZE(woal_handler),
+	.num_private = ARRAY_SIZE(woal_private_handler),
+	.num_private_args = ARRAY_SIZE(woal_uap_priv_args),
+	.standard = (iw_handler *) woal_handler,
+	.private = (iw_handler *) woal_private_handler,
+	.private_args = (struct iw_priv_args *)woal_uap_priv_args,
+#if WIRELESS_EXT > 20
+	.get_wireless_stats = woal_get_uap_wireless_stats,
+#endif
+};
+
+// clang-format on
+
+/**
+ *  @brief Get wireless statistics
+ *
+ *  @param dev          A pointer to net_device structure
+ *
+ *  @return             A pointer to iw_statistics buf
+ */
+struct iw_statistics *
+woal_get_uap_wireless_stats(struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u16 wait_option = MOAL_IOCTL_WAIT;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	/*
+	 * Since schedule() is not allowed from an atomic context
+	 * such as when dev_base_lock for netdevices is acquired
+	 * for reading/writing in kernel before this call, HostCmd
+	 * is issued in non-blocking way in such contexts and
+	 * blocking in other cases.
+	 */
+	if (in_atomic() || !write_can_lock(&dev_base_lock))
+		wait_option = MOAL_NO_WAIT;
+#endif
+
+	priv->w_stats.qual.qual = 0;
+	priv->w_stats.qual.level = 0;
+	priv->w_stats.discard.code = 0;
+	priv->w_stats.status = IW_MODE_MASTER;
+	woal_uap_get_stats(priv, wait_option, NULL);
+
+	LEAVE();
+	return &priv->w_stats;
+}
diff --git a/wlan_sd8987/mlinux/moal_usb.c b/wlan_sd8987/mlinux/moal_usb.c
new file mode 100755
index 0000000..0bba81b
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_usb.c
@@ -0,0 +1,2086 @@
+/** @file moal_usb.c
+ *
+ * @brief This file contains the interfaceing to USB bus
+ * driver.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#include "moal_main.h"
+#include "moal_usb.h"
+extern struct semaphore AddRemoveCardSem;
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+#if defined(USB8997) || defined(USB9098) || defined(USB9097) || defined(USB8978)
+/** Card-type detection frame response */
+typedef struct {
+	/** 32-bit ACK+WINNER field */
+	t_u32 ack_winner;
+	/** 32-bit Sequence number */
+	t_u32 seq;
+	/** 32-bit extend */
+	t_u32 extend;
+	/** 32-bit chip-revision code */
+	t_u32 chip_rev;
+	/** 32-bit strap setting */
+	t_u32 strap;
+} usb_ack_pkt;
+#endif
+
+/** NXP USB device */
+#define NXP_USB_DEVICE(vid, pid, name)                                         \
+	USB_DEVICE(vid, pid), .driver_info = (t_ptr)name
+
+/** Name of the USB driver */
+static const char usbdriver_name[] = "usbxxx";
+
+/** This structure contains the device signature */
+static struct usb_device_id woal_usb_table[] = {
+/* Enter the device signature inside */
+#ifdef USB8801
+	{NXP_USB_DEVICE(USB8801_VID_1, USB8801_PID_1, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8801_VID_1, USB8801_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB8897
+	{NXP_USB_DEVICE(USB8897_VID_1, USB8897_PID_1, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8897_VID_1, USB8897_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB8997
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_1, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997V2_PID_1,
+			"NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_2, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_3, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_4, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_5, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_6, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB8978
+	{NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_1, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_1_BT,
+			"NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2_BT,
+			"NXP WLAN USB Adapter")},
+#endif
+#ifdef USB9098
+	{NXP_USB_DEVICE(USB9098_VID_1, USB9098_PID_1, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB9098_VID_1, USB9098_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB9097
+	{NXP_USB_DEVICE(USB9097_VID_1, USB9097_PID_1, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB9097_VID_1, USB9097_PID_2, "NXP WLAN USB Adapter")},
+#endif
+	/* Terminating entry */
+	{},
+};
+
+/** This structure contains the device signature */
+static struct usb_device_id woal_usb_table_skip_fwdnld[] = {
+/* Enter the device signature inside */
+#ifdef USB8801
+	{NXP_USB_DEVICE(USB8801_VID_1, USB8801_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB8897
+	{NXP_USB_DEVICE(USB8897_VID_1, USB8897_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB8997
+	{NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB8978
+	{NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2, "NXP WLAN USB Adapter")},
+	{NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2_BT,
+			"NXP WLAN USB Adapter")},
+#endif
+#ifdef USB9098
+	{NXP_USB_DEVICE(USB9098_VID_1, USB9098_PID_2, "NXP WLAN USB Adapter")},
+#endif
+#ifdef USB9097
+	{NXP_USB_DEVICE(USB9097_VID_1, USB9097_PID_2, "NXP WLAN USB Adapter")},
+#endif
+	/* Terminating entry */
+	{},
+};
+
+static mlan_status woal_usb_submit_rx_urb(urb_context *ctx, int size);
+static int woal_usb_probe(struct usb_interface *intf,
+			  const struct usb_device_id *id);
+static void woal_usb_disconnect(struct usb_interface *intf);
+static mlan_status woal_usb_write_data_sync(moal_handle *handle,
+					    mlan_buffer *pmbuf, t_u32 endpoint,
+					    t_u32 timeout);
+static mlan_status woal_usb_read_data_sync(moal_handle *handle,
+					   mlan_buffer *pmbuf, t_u32 endpoint,
+					   t_u32 timeout);
+#ifdef CONFIG_PM
+static int woal_usb_suspend(struct usb_interface *intf, pm_message_t message);
+static int woal_usb_resume(struct usb_interface *intf);
+#endif /* CONFIG_PM */
+
+/** woal_usb_driver */
+static struct usb_driver REFDATA woal_usb_driver = {
+	/* Driver name */
+	.name = usbdriver_name,
+
+	/* Probe function name */
+	.probe = woal_usb_probe,
+
+	/* Disconnect function name */
+	.disconnect = woal_usb_disconnect,
+
+	/* Device signature table */
+	.id_table = woal_usb_table,
+#ifdef CONFIG_PM
+	/* Suspend function name */
+	.suspend = woal_usb_suspend,
+
+	/* Resume function name */
+	.resume = woal_usb_resume,
+
+	/* Reset resume function name */
+	.reset_resume = woal_usb_resume,
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+	/* Driver supports autosuspend */
+	.supports_autosuspend = 1,
+#endif
+#endif /* CONFIG_PM */
+};
+
+MODULE_DEVICE_TABLE(usb, woal_usb_table);
+MODULE_DEVICE_TABLE(usb, woal_usb_table_skip_fwdnld);
+
+/* moal interface ops */
+static moal_if_ops usb_ops;
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+/**
+ *  @brief This function receive packet of the data/cmd/event packet
+ *         and pass to MLAN
+ *
+ *  @param urb		Pointer to struct urb
+ *  @param regs		Registers
+ *
+ *  @return 	   	N/A
+ */
+static void
+woal_usb_receive(struct urb *urb, struct pt_regs *regs)
+#else
+/**
+ * @brief This function receive packet of the data/cmd/event packet
+ *         and pass to MLAN
+ *
+ *  @param urb		Pointer to struct urb
+ *
+ *  @return 	   	N/A
+ */
+static void
+woal_usb_receive(struct urb *urb)
+#endif
+{
+	urb_context *context = NULL;
+	moal_handle *handle = NULL;
+	mlan_buffer *pmbuf = NULL;
+	struct usb_card_rec *cardp = NULL;
+	int recv_length;
+	int size;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!urb || !urb->context) {
+		PRINTM(MERROR, "URB or URB context is not valid in USB Rx\n");
+		LEAVE();
+		return;
+	}
+	context = (urb_context *)urb->context;
+	handle = context->handle;
+	pmbuf = context->pmbuf;
+	recv_length = urb->actual_length;
+
+	if (!handle || !handle->card || !pmbuf) {
+		PRINTM(MERROR,
+		       "moal handle, card structure or mlan_buffer is not valid in USB Rx\n");
+		LEAVE();
+		return;
+	}
+	cardp = (struct usb_card_rec *)handle->card;
+	if (cardp->rx_cmd_ep == context->ep)
+		atomic_dec(&cardp->rx_cmd_urb_pending);
+	else
+		atomic_dec(&cardp->rx_data_urb_pending);
+
+	if (recv_length) {
+		if (urb->status || (handle->surprise_removed == MTRUE)) {
+			if (handle->surprise_removed || handle->is_suspended) {
+				woal_free_mlan_buffer(handle, pmbuf);
+				context->pmbuf = NULL;
+				goto rx_exit;
+			} else {
+				PRINTM(MERROR,
+				       "EP %d Rx URB status failure: %d\n",
+				       context->ep, urb->status);
+				/* Do not free mlan_buffer in case of command ep
+				 */
+				if (cardp->rx_cmd_ep != context->ep)
+					woal_free_mlan_buffer(handle, pmbuf);
+				goto setup_for_next;
+			}
+		}
+		pmbuf->data_len = recv_length;
+		pmbuf->flags |= MLAN_BUF_FLAG_RX_DEAGGR;
+		/* Send packet to MLAN */
+		atomic_inc(&handle->rx_pending);
+		status = mlan_recv(handle->pmlan_adapter, pmbuf, context->ep);
+		PRINTM(MINFO, "Receive length = 0x%x, status=%d\n", recv_length,
+		       status);
+		if (status == MLAN_STATUS_PENDING) {
+			queue_work(handle->workqueue, &handle->main_work);
+			/* urb for data_ep is re-submitted now, unless we reach
+			 * USB_HIGH_RX_PENDING */
+			/* urb for cmd_ep will be re-submitted in callback
+			 * moal_recv_complete */
+			if (cardp->rx_cmd_ep == context->ep)
+				goto rx_exit;
+			else if (atomic_read(&handle->rx_pending) >=
+				 USB_HIGH_RX_PENDING) {
+				context->pmbuf = NULL;
+				goto rx_exit;
+			}
+		} else {
+			atomic_dec(&handle->rx_pending);
+			if (status == MLAN_STATUS_FAILURE) {
+				PRINTM(MERROR,
+				       "MLAN fail to process the receive data\n");
+			} else if ((status == MLAN_STATUS_SUCCESS) &&
+				   (pmbuf->flags &
+				    MLAN_BUF_FLAG_SLEEPCFM_RESP)) {
+				pmbuf->flags &= ~MLAN_BUF_FLAG_SLEEPCFM_RESP;
+				queue_work(handle->workqueue,
+					   &handle->main_work);
+			}
+			/* Do not free mlan_buffer in case of command ep */
+			if (cardp->rx_cmd_ep != context->ep)
+				woal_free_mlan_buffer(handle, pmbuf);
+		}
+	} else if (urb->status) {
+		if (!((cardp->rx_data_ep == context->ep) &&
+		      (cardp->resubmit_urbs == 1))) {
+			if (!handle->is_suspended) {
+				PRINTM(MMSG, "Card is removed: %d\n",
+				       urb->status);
+				handle->surprise_removed = MTRUE;
+			}
+		}
+		woal_free_mlan_buffer(handle, pmbuf);
+		context->pmbuf = NULL;
+		goto rx_exit;
+	} else {
+		/* Do not free mlan_buffer in case of command ep */
+		if (cardp->rx_cmd_ep != context->ep)
+			woal_free_mlan_buffer(handle, pmbuf);
+		goto setup_for_next;
+	}
+
+setup_for_next:
+	if (cardp->rx_cmd_ep == context->ep) {
+		size = MLAN_RX_CMD_BUF_SIZE;
+	} else {
+		if (cardp->rx_deaggr_ctrl.enable) {
+			size = cardp->rx_deaggr_ctrl.aggr_max;
+			if (cardp->rx_deaggr_ctrl.aggr_mode ==
+			    MLAN_USB_AGGR_MODE_NUM) {
+				size *= MAX(MLAN_USB_MAX_PKT_SIZE,
+					    cardp->rx_deaggr_ctrl.aggr_align);
+				size = MAX(size, MLAN_RX_DATA_BUF_SIZE);
+			}
+		} else
+			size = MLAN_RX_DATA_BUF_SIZE;
+	}
+	woal_usb_submit_rx_urb(context, size);
+
+rx_exit:
+	LEAVE();
+	return;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+/**
+ *  @brief  Call back function to handle the status of the Tx data URB
+ *
+ *  @param urb      Pointer to urb structure
+ *  @param regs     Registers
+ *
+ *  @return         N/A
+ */
+static void
+woal_usb_tx_complete(struct urb *urb, struct pt_regs *regs)
+#else
+/**
+ * @brief  Call back function to handle the status of the Tx data URB
+ *
+ * @param urb      Pointer to urb structure
+ *
+ * @return         N/A
+ */
+static void
+woal_usb_tx_complete(struct urb *urb)
+#endif
+{
+	urb_context *context = NULL;
+	moal_handle *handle = NULL;
+	struct usb_card_rec *cardp = NULL;
+
+	ENTER();
+
+	if (!urb || !urb->context) {
+		PRINTM(MERROR,
+		       "URB or URB context is not valid in USB Tx complete\n");
+		LEAVE();
+		return;
+	}
+	context = (urb_context *)urb->context;
+	handle = context->handle;
+
+	if (!handle || !handle->card || !context->pmbuf) {
+		PRINTM(MERROR,
+		       "moal handle, card structure or mlan_buffer is not valid in USB Tx complete\n");
+		LEAVE();
+		return;
+	}
+	cardp = handle->card;
+
+	/* Handle the transmission complete validations */
+	if (urb->status) {
+		PRINTM(MERROR, "EP %d Tx URB status failure: %d\n", context->ep,
+		       urb->status);
+		mlan_write_data_async_complete(handle->pmlan_adapter,
+					       context->pmbuf, context->ep,
+					       MLAN_STATUS_FAILURE);
+	} else {
+		mlan_write_data_async_complete(handle->pmlan_adapter,
+					       context->pmbuf, context->ep,
+					       MLAN_STATUS_SUCCESS);
+	}
+
+	/* Decrease pending URB counter */
+	if (context->ep == cardp->tx_cmd_ep)
+		atomic_dec(&cardp->tx_cmd_urb_pending);
+	else if (context->ep == cardp->tx_data_ep)
+		atomic_dec(&cardp->tx_data_urb_pending);
+
+	queue_work(handle->workqueue, &handle->main_work);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function sets up the data to receive
+ *
+ *  @param ctx		Pointer to urb_context structure
+ *  @param size	        Skb size
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_usb_submit_rx_urb(urb_context *ctx, int size)
+{
+	moal_handle *handle = ctx->handle;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u8 *data = NULL;
+
+	ENTER();
+
+	if (handle->surprise_removed || handle->is_suspended) {
+		if ((cardp->rx_cmd_ep == ctx->ep) && ctx->pmbuf) {
+			woal_free_mlan_buffer(handle, ctx->pmbuf);
+			ctx->pmbuf = NULL;
+		}
+		PRINTM(MERROR,
+		       "Card removed/suspended, EP %d Rx URB submit skipped\n",
+		       ctx->ep);
+		goto rx_ret;
+	}
+
+	if (cardp->rx_cmd_ep != ctx->ep) {
+		ctx->pmbuf = woal_alloc_mlan_buffer(handle, size);
+		if (!ctx->pmbuf) {
+			PRINTM(MERROR,
+			       "Fail to submit Rx URB due to no memory/skb\n");
+			goto rx_ret;
+		}
+		ctx->pmbuf->data_offset = MLAN_RX_HEADER_LEN;
+		data = ctx->pmbuf->pbuf + ctx->pmbuf->data_offset;
+	} else {
+		ctx->pmbuf->data_offset = 0;
+		data = ctx->pmbuf->pbuf + ctx->pmbuf->data_offset;
+	}
+
+	if (cardp->rx_cmd_ep == ctx->ep &&
+	    cardp->rx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
+		usb_fill_int_urb(ctx->urb, cardp->udev,
+				 usb_rcvintpipe(cardp->udev, ctx->ep), data,
+				 size - ctx->pmbuf->data_offset,
+				 woal_usb_receive, (void *)ctx,
+				 cardp->rx_cmd_interval);
+	else
+		usb_fill_bulk_urb(ctx->urb, cardp->udev,
+				  usb_rcvbulkpipe(cardp->udev, ctx->ep), data,
+				  size - ctx->pmbuf->data_offset,
+				  woal_usb_receive, (void *)ctx);
+	if (cardp->rx_cmd_ep == ctx->ep)
+		atomic_inc(&cardp->rx_cmd_urb_pending);
+	else
+		atomic_inc(&cardp->rx_data_urb_pending);
+	if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) {
+		/* Submit URB failure */
+		PRINTM(MERROR, "Submit EP %d Rx URB failed: %d\n", ctx->ep,
+		       ret);
+		woal_free_mlan_buffer(handle, ctx->pmbuf);
+		if (cardp->rx_cmd_ep == ctx->ep)
+			atomic_dec(&cardp->rx_cmd_urb_pending);
+		else
+			atomic_dec(&cardp->rx_data_urb_pending);
+		ctx->pmbuf = NULL;
+		ret = MLAN_STATUS_FAILURE;
+	} else {
+		ret = MLAN_STATUS_SUCCESS;
+	}
+rx_ret:
+	LEAVE();
+	return ret;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+
+#if defined(USB8997) || defined(USB9098) || defined(USB9097) || defined(USB8978)
+/**
+ *  @brief  Check chip revision
+ *
+ *  @param handle        A pointer to moal_handle structure
+ *  @param usb_chip_rev  A pointer to usb_chip_rev variable
+ *  @param usb_strap     A pointer to usb_strap
+ *
+ *  @return 	   	 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_check_chip_revision(moal_handle *handle, t_u32 *usb_chip_rev,
+			 t_u32 *usb_strap)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_buffer mbuf;
+	t_u8 *tx_buff = NULL;
+	t_u8 *recv_buff = NULL;
+	usb_ack_pkt ack_pkt;
+	t_u32 extend_ver;
+	t_u8 tx_size = CHIP_REV_TX_BUF_SIZE;
+	struct usb_card_rec *cardp = handle->card;
+
+	ENTER();
+
+	/* Allocate memory for transmit */
+	tx_buff = kzalloc(tx_size, GFP_ATOMIC | GFP_DMA);
+	if (tx_buff == NULL) {
+		PRINTM(MERROR,
+		       "Could not allocate buffer for chip revision check frame transmission\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto cleanup;
+	}
+
+	/* Allocate memory for receive */
+	recv_buff = kzalloc(CHIP_REV_RX_BUF_SIZE, GFP_ATOMIC | GFP_DMA);
+	if (recv_buff == NULL) {
+		PRINTM(MERROR,
+		       "Could not allocate buffer for chip revision check frame response\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto cleanup;
+	}
+
+	/* The struct is initialised to all zero */
+	memset(&ack_pkt, 0, sizeof(usb_ack_pkt));
+
+	/* Send pseudo data to check winner status first */
+	memset(&mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = (t_u8 *)tx_buff;
+	mbuf.data_len = tx_size;
+
+	/* Send the chip revision check frame */
+	ret = woal_usb_write_data_sync(handle, &mbuf, cardp->tx_cmd_ep,
+				       MLAN_USB_BULK_MSG_TIMEOUT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Chip revision check frame dnld: write_data failed, ret %d\n",
+		       ret);
+		ret = MLAN_STATUS_FAILURE;
+		goto cleanup;
+	}
+
+	memset(&mbuf, 0, sizeof(mlan_buffer));
+	mbuf.pbuf = (t_u8 *)recv_buff;
+	mbuf.data_len = CHIP_REV_RX_BUF_SIZE;
+
+	/* Receive the chip revision check frame response */
+	ret = woal_usb_read_data_sync(handle, &mbuf, cardp->rx_cmd_ep,
+				      MLAN_USB_BULK_MSG_TIMEOUT);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR,
+		       "Chip revision check frame response: read_data failed, ret %d\n",
+		       ret);
+		ret = MLAN_STATUS_FAILURE;
+		goto cleanup;
+	}
+	moal_memcpy_ext(handle, &ack_pkt, recv_buff,
+			sizeof(usb_ack_pkt), sizeof(ack_pkt));
+	ack_pkt.ack_winner = woal_le32_to_cpu(ack_pkt.ack_winner);
+	ack_pkt.seq = woal_le32_to_cpu(ack_pkt.seq);
+	ack_pkt.extend = woal_le32_to_cpu(ack_pkt.extend);
+	ack_pkt.chip_rev = woal_le32_to_cpu(ack_pkt.chip_rev);
+	ack_pkt.strap = woal_le32_to_cpu(ack_pkt.strap);
+
+	if ((ack_pkt.extend & 0xffff0000) == EXTEND_HDR) {
+		extend_ver = ack_pkt.extend & 0x0000ffff;
+		*usb_chip_rev = ack_pkt.chip_rev & 0x000000ff;
+		if (extend_ver >= EXTEND_V2) {
+			PRINTM(MINFO, "chip_rev=0x%x, strap=0x%x\n",
+			       *usb_chip_rev, ack_pkt.strap);
+			*usb_strap = ack_pkt.strap & 0x7;
+		} else
+			PRINTM(MINFO, "chip_rev=0x%x\n", *usb_chip_rev);
+	}
+cleanup:
+	kfree(recv_buff);
+	kfree(tx_buff);
+
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief This function unlink urb
+ *
+ *  @param handle A pointer to moal_handle structure
+ *  @return 	  N/A
+ */
+static void
+woal_usb_unlink_urb(void *card_desc)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)card_desc;
+	int i;
+	ENTER();
+	if (cardp) {
+		/* Unlink Rx cmd URB */
+		if (atomic_read(&cardp->rx_cmd_urb_pending) &&
+		    cardp->rx_cmd.urb) {
+			usb_kill_urb(cardp->rx_cmd.urb);
+		}
+		/* Unlink Rx data URBs */
+		if (atomic_read(&cardp->rx_data_urb_pending)) {
+			for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+				if (cardp->rx_data_list[i].urb)
+					usb_kill_urb(cardp->rx_data_list[i].
+						     urb);
+			}
+		}
+		/* Unlink Tx cmd URB */
+		if (atomic_read(&cardp->tx_cmd_urb_pending) &&
+		    cardp->tx_cmd.urb) {
+			usb_kill_urb(cardp->tx_cmd.urb);
+		}
+		/* Unlink Tx data URBs */
+		if (atomic_read(&cardp->tx_data_urb_pending)) {
+			for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
+				if (cardp->tx_data_list[i].urb) {
+					usb_kill_urb(cardp->tx_data_list[i].
+						     urb);
+				}
+			}
+		}
+	}
+	LEAVE();
+}
+
+/**
+ *  @brief  Free Tx/Rx urb, skb and Rx buffer
+ *
+ *  @param cardp	Pointer usb_card_rec
+ *
+ *  @return 	   	N/A
+ */
+void
+woal_usb_free(struct usb_card_rec *cardp)
+{
+	int i;
+
+	ENTER();
+
+	woal_usb_unlink_urb(cardp);
+	/* Free Rx data URBs */
+	for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+		if (cardp->rx_data_list[i].urb) {
+			usb_free_urb(cardp->rx_data_list[i].urb);
+			cardp->rx_data_list[i].urb = NULL;
+		}
+	}
+	/* Free Rx cmd URB */
+	if (cardp->rx_cmd.urb) {
+		usb_free_urb(cardp->rx_cmd.urb);
+		cardp->rx_cmd.urb = NULL;
+	}
+
+	/* Free Tx data URBs */
+	for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
+		if (cardp->tx_data_list[i].urb) {
+			usb_free_urb(cardp->tx_data_list[i].urb);
+			cardp->tx_data_list[i].urb = NULL;
+		}
+	}
+	/* Free Tx cmd URB */
+	if (cardp->tx_cmd.urb) {
+		usb_free_urb(cardp->tx_cmd.urb);
+		cardp->tx_cmd.urb = NULL;
+	}
+
+	LEAVE();
+	return;
+}
+
+static t_u16
+woal_update_card_type(t_void *card)
+{
+	struct usb_card_rec *cardp_usb = (struct usb_card_rec *)card;
+	t_u16 card_type = 0;
+
+	/* Update card type */
+#ifdef USB8801
+	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8801_PID_1 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8801_PID_2) {
+		card_type = CARD_TYPE_USB8801;
+		moal_memcpy_ext(NULL, driver_version, CARD_USB8801,
+				strlen(CARD_USB8801), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION), V14, strlen(V14),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef USB8897
+	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8897_PID_1 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8897_PID_2) {
+		card_type = CARD_TYPE_USB8897;
+		moal_memcpy_ext(NULL, driver_version, CARD_USB8897,
+				strlen(CARD_USB8897), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V15, strlen(V15),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef USB8997
+	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997_PID_1 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997_PID_2 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997_PID_3 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997_PID_4 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997_PID_5 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997_PID_6 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8997V2_PID_1) {
+		card_type = CARD_TYPE_USB8997;
+		moal_memcpy_ext(NULL, driver_version, CARD_USB8997,
+				strlen(CARD_USB8997), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef USB8978
+	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8978_PID_1 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB8978_PID_2) {
+		card_type = CARD_TYPE_USB8978;
+		moal_memcpy_ext(NULL, driver_version, "USBIW416",
+				strlen("USBIW416"), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V16, strlen(V16),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef USB9098
+	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB9098_PID_1 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB9098_PID_2) {
+		card_type = CARD_TYPE_USB9098;
+		moal_memcpy_ext(NULL, driver_version, CARD_USB9098,
+				strlen(CARD_USB9098), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V17, strlen(V17),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+#ifdef USB9097
+	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB9097_PID_1 ||
+	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
+	    (__force __le16) USB9097_PID_2) {
+		card_type = CARD_TYPE_USB9097;
+		moal_memcpy_ext(NULL, driver_version, CARD_USBIW620,
+				strlen(CARD_USBIW620), strlen(driver_version));
+		moal_memcpy_ext(NULL,
+				driver_version + strlen(INTF_CARDTYPE) +
+				strlen(KERN_VERSION),
+				V17, strlen(V17),
+				strlen(driver_version) - strlen(INTF_CARDTYPE) -
+				strlen(KERN_VERSION));
+	}
+#endif
+	return card_type;
+}
+
+/**
+ *  @brief Sets the configuration values
+ *
+ *  @param intf		Pointer to usb_interface
+ *  @param id		Pointer to usb_device_id
+ *
+ *  @return 	   	Address of variable usb_cardp, error code otherwise
+ */
+static int
+woal_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *udev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int i;
+	struct usb_card_rec *usb_cardp = NULL;
+	t_u16 card_type = 0;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+	PRINTM(MMSG,
+	       "USB probe: idVendor=%x idProduct=%x bInterfaceNumber=%d\n",
+	       id->idVendor, id->idProduct, id->bInterfaceNumber);
+#endif
+
+	udev = interface_to_usbdev(intf);
+	usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+	if (!usb_cardp) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	/* Check probe is for our device */
+	for (i = 0; woal_usb_table[i].idVendor; i++) {
+		if (woal_cpu_to_le16(udev->descriptor.idVendor) ==
+		    (__force __le16) woal_usb_table[i].idVendor &&
+		    woal_cpu_to_le16(udev->descriptor.idProduct) ==
+		    (__force __le16) woal_usb_table[i].idProduct) {
+			PRINTM(MMSG, "VID/PID = %X/%X, Boot2 version = %X\n",
+			       woal_cpu_to_le16(udev->descriptor.idVendor),
+			       woal_cpu_to_le16(udev->descriptor.idProduct),
+			       woal_cpu_to_le16(udev->descriptor.bcdDevice));
+			switch (woal_cpu_to_le16(udev->descriptor.idProduct)) {
+#ifdef USB8801
+			case (__force __le16) USB8801_PID_1:
+#endif /* USB8801 */
+#ifdef USB8897
+			case (__force __le16) USB8897_PID_1:
+#endif /* USB8897 */
+#ifdef USB8997
+			case (__force __le16) USB8997_PID_1:
+			case (__force __le16) USB8997V2_PID_1:
+#endif /* USB8997 */
+#ifdef USB8978
+			case (__force __le16) USB8978_PID_1:
+			case (__force __le16) USB8978_PID_1_BT:
+#endif /* USB8978 */
+#ifdef USB9098
+			case (__force __le16) USB9098_PID_1:
+#endif /* USB9098 */
+#ifdef USB9097
+			case (__force __le16) USB9097_PID_1:
+#endif /* USB9097 */
+				/* If skip FW is set, we must return error so
+				 * the next driver can download the FW */
+				if (skip_fwdnld)
+					goto error;
+				else
+					usb_cardp->boot_state = USB_FW_DNLD;
+				break;
+#ifdef USB8801
+			case (__force __le16) USB8801_PID_2:
+#endif /* USB8801 */
+#ifdef USB8897
+			case (__force __le16) USB8897_PID_2:
+#endif /* USB8897 */
+#ifdef USB8997
+			case (__force __le16) USB8997_PID_2:
+#endif /* USB8997 */
+#ifdef USB8978
+			case (__force __le16) USB8978_PID_2:
+			case (__force __le16) USB8978_PID_2_BT:
+#endif /* USB8978 */
+#ifdef USB9098
+			case (__force __le16) USB9098_PID_2:
+#endif /* USB9098 */
+#ifdef USB9097
+			case (__force __le16) USB9097_PID_2:
+#endif /* USB9097 */
+				usb_cardp->boot_state = USB_FW_READY;
+				break;
+			}
+			/*To do, get card type */
+			/*                      if
+			   (woal_cpu_to_le16(udev->descriptor.idProduct) ==
+			   USB8897_PID_2) usb_cardp->card_type =
+			   CARD_TYPE_USB8897; else if
+			   (woal_cpu_to_le16(udev->descriptor.idProduct) ==
+			   USB8997_PID_2) usb_cardp->card_type =
+			   CARD_TYPE_USB997;
+			 */
+			break;
+		}
+	}
+
+	if (woal_usb_table[i].idVendor) {
+		usb_cardp->udev = udev;
+		iface_desc = intf->cur_altsetting;
+		usb_cardp->intf = intf;
+
+		PRINTM(MINFO,
+		       "bcdUSB = 0x%X bDeviceClass = 0x%X"
+		       " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
+		       woal_cpu_to_le16(udev->descriptor.bcdUSB),
+		       udev->descriptor.bDeviceClass,
+		       udev->descriptor.bDeviceSubClass,
+		       udev->descriptor.bDeviceProtocol);
+
+		for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+			endpoint = &iface_desc->endpoint[i].desc;
+			if ((usb_endpoint_is_bulk_in(endpoint) ||
+			     usb_endpoint_is_int_in(endpoint)) &&
+			    (usb_endpoint_num(endpoint) == MLAN_USB_EP_CMD_EVENT
+			     || usb_endpoint_num(endpoint) ==
+			     MLAN_USB_EP_CMD_EVENT_IF2)) {
+				usb_cardp->rx_cmd_ep_type =
+					usb_endpoint_type(endpoint);
+				usb_cardp->rx_cmd_interval =
+					endpoint->bInterval;
+				/* We found a bulk in command/event endpoint */
+				PRINTM(MCMND,
+				       "Rx CMD/EVT: max packet size = %d, address = %d ep_type=%d\n",
+				       woal_le16_to_cpu(endpoint->
+							wMaxPacketSize),
+				       endpoint->bEndpointAddress,
+				       usb_cardp->rx_cmd_ep_type);
+				usb_cardp->rx_cmd_ep =
+					(endpoint->
+					 bEndpointAddress &
+					 USB_ENDPOINT_NUMBER_MASK);
+
+				atomic_set(&usb_cardp->rx_cmd_urb_pending, 0);
+				if (usb_endpoint_num(endpoint) ==
+				    MLAN_USB_EP_CMD_EVENT_IF2)
+					usb_cardp->second_mac = MTRUE;
+			}
+			if (usb_endpoint_is_bulk_in(endpoint) &&
+			    (usb_endpoint_num(endpoint) == MLAN_USB_EP_DATA
+			     ||
+			     usb_endpoint_num(endpoint) ==
+			     MLAN_USB_EP_DATA_IF2)) {
+				/* We found a bulk in data endpoint */
+				PRINTM(MINFO,
+				       "Bulk IN: max packet size = %d, address = %d\n",
+				       woal_le16_to_cpu(endpoint->
+							wMaxPacketSize),
+				       endpoint->bEndpointAddress);
+				usb_cardp->rx_data_ep =
+					(endpoint->
+					 bEndpointAddress &
+					 USB_ENDPOINT_NUMBER_MASK);
+				atomic_set(&usb_cardp->rx_data_urb_pending, 0);
+			}
+			if (usb_endpoint_is_bulk_out(endpoint) &&
+			    (usb_endpoint_num(endpoint) == MLAN_USB_EP_DATA
+			     ||
+			     usb_endpoint_num(endpoint) ==
+			     MLAN_USB_EP_DATA_IF2)) {
+				/* We found a bulk out data endpoint */
+				PRINTM(MCMND,
+				       "Bulk OUT: max packet size = %d, address = %d\n",
+				       woal_le16_to_cpu(endpoint->
+							wMaxPacketSize),
+				       endpoint->bEndpointAddress);
+				usb_cardp->tx_data_ep =
+					endpoint->bEndpointAddress;
+				atomic_set(&usb_cardp->tx_data_urb_pending, 0);
+				usb_cardp->tx_data_maxpktsize =
+					(__force int)woal_le16_to_cpu(endpoint->
+								      wMaxPacketSize);
+			}
+
+			if ((usb_endpoint_is_bulk_out(endpoint) ||
+			     usb_endpoint_is_int_out(endpoint)) &&
+			    (usb_endpoint_num(endpoint) == MLAN_USB_EP_CMD_EVENT
+			     || usb_endpoint_num(endpoint) ==
+			     MLAN_USB_EP_CMD_EVENT_IF2)) {
+				usb_cardp->tx_cmd_ep_type =
+					usb_endpoint_type(endpoint);
+				usb_cardp->tx_cmd_interval =
+					endpoint->bInterval;
+				/* We found a bulk out command/event endpoint */
+				PRINTM(MCMND,
+				       "Tx CMD: max packet size = %d, address = %d ep_type=%d\n",
+				       woal_le16_to_cpu(endpoint->
+							wMaxPacketSize),
+				       endpoint->bEndpointAddress,
+				       usb_cardp->tx_cmd_ep_type);
+				usb_cardp->tx_cmd_ep =
+					endpoint->bEndpointAddress;
+				atomic_set(&usb_cardp->tx_cmd_urb_pending, 0);
+				usb_cardp->tx_cmd_maxpktsize =
+					(__force int)woal_le16_to_cpu(endpoint->
+								      wMaxPacketSize);
+			}
+		}
+
+		if (usb_cardp->boot_state == USB_FW_DNLD) {
+			if (!usb_cardp->tx_cmd_ep || !usb_cardp->rx_cmd_ep)
+				goto error;
+		} else if (usb_cardp->boot_state == USB_FW_READY) {
+			if (!usb_cardp->tx_cmd_ep || !usb_cardp->tx_data_ep ||
+			    !usb_cardp->rx_cmd_ep || !usb_cardp->rx_data_ep) {
+				PRINTM(MERROR,
+				       "%s: invalid endpoint assignment\n",
+				       __FUNCTION__);
+				goto error;
+			}
+		}
+
+		usb_cardp->tx_aggr_ctrl.enable = MFALSE;
+		usb_cardp->tx_aggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
+		usb_cardp->tx_aggr_ctrl.aggr_align =
+			MAX(max_tx_buf, MLAN_USB_TX_AGGR_ALIGN);
+		usb_cardp->tx_aggr_ctrl.aggr_max = MLAN_USB_TX_MAX_AGGR_NUM;
+		usb_cardp->tx_aggr_ctrl.aggr_tmo =
+			MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
+		usb_cardp->rx_deaggr_ctrl.enable = MFALSE;
+		usb_cardp->rx_deaggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
+		usb_cardp->rx_deaggr_ctrl.aggr_align = MLAN_USB_RX_ALIGN_SIZE;
+		usb_cardp->rx_deaggr_ctrl.aggr_max = MLAN_USB_RX_MAX_AGGR_NUM;
+		usb_cardp->rx_deaggr_ctrl.aggr_tmo =
+			MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
+		usb_set_intfdata(intf, usb_cardp);
+
+		card_type = woal_update_card_type(usb_cardp);
+		if (!card_type) {
+			PRINTM(MERROR,
+			       "usb probe: woal_update_card_type() failed\n");
+			goto error;
+		}
+
+		/* At this point wlan_add_card() will be called */
+		if (!(woal_add_card(usb_cardp, &usb_cardp->udev->dev, &usb_ops,
+				    card_type))) {
+			PRINTM(MERROR, "%s: woal_add_card failed\n",
+			       __FUNCTION__);
+			goto error;
+		}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+		/* Note: From 2.6.34.2 onwards, remote wakeup is NOT enabled by
+		 * default. So drivers wanting remote wakeup will have to enable
+		 * this using -
+		 * device_set_wakeup_enable(&udev->dev, 1);
+		 * It has been observed that some cards having device attr =
+		 * 0xa0 do not support remote wakeup. These cards come
+		 * immediately out of the suspend when power/wakeup file is set
+		 * to 'enabled'. To support all types of cards i.e. with/without
+		 * remote wakeup, we are NOT setting the 'power/wakeup' file
+		 * from here. Also in principle, we are not supposed to change
+		 * the wakeup policy, which is purely a userspace decision.
+		 */
+		/* if (udev->actconfig->desc.bmAttributes &
+		   USB_CONFIG_ATT_WAKEUP) intf->needs_remote_wakeup = 1; */
+#endif
+		usb_get_dev(udev);
+		LEAVE();
+		return 0;
+	} else {
+		PRINTM(MINFO, "Discard the Probe request\n");
+		PRINTM(MINFO, "VID = 0x%X PID = 0x%X\n",
+		       woal_cpu_to_le16(udev->descriptor.idVendor),
+		       woal_cpu_to_le16(udev->descriptor.idProduct));
+	}
+error:
+	kfree(usb_cardp);
+	usb_cardp = NULL;
+	LEAVE();
+	return -ENXIO;
+}
+
+/**
+ *  @brief Free resource and cleanup
+ *
+ *  @param intf		Pointer to usb_interface
+ *
+ *  @return 	   	N/A
+ */
+static void
+woal_usb_disconnect(struct usb_interface *intf)
+{
+	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+	moal_handle *phandle = NULL;
+	ENTER();
+	if (!cardp || !cardp->phandle) {
+		PRINTM(MERROR, "Card or phandle is not valid\n");
+		LEAVE();
+		return;
+	}
+	phandle = (moal_handle *)cardp->phandle;
+
+	/*
+	 * Update Surprise removed to TRUE
+	 *  Free all the URB's allocated
+	 */
+	phandle->surprise_removed = MTRUE;
+
+	/* Card is removed and we can call wlan_remove_card */
+	PRINTM(MINFO, "Call remove card\n");
+	woal_remove_card(cardp);
+
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(interface_to_usbdev(intf));
+	kfree(cardp);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief killall pending urbs
+ *
+ *  @param handle	  Pointer to moal_handle
+ *
+ *
+ *  @return 	   	  N/A
+ */
+void
+woal_kill_urbs(moal_handle *handle)
+{
+	ENTER();
+	handle->is_suspended = MTRUE;
+	woal_usb_unlink_urb(handle->card);
+	LEAVE();
+}
+
+/**
+ *  @brief resubmit urbs
+ *
+ *  @param handle	  Pointer to moal_handle
+ *
+ *
+ *  @return 	   	  N/A
+ */
+void
+woal_resubmit_urbs(moal_handle *handle)
+{
+	struct usb_card_rec *cardp = handle->card;
+
+	ENTER();
+	handle->is_suspended = MFALSE;
+
+	if (!atomic_read(&cardp->rx_data_urb_pending)) {
+		/* Submit multiple Rx data URBs */
+		woal_usb_submit_rx_data_urbs(handle);
+	}
+	if (!atomic_read(&cardp->rx_cmd_urb_pending)) {
+		cardp->rx_cmd.pmbuf =
+			woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE);
+		if (cardp->rx_cmd.pmbuf)
+			woal_usb_submit_rx_urb(&cardp->rx_cmd,
+					       MLAN_RX_CMD_BUF_SIZE);
+	}
+	LEAVE();
+}
+
+#ifdef CONFIG_PM
+/**
+ *  @brief Handle suspend
+ *
+ *  @param intf		  Pointer to usb_interface
+ *  @param message	  Pointer to pm_message_t structure
+ *
+ *  @return 	   	  MLAN_STATUS_SUCCESS
+ */
+static int
+woal_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+	moal_handle *handle = NULL;
+	int i;
+	int ret = 0;
+
+	ENTER();
+
+	PRINTM(MCMND, "<--- Enter woal_usb_suspend --->\n");
+	if (!cardp || !cardp->phandle) {
+		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
+		ret = 0;
+		goto done;
+	}
+	handle = cardp->phandle;
+	if (handle->is_suspended == MTRUE) {
+		PRINTM(MWARN, "Device already suspended\n");
+		ret = 0;
+		goto done;
+	}
+#ifdef STA_SUPPORT
+	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
+		if (handle->priv[i] &&
+		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA))
+			woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT);
+	}
+#endif
+	/* Enable Host Sleep */
+	woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
+
+	/* Indicate device suspended */
+	/* The flag must be set here before the usb_kill_urb() calls.
+	 * Reason: In the complete handlers, urb->status(= -ENOENT) and
+	 * 'is_suspended' flag is used in combination to distinguish
+	 * between a suspended state and a 'disconnect' one.
+	 */
+	handle->is_suspended = MTRUE;
+	for (i = 0; i < handle->priv_num; i++)
+		netif_carrier_off(handle->priv[i]->netdev);
+
+	/* Unlink Rx cmd URB */
+	if (atomic_read(&cardp->rx_cmd_urb_pending) && cardp->rx_cmd.urb) {
+		usb_kill_urb(cardp->rx_cmd.urb);
+	}
+	/* Unlink Rx data URBs */
+	if (atomic_read(&cardp->rx_data_urb_pending)) {
+		for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+			if (cardp->rx_data_list[i].urb) {
+				usb_kill_urb(cardp->rx_data_list[i].urb);
+				usb_init_urb(cardp->rx_data_list[i].urb);
+			}
+		}
+	}
+
+	/* Unlink Tx data URBs */
+	for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
+		if (cardp->tx_data_list[i].urb) {
+			usb_kill_urb(cardp->tx_data_list[i].urb);
+		}
+	}
+	/* Unlink Tx cmd URB */
+	if (cardp->tx_cmd.urb) {
+		usb_kill_urb(cardp->tx_cmd.urb);
+	}
+
+	handle->suspend_wait_q_woken = MTRUE;
+	wake_up_interruptible(&handle->suspend_wait_q);
+
+done:
+	PRINTM(MCMND, "<--- Leave woal_usb_suspend --->\n");
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Handle resume
+ *
+ *  @param intf		  Pointer to usb_interface
+ *
+ *  @return 	   	  MLAN_STATUS_SUCCESS
+ */
+static int
+woal_usb_resume(struct usb_interface *intf)
+{
+	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+	moal_handle *handle = NULL;
+	int i;
+
+	ENTER();
+
+	PRINTM(MCMND, "<--- Enter woal_usb_resume --->\n");
+	if (!cardp || !cardp->phandle) {
+		PRINTM(MERROR, "Card or adapter structure is not valid\n");
+		goto done;
+	}
+	handle = cardp->phandle;
+
+	if (handle->is_suspended == MFALSE) {
+		PRINTM(MWARN, "Device already resumed\n");
+		goto done;
+	}
+
+	/* Indicate device resumed.
+	 * The netdev queue will be resumed only after the urbs
+	 * have been resubmitted */
+	handle->is_suspended = MFALSE;
+
+	if (!atomic_read(&cardp->rx_data_urb_pending)) {
+		/* Submit multiple Rx data URBs */
+		woal_usb_submit_rx_data_urbs(handle);
+	}
+	if (!atomic_read(&cardp->rx_cmd_urb_pending)) {
+		cardp->rx_cmd.pmbuf =
+			woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE);
+		if (cardp->rx_cmd.pmbuf)
+			woal_usb_submit_rx_urb(&cardp->rx_cmd,
+					       MLAN_RX_CMD_BUF_SIZE);
+	}
+
+	for (i = 0; i < handle->priv_num; i++)
+		if (handle->priv[i]->media_connected == MTRUE)
+			netif_carrier_on(handle->priv[i]->netdev);
+
+	/* Disable Host Sleep */
+	if (handle->hs_activated)
+		woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
+			       MOAL_NO_WAIT);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+	/* Resume handler may be called due to remote wakeup,
+	   force to exit suspend anyway */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+	cardp->udev->autosuspend_disabled = 1;
+#else
+#ifdef CONFIG_PM_RUNTIME
+	cardp->udev->dev.power.runtime_auto = 0;
+#endif
+#endif /* < 2.6.35 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+	cardp->udev->autoresume_disabled = 0;
+#endif /* < 2.6.33 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+#ifdef CONFIG_PM_RUNTIME
+	atomic_inc(&(cardp->udev)->dev.power.usage_count);
+#endif
+#endif /* >= 2.6.34 */
+#endif /* >= 2.6.24 */
+
+done:
+	PRINTM(MCMND, "<--- Leave woal_usb_resume --->\n");
+	LEAVE();
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+/**
+ *  @brief This function initialize the tx URBs
+ *
+ *  @param handle 	Pointer to moal_handle structure
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_usb_tx_init(moal_handle *handle)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	int i;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cardp->tx_cmd.handle = handle;
+	cardp->tx_cmd.ep = cardp->tx_cmd_ep;
+	/* Allocate URB for command */
+	cardp->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!cardp->tx_cmd.urb) {
+		PRINTM(MERROR, "Tx command URB allocation failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto init_exit;
+	}
+
+	cardp->tx_data_ix = 0;
+	for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
+		cardp->tx_data_list[i].handle = handle;
+		cardp->tx_data_list[i].ep = cardp->tx_data_ep;
+		/* Allocate URB for data */
+		cardp->tx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!cardp->tx_data_list[i].urb) {
+			PRINTM(MERROR, "Tx data URB allocation failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto init_exit;
+		}
+	}
+
+init_exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function submits the rx data URBs
+ *
+ *  @param handle 	Pointer to moal_handle structure
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_usb_submit_rx_data_urbs(moal_handle *handle)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	int i;
+	mlan_status ret = MLAN_STATUS_FAILURE;
+	t_u32 buffer_len = MLAN_RX_DATA_BUF_SIZE;
+
+	ENTER();
+
+	if (cardp->rx_deaggr_ctrl.enable) {
+		buffer_len = cardp->rx_deaggr_ctrl.aggr_max;
+		if (cardp->rx_deaggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
+			buffer_len *= MAX(MLAN_USB_MAX_PKT_SIZE,
+					  cardp->rx_deaggr_ctrl.aggr_align);
+			buffer_len = MAX(buffer_len, MLAN_RX_DATA_BUF_SIZE);
+		}
+	}
+
+	for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+		/* Submit Rx data URB */
+		if (!cardp->rx_data_list[i].pmbuf) {
+			if (woal_usb_submit_rx_urb(&cardp->rx_data_list[i],
+						   buffer_len))
+				continue;
+		}
+		ret = MLAN_STATUS_SUCCESS;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function initialize the rx URBs and submit them
+ *
+ *  @param handle 	Pointer to moal_handle structure
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_usb_rx_init(moal_handle *handle)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	int i;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cardp->rx_cmd.handle = handle;
+	cardp->rx_cmd.ep = cardp->rx_cmd_ep;
+	/* Allocate URB for command/event */
+	cardp->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!cardp->rx_cmd.urb) {
+		PRINTM(MERROR, "Rx command URB allocation failed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto init_exit;
+	}
+
+	cardp->rx_cmd.pmbuf =
+		woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE);
+	if (cardp->rx_cmd.pmbuf) {
+		/* Submit Rx command URB */
+		if (woal_usb_submit_rx_urb(&cardp->rx_cmd,
+					   MLAN_RX_CMD_BUF_SIZE)) {
+			ret = MLAN_STATUS_FAILURE;
+			goto init_exit;
+		}
+	}
+	for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
+		cardp->rx_data_list[i].handle = handle;
+		cardp->rx_data_list[i].ep = cardp->rx_data_ep;
+		/* Allocate URB for data */
+		cardp->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!cardp->rx_data_list[i].urb) {
+			PRINTM(MERROR, "Rx data URB allocation failed\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto init_exit;
+		}
+	}
+	ret = woal_usb_submit_rx_data_urbs(handle);
+	if (ret) {
+		PRINTM(MERROR, "Rx data URB submission failed\n");
+		goto init_exit;
+	}
+
+init_exit:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function downloads data blocks to device
+ *
+ *  @param handle	Pointer to moal_handle structure
+ *  @param pmbuf	Pointer to mlan_buffer structure
+ *  @param ep		Endpoint to send
+ *  @param timeout 	Timeout value in milliseconds (if 0 the wait is forever)
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_usb_write_data_sync(moal_handle *handle,
+			 mlan_buffer *pmbuf, t_u32 endpoint, t_u32 timeout)
+{
+	struct usb_card_rec *cardp = handle->card;
+	t_u8 *data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	t_u8 ep = endpoint;
+	t_u32 length = pmbuf->data_len;
+	int actual_length;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int bulk_out_maxpktsize = 512;
+
+	if (ep == cardp->tx_cmd_ep)
+		bulk_out_maxpktsize = cardp->tx_cmd_maxpktsize;
+	else if (ep == cardp->tx_data_ep)
+		bulk_out_maxpktsize = cardp->tx_data_maxpktsize;
+
+	if (length % bulk_out_maxpktsize == 0)
+		length++;
+
+	/* Send the data block */
+	ret = usb_bulk_msg(cardp->udev, usb_sndbulkpipe(cardp->udev, ep),
+			   (t_u8 *)data, length, &actual_length, timeout);
+	if (ret) {
+		PRINTM(MERROR, "usb_blk_msg for send failed, ret %d\n", ret);
+		ret = MLAN_STATUS_FAILURE;
+	}
+
+	pmbuf->data_len = actual_length;
+	DBG_HEXDUMP(MIF_D, "write sync", data, actual_length);
+
+	return ret;
+}
+
+/**
+ *  @brief  This function read data blocks to device
+ *
+ *  @param handle	Pointer to moal_handle structure
+ *  @param pmbuf	Pointer to mlan_buffer structure
+ *  @param ep		Endpoint to receive
+ *  @param timeout 	Timeout value in milliseconds (if 0 the wait is forever)
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_usb_read_data_sync(moal_handle *handle,
+			mlan_buffer *pmbuf, t_u32 endpoint, t_u32 timeout)
+{
+	struct usb_card_rec *cardp = handle->card;
+	t_u8 *data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	t_u8 ep = endpoint;
+	t_u32 buf_len = pmbuf->data_len;
+	int actual_length;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+	/* Receive the data response */
+	ret = usb_bulk_msg(cardp->udev, usb_rcvbulkpipe(cardp->udev, ep), data,
+			   buf_len, &actual_length, timeout);
+	if (ret) {
+		PRINTM(MERROR, "usb_bulk_msg failed: %d\n", ret);
+		ret = MLAN_STATUS_FAILURE;
+	}
+	pmbuf->data_len = actual_length;
+	DBG_HEXDUMP(MIF_D, "read sync", data, actual_length);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function downloads data/command packet to device
+ *
+ *  @param handle	Pointer to moal_handle structure
+ *  @param pmbuf	Pointer to mlan_buffer structure
+ *  @param ep		Endpoint to send
+ *
+ *  @return 	   	MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE or
+ * MLAN_STATUS_RESOURCE
+ */
+mlan_status
+woal_write_data_async(moal_handle *handle, mlan_buffer *pmbuf, t_u8 ep)
+{
+	struct usb_card_rec *cardp = handle->card;
+	urb_context *context = NULL;
+	t_u8 *data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
+	struct urb *tx_urb = NULL;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 data_len = pmbuf->data_len;
+	int bulk_out_maxpktsize = 512;
+
+	ENTER();
+
+	/* Check if device is removed */
+	if (handle->surprise_removed) {
+		PRINTM(MERROR, "Device removed\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto tx_ret;
+	}
+
+	if ((ep == cardp->tx_data_ep) &&
+	    (atomic_read(&cardp->tx_data_urb_pending) >= MVUSB_TX_HIGH_WMARK)) {
+		ret = MLAN_STATUS_RESOURCE;
+		goto tx_ret;
+	}
+	PRINTM(MINFO, "woal_write_data_async: ep=%d\n", ep);
+
+	if (ep == cardp->tx_cmd_ep) {
+		context = &cardp->tx_cmd;
+		bulk_out_maxpktsize = cardp->tx_cmd_maxpktsize;
+	} else {
+		if (ep == cardp->tx_data_ep) {
+			bulk_out_maxpktsize = cardp->tx_data_maxpktsize;
+			if (cardp->tx_data_ix >= MVUSB_TX_HIGH_WMARK)
+				cardp->tx_data_ix = 0;
+			context = &cardp->tx_data_list[cardp->tx_data_ix++];
+		}
+	}
+
+	if (!context) {
+		PRINTM(MERROR, "Cannot allocate Tx urb_context\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto tx_ret;
+	}
+	context->handle = handle;
+	context->ep = ep;
+	context->pmbuf = pmbuf;
+
+	tx_urb = context->urb;
+
+	if (data_len % bulk_out_maxpktsize == 0)
+		data_len++;
+
+	/*
+	 * Use USB API usb_fill_bulk_urb() to set the
+	 * configuration information of the Tx bulk URB
+	 * and initialize the Tx callback
+	 */
+
+	if (ep == cardp->tx_cmd_ep &&
+	    cardp->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT) {
+		usb_fill_int_urb(tx_urb, cardp->udev,
+				 usb_sndintpipe(cardp->udev, ep), data,
+				 data_len, woal_usb_tx_complete,
+				 (void *)context, cardp->tx_cmd_interval);
+	} else
+		usb_fill_bulk_urb(tx_urb, cardp->udev,
+				  usb_sndbulkpipe(cardp->udev, ep), data,
+				  data_len, woal_usb_tx_complete,
+				  (void *)context);
+	/* We find on Ubuntu 12.10 this flag does not work */
+	// tx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+	if (ep == cardp->tx_cmd_ep)
+		atomic_inc(&cardp->tx_cmd_urb_pending);
+	else if (ep == cardp->tx_data_ep)
+		atomic_inc(&cardp->tx_data_urb_pending);
+	if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
+		/* Submit URB failure */
+		PRINTM(MERROR, "Submit EP %d Tx URB failed: %d\n", ep, ret);
+		if (ep == cardp->tx_cmd_ep)
+			atomic_dec(&cardp->tx_cmd_urb_pending);
+		else {
+			if (ep == cardp->tx_data_ep) {
+				atomic_dec(&cardp->tx_data_urb_pending);
+				if (cardp->tx_data_ix)
+					cardp->tx_data_ix--;
+				else
+					cardp->tx_data_ix = MVUSB_TX_HIGH_WMARK;
+			}
+		}
+		ret = MLAN_STATUS_FAILURE;
+	} else {
+		if (ep == cardp->tx_data_ep &&
+		    (atomic_read(&cardp->tx_data_urb_pending) ==
+		     MVUSB_TX_HIGH_WMARK))
+			ret = MLAN_STATUS_PRESOURCE;
+		else
+			ret = MLAN_STATUS_SUCCESS;
+	}
+
+tx_ret:
+
+	if (!ret)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  This function register usb device and initialize parameter
+ *
+ *  @param handle	Pointer to moal_handle structure
+ *
+ *  @return 	   	MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status
+woal_usb_register_dev(moal_handle *handle)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cardp->phandle = handle;
+	LEAVE();
+	return ret;
+}
+
+static void
+woal_usb_unregister_dev(moal_handle *handle)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+	PRINTM(MMSG, "USB: unregister device\n");
+	woal_usb_free(cardp);
+	cardp->phandle = NULL;
+	return;
+}
+
+/**
+ *  @brief This function registers driver.
+ *
+ *  @return 	 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+mlan_status
+woal_usb_bus_register(void)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	ENTER();
+
+	if (skip_fwdnld) {
+		woal_usb_driver.id_table = woal_usb_table_skip_fwdnld;
+	}
+	/*
+	 * API registers the NXP USB driver
+	 * to the USB system
+	 */
+	if (usb_register(&woal_usb_driver)) {
+		PRINTM(MFATAL, "USB Driver Registration Failed \n");
+		ret = MLAN_STATUS_FAILURE;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function removes usb driver.
+ *
+ *  @return 	   	N/A
+ */
+void
+woal_usb_bus_unregister(void)
+{
+	ENTER();
+	/* API unregisters the driver from USB subsystem */
+	usb_deregister(&woal_usb_driver);
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function check if this is second mac
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @return         MTRUE/MFALSE
+ *
+ */
+static t_u8
+woal_usb_is_second_mac(moal_handle *handle)
+{
+	return ((struct usb_card_rec *)(handle->card))->second_mac;
+}
+
+#ifdef CONFIG_USB_SUSPEND
+/**
+ *  @brief This function makes USB device to suspend.
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_enter_usb_suspend(moal_handle *handle)
+{
+	struct usb_device *udev = ((struct usb_card_rec *)(handle->card))->udev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+	struct usb_interface *intf =
+		((struct usb_card_rec *)(handle->card))->intf;
+#endif /* < 2.6.34 */
+#endif /* >= 2.6.24 */
+
+	ENTER();
+
+	PRINTM(MIOCTL, "USB suspend ioctl (state %d)\n", udev->state);
+
+	if (handle->is_suspended == MTRUE) {
+		PRINTM(MERROR, "Device already suspended\n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	handle->suspend_wait_q_woken = MFALSE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+	/* Enter into USB suspend */
+	usb_lock_device(udev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
+	udev->autosuspend_delay = 0;	/* Autosuspend delay in jiffies */
+#else
+	pm_runtime_set_autosuspend_delay(&udev->dev, 0);	/* Autosuspend delay in
+								   jiffies */
+#endif /* < 2.6.38 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+	udev->autosuspend_disabled = 0;	/* /sys/bus/usb/devices/.../power/level
+					   < auto */
+#endif /* < 2.6.34 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+	udev->autoresume_disabled = 0;
+#endif /* < 2.6.33 */
+	usb_unlock_device(udev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	intf->pm_usage_cnt = 1;
+#else
+	atomic_set(&intf->pm_usage_cnt, 1);
+#endif /* < 2.6.32 */
+	usb_autopm_put_interface(intf);
+#else
+	usb_lock_device(udev);
+	atomic_set(&udev->dev.power.usage_count, 1);
+	usb_enable_autosuspend(udev);
+	usb_unlock_device(udev);
+#endif /* < 2.6.34 */
+#endif /* >= 2.6.24 */
+
+	/* Wait for suspend to complete */
+	wait_event_interruptible(handle->suspend_wait_q,
+				 handle->suspend_wait_q_woken);
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief This function makes USB device to resume.
+ *
+ *  @param handle  A pointer to moal_handle structure
+ *
+ *  @return             0 --success, otherwise fail
+ */
+int
+woal_exit_usb_suspend(moal_handle *handle)
+{
+	struct usb_device *udev = ((struct usb_card_rec *)(handle->card))->udev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+	struct usb_interface *intf =
+		((struct usb_card_rec *)(handle->card))->intf;
+#endif /* < 2.6.34 */
+#endif /* >= 2.6.24 */
+
+	ENTER();
+
+	PRINTM(MIOCTL, "USB resume ioctl (state %d)\n", udev->state);
+
+	if (handle->is_suspended == MFALSE ||
+	    udev->state != USB_STATE_SUSPENDED) {
+		PRINTM(MERROR, "Device already resumed\n");
+		LEAVE();
+		return -EFAULT;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+	/* Exit from USB suspend */
+	usb_lock_device(udev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+	udev->autosuspend_disabled = 1;	/* /sys/bus/usb/devices/.../power/level
+					   < on */
+#endif /* < 2.6.34 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+	udev->autoresume_disabled = 0;
+#endif /* < 2.6.33 */
+	usb_unlock_device(udev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
+	intf->pm_usage_cnt = 0;
+#else
+	atomic_set(&intf->pm_usage_cnt, 0);
+#endif /* < 2.6.32 */
+	usb_autopm_get_interface(intf);
+#else
+	usb_lock_device(udev);
+	atomic_set(&udev->dev.power.usage_count, 0);
+	usb_disable_autosuspend(udev);
+	usb_unlock_device(udev);
+#endif /* < 2.6.34 */
+#endif /* >= 2.6.24 */
+
+	LEAVE();
+	return 0;
+}
+#endif /* CONFIG_USB_SUSPEND */
+
+/**
+ *  @brief This function will submit rx urb.
+ *
+ *  @param handle   Pointer to moal_handle
+ *  @param ep       Endpoint to re-submit urb
+ *
+ *  @return 	   	N/A
+ */
+void
+woal_submit_rx_urb(moal_handle *handle, t_u8 ep)
+{
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+
+	ENTER();
+
+	if ((ep == cardp->rx_cmd_ep) &&
+	    (!atomic_read(&cardp->rx_cmd_urb_pending))) {
+		woal_usb_submit_rx_urb(&cardp->rx_cmd, MLAN_RX_CMD_BUF_SIZE);
+	}
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function dump firmware memory to file
+ *
+ *  @param phandle   A pointer to moal_handle
+ *
+ *  @return         N/A
+ */
+static void
+woal_usb_dump_fw_info(moal_handle *phandle)
+{
+	moal_private *priv = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *pcfg_misc = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	priv = woal_get_priv(phandle, MLAN_BSS_ROLE_ANY);
+	if (!priv) {
+		PRINTM(MERROR, "woal_usb_dump_fw_info: priv is NULL!\n");
+		goto done;
+	}
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR, "woal_usb_dump_fw_info: alloc req fail!\n");
+		goto done;
+	}
+
+	/* Fill request buffer */
+	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
+	pcfg_misc->sub_command = MLAN_OID_MISC_FW_DUMP_EVENT;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	phandle->is_fw_dump_timer_set = MTRUE;
+	woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
+
+done:
+	LEAVE();
+	return;
+}
+
+static mlan_status
+woal_usb_get_fw_name(moal_handle *handle)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+#if defined(USB8997) || defined(USB9098) || defined(USB9097) || defined(USB8978)
+	t_u32 revision_id = 0;
+	t_u32 strap = 0;
+#endif
+	struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
+#if defined(USB9098)
+	moal_handle *ref_handle = NULL;
+#endif
+
+	ENTER();
+	if (handle->params.fw_name)
+		goto done;
+	if (cardp->boot_state == USB_FW_READY)
+		goto done;
+#ifdef USB8801
+	if (IS_USB8801(handle->card_type))
+		goto done;
+#endif
+
+#if defined(USB8997) || defined(USB9098) || defined(USB9097) || defined(USB8978)
+	ret = woal_check_chip_revision(handle, &revision_id, &strap);
+	if (ret != MLAN_STATUS_SUCCESS) {
+		PRINTM(MFATAL, "Chip revision check failure!\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	PRINTM(MCMND, "revision=0x%x, strap=0x%x\n", revision_id, strap);
+#endif
+
+#ifdef USB8997
+	if (IS_USB8997(handle->card_type)) {
+		if (strap == CARD_TYPE_USB_UART)
+			strcpy(handle->card_info->fw_name,
+			       USBUART8997_DEFAULT_COMBO_FW_NAME);
+		else if (strap != 0)
+			strcpy(handle->card_info->fw_name,
+			       USBUSB8997_DEFAULT_COMBO_FW_NAME);
+	}
+#endif
+
+#ifdef USB8978
+	if (IS_USB8978(handle->card_type)) {
+		if (strap == CARD_TYPE_USB_UART)
+			strcpy(handle->card_info->fw_name,
+			       USBUART8978_DEFAULT_COMBO_FW_NAME);
+		else if (strap != 0)
+			strcpy(handle->card_info->fw_name,
+			       USBUSB8978_DEFAULT_COMBO_FW_NAME);
+	}
+#endif
+
+#ifdef USB9098
+	if (IS_USB9098(handle->card_type)) {
+		if (cardp->second_mac) {
+			ref_handle = (moal_handle *)handle->pref_mac;
+			if (ref_handle) {
+				strcpy(handle->card_info->fw_name,
+				       ref_handle->card_info->fw_name);
+				strcpy(handle->card_info->fw_name_wlan,
+				       ref_handle->card_info->fw_name_wlan);
+			}
+			goto done;
+		}
+		switch (revision_id) {
+		case USB9098_Z1Z2:
+			if (strap != 0) {
+				if (strap == CARD_TYPE_USB_UART)
+					strcpy(handle->card_info->fw_name,
+					       USBUART9098_DEFAULT_COMBO_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       USBUSB9098_DEFAULT_COMBO_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       USB9098_DEFAULT_WLAN_FW_NAME);
+			break;
+		case USB9098_A0:
+		case USB9098_A1:
+		case USB9098_A2:
+			if (strap != 0) {
+				if (strap == CARD_TYPE_USB_UART)
+					strcpy(handle->card_info->fw_name,
+					       USBUART9098_COMBO_V1_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       USBUSB9098_COMBO_V1_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       USB9098_WLAN_V1_FW_NAME);
+			break;
+		}
+	}
+#endif
+#ifdef USB9097
+	if (IS_USB9097(handle->card_type)) {
+		switch (revision_id) {
+		case USB9097_B0:
+		case USB9097_B1:
+			if (strap != 0) {
+				if (strap == CARD_TYPE_USB_UART)
+					strcpy(handle->card_info->fw_name,
+					       USBUART9097_COMBO_V1_FW_NAME);
+				else
+					strcpy(handle->card_info->fw_name,
+					       USBUSB9097_COMBO_V1_FW_NAME);
+			}
+			strcpy(handle->card_info->fw_name_wlan,
+			       USB9097_WLAN_V1_FW_NAME);
+			break;
+		}
+	}
+#endif
+done:
+	PRINTM(MCMND, "combo fw:%s wlan fw:%s \n", handle->card_info->fw_name,
+	       handle->card_info->fw_name_wlan);
+	LEAVE();
+	return ret;
+}
+
+static moal_if_ops usb_ops = {
+	.register_dev = woal_usb_register_dev,
+	.unregister_dev = woal_usb_unregister_dev,
+	.read_data_sync = woal_usb_read_data_sync,
+	.write_data_sync = woal_usb_write_data_sync,
+	.get_fw_name = woal_usb_get_fw_name,
+	.dump_fw_info = woal_usb_dump_fw_info,
+	.is_second_mac = woal_usb_is_second_mac,
+};
diff --git a/wlan_sd8987/mlinux/moal_usb.h b/wlan_sd8987/mlinux/moal_usb.h
new file mode 100755
index 0000000..73637fc
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_usb.h
@@ -0,0 +1,245 @@
+/** @file moal_usb.h
+ *
+ * @brief This file contains definitions for USB interface.
+ * driver.
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/*************************************************************
+Change Log:
+    10/21/2008: initial version
+************************************************************/
+
+#ifndef _MOAL_USB_H
+#define _MOAL_USB_H
+
+#ifdef USB8801
+/** USB VID 1 */
+#define USB8801_VID_1   0x1286
+/** USB PID 1 */
+#define USB8801_PID_1   0x2049
+/** USB PID 2 */
+#define USB8801_PID_2   0x204a
+#endif /* USB8801 */
+#ifdef USB8997
+/** USB VID 1 */
+#define USB8997_VID_1 0x1286
+/** USB PID 1 */
+#define USB8997_PID_1 0x204D
+/** USB PID 2 */
+#define USB8997_PID_2 0x204E
+#define USB8997_PID_3 0x2047
+#define USB8997_PID_4 0x2048
+#define USB8997_PID_5 0x2050
+#define USB8997_PID_6 0x2051
+#define USB8997V2_PID_1 0x2052
+#endif /* USB8997 */
+
+#ifdef USB8978
+/** USB VID 1 */
+#define USB8978_VID_1 0x1286
+/** USB PID 1 */
+#define USB8978_PID_1 0x2062
+/** USB PID 2 */
+#define USB8978_PID_2 0x2063
+/* BT downloaded combo  firmware; register for WLAN enumeration */
+#define USB8978_PID_1_BT 0x2064
+#define USB8978_PID_2_BT 0x2065
+#endif
+
+#ifdef USB8897
+/** USB VID 1 */
+#define USB8897_VID_1 0x1286
+/** USB PID 1 */
+#define USB8897_PID_1 0x2045
+/** USB PID 2 */
+#define USB8897_PID_2 0x2046
+#endif /* USB8897 */
+
+#ifdef USB9098
+/** USB VID 1 */
+#define USB9098_VID_1 0x1286
+/** USB PID 1 */
+#define USB9098_PID_1 0x2056
+/** USB PID 2 */
+#define USB9098_PID_2 0x2057
+#endif /* USB9098 */
+
+#ifdef USB9097
+/** USB VID 1 */
+#define USB9097_VID_1 0x1286
+/** USB PID 1 */
+#define USB9097_PID_1 0x2060
+/** USB PID 2 */
+#define USB9097_PID_2 0x2061
+#endif /* USB9097 */
+
+/** Boot state: FW download */
+#define USB_FW_DNLD 1
+/** Boot state: FW ready */
+#define USB_FW_READY 2
+
+/** High watermark for Tx data */
+#define MVUSB_TX_HIGH_WMARK 12
+
+/** Number of Rx data URB */
+#define MVUSB_RX_DATA_URB 6
+
+#if defined(USB8997) || defined(USB9098) || defined(USB9097) || defined(USB8978) || defined(USB8801)
+/* Transmit buffer size for chip revision check */
+#define CHIP_REV_TX_BUF_SIZE 16
+/* Receive buffer size for chip revision check */
+#define CHIP_REV_RX_BUF_SIZE 2048
+
+/* Extensions */
+#define EXTEND_HDR (0xAB950000)
+#define EXTEND_V1 (0x00000001)
+#define EXTEND_V2 (0x00000002)
+#ifdef USB8801
+#define USB8801_DEFAULT_WLAN_FW_NAME	"nxp/usb8801_uapsta.bin"
+#endif /* USB8801 */
+
+#endif
+
+/** Default firmaware name */
+#ifdef USB8997
+#define USB8997_DEFAULT_COMBO_FW_NAME "nxp/usbusb8997_combo_v4.bin"
+#define USB8997_DEFAULT_WLAN_FW_NAME "nxp/usb8997_wlan_v4.bin"
+#define USBUART8997_DEFAULT_COMBO_FW_NAME "nxp/usbuart8997_combo_v4.bin"
+#define USBUSB8997_DEFAULT_COMBO_FW_NAME "nxp/usbusb8997_combo_v4.bin"
+
+#endif /* USB8997 */
+
+#ifdef USB8978
+#define USB8978_DEFAULT_COMBO_FW_NAME "nxp/usbusbiw416_combo.bin"
+#define USB8978_DEFAULT_WLAN_FW_NAME "nxp/usbiw416_wlan.bin"
+#define USBUART8978_DEFAULT_COMBO_FW_NAME "nxp/usbuartiw416_combo.bin"
+#define USBUSB8978_DEFAULT_COMBO_FW_NAME "nxp/usbusbiw416_combo.bin"
+#endif /* USB8978 */
+
+#ifdef USB8897
+#define USB8897_DEFAULT_COMBO_FW_NAME "nxp/usb8897_uapsta.bin"
+#define USB8897_DEFAULT_WLAN_FW_NAME "nxp/usb8897_wlan.bin"
+#endif /* USB8897 */
+
+#ifdef USB9098
+#define USB9098_Z1Z2 0x00
+#define USB9098_A0 0x01
+#define USB9098_A1 0x02
+#define USB9098_A2 0x03
+#define USB9098_DEFAULT_COMBO_FW_NAME "nxp/usbusb9098_combo.bin"
+#define USB9098_DEFAULT_WLAN_FW_NAME "nxp/usb9098_wlan.bin"
+#define USBUART9098_DEFAULT_COMBO_FW_NAME "nxp/usbuart9098_combo.bin"
+#define USBUSB9098_DEFAULT_COMBO_FW_NAME "nxp/usbusb9098_combo.bin"
+#define USB9098_WLAN_V1_FW_NAME "nxp/usb9098_wlan_v1.bin"
+#define USBUART9098_COMBO_V1_FW_NAME "nxp/usbuart9098_combo_v1.bin"
+#define USBUSB9098_COMBO_V1_FW_NAME "nxp/usbusb9098_combo_v1.bin"
+#endif /* USB9098 */
+
+#ifdef USB9097
+#define USB9097_B0 0x01
+#define USB9097_B1 0x02
+#define USB9097_DEFAULT_COMBO_FW_NAME "nxp/usbusbiw620_combo_v1.bin"
+#define USB9097_DEFAULT_WLAN_FW_NAME "nxp/usbiw620_wlan_v1.bin"
+#define USB9097_WLAN_V1_FW_NAME "nxp/usbiw620_wlan_v1.bin"
+#define USBUART9097_COMBO_V1_FW_NAME "nxp/usbuartiw620_combo_v1.bin"
+#define USBUSB9097_COMBO_V1_FW_NAME "nxp/usbusbiw620_combo_v1.bin"
+#endif /* USB9097 */
+
+/** urb context */
+typedef struct _urb_context {
+	/** Pointer to moal_handle structure */
+	moal_handle *handle;
+	/** Pointer to mlan buffer */
+	mlan_buffer *pmbuf;
+	/** URB */
+	struct urb *urb;
+	/** EP */
+	t_u8 ep;
+} urb_context;
+
+/** USB card description structure*/
+struct usb_card_rec {
+	/** USB device */
+	struct usb_device *udev;
+	/** MOAL handle */
+	moal_handle *phandle;
+	/** USB interface */
+	struct usb_interface *intf;
+	/** Rx command endpoint type */
+	int rx_cmd_ep_type;
+	/** Rx command interval for INTR type */
+	t_u8 rx_cmd_interval;
+	/** Rx data endpoint address */
+	t_u8 rx_cmd_ep;
+	/** Rx cmd contxt */
+	urb_context rx_cmd;
+	/** Rx command URB pending count */
+	atomic_t rx_cmd_urb_pending;
+	/** Rx data context list */
+	urb_context rx_data_list[MVUSB_RX_DATA_URB];
+	/** Flag to indicate boot state */
+	t_u8 boot_state;
+	/** Rx data endpoint address */
+	t_u8 rx_data_ep;
+	/** Rx data URB pending count */
+	atomic_t rx_data_urb_pending;
+	/** Tx data endpoint address */
+	t_u8 tx_data_ep;
+	/** Tx command endpoint type */
+	int tx_cmd_ep_type;
+	/** Tx command interval for INTR type */
+	t_u8 tx_cmd_interval;
+	/** Tx command endpoint address */
+	t_u8 tx_cmd_ep;
+	/** Tx data URB pending count */
+	atomic_t tx_data_urb_pending;
+	/** Tx command URB pending count */
+	atomic_t tx_cmd_urb_pending;
+	/** Tx data endpoint max pkt size */
+	int tx_data_maxpktsize;
+	/** Tx cmd endpoint max pkt size */
+	int tx_cmd_maxpktsize;
+	/** Pre-allocated urb for command */
+	urb_context tx_cmd;
+	/** Index to point to next data urb to use */
+	int tx_data_ix;
+	/** Pre-allocated urb for data */
+	urb_context tx_data_list[MVUSB_TX_HIGH_WMARK];
+	usb_aggr_ctrl_cfg tx_aggr_ctrl;
+	usb_aggr_ctrl_cfg rx_deaggr_ctrl;
+	t_u8 resubmit_urbs;
+	/** USB card type */
+	t_u16 card_type;
+	t_u8 second_mac;
+};
+
+void woal_kill_urbs(moal_handle *handle);
+void woal_resubmit_urbs(moal_handle *handle);
+
+mlan_status woal_write_data_async(moal_handle *handle, mlan_buffer *pmbuf,
+				  t_u8 ep);
+mlan_status woal_usb_submit_rx_data_urbs(moal_handle *handle);
+mlan_status woal_usb_rx_init(moal_handle *handle);
+mlan_status woal_usb_tx_init(moal_handle *handle);
+mlan_status woal_usb_aggr_init(moal_handle *handle);
+void woal_submit_rx_urb(moal_handle *handle, t_u8 ep);
+void woal_usb_bus_unregister(void);
+mlan_status woal_usb_bus_register(void);
+void woal_usb_free(struct usb_card_rec *cardp);
+#endif /*_MOAL_USB_H */
diff --git a/wlan_sd8987/mlinux/moal_wext.c b/wlan_sd8987/mlinux/moal_wext.c
new file mode 100755
index 0000000..f792e51
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_wext.c
@@ -0,0 +1,3419 @@
+/** @file  moal_wext.c
+ *
+ * @brief This file contains wireless extension standard ioctl functions
+ *
+ *
+ * Copyright 2008-2021 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/************************************************************************
+Change log:
+    10/21/2008: initial version
+************************************************************************/
+
+#include "moal_main.h"
+
+#ifdef STA_SUPPORT
+/** Approximate amount of data needed to pass a scan result back to iwlist */
+#define MAX_SCAN_CELL_SIZE                                                     \
+	(IW_EV_ADDR_LEN + MLAN_MAX_SSID_LENGTH + IW_EV_UINT_LEN +              \
+	 IW_EV_FREQ_LEN + IW_EV_QUAL_LEN + MLAN_MAX_SSID_LENGTH +              \
+	 IW_EV_PARAM_LEN + 40)	/* 40 for WPAIE */
+
+/********************************************************
+			Local Variables
+********************************************************/
+/**
+ * iwpriv ioctl handlers
+ */
+static const struct iw_priv_args woal_private_args[] = {
+	{WOAL_SETONEINT_GETWORDCHAR, IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_CHAR | 128, ""},
+	{WOAL_VERSION, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128,
+	 "version"},
+	{WOAL_VEREXT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128, "verext"},
+	{WOAL_SETNONE_GETNONE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, ""},
+	{WOAL_WARMRESET, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "warmreset"},
+#ifdef CONFIG_USB_SUSPEND
+	{WOAL_USB_SUSPEND, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "usbsuspend"},
+	{WOAL_USB_RESUME, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "usbresume"},
+#endif /* CONFIG_USB_SUSPEND */
+	{WOAL_SETONEINT_GETONEINT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 ""},
+	{WOAL_SET_GET_TXRATE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "txratecfg"},
+	{WOAL_SET_GET_REGIONCODE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "regioncode"},
+	{WOAL_SET_RADIO, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "radioctrl"},
+	{WOAL_WMM_ENABLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "wmmcfg"},
+	{WOAL_11D_ENABLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "11dcfg"},
+	{WOAL_11D_CLR_CHAN_TABLE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE,
+	 "11dclrtbl"},
+	{WOAL_SET_GET_QOS_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "qoscfg"},
+#ifndef OPCHAN
+	{WOAL_SET_GET_WWS_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "wwscfg"},
+#endif
+#if defined(REASSOCIATION)
+	{WOAL_SET_GET_REASSOC, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "reassoctrl"},
+#endif
+	{WOAL_TXBUF_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "txbufcfg"},
+	{WOAL_SLEEP_PD, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "sleeppd"},
+	{WOAL_AUTH_TYPE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "authtype"},
+	{WOAL_PORT_CTRL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "port_ctrl"},
+#ifdef WIFI_DIRECT_SUPPORT
+#if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
+	{WOAL_SET_GET_BSS_ROLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "bssrole"},
+#endif
+#endif
+	{WOAL_SET_GET_11H_LOCAL_PWR_CONSTRAINT, IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1, "powercons"},
+	{WOAL_HT_STREAM_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "htstreamcfg"},
+	{WOAL_MAC_CONTROL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "macctrl"},
+	{WOAL_THERMAL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "thermal"},
+	{WOAL_CFG_HOTSPOT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "hotspotcfg"},
+	{WOAL_SET_GET_SIXTEEN_INT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 ""},
+	{WOAL_TX_POWERCFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "txpowercfg"},
+#ifdef DEBUG_LEVEL1
+	{WOAL_DRV_DBG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "drvdbg"},
+#endif
+	{WOAL_BEACON_INTERVAL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "bcninterval"},
+	{WOAL_SIGNAL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "getsignal"},
+	{
+	 WOAL_DEEP_SLEEP,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "deepsleep",
+	 },
+	{WOAL_11N_TX_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "httxcfg"},
+	{WOAL_11N_HTCAP_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "htcapinfo"},
+	{WOAL_PRIO_TBL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "aggrpriotbl"},
+	{WOAL_11N_AMSDU_AGGR_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "amsduaggrctrl"},
+	{WOAL_ADDBA_UPDT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "addbapara"},
+	{WOAL_ADDBA_REJECT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "addbareject"},
+	{WOAL_TX_BF_CAP, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "httxbfcap"},
+	{WOAL_HS_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "hscfg"},
+	{WOAL_HS_SETPARA, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "hssetpara"},
+	{WOAL_REG_READ_WRITE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "regrdwr"},
+	{WOAL_BAND_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "bandcfg"},
+	{WOAL_INACTIVITY_TIMEOUT_EXT, IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16, "inactivityto"},
+#ifdef SDIO
+	{WOAL_SDIO_CLOCK, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "sdioclock"},
+	{WOAL_CMD_52RDWR, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "sdcmd52rw"},
+#endif
+	{WOAL_SCAN_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "scancfg"},
+	{WOAL_PS_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "pscfg"},
+	{WOAL_MEM_READ_WRITE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "memrdwr"},
+#ifdef SDIO
+	{WOAL_SDIO_MPA_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "mpactrl"},
+#endif
+	{WOAL_SLEEP_PARAMS, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "sleepparams"},
+	{WOAL_DFS_TESTING, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "dfstesting"},
+	{WOAL_MGMT_FRAME_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "mgmtframectrl"},
+	{WOAL_CFP_CODE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "cfpcode"},
+	{WOAL_SET_GET_TX_RX_ANT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "antcfg"},
+	{WOAL_IND_RST_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
+	 "indrstcfg"},
+	{WOALGETLOG, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | GETLOG_BUFSIZE,
+	 "getlog"},
+	{WOAL_SETADDR_GETNONE, IW_PRIV_TYPE_ADDR | 1, IW_PRIV_TYPE_NONE, ""},
+	{WOAL_DEAUTH, IW_PRIV_TYPE_ADDR | 1, IW_PRIV_TYPE_NONE, "deauth"},
+	{WOAL_SET_GET_256_CHAR, IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256, ""},
+	{WOAL_PASSPHRASE, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "passphrase"},
+	{WOAL_GET_KEY, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "getkey"},
+	{WOAL_ASSOCIATE, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "associate"},
+	{WOAL_WMM_QUEUE_STATUS, IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256, "qstatus"},
+	{WOAL_WMM_TS_STATUS, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "ts_status"},
+	{WOAL_IP_ADDRESS, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "ipaddr"},
+	{WOAL_TX_BF_CFG, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
+	 "httxbfcfg"},
+	{WOAL_SETNONE_GETTWELVE_CHAR, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12,
+	 ""},
+	{WOAL_WPS_SESSION, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12,
+	 "wpssession"},
+	{WOAL_SETNONE_GET_FOUR_INT, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | 4,
+	 ""},
+	{WOAL_DATA_RATE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | 4,
+	 "getdatarate"},
+	{WOAL_ESUPP_MODE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | 4, "esuppmode"},
+	{WOAL_SET_GET_64_INT, IW_PRIV_TYPE_INT | 64, IW_PRIV_TYPE_INT | 64, ""},
+	{WOAL_ECL_SYS_CLOCK, IW_PRIV_TYPE_INT | 64, IW_PRIV_TYPE_INT | 64,
+	 "sysclock"},
+	{WOAL_HOST_CMD, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047,
+	 "hostcmd"},
+	{WOAL_ARP_FILTER, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047,
+	 "arpfilter"},
+	{WOAL_SET_INTS_GET_CHARS, IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_BYTE | 256, ""},
+	{WOAL_READ_EEPROM, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_BYTE | 256,
+	 "rdeeprom"},
+	{WOAL_SET_GET_2K_BYTES, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, ""},
+#if defined(SDIO)
+	{WOAL_CMD_53RDWR, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "sdcmd53rw"},
+#endif
+	{WOAL_SET_USER_SCAN, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "setuserscan"},
+	{WOAL_GET_SCAN_TABLE, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "getscantable"},
+	{WOAL_SET_USER_SCAN_EXT, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "setuserscanext"},
+	{WOAL_WMM_ADDTS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "addts"},
+	{WOAL_WMM_DELTS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "delts"},
+	{WOAL_WMM_QUEUE_CONFIG, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "qconfig"},
+	{WOAL_WMM_QUEUE_STATS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "qstats"},
+	{WOAL_BYPASSED_PACKET, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
+	 IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "pb_bypass"},
+#ifdef UAP_WEXT
+	{WOAL_FROYO_START, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "START"},
+	{WOAL_FROYO_STOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "STOP"},
+	{WOAL_FROYO_WL_FW_RELOAD, IW_PRIV_TYPE_CHAR | 256,
+	 IW_PRIV_TYPE_CHAR | 256, "WL_FW_RELOAD"},
+#endif
+};
+
+/********************************************************
+			Local Functions
+********************************************************/
+
+/**
+ *  @brief Compare two SSIDs
+ *
+ *  @param ssid1    A pointer to ssid to compare
+ *  @param ssid2    A pointer to ssid to compare
+ *
+ *  @return         0--ssid is same, otherwise is different
+ */
+static t_s32
+woal_ssid_cmp(mlan_802_11_ssid *ssid1, mlan_802_11_ssid *ssid2)
+{
+	ENTER();
+
+	if (!ssid1 || !ssid2) {
+		LEAVE();
+		return -1;
+	}
+	if (ssid1->ssid_len != ssid2->ssid_len) {
+		LEAVE();
+		return -1;
+	}
+
+	LEAVE();
+	return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
+}
+
+/**
+ *  @brief Sort Channels
+ *
+ *  @param freq                 A pointer to iw_freq structure
+ *  @param num                  Number of Channels
+ *
+ *  @return                     N/A
+ */
+static inline void
+woal_sort_channels(struct iw_freq *freq, int num)
+{
+	int i, j;
+	struct iw_freq temp;
+
+	for (i = 0; i < num; i++)
+		for (j = i + 1; j < num; j++)
+			if (freq[i].i > freq[j].i) {
+				temp.i = freq[i].i;
+				temp.m = freq[i].m;
+
+				freq[i].i = freq[j].i;
+				freq[i].m = freq[j].m;
+
+				freq[j].i = temp.i;
+				freq[j].m = temp.m;
+			}
+}
+
+/**
+ *  @brief Convert RSSI to quality
+ *
+ *  @param rssi     RSSI in dBm
+ *
+ *  @return         Quality of the link (0-5)
+ */
+static t_u8
+woal_rssi_to_quality(t_s16 rssi)
+{
+/** Macro for RSSI range */
+#define MOAL_RSSI_NO_SIGNAL -90
+#define MOAL_RSSI_VERY_LOW -80
+#define MOAL_RSSI_LOW -70
+#define MOAL_RSSI_GOOD -60
+#define MOAL_RSSI_VERY_GOOD -50
+#define MOAL_RSSI_INVALID 0
+	if (rssi <= MOAL_RSSI_NO_SIGNAL || rssi == MOAL_RSSI_INVALID)
+		return 0;
+	else if (rssi <= MOAL_RSSI_VERY_LOW)
+		return 1;
+	else if (rssi <= MOAL_RSSI_LOW)
+		return 2;
+	else if (rssi <= MOAL_RSSI_GOOD)
+		return 3;
+	else if (rssi <= MOAL_RSSI_VERY_GOOD)
+		return 4;
+	else
+		return 5;
+}
+
+/**
+ *  @brief Set Adapter Node Name
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_nick(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	ENTER();
+	/*
+	 * Check the size of the string
+	 */
+	if (dwrq->length > 16) {
+		LEAVE();
+		return -E2BIG;
+	}
+	memset(priv->nick_name, 0, sizeof(priv->nick_name));
+	moal_memcpy_ext(priv->phandle, priv->nick_name, extra, dwrq->length,
+			sizeof(priv->nick_name));
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get Adapter Node Name
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success
+ */
+static int
+woal_get_nick(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	ENTER();
+	/*
+	 * Get the Nick Name saved
+	 */
+	strncpy(extra, (char *)priv->nick_name, 16);
+	extra[16] = '\0';
+	/*
+	 * If none, we may want to get the one that was set
+	 */
+
+	/*
+	 * Push it out !
+	 */
+	dwrq->length = strlen(extra) + 1;
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Commit handler: called after a bunch of SET operations
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param cwrq         A pointer to char buffer
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success
+ */
+static int
+woal_config_commit(struct net_device *dev,
+		   struct iw_request_info *info, union iwreq_data *cwrq,
+		   char *extra)
+{
+	ENTER();
+
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Get name
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param cwrq         A pointer to char buffer
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success
+ */
+static int
+woal_get_name(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	char *cwrq = wrqu->name;
+	ENTER();
+	strcpy(cwrq, "IEEE 802.11-DS");
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Set frequency
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param fwrq                 A pointer to iw_freq structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_freq(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_freq *fwrq = &wrqu->freq;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	/*
+	 * If setting by frequency, convert to a channel
+	 */
+	if (fwrq->e == 1) {
+		long f = fwrq->m / 100000;
+		bss->param.bss_chan.freq = f;
+	} else
+		bss->param.bss_chan.channel = fwrq->m;
+
+	bss->sub_command = MLAN_OID_BSS_CHANNEL;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_change_adhoc_chan(priv, bss->param.bss_chan.channel,
+				   MOAL_IOCTL_WAIT))
+		ret = -EFAULT;
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get frequency
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param fwrq                 A pointer to iw_freq structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_freq(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_freq *fwrq = &wrqu->freq;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_CHANNEL;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_GET;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	fwrq->m = (long)bss->param.bss_chan.freq;
+	fwrq->i = (long)bss->param.bss_chan.channel;
+	fwrq->e = 6;
+	fwrq->flags = IW_FREQ_FIXED;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set wlan mode
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param uwrq                 Wireless mode to set
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_bss_mode(struct net_device *dev,
+		  struct iw_request_info *info, union iwreq_data *wrqu,
+		  char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u32 *uwrq = &wrqu->mode;
+	mlan_ds_bss *bss = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	bss = (mlan_ds_bss *)req->pbuf;
+	bss->sub_command = MLAN_OID_BSS_MODE;
+	req->req_id = MLAN_IOCTL_BSS;
+	req->action = MLAN_ACT_SET;
+
+	switch (*uwrq) {
+	case IW_MODE_INFRA:
+		bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
+		break;
+	case IW_MODE_ADHOC:
+		bss->param.bss_mode = MLAN_BSS_MODE_IBSS;
+		break;
+	case IW_MODE_AUTO:
+		bss->param.bss_mode = MLAN_BSS_MODE_AUTO;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret)
+		goto done;
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get current BSSID
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param awrq         A pointer to sockaddr structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success
+ */
+static int
+woal_get_wap(struct net_device *dev, struct iw_request_info *info,
+	     union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct sockaddr *awrq = &wrqu->addr;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+	if (bss_info.media_connected == MTRUE)
+		moal_memcpy_ext(priv->phandle, awrq->sa_data, &bss_info.bssid,
+				MLAN_MAC_ADDR_LENGTH, sizeof(awrq->sa_data));
+	else
+		memset(awrq->sa_data, 0, MLAN_MAC_ADDR_LENGTH);
+	awrq->sa_family = ARPHRD_ETHER;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Connect to the AP or Ad-hoc Network with specific bssid
+ *
+ * NOTE: Scan should be issued by application before this function is called
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param awrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_set_wap(struct net_device *dev, struct iw_request_info *info,
+	     union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	const t_u8 bcast[MLAN_MAC_ADDR_LENGTH] =
+		{ 255, 255, 255, 255, 255, 255 };
+	const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 };
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct sockaddr *awrq = &wrqu->addr;
+	mlan_ssid_bssid ssid_bssid;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	if (awrq->sa_family != ARPHRD_ETHER) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	PRINTM(MINFO, "ASSOC: WAP: sa_data: " MACSTR "\n",
+	       MAC2STR((t_u8 *)awrq->sa_data));
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef REASSOCIATION
+	/* Cancel re-association */
+	priv->reassoc_required = MFALSE;
+#endif
+
+	/* zero_mac means disconnect */
+	if (!memcmp(zero_mac, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
+		woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
+				DEF_DEAUTH_REASON_CODE);
+		goto done;
+	}
+
+	/* Broadcast MAC means search for best network */
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+	if (memcmp(bcast, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
+		/* Check if we are already assoicated to the AP */
+		if (bss_info.media_connected == MTRUE) {
+			if (!memcmp(awrq->sa_data, &bss_info.bssid, ETH_ALEN))
+				goto done;
+		}
+		moal_memcpy_ext(priv->phandle, &ssid_bssid.bssid, awrq->sa_data,
+				ETH_ALEN, sizeof(ssid_bssid.bssid));
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		PRINTM(MERROR,
+		       "ASSOC: WAP: MAC address not found in BSSID List\n");
+		ret = -ENETUNREACH;
+		goto done;
+	}
+	/* Zero SSID implies use BSSID to connect */
+	memset(&ssid_bssid.ssid, 0, sizeof(mlan_802_11_ssid));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		ret = -EFAULT;
+		goto done;
+	}
+#ifdef REASSOCIATION
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
+			&bss_info.ssid, sizeof(mlan_802_11_ssid),
+			sizeof(priv->prev_ssid_bssid.ssid));
+	moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
+			&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
+			sizeof(priv->prev_ssid_bssid.bssid));
+#endif /* REASSOCIATION */
+
+done:
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get wlan mode
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param uwrq                 A pointer to t_u32 string
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success
+ */
+static int
+woal_get_bss_mode(struct net_device *dev,
+		  struct iw_request_info *info, union iwreq_data *wrqu,
+		  char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u32 *uwrq = &wrqu->mode;
+	ENTER();
+	*uwrq = woal_get_mode(priv, MOAL_IOCTL_WAIT);
+	LEAVE();
+	return 0;
+}
+
+/**
+ *  @brief Set sensitivity
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success
+ */
+static int
+woal_set_sens(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+
+	ENTER();
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get sensitivity
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     -1
+ */
+static int
+woal_get_sens(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = -1;
+
+	ENTER();
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Tx power
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_txpow(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_power_cfg_t power_cfg;
+
+	ENTER();
+	if (vwrq->disabled) {
+		woal_set_radio(priv, 0);
+		goto done;
+	}
+	woal_set_radio(priv, 1);
+
+	if (!vwrq->fixed)
+		power_cfg.is_power_auto = 1;
+	else {
+		power_cfg.is_power_auto = 0;
+		power_cfg.power_level = vwrq->value;
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_tx_power(priv, MLAN_ACT_SET, &power_cfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Tx power
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_txpow(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_power_cfg_t power_cfg;
+	mlan_bss_info bss_info;
+
+	ENTER();
+
+	memset(&power_cfg, 0, sizeof(mlan_power_cfg_t));
+	memset(&bss_info, 0, sizeof(bss_info));
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_tx_power(priv, MLAN_ACT_GET, &power_cfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	vwrq->value = power_cfg.power_level;
+	if (power_cfg.is_power_auto)
+		vwrq->fixed = 0;
+	else
+		vwrq->fixed = 1;
+	if (bss_info.radio_on) {
+		vwrq->disabled = 0;
+		vwrq->flags = IW_TXPOW_DBM;
+	} else {
+		vwrq->disabled = 1;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Set power management
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_set_power(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	int ret = 0, disabled;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	ENTER();
+
+	if (moal_extflg_isset(priv->phandle, EXT_HW_TEST)) {
+		PRINTM(MIOCTL, "block set power in hw_test mode\n");
+		LEAVE();
+		return ret;
+	}
+	disabled = vwrq->disabled;
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_power_mgmt(priv, MLAN_ACT_SET, &disabled, vwrq->flags,
+				    MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Get power management
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int
+woal_get_power(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	int ret = 0, ps_mode = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
+							   &ps_mode, 0,
+							   MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+	}
+
+	if (ps_mode)
+		vwrq->disabled = 0;
+	else
+		vwrq->disabled = 1;
+
+	vwrq->value = 0;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Tx retry count
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_retry(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	int ret = 0, retry_val = vwrq->value;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	ENTER();
+
+	if (vwrq->flags == IW_RETRY_LIMIT) {
+		/*
+		 * The MAC has a 4-bit Total_Tx_Count register
+		 * Total_Tx_Count = 1 + Tx_Retry_Count
+		 */
+
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_retry(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
+				       &retry_val)) {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Tx retry count
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_retry(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	int retry_val, ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_retry(priv, MLAN_ACT_GET,
+						      MOAL_IOCTL_WAIT,
+						      &retry_val)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	vwrq->disabled = 0;
+	if (!vwrq->flags) {
+		vwrq->flags = IW_RETRY_LIMIT;
+		/* Get Tx retry count */
+		vwrq->value = retry_val;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set encryption key
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_encode(struct net_device *dev, struct iw_request_info *info,
+		struct iw_point *dwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	int index = 0;
+	t_u32 auth_mode = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+
+	/* Check index */
+	index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+	if (index > 3) {
+		PRINTM(MERROR, "Key index #%d out of range\n", index);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	sec->param.encrypt_key.key_len = 0;
+	if (!(dwrq->flags & IW_ENCODE_NOKEY) && dwrq->length) {
+		if (dwrq->length > MAX_WEP_KEY_SIZE) {
+			PRINTM(MERROR, "Key length (%d) out of range\n",
+			       dwrq->length);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (index < 0)
+			sec->param.encrypt_key.key_index =
+				MLAN_KEY_INDEX_DEFAULT;
+		else
+			sec->param.encrypt_key.key_index = index;
+		moal_memcpy_ext(priv->phandle,
+				sec->param.encrypt_key.key_material, extra,
+				dwrq->length,
+				sizeof(sec->param.encrypt_key.key_material));
+		/* Set the length */
+		if (dwrq->length > MIN_WEP_KEY_SIZE)
+			sec->param.encrypt_key.key_len = MAX_WEP_KEY_SIZE;
+		else
+			sec->param.encrypt_key.key_len = MIN_WEP_KEY_SIZE;
+	} else {
+		/*
+		 * No key provided so it is either enable key,
+		 * on or off
+		 */
+		if (dwrq->flags & IW_ENCODE_DISABLED) {
+			PRINTM(MINFO, "*** iwconfig mlanX key off ***\n");
+			sec->param.encrypt_key.key_disable = MTRUE;
+		} else {
+			/*
+			 * iwconfig mlanX key [n]
+			 * iwconfig mlanX key on
+			 * iwconfig mlanX key open
+			 * iwconfig mlanX key restricted
+			 * Do we want to just set the transmit key index ?
+			 */
+			if (index < 0) {
+				PRINTM(MINFO,
+				       "*** iwconfig mlanX key on ***\n");
+				sec->param.encrypt_key.key_index =
+					MLAN_KEY_INDEX_DEFAULT;
+			} else
+				sec->param.encrypt_key.key_index = index;
+			sec->param.encrypt_key.is_current_wep_key = MTRUE;
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (dwrq->flags & (IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)) {
+		switch (dwrq->flags & 0xf000) {
+		case IW_ENCODE_RESTRICTED:
+			/* iwconfig mlanX restricted key [1] */
+			auth_mode = MLAN_AUTH_MODE_SHARED;
+			PRINTM(MINFO, "Auth mode restricted!\n");
+			break;
+		case IW_ENCODE_OPEN:
+			/* iwconfig mlanX key [2] open */
+			auth_mode = MLAN_AUTH_MODE_OPEN;
+			PRINTM(MINFO, "Auth mode open!\n");
+			break;
+		case IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN:
+		default:
+			/* iwconfig mlanX key [2] open restricted */
+			auth_mode = MLAN_AUTH_MODE_AUTO;
+			PRINTM(MINFO, "Auth mode auto!\n");
+			break;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode))
+			ret = -EFAULT;
+	}
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get encryption key
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_encode(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	mlan_ds_sec_cfg *sec = NULL;
+	mlan_ioctl_req *req = NULL;
+	t_u32 auth_mode;
+	int index = (dwrq->flags & IW_ENCODE_INDEX);
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	if (index < 0 || index > 4) {
+		PRINTM(MERROR, "Key index #%d out of range\n", index);
+		ret = -EINVAL;
+		goto done;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	dwrq->flags = 0;
+	/*
+	 * Check encryption mode
+	 */
+	switch (auth_mode) {
+	case MLAN_AUTH_MODE_OPEN:
+		dwrq->flags = IW_ENCODE_OPEN;
+		break;
+
+	case MLAN_AUTH_MODE_SHARED:
+	case MLAN_AUTH_MODE_NETWORKEAP:
+		dwrq->flags = IW_ENCODE_RESTRICTED;
+		break;
+
+	case MLAN_AUTH_MODE_AUTO:
+		dwrq->flags = IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED;
+		break;
+
+	default:
+		dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
+		break;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_GET;
+
+	if (!index)
+		sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
+	else
+		sec->param.encrypt_key.key_index = index - 1;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(extra, 0, 16);
+	if (sec->param.encrypt_key.key_len) {
+		moal_memcpy_ext(priv->phandle, extra,
+				sec->param.encrypt_key.key_material,
+				sec->param.encrypt_key.key_len,
+				sec->param.encrypt_key.key_len);
+		dwrq->length = sec->param.encrypt_key.key_len;
+		dwrq->flags |= (sec->param.encrypt_key.key_index + 1);
+		dwrq->flags &= ~IW_ENCODE_DISABLED;
+	} else if (sec->param.encrypt_key.key_disable)
+		dwrq->flags |= IW_ENCODE_DISABLED;
+	else
+		dwrq->flags &= ~IW_ENCODE_DISABLED;
+
+	dwrq->flags |= IW_ENCODE_NOKEY;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set data rate
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param vwrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_set_rate(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_rate_cfg_t rate_cfg;
+
+	ENTER();
+
+	if (vwrq->value == -1) {
+		rate_cfg.is_rate_auto = 1;
+	} else {
+		rate_cfg.is_rate_auto = 0;
+		rate_cfg.rate_type = MLAN_RATE_VALUE;
+		rate_cfg.rate = vwrq->value / 500000;
+	}
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_data_rate(priv, MLAN_ACT_SET, &rate_cfg)) {
+		ret = -EFAULT;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get data rate
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param vwrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0 --success, otherwise fail
+ */
+static int
+woal_get_rate(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_rate_cfg_t rate_cfg;
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_data_rate(priv, MLAN_ACT_GET, &rate_cfg)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (rate_cfg.is_rate_auto)
+		vwrq->fixed = 0;
+	else
+		vwrq->fixed = 1;
+	vwrq->value = rate_cfg.rate * 500000;
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set RTS threshold
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_rts(struct net_device *dev, struct iw_request_info *info,
+	     struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int rthr = vwrq->value;
+
+	ENTER();
+
+	if (vwrq->disabled) {
+		rthr = MLAN_RTS_MAX_VALUE;
+	} else {
+		if (rthr < MLAN_RTS_MIN_VALUE || rthr > MLAN_RTS_MAX_VALUE) {
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_rts(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &rthr)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get RTS threshold
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_rts(struct net_device *dev, struct iw_request_info *info,
+	     struct iw_param *vwrq, char *extra)
+{
+	int rthr, ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_rts(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &rthr)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	vwrq->value = rthr;
+	vwrq->disabled = ((vwrq->value < MLAN_RTS_MIN_VALUE) ||
+			  (vwrq->value > MLAN_RTS_MAX_VALUE));
+	vwrq->fixed = 1;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Fragment threshold
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_frag(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int fthr = vwrq->value;
+
+	ENTER();
+
+	if (vwrq->disabled) {
+		fthr = MLAN_FRAG_MAX_VALUE;
+	} else {
+		if (fthr < MLAN_FRAG_MIN_VALUE || fthr > MLAN_FRAG_MAX_VALUE) {
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_frag(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &fthr)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get Fragment threshold
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_frag(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0, fthr;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_set_get_frag(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &fthr)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	vwrq->value = fthr;
+	vwrq->disabled = ((vwrq->value < MLAN_FRAG_MIN_VALUE) ||
+			  (vwrq->value > MLAN_FRAG_MAX_VALUE));
+	vwrq->fixed = 1;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+#if (WIRELESS_EXT >= 18)
+/**
+ *  @brief Get IE
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_gen_ie(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	int copy_size = 0, ie_len;
+	t_u8 ie[MAX_IE_SIZE];
+
+	ENTER();
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_gen_ie(priv, MLAN_ACT_GET, ie,
+						       &ie_len,
+						       MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	copy_size = MIN(ie_len, dwrq->length);
+	moal_memcpy_ext(priv->phandle, extra, ie, copy_size, copy_size);
+	dwrq->length = copy_size;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set IE
+ *
+ *  Pass an opaque block of data, expected to be IEEE IEs, to the driver
+ *    for eventual passthrough to the firmware in an associate/join
+ *    (and potentially start) command.
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_gen_ie(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	int ie_len = dwrq->length;
+	const t_u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
+	mlan_ds_wps_cfg *pwps = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	/* extra + 2 to skip element id and length */
+	if (!memcmp((t_u8 *)(extra + 2), wps_oui, sizeof(wps_oui))) {
+		req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg));
+		if (req == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+
+		pwps = (mlan_ds_wps_cfg *)req->pbuf;
+		req->req_id = MLAN_IOCTL_WPS_CFG;
+		req->action = MLAN_ACT_SET;
+		pwps->sub_command = MLAN_OID_WPS_CFG_SESSION;
+		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START;
+
+		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+		if (status != MLAN_STATUS_SUCCESS) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (MLAN_STATUS_SUCCESS != woal_set_get_gen_ie(priv, MLAN_ACT_SET,
+						       (t_u8 *)extra, &ie_len,
+						       MOAL_IOCTL_WAIT)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Extended version of encoding configuration
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return              0 --success, otherwise fail
+ */
+static int
+woal_set_encode_ext(struct net_device *dev,
+		    struct iw_request_info *info,
+		    union iwreq_data *wrqu, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	int key_index;
+	t_u8 *pkey_material = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_sec_cfg *sec = NULL;
+	int ret = 0;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+	key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+	if (key_index < 0 || key_index > 5) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (ext->key_len > (MLAN_MAX_KEY_LENGTH)) {
+		ret = -EINVAL;
+		goto done;
+	}
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	sec = (mlan_ds_sec_cfg *)req->pbuf;
+	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
+	req->req_id = MLAN_IOCTL_SEC_CFG;
+	req->action = MLAN_ACT_SET;
+	pkey_material = (t_u8 *)(ext + 1);
+	sec->param.encrypt_key.key_len = ext->key_len;
+	moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
+			(u8 *)ext->addr.sa_data, ETH_ALEN,
+			sizeof(sec->param.encrypt_key.mac_addr));
+	/* Disable and Remove Key */
+	if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) {
+		sec->param.encrypt_key.key_remove = MTRUE;
+		sec->param.encrypt_key.key_index = key_index;
+		sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY;
+		PRINTM(MIOCTL,
+		       "Remove key key_index=%d, dwrq->flags=0x%x " MACSTR "\n",
+		       key_index, dwrq->flags,
+		       MAC2STR(sec->param.encrypt_key.mac_addr));
+	} else if (ext->key_len <= MAX_WEP_KEY_SIZE) {
+		/* Set WEP key */
+		sec->param.encrypt_key.key_index = key_index;
+		sec->param.encrypt_key.key_flags = ext->ext_flags;
+		moal_memcpy_ext(priv->phandle,
+				sec->param.encrypt_key.key_material,
+				pkey_material, ext->key_len,
+				sizeof(sec->param.encrypt_key.key_material));
+		if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+			sec->param.encrypt_key.is_current_wep_key = MTRUE;
+	} else {
+		/* Set WPA key */
+		sec->param.encrypt_key.key_index = key_index;
+		sec->param.encrypt_key.key_flags = ext->ext_flags;
+		if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.pn,
+					(t_u8 *)ext->rx_seq, SEQ_MAX_SIZE,
+					sizeof(sec->param.encrypt_key.pn));
+			DBG_HEXDUMP(MCMD_D, "Rx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) {
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.pn,
+					(t_u8 *)ext->tx_seq, SEQ_MAX_SIZE,
+					sizeof(sec->param.encrypt_key.pn));
+			DBG_HEXDUMP(MCMD_D, "Tx PN", sec->param.encrypt_key.pn,
+				    SEQ_MAX_SIZE);
+		}
+		moal_memcpy_ext(priv->phandle,
+				sec->param.encrypt_key.key_material,
+				pkey_material, ext->key_len,
+				sizeof(sec->param.encrypt_key.key_material));
+		PRINTM(MIOCTL,
+		       "set wpa key key_index=%d, key_len=%d key_flags=0x%x "
+		       MACSTR "\n", key_index, ext->key_len,
+		       sec->param.encrypt_key.key_flags,
+		       MAC2STR(sec->param.encrypt_key.mac_addr));
+		DBG_HEXDUMP(MCMD_D, "wpa key", pkey_material, ext->key_len);
+#define IW_ENCODE_ALG_AES_CMAC 5
+		if (ext->alg == IW_ENCODE_ALG_AES_CMAC)
+			sec->param.encrypt_key.key_flags |=
+				KEY_FLAG_AES_MCAST_IGTK;
+#define IW_ENCODE_ALG_SMS4 0x20
+		/* Set WAPI key */
+		if (ext->alg == IW_ENCODE_ALG_SMS4) {
+			sec->param.encrypt_key.is_wapi_key = MTRUE;
+			moal_memcpy_ext(priv->phandle,
+					sec->param.encrypt_key.pn,
+					(t_u8 *)ext->tx_seq, SEQ_MAX_SIZE,
+					sizeof(sec->param.encrypt_key.pn));
+			moal_memcpy_ext(priv->phandle,
+					&sec->param.encrypt_key.
+					pn[SEQ_MAX_SIZE], (t_u8 *)ext->rx_seq,
+					SEQ_MAX_SIZE,
+					sizeof(sec->param.encrypt_key.pn) -
+					SEQ_MAX_SIZE);
+			DBG_HEXDUMP(MCMD_D, "WAPI PN",
+				    sec->param.encrypt_key.pn, PN_SIZE);
+		}
+	}
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS)
+		ret = -EFAULT;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Extended version of encoding configuration
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             -EOPNOTSUPP
+ */
+static int
+woal_get_encode_ext(struct net_device *dev,
+		    struct iw_request_info *info,
+		    union iwreq_data *wrqu, char *extra)
+{
+	ENTER();
+	LEAVE();
+	return -EOPNOTSUPP;
+}
+
+/**
+ *  @brief  Request MLME operation
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0--success, otherwise fail
+ */
+static int
+woal_set_mlme(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	struct iw_mlme *mlme = (struct iw_mlme *)extra;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+
+	ENTER();
+	if ((mlme->cmd == IW_MLME_DEAUTH) || (mlme->cmd == IW_MLME_DISASSOC)) {
+
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_disconnect(priv, MOAL_IOCTL_WAIT,
+				    (t_u8 *)mlme->addr.sa_data,
+				    DEF_DEAUTH_REASON_CODE))
+			ret = -EFAULT;
+	}
+	LEAVE();
+	return ret;
+}
+
+/** @brief Set authentication mode parameters
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_auth(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_param *vwrq = &wrqu->param;
+	t_u32 auth_mode = 0;
+	t_u32 encrypt_mode = 0;
+	ENTER();
+
+	switch (vwrq->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_CIPHER_PAIRWISE:
+	case IW_AUTH_CIPHER_GROUP:
+		if (vwrq->value & IW_AUTH_CIPHER_NONE)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_NONE;
+		else if (vwrq->value & IW_AUTH_CIPHER_WEP40)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_WEP40;
+		else if (vwrq->value & IW_AUTH_CIPHER_WEP104)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_WEP104;
+		else if (vwrq->value & IW_AUTH_CIPHER_TKIP)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_TKIP;
+		else if (vwrq->value & IW_AUTH_CIPHER_CCMP)
+			encrypt_mode = MLAN_ENCRYPTION_MODE_CCMP;
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_encrypt_mode(priv, MOAL_IOCTL_WAIT, encrypt_mode))
+			ret = -EFAULT;
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		switch (vwrq->value) {
+		case IW_AUTH_ALG_SHARED_KEY:
+			PRINTM(MINFO, "Auth mode shared key!\n");
+			auth_mode = MLAN_AUTH_MODE_SHARED;
+			break;
+		case IW_AUTH_ALG_LEAP:
+			PRINTM(MINFO, "Auth mode LEAP!\n");
+			auth_mode = MLAN_AUTH_MODE_NETWORKEAP;
+			break;
+		case IW_AUTH_ALG_OPEN_SYSTEM:
+			PRINTM(MINFO, "Auth mode open!\n");
+			auth_mode = MLAN_AUTH_MODE_OPEN;
+			break;
+		case IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM:
+		default:
+			PRINTM(MINFO, "Auth mode auto!\n");
+			auth_mode = MLAN_AUTH_MODE_AUTO;
+			break;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode))
+			ret = -EFAULT;
+		break;
+	case IW_AUTH_WPA_ENABLED:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wpa_enable(priv, MOAL_IOCTL_WAIT, vwrq->value))
+			ret = -EFAULT;
+		break;
+#define IW_AUTH_WAPI_ENABLED 0x20
+	case IW_AUTH_WAPI_ENABLED:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, vwrq->value))
+			ret = -EFAULT;
+		break;
+	case IW_AUTH_WPA_VERSION:
+		/* set WPA_VERSION_DISABLED/VERSION_WPA/VERSION_WP2 */
+		priv->wpa_version = vwrq->value;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		/* set KEY_MGMT_802_1X/KEY_MGMT_PSK */
+		priv->key_mgmt = vwrq->value;
+		break;
+	case IW_AUTH_TKIP_COUNTERMEASURES:
+	case IW_AUTH_DROP_UNENCRYPTED:
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+	case IW_AUTH_ROAMING_CONTROL:
+	case IW_AUTH_PRIVACY_INVOKED:
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	case IW_AUTH_MFP:
+#endif
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get authentication mode parameters
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param vwrq                 A pointer to iw_param structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_auth(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_param *vwrq = &wrqu->param;
+	t_u32 encrypt_mode = 0;
+	t_u32 auth_mode;
+	t_u32 wpa_enable;
+	ENTER();
+	switch (vwrq->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_CIPHER_PAIRWISE:
+	case IW_AUTH_CIPHER_GROUP:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_encrypt_mode(priv, MOAL_IOCTL_WAIT, &encrypt_mode))
+			ret = -EFAULT;
+		else {
+			if (encrypt_mode == MLAN_ENCRYPTION_MODE_NONE)
+				vwrq->value = IW_AUTH_CIPHER_NONE;
+			else if (encrypt_mode == MLAN_ENCRYPTION_MODE_WEP40)
+				vwrq->value = IW_AUTH_CIPHER_WEP40;
+			else if (encrypt_mode == MLAN_ENCRYPTION_MODE_TKIP)
+				vwrq->value = IW_AUTH_CIPHER_TKIP;
+			else if (encrypt_mode == MLAN_ENCRYPTION_MODE_CCMP)
+				vwrq->value = IW_AUTH_CIPHER_CCMP;
+			else if (encrypt_mode == MLAN_ENCRYPTION_MODE_WEP104)
+				vwrq->value = IW_AUTH_CIPHER_WEP104;
+		}
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode))
+			ret = -EFAULT;
+		else {
+			if (auth_mode == MLAN_AUTH_MODE_SHARED)
+				vwrq->value = IW_AUTH_ALG_SHARED_KEY;
+			else if (auth_mode == MLAN_AUTH_MODE_NETWORKEAP)
+				vwrq->value = IW_AUTH_ALG_LEAP;
+			else
+				vwrq->value = IW_AUTH_ALG_OPEN_SYSTEM;
+		}
+		break;
+	case IW_AUTH_WPA_ENABLED:
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_wpa_enable(priv, MOAL_IOCTL_WAIT, &wpa_enable))
+			ret = -EFAULT;
+		else
+			vwrq->value = wpa_enable;
+		break;
+	case IW_AUTH_WPA_VERSION:
+		vwrq->value = priv->wpa_version;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		vwrq->value = priv->key_mgmt;
+		break;
+	case IW_AUTH_TKIP_COUNTERMEASURES:
+	case IW_AUTH_DROP_UNENCRYPTED:
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+	case IW_AUTH_ROAMING_CONTROL:
+	case IW_AUTH_PRIVACY_INVOKED:
+	default:
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set PMKSA Cache
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param info     A pointer to iw_request_info structure
+ *  @param vwrq     A pointer to iw_param structure
+ *  @param extra    A pointer to extra data buf
+ *
+ *  @return         -EOPNOTSUPP
+ */
+static int
+woal_set_pmksa(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_param *vwrq, char *extra)
+{
+	ENTER();
+	LEAVE();
+	return -EOPNOTSUPP;
+}
+
+#endif /* WE >= 18 */
+
+/* Data rate listing
+ *      MULTI_BANDS:
+ *              abg             a       b       b/g
+ *  Infra       G(12)           A(8)    B(4)    G(12)
+ *  Adhoc       A+B(12)         A(8)    B(4)    B(4)
+ *      non-MULTI_BANDS:
+										b       b/g
+ *  Infra                               B(4)    G(12)
+ *  Adhoc                               B(4)    B(4)
+ */
+/**
+ *  @brief Get Range Info
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param info                 A pointer to iw_request_info structure
+ *  @param dwrq                 A pointer to iw_point structure
+ *  @param extra                A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_get_range(struct net_device *dev, struct iw_request_info *info,
+	       union iwreq_data *wrqu, char *extra)
+{
+	int i;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	struct iw_range *range = (struct iw_range *)extra;
+	moal_802_11_rates rates;
+	mlan_chan_list *pchan_list = NULL;
+	mlan_bss_info bss_info;
+	gfp_t flag;
+
+	ENTER();
+
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	pchan_list = kzalloc(sizeof(mlan_chan_list), flag);
+	if (!pchan_list) {
+		LEAVE();
+		return -ENOMEM;
+	}
+
+	dwrq->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+
+	range->min_nwid = 0;
+	range->max_nwid = 0;
+
+	memset(&rates, 0, sizeof(rates));
+	woal_get_data_rates(priv, MOAL_IOCTL_WAIT, &rates);
+	range->num_bitrates = rates.num_of_rates;
+
+	for (i = 0;
+	     i < MIN(range->num_bitrates, IW_MAX_BITRATES) && rates.rates[i];
+	     i++) {
+		range->bitrate[i] = (rates.rates[i] & 0x7f) * 500000;
+	}
+	range->num_bitrates = i;
+	PRINTM(MINFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
+	       range->num_bitrates);
+
+	range->num_frequency = 0;
+
+	woal_get_channel_list(priv, MOAL_IOCTL_WAIT, pchan_list);
+
+	range->num_frequency = MIN(pchan_list->num_of_chan, IW_MAX_FREQUENCIES);
+
+	for (i = 0; i < range->num_frequency; i++) {
+		range->freq[i].i = (long)pchan_list->cf[i].channel;
+		range->freq[i].m = (long)pchan_list->cf[i].freq * 100000;
+		range->freq[i].e = 1;
+	}
+	kfree(pchan_list);
+
+	PRINTM(MINFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
+	       IW_MAX_FREQUENCIES, range->num_frequency);
+
+	range->num_channels = range->num_frequency;
+
+	woal_sort_channels(&range->freq[0], range->num_frequency);
+
+	/*
+	 * Set an indication of the max TCP throughput in bit/s that we can
+	 * expect using this interface
+	 */
+	if (i > 2)
+		range->throughput = 5000 * 1000;
+	else
+		range->throughput = 1500 * 1000;
+
+	range->min_rts = MLAN_RTS_MIN_VALUE;
+	range->max_rts = MLAN_RTS_MAX_VALUE;
+	range->min_frag = MLAN_FRAG_MIN_VALUE;
+	range->max_frag = MLAN_FRAG_MAX_VALUE;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = 4;
+
+/** Minimum power period */
+#define IW_POWER_PERIOD_MIN 1000000	/* 1 sec */
+/** Maximum power period */
+#define IW_POWER_PERIOD_MAX 120000000	/* 2 min */
+/** Minimum power timeout value */
+#define IW_POWER_TIMEOUT_MIN 1000	/* 1 ms  */
+/** Maximim power timeout value */
+#define IW_POWER_TIMEOUT_MAX 1000000	/* 1 sec */
+
+	/* Power Management duration & timeout */
+	range->min_pmp = IW_POWER_PERIOD_MIN;
+	range->max_pmp = IW_POWER_PERIOD_MAX;
+	range->min_pmt = IW_POWER_TIMEOUT_MIN;
+	range->max_pmt = IW_POWER_TIMEOUT_MAX;
+	range->pmp_flags = IW_POWER_PERIOD;
+	range->pmt_flags = IW_POWER_TIMEOUT;
+	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
+
+	/*
+	 * Minimum version we recommend
+	 */
+	range->we_version_source = 15;
+
+	/*
+	 * Version we are compiled with
+	 */
+	range->we_version_compiled = WIRELESS_EXT;
+
+	range->retry_capa = IW_RETRY_LIMIT;
+	range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+
+	range->min_retry = MLAN_TX_RETRY_MIN;
+	range->max_retry = MLAN_TX_RETRY_MAX;
+
+	/*
+	 * Set the qual, level and noise range values
+	 */
+	/*
+	 * need to put the right values here
+	 */
+/** Maximum quality percentage */
+#define IW_MAX_QUAL_PERCENT 5
+/** Average quality percentage */
+#define IW_AVG_QUAL_PERCENT 3
+	range->max_qual.qual = IW_MAX_QUAL_PERCENT;
+	range->max_qual.level = 0;
+	range->max_qual.noise = 0;
+
+	range->avg_qual.qual = IW_AVG_QUAL_PERCENT;
+	range->avg_qual.level = 0;
+	range->avg_qual.noise = 0;
+
+	range->sensitivity = 0;
+
+	/*
+	 * Setup the supported power level ranges
+	 */
+	memset(range->txpower, 0, sizeof(range->txpower));
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
+
+	range->txpower[0] = bss_info.min_power_level;
+	range->txpower[1] = bss_info.max_power_level;
+	range->num_txpower = 2;
+	range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
+
+#if (WIRELESS_EXT >= 18)
+	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+		IW_ENC_CAPA_CIPHER_CCMP | IW_ENC_CAPA_CIPHER_TKIP;
+#endif
+	LEAVE();
+	return 0;
+}
+
+#ifdef MEF_CFG_RX_FILTER
+/**
+ *  @brief Enable/disable Rx broadcast/multicast filter in non-HS mode
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param enable               MTRUE/MFALSE: enable/disable
+ *
+ *  @return                     0 -- success, otherwise fail
+ */
+static int
+woal_set_rxfilter(moal_private *priv, BOOLEAN enable)
+{
+	int ret = 0;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_misc_mef_cfg *mef_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	mef_cfg = &misc->param.mef_cfg;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc->sub_command = MLAN_OID_MISC_MEF_CFG;
+	req->action = MLAN_ACT_SET;
+
+	mef_cfg->sub_id = (enable ? MEF_CFG_RX_FILTER_ENABLE : MEF_CFG_DISABLE);
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+#endif
+
+/**
+ *  @brief Set priv command
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return                     0 --success, otherwise fail
+ */
+static int
+woal_set_priv(struct net_device *dev, struct iw_request_info *info,
+	      union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	char *buf = NULL;
+	int power_mode = 0;
+	int band = 0;
+	char *pband = NULL;
+	mlan_bss_info bss_info;
+	mlan_ds_get_signal signal;
+	mlan_rate_cfg_t rate;
+	char *pdata = NULL;
+	t_u8 country_code[COUNTRY_CODE_LEN];
+	int len = 0;
+	gfp_t flag;
+	ENTER();
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is NULL\n");
+		ret = -EFAULT;
+		goto done;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	buf = kzalloc(dwrq->length + 1, flag);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	if (copy_from_user(buf, dwrq->pointer, dwrq->length)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	buf[dwrq->length] = '\0';
+	PRINTM(MIOCTL, "SIOCSIWPRIV request = %s\n", buf);
+	if (strncmp(buf, "RSSILOW-THRESHOLD", strlen("RSSILOW-THRESHOLD")) == 0) {
+		if (dwrq->length > strlen("RSSILOW-THRESHOLD") + 1) {
+			pdata = buf + strlen("RSSILOW-THRESHOLD") + 1;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_rssi_low_threshold(priv, pdata,
+							MOAL_IOCTL_WAIT)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "OK\n") + 1;
+		} else {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (strncmp(buf, "RSSI", strlen("RSSI")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		if (bss_info.media_connected) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_get_signal_info(priv, MOAL_IOCTL_WAIT,
+						 &signal)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "%s rssi %d\n", bss_info.ssid.ssid,
+				      signal.bcn_rssi_avg) + 1;
+		} else {
+			len = sprintf(buf, "OK\n") + 1;
+		}
+	} else if (strncmp(buf, "LINKSPEED", strlen("LINKSPEED")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_get_data_rate(priv, MLAN_ACT_GET, &rate)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		PRINTM(MIOCTL, "tx rate=%d\n", (int)rate.rate);
+		len = sprintf(buf, "LinkSpeed %d\n",
+			      (int)(rate.rate * 500000 / 1000000)) + 1;
+	} else if (strncmp(buf, "MACADDR", strlen("MACADDR")) == 0) {
+		len = sprintf(buf, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+			      priv->current_addr[0], priv->current_addr[1],
+			      priv->current_addr[2], priv->current_addr[3],
+			      priv->current_addr[4], priv->current_addr[5]) + 1;
+	} else if (strncmp(buf, "GETPOWER", strlen("GETPOWER")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_get_powermode(priv, &power_mode)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "powermode = %d\n", power_mode) + 1;
+	} else if (strncmp(buf, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->scan_type = MLAN_SCAN_TYPE_ACTIVE;
+		PRINTM(MIOCTL, "Set Active Scan\n");
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->scan_type = MLAN_SCAN_TYPE_PASSIVE;
+		PRINTM(MIOCTL, "Set Passive Scan\n");
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "POWERMODE", strlen("POWERMODE")) == 0) {
+		if (dwrq->length > strlen("POWERMODE") + 1) {
+			pdata = buf + strlen("POWERMODE") + 1;
+			if (!moal_extflg_isset(priv->phandle, EXT_HW_TEST)) {
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_set_powermode(priv, pdata)) {
+					ret = -EFAULT;
+					goto done;
+				}
+			}
+			len = sprintf(buf, "OK\n") + 1;
+		} else {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (strncmp(buf, "COUNTRY", strlen("COUNTRY")) == 0) {
+		memset(country_code, 0, sizeof(country_code));
+		if ((strlen(buf) - strlen("COUNTRY") - 1) > COUNTRY_CODE_LEN) {
+			ret = -EFAULT;
+			goto done;
+		}
+		moal_memcpy_ext(priv->phandle, country_code,
+				buf + strlen("COUNTRY") + 1,
+				COUNTRY_CODE_LEN - 1, sizeof(country_code) - 1);
+		PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code);
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_region_code(priv, country_code)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (memcmp(buf, WEXT_CSCAN_HEADER, strlen(WEXT_CSCAN_HEADER)) ==
+		   0) {
+		PRINTM(MIOCTL, "Set Combo Scan\n");
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_combo_scan(priv, buf, dwrq->length)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "GETBAND", strlen("GETBAND")) == 0) {
+		if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "Band %d\n", band) + 1;
+	} else if (strncmp(buf, "SETBAND", strlen("SETBAND")) == 0) {
+		pband = buf + strlen("SETBAND") + 1;
+		if (MLAN_STATUS_SUCCESS != woal_set_band(priv, pband)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "START", strlen("START")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "STOP", strlen("STOP")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "SETSUSPENDOPT", strlen("SETSUSPENDOPT")) == 0) {
+		/* it will be done by GUI */
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BTCOEXSCAN-START",
+			   strlen("BTCOEXSCAN-START")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BTCOEXSCAN-STOP", strlen("BTCOEXSCAN-STOP")) ==
+		   0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BGSCAN-START", strlen("BGSCAN-START")) == 0) {
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BGSCAN-CONFIG", strlen("BGSCAN-CONFIG")) == 0) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_set_bg_scan(priv, buf, dwrq->length)) {
+			ret = -EFAULT;
+			goto done;
+		}
+		priv->bg_scan_start = MTRUE;
+		priv->bg_scan_reported = MFALSE;
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) {
+		if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_stop_bg_scan(priv, MOAL_IOCTL_WAIT)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			priv->bg_scan_start = MFALSE;
+			priv->bg_scan_reported = MFALSE;
+		}
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RXFILTER-START", strlen("RXFILTER-START")) ==
+		   0) {
+#ifdef MEF_CFG_RX_FILTER
+		ret = woal_set_rxfilter(priv, MTRUE);
+		if (ret)
+			goto done;
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RXFILTER-STOP", strlen("RXFILTER-STOP")) == 0) {
+#ifdef MEF_CFG_RX_FILTER
+		ret = woal_set_rxfilter(priv, MFALSE);
+		if (ret)
+			goto done;
+#endif
+		len = sprintf(buf, "OK\n") + 1;
+	} else if (strncmp(buf, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) {
+		if (dwrq->length > strlen("RXFILTER-ADD") + 1) {
+			pdata = buf + strlen("RXFILTER-ADD") + 1;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_add_rxfilter(priv, pdata)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "OK\n") + 1;
+		} else {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (strncmp(buf, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) ==
+		   0) {
+		if (dwrq->length > strlen("RXFILTER-REMOVE") + 1) {
+			pdata = buf + strlen("RXFILTER-REMOVE") + 1;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_remove_rxfilter(priv, pdata)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "OK\n") + 1;
+		} else {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (strncmp(buf, "QOSINFO", strlen("QOSINFO")) == 0) {
+		if (dwrq->length > strlen("QOSINFO") + 1) {
+			pdata = buf + strlen("QOSINFO") + 1;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_priv_qos_cfg(priv, MLAN_ACT_SET, pdata)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "OK\n") + 1;
+		} else {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else if (strncmp(buf, "SLEEPPD", strlen("SLEEPPD")) == 0) {
+		if (dwrq->length > strlen("SLEEPPD") + 1) {
+			pdata = buf + strlen("SLEEPPD") + 1;
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_set_sleeppd(priv, pdata)) {
+				ret = -EFAULT;
+				goto done;
+			}
+			len = sprintf(buf, "OK\n") + 1;
+		} else {
+			ret = -EFAULT;
+			goto done;
+		}
+	} else {
+		PRINTM(MIOCTL, "Unknow PRIVATE command: %s, ignored\n", buf);
+		ret = -EFAULT;
+		goto done;
+	}
+	PRINTM(MIOCTL, "PRIV Command return: %s, length=%d\n", buf, len);
+	dwrq->length = (t_u16)len;
+	if (copy_to_user((void __user *)dwrq->pointer, buf, dwrq->length))
+		ret = -EFAULT;
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Request a scan
+ *
+ *  @param priv                 A pointer to moal_private structure
+ *  @param wait_option          Wait option
+ *  @param req_ssid             A pointer to mlan_802_11_ssid structure
+ *
+ *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
+ */
+static mlan_status
+woal_wext_request_scan(moal_private *priv, t_u8 wait_option,
+		       mlan_802_11_ssid *req_ssid)
+{
+	wlan_user_scan_cfg scan_req;
+	mlan_scan_cfg scan_cfg;
+	ENTER();
+	if (!woal_is_any_interface_active(priv->phandle)) {
+		LEAVE();
+		return woal_request_scan(priv, wait_option, req_ssid);
+	}
+	memset(&scan_cfg, 0, sizeof(scan_cfg));
+	memset(&scan_req, 0, sizeof(scan_req));
+	if (req_ssid && req_ssid->ssid_len != 0) {
+		moal_memcpy_ext(priv->phandle, scan_req.ssid_list[0].ssid,
+				req_ssid->ssid, req_ssid->ssid_len,
+				MLAN_MAX_SSID_LENGTH);
+		scan_req.ssid_list[0].max_len = 0;
+	}
+	woal_get_scan_config(priv, &scan_cfg);
+	if (scan_cfg.scan_chan_gap)
+		scan_req.scan_chan_gap = scan_cfg.scan_chan_gap;
+	else
+		scan_req.scan_chan_gap = priv->phandle->scan_chan_gap;
+	/** indicate FW, gap is optional */
+	if (scan_req.scan_chan_gap && priv->phandle->pref_mac)
+		scan_req.scan_chan_gap |= GAP_FLAG_OPTIONAL;
+	LEAVE();
+	return woal_request_userscan(priv, wait_option, &scan_req);
+}
+
+/**
+ *  @brief Scan Network
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param vwrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0--success, otherwise fail
+ */
+static int
+woal_set_scan(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_param *vwrq, char *extra)
+{
+	int ret = 0;
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	moal_handle *handle = priv->phandle;
+#if WIRELESS_EXT >= 18
+	struct iw_scan_req *req;
+	struct iw_point *dwrq = (struct iw_point *)vwrq;
+#endif
+	mlan_802_11_ssid req_ssid;
+
+	ENTER();
+	if (handle->scan_pending_on_block == MTRUE) {
+		PRINTM(MINFO, "scan already in processing...\n");
+		LEAVE();
+		return ret;
+	}
+#ifdef REASSOCIATION
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_set_scan\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#endif /* REASSOCIATION */
+	priv->report_scan_result = MTRUE;
+
+	memset(&req_ssid, 0x00, sizeof(mlan_802_11_ssid));
+
+#if WIRELESS_EXT >= 18
+	if ((dwrq->flags & IW_SCAN_THIS_ESSID) &&
+	    (dwrq->length == sizeof(struct iw_scan_req))) {
+		req = (struct iw_scan_req *)extra;
+
+		if (req->essid_len <= MLAN_MAX_SSID_LENGTH) {
+			req_ssid.ssid_len = req->essid_len;
+			moal_memcpy_ext(priv->phandle, req_ssid.ssid,
+					(t_u8 *)req->essid, req->essid_len,
+					sizeof(req_ssid.ssid));
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_wext_request_scan(priv, MOAL_NO_WAIT,
+						   &req_ssid)) {
+				ret = -EFAULT;
+				goto done;
+			}
+		}
+	} else {
+#endif
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_wext_request_scan(priv, MOAL_NO_WAIT, &req_ssid)) {
+			ret = -EFAULT;
+			goto done;
+		}
+#if WIRELESS_EXT >= 18
+	}
+#endif
+
+	if (priv->phandle->surprise_removed) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set essid
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0--success, otherwise fail
+ */
+static int
+woal_set_essid(struct net_device *dev, struct iw_request_info *info,
+	       union iwreq_data *wrqu, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	struct iw_point *dwrq = &wrqu->data;
+	mlan_802_11_ssid req_ssid;
+	mlan_ssid_bssid ssid_bssid;
+#ifdef REASSOCIATION
+	moal_handle *handle = priv->phandle;
+	mlan_bss_info bss_info;
+#endif
+	int ret = 0;
+	t_u32 mode = 0;
+
+	ENTER();
+
+#ifdef REASSOCIATION
+	/* Cancel re-association */
+	priv->reassoc_required = MFALSE;
+
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_set_essid\n");
+		LEAVE();
+		return -EBUSY;
+	}
+#endif /* REASSOCIATION */
+
+	/* Check the size of the string */
+	if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+		ret = -E2BIG;
+		goto setessid_ret;
+	}
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
+	memset(&req_ssid, 0, sizeof(mlan_802_11_ssid));
+	memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
+
+#if WIRELESS_EXT > 20
+	req_ssid.ssid_len = dwrq->length;
+#else
+	req_ssid.ssid_len = dwrq->length - 1;
+#endif
+
+	/*
+	 * Check if we asked for `any' or 'particular'
+	 */
+	if (!dwrq->flags) {
+#ifdef REASSOCIATION
+		if (!req_ssid.ssid_len) {
+			memset(&priv->prev_ssid_bssid.ssid, 0x00,
+			       sizeof(mlan_802_11_ssid));
+			memset(&priv->prev_ssid_bssid.bssid, 0x00,
+			       MLAN_MAC_ADDR_LENGTH);
+			goto setessid_ret;
+		}
+#endif
+		/* Do normal SSID scanning */
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_request_scan(priv, MOAL_IOCTL_WAIT, NULL)) {
+			ret = -EFAULT;
+			goto setessid_ret;
+		}
+	} else {
+		/* Set the SSID */
+		moal_memcpy_ext(priv->phandle, req_ssid.ssid, extra,
+				MIN(req_ssid.ssid_len, MLAN_MAX_SSID_LENGTH),
+				sizeof(req_ssid.ssid));
+		if (!req_ssid.ssid_len ||
+		    (MFALSE == woal_ssid_valid(&req_ssid))) {
+			PRINTM(MERROR, "Invalid SSID - aborting set_essid\n");
+			ret = -EINVAL;
+			goto setessid_ret;
+		}
+
+		PRINTM(MINFO, "Requested new SSID = %s\n",
+		       (char *)req_ssid.ssid);
+		moal_memcpy_ext(priv->phandle, &ssid_bssid.ssid, &req_ssid,
+				sizeof(mlan_802_11_ssid),
+				sizeof(ssid_bssid.ssid));
+		if (MTRUE == woal_is_connected(priv, &ssid_bssid)) {
+			PRINTM(MIOCTL, "Already connect to the network\n");
+			goto setessid_ret;
+		}
+
+		if (dwrq->flags != 0xFFFF) {
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_find_essid(priv, &ssid_bssid,
+					    MOAL_IOCTL_WAIT)) {
+				/* Do specific SSID scanning */
+				if (MLAN_STATUS_SUCCESS !=
+				    woal_request_scan(priv, MOAL_IOCTL_WAIT,
+						      &req_ssid)) {
+					ret = -EFAULT;
+					goto setessid_ret;
+				}
+			}
+		}
+	}
+
+	mode = woal_get_mode(priv, MOAL_IOCTL_WAIT);
+	if (mode == IW_MODE_ADHOC)
+		/* disconnect before try to associate */
+		woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
+				DEF_DEAUTH_REASON_CODE);
+
+	if (mode != IW_MODE_ADHOC) {
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_find_best_network(priv, MOAL_IOCTL_WAIT,
+					   &ssid_bssid)) {
+			ret = -EFAULT;
+			goto setessid_ret;
+		}
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_11d_check_ap_channel(priv, MOAL_IOCTL_WAIT,
+					      &ssid_bssid)) {
+			PRINTM(MERROR,
+			       "The AP's channel is invalid for current region\n");
+			ret = -EFAULT;
+			goto setessid_ret;
+		}
+	} else if (MLAN_STATUS_SUCCESS !=
+		   woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid))
+		/* Adhoc start, Check the channel command */
+		woal_11h_channel_check_ioctl(priv, MOAL_IOCTL_WAIT);
+
+#ifdef REASSOCIATION
+	if (priv->reassoc_on == MTRUE && req_ssid.ssid_len) {
+		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
+				&req_ssid, sizeof(mlan_802_11_ssid),
+				sizeof(priv->prev_ssid_bssid.ssid));
+		memset(&priv->prev_ssid_bssid.bssid, 0x00,
+		       MLAN_MAC_ADDR_LENGTH);
+	}
+#endif /* REASSOCIATION */
+
+	/* Connect to BSS by ESSID */
+	memset(&ssid_bssid.bssid, 0, MLAN_MAC_ADDR_LENGTH);
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
+		ret = -EFAULT;
+		goto setessid_ret;
+	}
+#ifdef REASSOCIATION
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto setessid_ret;
+	}
+	moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
+			&bss_info.ssid, sizeof(mlan_802_11_ssid),
+			sizeof(priv->prev_ssid_bssid.ssid));
+	moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
+			&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
+			sizeof(priv->prev_ssid_bssid.bssid));
+#endif /* REASSOCIATION */
+
+setessid_ret:
+	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
+		woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
+#ifdef REASSOCIATION
+	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
+#endif
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get current essid
+ *
+ *  @param dev      A pointer to net_device structure
+ *  @param info     A pointer to iw_request_info structure
+ *  @param dwrq     A pointer to iw_point structure
+ *  @param extra    A pointer to extra data buf
+ *
+ *  @return         0--success, otherwise fail
+ */
+static int
+woal_get_essid(struct net_device *dev, struct iw_request_info *info,
+	       struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	mlan_bss_info bss_info;
+	int ret = 0;
+
+	ENTER();
+
+	memset(&bss_info, 0, sizeof(bss_info));
+
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (bss_info.media_connected) {
+		dwrq->length = MIN(dwrq->length, bss_info.ssid.ssid_len);
+		moal_memcpy_ext(priv->phandle, extra, bss_info.ssid.ssid,
+				dwrq->length, dwrq->length);
+	} else
+		dwrq->length = 0;
+
+	if (bss_info.scan_table_idx)
+		dwrq->flags = (bss_info.scan_table_idx + 1) & IW_ENCODE_INDEX;
+	else
+		dwrq->flags = 1;
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief  Retrieve the scan table entries via wireless tools IOCTL call
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             0--success, otherwise fail
+ */
+static int
+woal_get_scan(struct net_device *dev, struct iw_request_info *info,
+	      struct iw_point *dwrq, char *extra)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	int ret = 0;
+	char *current_ev = extra;
+	char *end_buf = extra + IW_SCAN_MAX_DATA;
+	char *current_val;	/* For rates */
+	struct iw_event iwe;	/* Temporary buffer */
+	unsigned int i;
+	unsigned int j;
+	mlan_scan_resp scan_resp;
+	mlan_bss_info bss_info;
+	BSSDescriptor_t *scan_table;
+	mlan_ds_get_signal rssi;
+	t_u16 buf_size = 16 + 256 * 2;
+	char *buf = NULL;
+	char *ptr;
+#if WIRELESS_EXT >= 18
+	t_u8 *praw_data;
+#endif
+	int beacon_size;
+	t_u8 *pbeacon;
+	IEEEtypes_ElementId_e element_id;
+	t_u8 element_len;
+	gfp_t flag;
+
+	ENTER();
+
+	if (priv->phandle->scan_pending_on_block == MTRUE) {
+		LEAVE();
+		return -EAGAIN;
+	}
+	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
+	buf = kzalloc((buf_size), flag);
+	if (!buf) {
+		PRINTM(MERROR, "Cannot allocate buffer!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	memset(&bss_info, 0, sizeof(bss_info));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	memset(&scan_resp, 0, sizeof(scan_resp));
+	if (MLAN_STATUS_SUCCESS !=
+	    woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
+		ret = -EFAULT;
+		goto done;
+	}
+	scan_table = (BSSDescriptor_t *)scan_resp.pscan_table;
+	if (dwrq->length)
+		end_buf = extra + dwrq->length;
+	if (priv->media_connected == MTRUE)
+		PRINTM(MINFO, "Current Ssid: %-32s\n", bss_info.ssid.ssid);
+	PRINTM(MINFO, "Scan: Get: NumInScanTable = %d\n",
+	       (int)scan_resp.num_in_scan_table);
+
+#if WIRELESS_EXT > 13
+	/* The old API using SIOCGIWAPLIST had a hard limit of
+	 * IW_MAX_AP. The new API using SIOCGIWSCAN is only
+	 * limited by buffer size WE-14 -> WE-16 the buffer is
+	 * limited to IW_SCAN_MAX_DATA bytes which is 4096.
+	 */
+	for (i = 0; i < MIN(scan_resp.num_in_scan_table, 64); i++) {
+		if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) {
+			PRINTM(MINFO,
+			       "i=%d break out: current_ev=%p end_buf=%p "
+			       "MAX_SCAN_CELL_SIZE=%d\n",
+			       i, current_ev, end_buf,
+			       (t_u32)MAX_SCAN_CELL_SIZE);
+			ret = -E2BIG;
+			break;
+		}
+		if (!scan_table[i].freq) {
+			PRINTM(MWARN, "Invalid channel number %d\n",
+			       (int)scan_table[i].channel);
+			continue;
+		}
+		PRINTM(MINFO, "i=%d  Ssid: %-32s\n", i,
+		       scan_table[i].ssid.ssid);
+
+		/* check ssid is valid or not, ex. hidden ssid will be filter
+		 * out */
+		if (woal_ssid_valid(&scan_table[i].ssid) == MFALSE)
+			continue;
+
+		/* First entry *MUST* be the AP MAC address */
+		iwe.cmd = SIOCGIWAP;
+		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		moal_memcpy_ext(priv->phandle, iwe.u.ap_addr.sa_data,
+				&scan_table[i].mac_address, ETH_ALEN,
+				sizeof(iwe.u.ap_addr.sa_data));
+
+		iwe.len = IW_EV_ADDR_LEN;
+		current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
+						  &iwe, iwe.len);
+
+		/* Add the ESSID */
+		iwe.u.data.length = scan_table[i].ssid.ssid_len;
+
+		if (iwe.u.data.length > 32)
+			iwe.u.data.length = 32;
+
+		iwe.cmd = SIOCGIWESSID;
+		iwe.u.essid.flags = (i + 1) & IW_ENCODE_INDEX;
+		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+		current_ev =
+			IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,
+					     (char *)scan_table[i].ssid.ssid);
+
+		/* Add mode */
+		iwe.cmd = SIOCGIWMODE;
+		if (scan_table[i].bss_mode == MLAN_BSS_MODE_IBSS)
+			iwe.u.mode = IW_MODE_ADHOC;
+		else if (scan_table[i].bss_mode == MLAN_BSS_MODE_INFRA)
+			iwe.u.mode = IW_MODE_MASTER;
+		else
+			iwe.u.mode = IW_MODE_AUTO;
+
+		iwe.len = IW_EV_UINT_LEN;
+		current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
+						  &iwe, iwe.len);
+
+		/* Frequency */
+		iwe.cmd = SIOCGIWFREQ;
+		iwe.u.freq.m = (long)scan_table[i].freq;
+		iwe.u.freq.e = 6;
+		iwe.u.freq.flags = IW_FREQ_FIXED;
+		iwe.len = IW_EV_FREQ_LEN;
+		current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
+						  &iwe, iwe.len);
+
+		memset(&iwe, 0, sizeof(iwe));
+		/* Add quality statistics */
+		iwe.cmd = IWEVQUAL;
+		iwe.u.qual.level = SCAN_RSSI(scan_table[i].rssi);
+		if (!bss_info.bcn_nf_last)
+			iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+		else
+			iwe.u.qual.noise = bss_info.bcn_nf_last;
+
+		if ((bss_info.bss_mode == MLAN_BSS_MODE_IBSS) &&
+		    !woal_ssid_cmp(&bss_info.ssid, &scan_table[i].ssid) &&
+		    bss_info.adhoc_state == ADHOC_STARTED) {
+			memset(&rssi, 0, sizeof(mlan_ds_get_signal));
+			if (MLAN_STATUS_SUCCESS !=
+			    woal_get_signal_info(priv, MOAL_IOCTL_WAIT,
+						 &rssi)) {
+				ret = -EFAULT;
+				break;
+			}
+			iwe.u.qual.level = rssi.data_rssi_avg;
+		}
+		iwe.u.qual.qual =
+			woal_rssi_to_quality((t_s16)(iwe.u.qual.level - 0x100));
+		iwe.len = IW_EV_QUAL_LEN;
+		current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
+						  &iwe, iwe.len);
+
+		/* Add encryption capability */
+		iwe.cmd = SIOCGIWENCODE;
+		if (scan_table[i].privacy)
+			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+		else
+			iwe.u.data.flags = IW_ENCODE_DISABLED;
+
+		iwe.u.data.length = 0;
+		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+		current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,
+						  &iwe, NULL);
+
+		current_val = current_ev + IW_EV_LCP_LEN;
+
+		iwe.cmd = SIOCGIWRATE;
+
+		iwe.u.bitrate.fixed = 0;
+		iwe.u.bitrate.disabled = 0;
+		iwe.u.bitrate.value = 0;
+
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
+			if (!scan_table[i].supported_rates[j])
+				break;
+
+			iwe.u.bitrate.value =
+				(scan_table[i].supported_rates[j] & 0x7f) *
+				500000;
+			iwe.len = IW_EV_PARAM_LEN;
+			current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
+							   current_val, end_buf,
+							   &iwe, iwe.len);
+		}
+		if ((bss_info.bss_mode == MLAN_BSS_MODE_IBSS) &&
+		    !woal_ssid_cmp(&bss_info.ssid, &scan_table[i].ssid) &&
+		    bss_info.adhoc_state == ADHOC_STARTED) {
+			iwe.u.bitrate.value = 22 * 500000;
+			iwe.len = IW_EV_PARAM_LEN;
+			current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
+							   current_val, end_buf,
+							   &iwe, iwe.len);
+		}
+
+		/* Check if an event is added */
+		if ((unsigned int)(current_val - current_ev) >= IW_EV_PARAM_LEN)
+			current_ev = current_val;
+
+		/* Beacon Interval */
+		memset(&iwe, 0, sizeof(iwe));
+		ptr = buf;
+		ptr += sprintf(ptr, "Beacon interval=%d",
+			       scan_table[i].beacon_period);
+
+		iwe.u.data.length = strlen(buf);
+		iwe.cmd = IWEVCUSTOM;
+		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+		current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,
+						  &iwe, buf);
+		current_val = current_ev + IW_EV_LCP_LEN + strlen(buf);
+
+		/* Parse and send the IEs */
+		pbeacon = scan_table[i].pbeacon_buf;
+		beacon_size = scan_table[i].beacon_buf_size;
+
+		/* Skip time stamp, beacon interval and capability */
+		if (pbeacon) {
+			pbeacon += sizeof(scan_table[i].beacon_period) +
+				sizeof(scan_table[i].time_stamp) +
+				sizeof(scan_table[i].cap_info);
+			beacon_size -= sizeof(scan_table[i].beacon_period) +
+				sizeof(scan_table[i].time_stamp) +
+				sizeof(scan_table[i].cap_info);
+
+			while ((unsigned int)beacon_size >=
+			       sizeof(IEEEtypes_Header_t)) {
+				element_id =
+					(IEEEtypes_ElementId_e)(*(t_u8 *)
+								pbeacon);
+				element_len = *((t_u8 *)pbeacon + 1);
+				if ((unsigned int)beacon_size <
+				    (unsigned int)element_len +
+				    sizeof(IEEEtypes_Header_t)) {
+					PRINTM(MERROR,
+					       "Get scan: Error in processing IE, "
+					       "bytes left < IE length\n");
+					break;
+				}
+
+				switch (element_id) {
+#if WIRELESS_EXT >= 18
+				case VENDOR_SPECIFIC_221:
+				case RSN_IE:
+				case WAPI_IE:
+					praw_data = (t_u8 *)pbeacon;
+					memset(&iwe, 0, sizeof(iwe));
+					memset(buf, 0, buf_size);
+					ptr = buf;
+					moal_memcpy_ext(priv->phandle, buf,
+							praw_data,
+							element_len +
+							sizeof
+							(IEEEtypes_Header_t),
+							buf_size);
+					iwe.cmd = IWEVGENIE;
+					iwe.u.data.length =
+						element_len +
+						sizeof(IEEEtypes_Header_t);
+					iwe.len = IW_EV_POINT_LEN +
+						iwe.u.data.length;
+					current_ev =
+						IWE_STREAM_ADD_POINT(info,
+								     current_ev,
+								     end_buf,
+								     &iwe, buf);
+					current_val =
+						current_ev + IW_EV_LCP_LEN +
+						strlen(buf);
+					break;
+#endif
+				default:
+					break;
+				}
+				pbeacon += element_len +
+					sizeof(IEEEtypes_Header_t);
+				beacon_size -= element_len +
+					sizeof(IEEEtypes_Header_t);
+			}
+		}
+#if WIRELESS_EXT > 14
+		memset(&iwe, 0, sizeof(iwe));
+		memset(buf, 0, buf_size);
+		ptr = buf;
+		ptr += sprintf(ptr, "band=");
+		memset(&iwe, 0, sizeof(iwe));
+		if (scan_table[i].bss_band == BAND_A)
+			ptr += sprintf(ptr, "a");
+		else
+			ptr += sprintf(ptr, "bg");
+		iwe.u.data.length = strlen(buf);
+		PRINTM(MINFO, "iwe.u.data.length %d\n", iwe.u.data.length);
+		PRINTM(MINFO, "BUF: %s\n", buf);
+		iwe.cmd = IWEVCUSTOM;
+		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+		current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,
+						  &iwe, buf);
+		current_val = current_ev + IW_EV_LCP_LEN + strlen(buf);
+#endif
+		current_val = current_ev + IW_EV_LCP_LEN;
+
+		/*
+		 * Check if we added any event
+		 */
+		if ((unsigned int)(current_val - current_ev) > IW_EV_LCP_LEN)
+			current_ev = current_val;
+	}
+
+	dwrq->length = (current_ev - extra);
+	dwrq->flags = 0;
+#endif
+
+done:
+	kfree(buf);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * iwconfig settable callbacks
+ */
+static const iw_handler woal_handler[] = {
+	(iw_handler) woal_config_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) woal_get_name,	/* SIOCGIWNAME */
+	(iw_handler) NULL,	/* SIOCSIWNWID */
+	(iw_handler) NULL,	/* SIOCGIWNWID */
+	(iw_handler) woal_set_freq,	/* SIOCSIWFREQ */
+	(iw_handler) woal_get_freq,	/* SIOCGIWFREQ */
+	(iw_handler) woal_set_bss_mode,	/* SIOCSIWMODE */
+	(iw_handler) woal_get_bss_mode,	/* SIOCGIWMODE */
+	(iw_handler) woal_set_sens,	/* SIOCSIWSENS */
+	(iw_handler) woal_get_sens,	/* SIOCGIWSENS */
+	(iw_handler) NULL,	/* SIOCSIWRANGE */
+	(iw_handler) woal_get_range,	/* SIOCGIWRANGE */
+	(iw_handler) woal_set_priv,	/* SIOCSIWPRIV */
+	(iw_handler) NULL,	/* SIOCGIWPRIV */
+	(iw_handler) NULL,	/* SIOCSIWSTATS */
+	(iw_handler) NULL,	/* SIOCGIWSTATS */
+#if WIRELESS_EXT > 15
+#ifdef CONFIG_WEXT_SPY
+	iw_handler_set_spy,	/* SIOCSIWSPY */
+	iw_handler_get_spy,	/* SIOCGIWSPY */
+	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
+#else
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+#endif
+#else /* WIRELESS_EXT > 15 */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+#endif /* WIRELESS_EXT > 15 */
+	(iw_handler) woal_set_wap,	/* SIOCSIWAP */
+	(iw_handler) woal_get_wap,	/* SIOCGIWAP */
+#if WIRELESS_EXT >= 18
+	(iw_handler) woal_set_mlme,	/* SIOCSIWMLME  */
+#else
+	(iw_handler) NULL,	/* -- hole -- */
+#endif
+	/* (iw_handler) wlan_get_aplist, *//* SIOCGIWAPLIST */
+	NULL,			/* SIOCGIWAPLIST */
+#if WIRELESS_EXT > 13
+	(iw_handler) woal_set_scan,	/* SIOCSIWSCAN */
+	(iw_handler) woal_get_scan,	/* SIOCGIWSCAN */
+#else /* WIRELESS_EXT > 13 */
+	(iw_handler) NULL,	/* SIOCSIWSCAN */
+	(iw_handler) NULL,	/* SIOCGIWSCAN */
+#endif /* WIRELESS_EXT > 13 */
+	(iw_handler) woal_set_essid,	/* SIOCSIWESSID */
+	(iw_handler) woal_get_essid,	/* SIOCGIWESSID */
+	(iw_handler) woal_set_nick,	/* SIOCSIWNICKN */
+	(iw_handler) woal_get_nick,	/* SIOCGIWNICKN */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) woal_set_rate,	/* SIOCSIWRATE */
+	(iw_handler) woal_get_rate,	/* SIOCGIWRATE */
+	(iw_handler) woal_set_rts,	/* SIOCSIWRTS */
+	(iw_handler) woal_get_rts,	/* SIOCGIWRTS */
+	(iw_handler) woal_set_frag,	/* SIOCSIWFRAG */
+	(iw_handler) woal_get_frag,	/* SIOCGIWFRAG */
+	(iw_handler) woal_set_txpow,	/* SIOCSIWTXPOW */
+	(iw_handler) woal_get_txpow,	/* SIOCGIWTXPOW */
+	(iw_handler) woal_set_retry,	/* SIOCSIWRETRY */
+	(iw_handler) woal_get_retry,	/* SIOCGIWRETRY */
+	(iw_handler) woal_set_encode,	/* SIOCSIWENCODE */
+	(iw_handler) woal_get_encode,	/* SIOCGIWENCODE */
+	(iw_handler) woal_set_power,	/* SIOCSIWPOWER */
+	(iw_handler) woal_get_power,	/* SIOCGIWPOWER */
+#if (WIRELESS_EXT >= 18)
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) woal_set_gen_ie,	/* SIOCSIWGENIE */
+	(iw_handler) woal_get_gen_ie,	/* SIOCGIWGENIE */
+	(iw_handler) woal_set_auth,	/* SIOCSIWAUTH  */
+	(iw_handler) woal_get_auth,	/* SIOCGIWAUTH  */
+	(iw_handler) woal_set_encode_ext,	/* SIOCSIWENCODEEXT */
+	(iw_handler) woal_get_encode_ext,	/* SIOCGIWENCODEEXT */
+	(iw_handler) woal_set_pmksa,	/* SIOCSIWPMKSA */
+#endif /* WIRELESSS_EXT >= 18 */
+};
+
+/**
+ * iwpriv settable callbacks
+ */
+static const iw_handler woal_private_handler[] = {
+	NULL,			/* SIOCIWFIRSTPRIV */
+};
+#endif /* STA_SUPPORT */
+
+/********************************************************
+			Global Functions
+********************************************************/
+
+#if WIRELESS_EXT > 14
+
+/**
+ *  @brief This function sends customized event to application.
+ *
+ *  @param priv    A pointer to moal_private structure
+ *  @param str     A pointer to event string
+ *
+ *  @return        N/A
+ */
+void
+woal_send_iwevcustom_event(moal_private *priv, char *str)
+{
+	union iwreq_data iwrq;
+	char buf[IW_CUSTOM_MAX];
+
+	ENTER();
+
+	memset(&iwrq, 0, sizeof(union iwreq_data));
+	memset(buf, 0, sizeof(buf));
+
+	snprintf(buf, sizeof(buf) - 1, "%s", str);
+
+	iwrq.data.pointer = (t_u8 __user *)buf;
+	iwrq.data.length = strlen(buf) + 1;
+
+	/* Send Event to upper layer */
+	wireless_send_event(priv->netdev, IWEVCUSTOM, &iwrq, buf);
+	PRINTM(MINFO, "Wireless event %s is sent to application\n", str);
+
+	LEAVE();
+	return;
+}
+#endif
+
+#if WIRELESS_EXT >= 18
+/**
+ *  @brief This function sends mic error event to application.
+ *
+ *  @param priv    A pointer to moal_private structure
+ *  @param event   MIC MERROR EVENT.
+ *
+ *  @return        N/A
+ */
+void
+woal_send_mic_error_event(moal_private *priv, t_u32 event)
+{
+	union iwreq_data iwrq;
+	struct iw_michaelmicfailure mic;
+
+	ENTER();
+
+	memset(&iwrq, 0, sizeof(iwrq));
+	memset(&mic, 0, sizeof(mic));
+	if (event == MLAN_EVENT_ID_FW_MIC_ERR_UNI)
+		mic.flags = IW_MICFAILURE_PAIRWISE;
+	else
+		mic.flags = IW_MICFAILURE_GROUP;
+	iwrq.data.pointer = (t_u8 __user *)&mic;
+	iwrq.data.length = sizeof(mic);
+
+	wireless_send_event(priv->netdev, IWEVMICHAELMICFAILURE, &iwrq,
+			    (char *)&mic);
+
+	LEAVE();
+	return;
+}
+#endif
+
+// clang-format off
+#ifdef STA_SUPPORT
+/** wlan_handler_def */
+struct iw_handler_def woal_handler_def = {
+	.num_standard = ARRAY_SIZE(woal_handler),
+	.num_private = ARRAY_SIZE(woal_private_handler),
+	.num_private_args = ARRAY_SIZE(woal_private_args),
+	.standard = (iw_handler *) woal_handler,
+	.private = (iw_handler *) woal_private_handler,
+	.private_args = (struct iw_priv_args *)woal_private_args,
+#if WIRELESS_EXT > 20
+	.get_wireless_stats = woal_get_wireless_stats,
+#endif
+};
+
+// clang-format on
+
+/**
+ *  @brief Get wireless statistics
+ *
+ *  @param dev          A pointer to net_device structure
+ *
+ *  @return             A pointer to iw_statistics buf
+ */
+struct iw_statistics *
+woal_get_wireless_stats(struct net_device *dev)
+{
+	moal_private *priv = (moal_private *)netdev_priv(dev);
+	t_u16 wait_option = MOAL_IOCTL_WAIT;
+
+	ENTER();
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	/*
+	 * Since schedule() is not allowed from an atomic context
+	 * such as when dev_base_lock for netdevices is acquired
+	 * for reading/writing in kernel before this call, HostCmd
+	 * is issued in non-blocking way in such contexts and
+	 * blocking in other cases.
+	 */
+	if (in_atomic() || !write_can_lock(&dev_base_lock))
+		wait_option = MOAL_NO_WAIT;
+#endif
+
+	priv->w_stats.status = woal_get_mode(priv, wait_option);
+	priv->w_stats.discard.retries = priv->stats.tx_errors;
+	priv->w_stats.qual.qual = 0;
+
+	/* Send RSSI command to get beacon RSSI/NF, valid only if associated */
+	if (priv->media_connected == MTRUE) {
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_get_signal_info(priv, wait_option, NULL))
+			priv->w_stats.qual.qual = woal_rssi_to_quality((t_s16)
+								       (priv->
+									w_stats.
+									qual.
+									level -
+									0x100));
+	}
+#if WIRELESS_EXT > 18
+	priv->w_stats.qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
+#else
+	priv->w_stats.qual.updated |= 7;
+#endif
+	if (!priv->w_stats.qual.noise && priv->media_connected == MTRUE)
+		priv->w_stats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+
+	PRINTM(MINFO, "Link Quality = %#x\n", priv->w_stats.qual.qual);
+	PRINTM(MINFO, "Signal Level = %#x\n", priv->w_stats.qual.level);
+	PRINTM(MINFO, "Noise = %#x\n", priv->w_stats.qual.noise);
+	priv->w_stats.discard.code = 0;
+	if (MLAN_STATUS_SUCCESS != woal_get_stats_info(priv, wait_option, NULL))
+		PRINTM(MERROR, "Error getting stats information\n");
+
+	LEAVE();
+	return &priv->w_stats;
+}
+#endif /* STA_SUPPORT */
diff --git a/wlan_sd8987/mlinux/moal_wext.h b/wlan_sd8987/mlinux/moal_wext.h
new file mode 100755
index 0000000..c7ae47b
--- /dev/null
+++ b/wlan_sd8987/mlinux/moal_wext.h
@@ -0,0 +1,58 @@
+/** @file moal_wext.h
+ *
+ * @brief This file contains definition for wireless extension IOCTL call.
+ *
+ *
+ * Copyright 2008-2020 NXP
+ *
+ * This software file (the File) is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the License).  You may use, redistribute and/or modify the File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+
+/********************************************************
+Change log:
+    10/21/2008: initial version
+********************************************************/
+
+#ifndef _WOAL_WEXT_H_
+#define _WOAL_WEXT_H_
+
+/** NF value for default scan */
+#define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+/** Add event */
+#define IWE_STREAM_ADD_EVENT(i, c, e, w, l)                                    \
+	iwe_stream_add_event((i), (c), (e), (w), (l))
+/** Add point */
+#define IWE_STREAM_ADD_POINT(i, c, e, w, p)                                    \
+	iwe_stream_add_point((i), (c), (e), (w), (p))
+/** Add value */
+#define IWE_STREAM_ADD_VALUE(i, c, v, e, w, l)                                 \
+	iwe_stream_add_value((i), (c), (v), (e), (w), (l))
+#else
+/** Add event */
+#define IWE_STREAM_ADD_EVENT(i, c, e, w, l)                                    \
+	iwe_stream_add_event((c), (e), (w), (l))
+/** Add point */
+#define IWE_STREAM_ADD_POINT(i, c, e, w, p)                                    \
+	iwe_stream_add_point((c), (e), (w), (p))
+/** Add value */
+#define IWE_STREAM_ADD_VALUE(i, c, v, e, w, l)                                 \
+	iwe_stream_add_value((c), (v), (e), (w), (l))
+#endif
+
+extern struct iw_handler_def woal_handler_def;
+struct iw_statistics *woal_get_wireless_stats(struct net_device *dev);
+#endif /* _WOAL_WEXT_H_ */